From 0ba329781cb4a526b815bb3b2ba740e39b6bfc06 Mon Sep 17 00:00:00 2001 From: Oliver Eyton-Williams Date: Fri, 28 Feb 2025 13:47:18 +0100 Subject: [PATCH] chore: move playwright tests from main repo (#1341) * chore: move playwright tests from main repo * fix: update import paths --- .github/workflows/mobile-curriculum-e2e.yml | 2 +- .gitignore | 4 + e2e/learn.spec.js | 61 ++++++++++ e2e/playwright.config.js | 53 +++++++++ package-lock.json | 116 ++++++++++++++++++++ package.json | 2 + 6 files changed, 237 insertions(+), 1 deletion(-) create mode 100644 e2e/learn.spec.js create mode 100644 e2e/playwright.config.js diff --git a/.github/workflows/mobile-curriculum-e2e.yml b/.github/workflows/mobile-curriculum-e2e.yml index f5661e851..9adcaee80 100644 --- a/.github/workflows/mobile-curriculum-e2e.yml +++ b/.github/workflows/mobile-curriculum-e2e.yml @@ -76,7 +76,7 @@ jobs: run: npm install -g serve - name: Run playwright tests - run: npx playwright test --config=playwright-mobile.config.ts + run: npx playwright test --config=mobile/e2e/playwright.config.js - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4 if: ${{ !cancelled() }} diff --git a/.gitignore b/.gitignore index c7d31502f..2fe6f4e66 100644 --- a/.gitignore +++ b/.gitignore @@ -66,3 +66,7 @@ play-store-credentials.json generated-tests/ curriculum.json + +# e2e tests + +/e2e/playwright diff --git a/e2e/learn.spec.js b/e2e/learn.spec.js new file mode 100644 index 000000000..d1fc5cf06 --- /dev/null +++ b/e2e/learn.spec.js @@ -0,0 +1,61 @@ +import { expect, test } from "@playwright/test"; + +// These are all in the freeCodeCamp repo. That repo is installed at the root +// in CI. +import currData from "../../shared/config/curriculum.json"; +import { orderedSuperBlockInfo } from "../../tools/scripts/build/build-external-curricula-data"; +import { SuperBlocks } from "../../shared/config/curriculum"; + +// non editor superblocks should be skipped because they are not +// checked if they are compatible with the mobile app. + +const nonEditorSB = [ + SuperBlocks.PythonForEverybody, + SuperBlocks.DataAnalysisPy, + SuperBlocks.MachineLearningPy, + SuperBlocks.CollegeAlgebraPy, + SuperBlocks.A2English, + SuperBlocks.B1English, +]; + +const publicSB = orderedSuperBlockInfo + .filter((sb) => sb.public === true && !nonEditorSB.includes(sb.dashedName)) + .map((sb) => sb.dashedName); + +const removeCertSuperBlock = (currData) => { + const copy = currData; + delete copy["certifications"]; + return copy; +}; + +const typedCurriculum = removeCertSuperBlock(currData); + +test.describe("Test challenges in mobile", () => { + for (const superBlock of publicSB) { + for (const currBlock of Object.values( + typedCurriculum[superBlock]["blocks"] + )) { + test.describe(`SuperBlock: ${superBlock} - Block: ${currBlock["meta"]["name"]}`, () => { + for (const currChallenge of currBlock["challenges"]) { + // Skip non-editor challenges + if (![0, 1, 5, 6, 14].includes(currChallenge["challengeType"])) { + continue; + } + + test(`Challenge: ${currChallenge["title"]}(${currChallenge["id"]})`, async ({ + page, + }) => { + const logMsges = []; + page.on("console", (msg) => { + logMsges.push(msg.text()); + }); + await page.goto( + `/${superBlock}/${currChallenge["block"]}/${currChallenge["id"]}` + ); + expect(logMsges).toContain("completed"); + }); + } + }); + } + } +}); diff --git a/e2e/playwright.config.js b/e2e/playwright.config.js new file mode 100644 index 000000000..0cbb8982d --- /dev/null +++ b/e2e/playwright.config.js @@ -0,0 +1,53 @@ +import path from 'path'; +import { config as dotenvConfig } from 'dotenv'; +import { defineConfig, devices } from '@playwright/test'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +const envPath = path.resolve(__dirname, '.env'); +dotenvConfig({ path: envPath }); +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: '.', + testMatch: '*.spec.js', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: [['html', { outputFolder: 'playwright/reporter' }]], + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + timeout: 15 * 1000, + outputDir: 'playwright/test-results', + + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://127.0.0.1:3000/', + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Use custom test attribute */ + testIdAttribute: 'data-playwright-test-label' + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'Mobile Chrome', + use: { ...devices['Pixel 5'] } + } + ], + + /* Run your local dev server before starting the tests */ + webServer: { + command: 'cd ../mobile-app && npx serve generated-tests', + url: 'http://127.0.0.1:3000', + reuseExistingServer: !process.env.CI + } +}); diff --git a/package-lock.json b/package-lock.json index a035ab8d2..431078222 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,8 @@ "hasInstallScript": true, "license": "BSD-3-Clause", "devDependencies": { + "@playwright/test": "1.50.1", + "dotenv": "16.4.7", "husky": "9.0.11", "lint-staged": "15.2.7", "npm-run-all2": "6.2.0", @@ -20,6 +22,22 @@ "npm": ">=8" } }, + "node_modules/@playwright/test": { + "version": "1.50.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.50.1.tgz", + "integrity": "sha512-Jii3aBg+CEDpgnuDxEp/h7BimHcUTDlpEtce89xEumlJ5ef2hqepZ+PWp1DDpYC/VO9fmWVI1IlEaoI5fK9FXQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.50.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/ansi-escapes": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", @@ -183,6 +201,19 @@ } } }, + "node_modules/dotenv": { + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/emoji-regex": { "version": "10.3.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", @@ -237,6 +268,21 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -734,6 +780,38 @@ "node": ">=0.10" } }, + "node_modules/playwright": { + "version": "1.50.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.50.1.tgz", + "integrity": "sha512-G8rwsOQJ63XG6BbKj2w5rHeavFjy5zynBA9zsJMMtBoe/Uf757oG12NXz6e6OirF7RCrTVAKFXbLmn1RbL7Qaw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.50.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.50.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.50.1.tgz", + "integrity": "sha512-ra9fsNWayuYumt+NiM069M6OkcRb1FZSK8bgi66AtpFoWkg2+y0bJSNmkFrWhMbEBbVKC/EruAHH3g0zmtwGmQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/read-package-json-fast": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", @@ -1041,6 +1119,15 @@ } }, "dependencies": { + "@playwright/test": { + "version": "1.50.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.50.1.tgz", + "integrity": "sha512-Jii3aBg+CEDpgnuDxEp/h7BimHcUTDlpEtce89xEumlJ5ef2hqepZ+PWp1DDpYC/VO9fmWVI1IlEaoI5fK9FXQ==", + "dev": true, + "requires": { + "playwright": "1.50.1" + } + }, "ansi-escapes": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", @@ -1147,6 +1234,12 @@ "ms": "2.1.2" } }, + "dotenv": { + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "dev": true + }, "emoji-regex": { "version": "10.3.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", @@ -1191,6 +1284,13 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -1526,6 +1626,22 @@ "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", "dev": true }, + "playwright": { + "version": "1.50.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.50.1.tgz", + "integrity": "sha512-G8rwsOQJ63XG6BbKj2w5rHeavFjy5zynBA9zsJMMtBoe/Uf757oG12NXz6e6OirF7RCrTVAKFXbLmn1RbL7Qaw==", + "dev": true, + "requires": { + "fsevents": "2.3.2", + "playwright-core": "1.50.1" + } + }, + "playwright-core": { + "version": "1.50.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.50.1.tgz", + "integrity": "sha512-ra9fsNWayuYumt+NiM069M6OkcRb1FZSK8bgi66AtpFoWkg2+y0bJSNmkFrWhMbEBbVKC/EruAHH3g0zmtwGmQ==", + "dev": true + }, "read-package-json-fast": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", diff --git a/package.json b/package.json index cb0813853..c2ee33742 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,8 @@ "prepare": "husky" }, "devDependencies": { + "@playwright/test": "1.50.1", + "dotenv": "16.4.7", "husky": "9.0.11", "lint-staged": "15.2.7", "npm-run-all2": "6.2.0",