diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5f98f29c9..cb8f7f126 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,7 +23,7 @@ env: jobs: build: - timeout-minutes: 15 + timeout-minutes: 20 runs-on: ubuntu-latest permissions: contents: read @@ -60,12 +60,9 @@ jobs: - run: npm run ci env: VITE_SENTRY_DSN: ${{ secrets.SENTRY_DSN }} - - run: mkdir -p /tmp/app${BASE_URL} && cp -r build/* /tmp/app${BASE_URL} && npx serve --no-clipboard -l 3000 /tmp/app & - if: env.STAGE == 'REVIEW' || env.STAGE == 'STAGING' - - run: curl --insecure -4 --retry 7 --retry-connrefused http://localhost:3000 1>/dev/null - if: env.STAGE == 'REVIEW' || env.STAGE == 'STAGING' - name: Run Playwright tests if: env.STAGE == 'REVIEW' || env.STAGE == 'STAGING' + timeout-minutes: 10 uses: docker://mcr.microsoft.com/playwright:v1.63.0-noble with: args: npx playwright test @@ -73,8 +70,8 @@ jobs: if: (env.STAGE == 'REVIEW' || env.STAGE == 'STAGING') && failure() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: - name: reports - path: reports/ + name: playwright-report + path: playwright-report/ retention-days: 3 - run: npm run deploy if: github.repository_owner == 'microbit-foundation' && (env.STAGE == 'REVIEW' || success()) diff --git a/.prettierignore b/.prettierignore index e8734ec6c..051b4f585 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,4 @@ src/editor/codemirror/lint/lint.ts styled-system src/styled-system.css +src/micropython/main/typeshed.*.json diff --git a/README.md b/README.md index 5994c9d56..caecce7bc 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,9 @@ Getting up and running: 1. Ensure you have a working [Node.js environment](https://nodejs.org/en/download/). We recommend using the LTS version of Node and NPM version 8 or newer. 2. Checkout this repository with Git. GitHub have some [learning resources for Git](https://docs.github.com/en/get-started/quickstart/git-and-github-learning-resources) that you may find useful. 3. Install the dependencies by running `npm install` on the command line in the checkout folder. -4. Choose from the NPM scripts documented below. Try `npm start` if you're not sure. +4. Choose from the NPM scripts documented below. Try `npm run dev` if you're not sure. -### `npm start` +### `npm run dev` Runs the app in the development mode. @@ -48,13 +48,16 @@ If you have a connected micro:bit device, then setting the environment variable ### `npm run test:e2e` -Launches the test runner in the interactive watch mode running the end to end tests. +Opens the [Playwright](https://playwright.dev/) UI to run the end to end tests. +`npm run test:e2e:headless` runs them without it. These are excluded from the normal test run. -The tests expect the app to already be running on http://localhost:3000, for example via `npm start`. +Playwright starts the dev server itself, reusing one already running on +http://localhost:3000 if there is one. -We use [Playwright](https://playwright.dev/). +The browsers are a separate download: run `npx playwright install` before the +first run. The CI tests run these end-to-end tests against a production build. diff --git a/package.json b/package.json index 274303be8..f28b67b55 100644 --- a/package.json +++ b/package.json @@ -85,28 +85,30 @@ "npm": ">=11.18.0" }, "scripts": { + "dev": "vite dev", + "predev": "npm run generate", "build": "vite build", "prebuild": "npm run generate", - "ci": "npm run typecheck && npm run test && npm run lint && npm run i18n:tidy -- --check && npm run build", - "deploy": "website-deploy-aws", - "dev:link-ui": "rm -rf node_modules/@microbit/ui node_modules/@microbit/ui-patterns node_modules/@microbit/i18n-tools && ln -s ../../../ui/packages/ui node_modules/@microbit/ui && ln -s ../../../ui/packages/ui-patterns node_modules/@microbit/ui-patterns && ln -s ../../../ui/packages/i18n-tools node_modules/@microbit/i18n-tools && ln -sf ../@microbit/i18n-tools/bin/microbit-i18n.mjs node_modules/.bin/microbit-i18n && rm -rf styled-system node_modules/.vite && npm run panda", - "generate": "npm run panda && npm run i18n:compile && npm run stubs", - "i18n:compile": "microbit-i18n compile", - "invalidate": "aws cloudfront create-invalidation --distribution-id $(printenv ${STAGE}_CLOUDFRONT_DISTRIBUTION_ID) --paths \"/*\"", - "lint": "eslint . --max-warnings 0", - "prepare": "npm run generate", + "preview": "vite preview", "panda": "panda codegen", "panda:watch": "panda codegen --watch", - "serve": "npx serve --no-clipboard -l 3000 -- build/", - "prestart": "npm run generate", - "start": "vite dev", + "generate": "npm run panda && npm run i18n:compile && npm run stubs", "stubs": "cp node_modules/@microbit/micropython-microbit-stubs/typeshed.*.json src/micropython/main/", - "test:e2e:headless": "playwright test", - "test:e2e": "playwright test --ui", - "test": "vitest", - "pretypecheck": "npm run generate", + "postinstall": "npm run generate", + "lint": "eslint . --max-warnings 0", + "format": "prettier --write src", + "format:check": "prettier --check src", "typecheck": "tsc --noEmit", + "pretypecheck": "npm run generate", "typecheck:watch": "tsc --noEmit --watch", + "test": "vitest", + "test:e2e": "playwright test --ui", + "test:e2e:headless": "playwright test", + "ci": "npm run typecheck && npm run lint && npm run test && npm run i18n:tidy -- --check && npm run build", + "deploy": "website-deploy-aws", + "invalidate": "invalidate-cloudfront-distribution", + "dev:link-ui": "rm -rf node_modules/@microbit/ui node_modules/@microbit/ui-patterns node_modules/@microbit/i18n-tools && ln -s ../../../ui/packages/ui node_modules/@microbit/ui && ln -s ../../../ui/packages/ui-patterns node_modules/@microbit/ui-patterns && ln -s ../../../ui/packages/i18n-tools node_modules/@microbit/i18n-tools && ln -sf ../@microbit/i18n-tools/bin/microbit-i18n.mjs node_modules/.bin/microbit-i18n && rm -rf styled-system node_modules/.vite && npm run panda", + "i18n:compile": "microbit-i18n compile", "i18n:tidy": "microbit-i18n tidy", "i18n:download": "microbit-i18n download", "i18n:upload": "microbit-i18n upload", diff --git a/playwright.config.ts b/playwright.config.ts index 2a672411f..6454be1bd 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -1,5 +1,11 @@ import { defineConfig, devices } from "@playwright/test"; +// The page objects build their absolute URLs from E2E_PORT, so it has to +// name whichever server this run starts: the dev server locally, or +// `vite preview` on the production build in CI. +const port = process.env.CI ? 4000 : 3000; +process.env.E2E_PORT ??= String(port); + /** * See https://playwright.dev/docs/test-configuration. */ @@ -35,12 +41,12 @@ export default defineConfig({ webServer: { ...(process.env.CI ? { - command: `npx vite preview --port 3000 --base ${process.env.BASE_URL}`, - url: `http://localhost:3000${process.env.BASE_URL}`, + command: `npx vite preview --port ${port} --base ${process.env.BASE_URL}`, + url: `http://localhost:${port}${process.env.BASE_URL}`, } : { - command: "npm run start", - url: "http://localhost:3000", + command: "npm run dev", + url: `http://localhost:${port}`, }), reuseExistingServer: !process.env.CI, }, diff --git a/src/common/chunk-util.ts b/src/common/chunk-util.ts index 21c13da11..8bb416654 100644 --- a/src/common/chunk-util.ts +++ b/src/common/chunk-util.ts @@ -14,7 +14,7 @@ export const retryAsyncLoad = async ( ): Promise => { let waitTime = 250; let attempts = 0; - + while (true) { try { // Must await here! diff --git a/vite.config.ts b/vite.config.ts index d40ff7839..db42bcc2b 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -110,6 +110,11 @@ export default defineConfig(({ mode }) => { }, server: { port: 3000, + strictPort: true, + }, + preview: { + port: 4000, + strictPort: true, }, assetsInclude: ["**/*.hex"], plugins: [