diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index afe94ca8e4..8d20b806ce 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -228,8 +228,32 @@ jobs: pushd e2e_project_sveltekit dfx canister create e2e_project_sveltekit_frontend --specified-id erxue-5aaaa-aaaab-qaagq-cai dfx deploy + popd rm -rf e2e_project_sveltekit + - name: Deploy react starter project + run: | + dfx new e2e_project_react --frontend react + pushd e2e_project_react + dfx canister create e2e_project_react_frontend --specified-id rdbii-uiaaa-aaaab-qadva-cai + dfx deploy + popd + rm -rf e2e_project_react + - name: Deploy vanilla starter project + run: | + dfx new e2e_project_vanilla --frontend vanilla + pushd e2e_project_vanilla + dfx canister create e2e_project_vanilla_frontend --specified-id qjoks-wyaaa-aaaab-qadsa-cai + dfx deploy popd + rm -rf e2e_project_vanilla + - name: Deploy vue starter project + run: | + dfx new e2e_project_vue --frontend vue + pushd e2e_project_vue + dfx canister create e2e_project_vue_frontend --specified-id qopmg-3aaaa-aaaab-qadsq-cai + dfx deploy + popd + rm -rf e2e_project_vue # Add any additional deployments here - name: Install Playwright Browsers and Run Tests run: | @@ -239,7 +263,6 @@ jobs: npx playwright test popd - aggregate: name: e2e:required if: always() && needs.changes.outputs.sources == 'true' diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a9c7ee49b..34ef8a43f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,9 @@ Due to the incompatibility between the APIs on the replica port and the PocketIC port, `dfx info replica-port` no longer works with PocketIC, and the PocketIC port is provided by a new command, `dfx info pocketic-config-port`. -### test: adds playwright test for svelte `dfx new` project +### test: adds playwright tests for `dfx new` project frontends -The first of a suite of baseline tests to automate testing starter projects. Makes sure they are compatible with other dfx or asset canister changes. +The first of a suite of baseline tests to automate testing starter projects. Makes sure that sveltekit, react, vue, and vanilla frontends are compatible with other dfx or asset canister changes. ### fix: template frontends now have unsupported browser warnings @@ -285,7 +285,7 @@ had not been previously built for the local network. Added support for the canister log allowed viewer list, enabling specified users to access a canister's logs without needing to be set as the canister's controller. Valid settings are: -- `--add-log-viewer`, `--remove-log-viewer` and `--set-log-viewer` flags with `dfx canister update-settings` +- `--add-log-viewer`, `--remove-log-viewer` and `--set-log-viewer` flags with `dfx canister update-settings` - `--log-viewer` flag with `dfx canister create` - `canisters[].initialization_values.log_visibility.allowed_viewers` in `dfx.json` @@ -381,7 +381,7 @@ Module hash 15da2adc4426b8037c9e716b81cb6a8cf1a835ac37589be2cef8cb3f4a04adaa `dfx deploy --mode` now takes the same possible values as `dfx canister install --mode`: "install", "reinstall", "upgrade" and "auto". -In "auto" mode, the upgrade options are hints which only take effects when the actual install mode is "upgrade". +In "auto" mode, the upgrade options are hints which only take effects when the actual install mode is "upgrade". To maintain backward compatibility, a minor difference between the two commands remains. If the `--mode` is not set, `dfx deploy` defaults to "auto", while `dfx canister install` defaults to "install". diff --git a/e2e/playwright/tests/react.spec.ts b/e2e/playwright/tests/react.spec.ts new file mode 100644 index 0000000000..82a585161e --- /dev/null +++ b/e2e/playwright/tests/react.spec.ts @@ -0,0 +1,43 @@ +import { test, expect } from "@playwright/test"; + +test("has title", async ({ page }) => { + await page.goto("http://rdbii-uiaaa-aaaab-qadva-cai.localhost:4943/"); + + // Expect a title "to contain" a substring. + await expect(page).toHaveTitle(/IC Hello Starter/); +}); + +test("image has loaded", async ({ page }) => { + await page.goto("http://rdbii-uiaaa-aaaab-qadva-cai.localhost:4943/"); + + // Set the attribute so we can read it + await page.evaluate(async () => { + await new Promise((resolve) => { + setTimeout(() => { + document.querySelectorAll("img").forEach((img) => { + img.setAttribute("complete", String(img.complete)); + }); + resolve(); + }, 1_000); + }); + }); + + const image = await page.getByAltText("DFINITY logo"); + await expect(await image.getAttribute("complete")).toBe("true"); +}); + +test("has hello form", async ({ page }) => { + await page.goto("http://rdbii-uiaaa-aaaab-qadva-cai.localhost:4943/"); + + // Fill out the form + const nameInput = await page.getByLabel("name"); + nameInput.fill("World"); + + const submitButton = await page.locator("button[type='submit']"); + await submitButton.click(); + + // Expects page to have a heading with the name of Installation. + const greeting = await page.locator("#greeting"); + await expect(greeting).toBeVisible(); + await expect(await greeting.innerText()).toBe("Hello, World!"); +}); diff --git a/e2e/playwright/tests/vanilla.spec.ts b/e2e/playwright/tests/vanilla.spec.ts new file mode 100644 index 0000000000..4bba818247 --- /dev/null +++ b/e2e/playwright/tests/vanilla.spec.ts @@ -0,0 +1,43 @@ +import { test, expect } from "@playwright/test"; + +test("has title", async ({ page }) => { + await page.goto("http://qjoks-wyaaa-aaaab-qadsa-cai.localhost:4943/"); + + // Expect a title "to contain" a substring. + await expect(page).toHaveTitle(/IC Hello Starter/); +}); + +test("image has loaded", async ({ page }) => { + await page.goto("http://qjoks-wyaaa-aaaab-qadsa-cai.localhost:4943/"); + + // Set the attribute so we can read it + await page.evaluate(async () => { + await new Promise((resolve) => { + setTimeout(() => { + document.querySelectorAll("img").forEach((img) => { + img.setAttribute("complete", String(img.complete)); + }); + resolve(); + }, 1_000); + }); + }); + + const image = await page.getByAltText("DFINITY logo"); + await expect(await image.getAttribute("complete")).toBe("true"); +}); + +test("has hello form", async ({ page }) => { + await page.goto("http://qjoks-wyaaa-aaaab-qadsa-cai.localhost:4943/"); + + // Fill out the form + const nameInput = await page.getByLabel("name"); + nameInput.fill("World"); + + const submitButton = await page.locator("button[type='submit']"); + await submitButton.click(); + + // Expects page to have a heading with the name of Installation. + const greeting = await page.locator("#greeting"); + await expect(greeting).toBeVisible(); + await expect(await greeting.innerText()).toBe("Hello, World!"); +}); diff --git a/e2e/playwright/tests/vue.spec.ts b/e2e/playwright/tests/vue.spec.ts new file mode 100644 index 0000000000..d26b12fff1 --- /dev/null +++ b/e2e/playwright/tests/vue.spec.ts @@ -0,0 +1,43 @@ +import { test, expect } from "@playwright/test"; + +test("has title", async ({ page }) => { + await page.goto("http://qopmg-3aaaa-aaaab-qadsq-cai.localhost:4943/"); + + // Expect a title "to contain" a substring. + await expect(page).toHaveTitle(/IC Hello Starter/); +}); + +test("image has loaded", async ({ page }) => { + await page.goto("http://qopmg-3aaaa-aaaab-qadsq-cai.localhost:4943/"); + + // Set the attribute so we can read it + await page.evaluate(async () => { + await new Promise((resolve) => { + setTimeout(() => { + document.querySelectorAll("img").forEach((img) => { + img.setAttribute("complete", String(img.complete)); + }); + resolve(); + }, 1_000); + }); + }); + + const image = await page.getByAltText("DFINITY logo"); + await expect(await image.getAttribute("complete")).toBe("true"); +}); + +test("has hello form", async ({ page }) => { + await page.goto("http://qopmg-3aaaa-aaaab-qadsq-cai.localhost:4943/"); + + // Fill out the form + const nameInput = await page.getByLabel("name"); + nameInput.fill("World"); + + const submitButton = await page.locator("button[type='submit']"); + await submitButton.click(); + + // Expects page to have a heading with the name of Installation. + const greeting = await page.locator("#greeting"); + await expect(greeting).toBeVisible(); + await expect(await greeting.innerText()).toBe("Hello, World!"); +});