Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Headless tests improvements #2463

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/workflows/wasp-app-runner.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Publish Wasp App Runner
on:
push:
paths:
- "wasp-app-runner/**"
branches:
- release

defaults:
run:
shell: bash
working-directory: wasp-app-runner

jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v3
with:
node-version: "20"
- run: npm ci
- uses: JS-DevTools/npm-publish@v3
with:
token: ${{ secrets.NPM_TOKEN }}
48 changes: 29 additions & 19 deletions .github/workflows/waspc-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ name: WASPC-CI
on:
push:
paths:
- 'waspc/**'
- "waspc/**"
branches:
- main
- release
pull_request:
paths:
- 'waspc/**'
- "waspc/**"
create: { tags: [v*] }
schedule:
# Additionally run once per week (At 00:00 on Sunday) to avoid loosing cache
# (GH deletes it after 7 days of not using it).
- cron: '0 0 * * 0'
- cron: "0 0 * * 0"

env:
WASP_TELEMETRY_DISABLE: 1
Expand Down Expand Up @@ -51,24 +51,24 @@ jobs:
- macos-latest
- windows-latest
node-version:
- 'latest'
- "latest"
ghc:
- '8.10.7'
- "8.10.7"
cabal:
- '3.6.2.0'
- "3.6.2.0"
# In addition to the default matrix, we also want to run the build job for
# additional Node.js versions, to make sure that Wasp works with them.
# To reduce the number of jobs, we only test the Node.js versions on
# Ubuntu 20.04.
include:
- os: ubuntu-20.04
node-version: 18
ghc: '8.10.7'
cabal: '3.6.2.0'
ghc: "8.10.7"
cabal: "3.6.2.0"
- os: ubuntu-20.04
node-version: 20
ghc: '8.10.7'
cabal: '3.6.2.0'
ghc: "8.10.7"
cabal: "3.6.2.0"

steps:
- name: Configure git
Expand All @@ -80,7 +80,7 @@ jobs:
git config --global core.autocrlf input
git config --global core.eol lf

- uses: 'actions/checkout@v3'
- uses: "actions/checkout@v3"
with:
# Workaround for a Github Checkout action bug
# https://github.com/actions/checkout/issues/1359#issuecomment-1567902034
Expand Down Expand Up @@ -170,18 +170,29 @@ jobs:
path: ~/.npm
key: node-modules-${{ hashFiles('./waspc/headless-test/package-lock.json') }}-${{ matrix.os }}-${{ matrix.node-version }}

# TODO: remove this once we start publishing the wasp-app-runner
# as a npm package
- name: Headless - Setup the Wasp app runner
id: headless-setup-wasp-app-runner
if: matrix.os == 'ubuntu-20.04'
run: |
cd ../wasp-app-runner
npm ci
# Installs the wasp-app-runner globally so that it can be used in the tests
npm run install:global

- name: Headless - Install Dependencies
id: headless-install-dependencies
if: matrix.os == 'ubuntu-20.04'
run: |
cd headless-test
cd examples/todoApp
npm ci

- name: Headless - Store Playwright's Version
id: headless-store-playwright-version
if: matrix.os == 'ubuntu-20.04'
run: |
cd headless-test
cd examples/todoApp
PLAYWRIGHT_VERSION=$(npm ls @playwright/test | grep @playwright | sed 's/.*@//')
echo "Playwright's Version: $PLAYWRIGHT_VERSION"
echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> $GITHUB_ENV
Expand All @@ -198,18 +209,17 @@ jobs:
id: headless-setup-playwright
if: steps.cache-playwright-browsers.outputs.cache-hit != 'true' && matrix.os == 'ubuntu-20.04'
run: |
cd headless-test
cd examples/todoApp
npx playwright install --with-deps

- name: Headless - Run Playwright Tests
id: headless-run-playwright-tests
if: matrix.os == 'ubuntu-20.04'
run: |
cd headless-test
npm ci
cd examples/todoApp
# Runs the tests with the debug flag so that we can see Wasp output
DEBUG=pw:webserver npx playwright test
DEBUG=pw:webserver npx playwright test --config headless-tests/

- name: Run e2e tests
run: cabal test e2e-test

Expand All @@ -226,7 +236,7 @@ jobs:
with:
draft: true
allowUpdates: true
artifacts: 'waspc/artifacts/*'
artifacts: "waspc/artifacts/*"
artifactErrorsFailBuild: true
replacesArtifacts: true
token: ${{ secrets.GITHUB_TOKEN }}
3 changes: 3 additions & 0 deletions examples/todo-typescript/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ node_modules/
# Don't ignore example dotenv files.
!.env.example
!.env.*.example

# Headless tests
test-results/
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,13 @@ export default defineConfig({

/* Run your local dev server before starting the tests */
webServer: {
command: "npm run example-app:start",
command:
"wasp-app-runner --app-path=../ --app-name=examples-todo-typescript --db-type=sqlite",

// Wait for the backend to start
url: "http://localhost:3001",
reuseExistingServer: !process.env.CI,
timeout: 120 * 1000,
timeout: 180 * 1000,
gracefulShutdown: { signal: "SIGTERM", timeout: 500 },
},
});
43 changes: 43 additions & 0 deletions examples/todo-typescript/headless-tests/tests/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import type { Page } from "@playwright/test";

export async function performSignup(
page: Page,
{ username, password }: { username: string; password: string }
) {
await page.goto("/signup");

await page.waitForSelector("text=Create a new account");

await page.locator("input[name='username']").fill(username);
await page.locator("input[type='password']").fill(password);
await page.locator("button").click();
}

export async function performLogin(
page: Page,
{
username,
password,
}: {
username: string;
password: string;
}
) {
await page.goto("/login");

await page.waitForSelector("text=Log in to your account");

await page.locator("input[name='username']").fill(username);
await page.locator("input[type='password']").fill(password);
await page.getByRole("button", { name: "Log in" }).click();
}

export function generateRandomCredentials(): {
username: string;
password: string;
} {
return {
username: `test${Math.random().toString(36).substring(7)}`,
password: "12345678",
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,64 +8,49 @@ import {
test("has title", async ({ page }) => {
await page.goto("/");

await expect(page).toHaveTitle(/ToDo App/);
await expect(page).toHaveTitle(/ToDo TypeScript/);
});
test.describe("signup and login", () => {
const { email, password } = generateRandomCredentials();
const { username, password } = generateRandomCredentials();

test.describe.configure({ mode: "serial" });

test("social button renders", async ({ page }) => {
await page.goto("/signup");

await page.waitForSelector("text=Create a new account");

await expect(
page.locator("a[href='http://localhost:3001/auth/google/login']")
).toBeVisible();
});

test("can sign up", async ({ page }) => {
await performSignup(page, {
email,
username,
password,
});

await expect(page.locator("body")).toContainText(
`You've signed up successfully! Check your email for the confirmation link.`
);
await expect(page).toHaveURL("/");

await page.locator("button.logout").click();

await expect(page).toHaveURL("/login");
});

test("can log in and create a task", async ({ page }) => {
await performLogin(page, {
email,
username,
password: "12345678xxx",
});

await expect(page.locator("body")).toContainText("Invalid credentials");

await performLogin(page, {
email,
username,
password,
});

await expect(page).toHaveURL("/profile");

await page.goto("/");
await expect(page).toHaveURL("/");

// Create a new task
const randomTask = `New Task ${Math.random().toString(36).substring(7)}`;
await page.locator("input[type='text']").fill(randomTask);
await page.getByText("Create new task").click();
await page.getByText("Create task").click();

const fullTaskText = `${randomTask} by ${email}`;
const fullTaskText = `${randomTask}`;
await page.waitForSelector(`text=${fullTaskText}`);

await expect(page.locator("body")).toContainText(fullTaskText);

// Navigate to task page
await page.locator(`text=${fullTaskText}`).click();
const taskPageText = `description: ${randomTask}`;
await page.waitForSelector(`text=${taskPageText}`);
});
});
56 changes: 56 additions & 0 deletions examples/todo-typescript/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions examples/todo-typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "todoTypescript",
"type": "module",
"dependencies": {
"@playwright/test": "^1.50.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.26.2",
Expand Down
5 changes: 3 additions & 2 deletions examples/todo-typescript/src/Main.css
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ img {
max-height: 100px;
}

.logout {
.logout,
.delete-tasks {
margin-top: 1rem;
}

Expand Down Expand Up @@ -70,4 +71,4 @@ li {
flex-direction: row;
justify-content: space-between;
align-items: center;
}
}
Loading
Loading