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

Setup Cloud e2e test framework and write first tests #6244

Draft
wants to merge 37 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
23cc133
Create a global test object with `beforeAll`, `afterAll`
ericpgreen2 Dec 10, 2024
c2647d4
Add a test for unauthenticated users
ericpgreen2 Dec 10, 2024
5b08863
Progress
ericpgreen2 Dec 10, 2024
f332258
Add `baseURL`
ericpgreen2 Dec 11, 2024
6827379
Add option to skip global setup
ericpgreen2 Dec 12, 2024
67078bd
Use port 3000 for `vite preview`
ericpgreen2 Dec 12, 2024
6f7ff66
Try to reuse existing web server (if not in CI)
ericpgreen2 Dec 12, 2024
8fe9aab
Add `rill deploy` test
ericpgreen2 Dec 12, 2024
edfd77e
Use public `rill-examples` repo
ericpgreen2 Dec 12, 2024
3389b81
Add auth step
ericpgreen2 Dec 12, 2024
c5ef656
Use Playwright's native `globalSetup` config
ericpgreen2 Dec 13, 2024
19594db
Use fixture for anon users
ericpgreen2 Dec 13, 2024
5f4d1c6
Cleanup
ericpgreen2 Dec 13, 2024
0b59304
Add CLI fixture
ericpgreen2 Dec 13, 2024
2414a31
Add test for the org page
ericpgreen2 Dec 13, 2024
5ab68a6
Organize the Homepage tests into a suite
ericpgreen2 Dec 13, 2024
d5a3731
Add test for project deployment
ericpgreen2 Dec 13, 2024
45c34e6
Rename to `.spec`
ericpgreen2 Dec 13, 2024
41b7e41
Add organization fixture
ericpgreen2 Dec 13, 2024
d5baafc
Add Explore test
ericpgreen2 Dec 13, 2024
9f7b47b
Run tests in CI
ericpgreen2 Dec 18, 2024
1dc3cbe
Fix lint
ericpgreen2 Dec 18, 2024
a5705f0
(Test) Add `rill` binary to PATH
ericpgreen2 Dec 18, 2024
10e57a7
Fix lint (x2)
ericpgreen2 Dec 18, 2024
14e378f
Use any boolean
ericpgreen2 Dec 18, 2024
e1474dd
Setup admin & viewer accounts
ericpgreen2 Jan 2, 2025
10b876f
e2e github actions (#6303)
himadrisingh Jan 2, 2025
a0ad1db
Fix homepage test
ericpgreen2 Jan 2, 2025
d205b49
Add a `spawnAndMatch` util to capture URLs in CLI output
ericpgreen2 Jan 2, 2025
47f0e89
Manually open up the GitHub auth URL
ericpgreen2 Jan 2, 2025
857f695
Add HTML reporter
ericpgreen2 Jan 2, 2025
c863772
Merge branch 'main' into cloud-e2e-setup-services
ericpgreen2 Jan 3, 2025
18e0284
Update playwright
ericpgreen2 Jan 3, 2025
1ad4807
Move project deployment to a "bootstrap" project
ericpgreen2 Jan 3, 2025
028ca43
Add playwright artifacts to top-level gitignore
ericpgreen2 Jan 3, 2025
836e927
Remove unneeded org and project fixtures
ericpgreen2 Jan 3, 2025
88d485c
Add comment
ericpgreen2 Jan 3, 2025
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
64 changes: 50 additions & 14 deletions .github/workflows/web-test-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: End-to-end tests of web+runtime
on:
pull_request:
paths:
- ".github/workflows/web-test.yml"
- ".github/workflows/web-test-e2e.yml"
- "admin/**"
- "cli/**"
- "runtime/**"
Expand All @@ -13,6 +13,9 @@ on:
jobs:
build:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.matrix.outputs.matrix }}

steps:
- name: Checkout code
uses: actions/checkout@v4
Expand All @@ -23,25 +26,45 @@ jobs:
with:
filters: |
admin:
- ".github/workflows/web-test.yml"
- ".github/workflows/web-test-e2e.yml"
- "admin/**"
- "cli/**"
- "runtime/**"
- "web-admin/**"
auth:
- ".github/workflows/web-test.yml"
- ".github/workflows/web-test-e2e.yml"
- "web-auth/**"
local:
- ".github/workflows/web-test.yml"
- ".github/workflows/web-test-e2e.yml"
- "cli/**"
- "runtime/**"
- "web-local/**"
common:
- ".github/workflows/web-test.yml"
- ".github/workflows/web-test-e2e.yml"
- "cli/**"
- "runtime/**"
- "web-common/**"

- name: Evaluate e2e tests matrix
id: matrix
run: |
echo "matrix=$(jq -n '[
"web-admin" | select(env.FILTER_ADMIN == "true" or env.FILTER_COMMON == "true"),
"web-local" | select(env.FILTER_LOCAL == "true" or env.FILTER_COMMON == "true")
]' | jq -c)" >> "$GITHUB_OUTPUT"
env:
FILTER_ADMIN: ${{ steps.filter.outputs.admin }}
FILTER_COMMON: ${{ steps.filter.outputs.common }}
FILTER_LOCAL: ${{ steps.filter.outputs.local }}

e2e:
runs-on: ubuntu-latest
needs: build
strategy:
fail-fast: false
matrix:
name: ${{ fromJson(needs.build.outputs.matrix) }}
steps:
- name: Set up NodeJS
uses: actions/setup-node@v4
with:
Expand All @@ -51,6 +74,10 @@ jobs:
uses: actions/setup-go@v5
with:
go-version: 1.23

- name: Checkout code
uses: actions/checkout@v4

- name: go build cache
uses: actions/cache@v4
with:
Expand All @@ -70,21 +97,30 @@ jobs:
- name: Build and embed static UI
run: PLAYWRIGHT_TEST=true make cli

- name: Add CLI binary to PATH
run: echo "$GITHUB_WORKSPACE" >> $GITHUB_PATH

- name: Install browser for UI tests
run: npx playwright install

- name: Test web local
if: ${{ steps.filter.outputs.local == 'true' || steps.filter.outputs.common == 'true' }}
run: npm run test -w web-local
- name: Authenticate GCloud
uses: google-github-actions/auth@v2
if: matrix.name == 'web-admin'
with:
credentials_json: "${{ secrets.RILL_BINARY_SA }}"

- name: Set up GCloud SDK
if: matrix.name == 'web-admin'
uses: google-github-actions/setup-gcloud@v2

- name: Test ${{ matrix.name }}
run: |-
npm run build -w ${{ matrix.name }}
npm run test -w ${{ matrix.name }}

- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: web-local/playwright-report/
path: ${{ matrix.name }}/playwright-report/
retention-days: 30

- name: Build web admin
if: ${{ steps.filter.outputs.admin == 'true' || steps.filter.outputs.common == 'true' }}
run: |-
npm run build -w web-admin
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ tsc-tmp/
/dev-project*
/dev-cloud-state*
/e2e-cloud-state*
/playwright-report
**/playwright-report
**/test-results

# data files
*.duckdb
Expand Down
24 changes: 15 additions & 9 deletions package-lock.json

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

3 changes: 2 additions & 1 deletion web-admin/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/.svelte-kit
build
build
playwright
2 changes: 1 addition & 1 deletion web-admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
},
"devDependencies": {
"@fontsource/fira-mono": "^4.5.0",
"@playwright/test": "^1.33.0",
"@playwright/test": "^1.49.1",
"@rilldata/svelte-query": "^4.29.20-0.0.3",
"@sveltejs/adapter-static": "^3.0.5",
"@sveltejs/kit": "^2.7.1",
Expand Down
37 changes: 35 additions & 2 deletions web-admin/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,43 @@
import type { PlaywrightTestConfig } from "@playwright/test";
import { devices, type PlaywrightTestConfig } from "@playwright/test";
import dotenv from "dotenv";
import path from "path";
import { fileURLToPath } from "url";
import { ADMIN_AUTH_FILE } from "./tests/setup/constants";

// Load environment variables from our root `.env` file
const __dirname = path.dirname(fileURLToPath(import.meta.url));
dotenv.config({ path: path.resolve(__dirname, "../.env") });

const config: PlaywrightTestConfig = {
globalSetup: "./tests/setup/globalSetup.ts",
globalTeardown: "./tests/setup/globalTeardown.ts",
webServer: {
command: "npm run build && npm run preview",
port: 4173,
port: 3000,
reuseExistingServer: !process.env.CI,
timeout: 120_000,
},
retries: 0,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: "html",
use: {
baseURL: "http://localhost:3000",
...devices["Desktop Chrome"],
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: "on-first-retry",
video: "retain-on-failure",
},
projects: [
{ name: "bootstrap", testMatch: "bootstrap.spec.ts" },
{
name: "e2e",
dependencies: process.env.E2E_SKIP_BOOTSTRAP ? [] : ["bootstrap"],
testIgnore: "/setup",
use: {
storageState: ADMIN_AUTH_FILE,
},
},
],
};

export default config;
19 changes: 19 additions & 0 deletions web-admin/tests/explores.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { expect } from "@playwright/test";
import { test } from "./setup/base";

test.describe("Explores", () => {
test("should have data", async ({ page }) => {
await page.goto("/e2e/openrtb");

// Navigate to the explore
await page
.getByRole("link", { name: "Programmatic Ads Auction" })
.first()
.click();

// Check the Big Number
await expect(
page.getByRole("button", { name: "Requests 635M" }),
).toBeVisible();
});
});
16 changes: 16 additions & 0 deletions web-admin/tests/homepage.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { expect } from "@playwright/test";
import { test } from "./setup/base";

test.describe("Homepage", () => {
test("Authenticated user should see the homepage", async ({ page }) => {
await page.goto("/");
await expect(page.getByText("Hi [email protected]!")).toBeVisible();
});

test("Unauthenticated user should be redirected to login", async ({
anonPage,
}) => {
await anonPage.goto("/");
await expect(anonPage.getByText("Log in to Rill")).toBeVisible();
});
});
12 changes: 12 additions & 0 deletions web-admin/tests/organizations.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { expect } from "@playwright/test";
import { test } from "./setup/base";

test.describe("Organizations", () => {
test("admins should see the admin-only pages", async ({ adminPage }) => {
await adminPage.goto("/e2e");
await expect(adminPage.getByRole("link", { name: "Users" })).toBeVisible();
await expect(
adminPage.getByRole("link", { name: "Settings" }),
).toBeVisible();
});
});
12 changes: 12 additions & 0 deletions web-admin/tests/projects.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { expect } from "@playwright/test";
import { test } from "./setup/base";

test.describe("Projects", () => {
test("admins should see the admin-only pages", async ({ adminPage }) => {
await adminPage.goto("/e2e/openrtb");
await expect(adminPage.getByRole("link", { name: "Status" })).toBeVisible();
await expect(
adminPage.getByRole("link", { name: "Settings" }),
).toBeVisible();
});
});
47 changes: 47 additions & 0 deletions web-admin/tests/setup/base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { test as base, type Page } from "@playwright/test";
import { ADMIN_AUTH_FILE, VIEWER_AUTH_FILE } from "./constants";
import { cliLogin, cliLogout } from "./fixtures/cli";

type MyFixtures = {
adminPage: Page;
viewerPage: Page;
anonPage: Page;
cli: void;
};

export const test = base.extend<MyFixtures>({
// Note: the `e2e` project uses the admin auth file by default, so it's likely that
// this fixture won't be used often.
adminPage: async ({ browser }, use) => {
const context = await browser.newContext({
storageState: ADMIN_AUTH_FILE,
});
const adminPage = await context.newPage();
await use(adminPage);
await context.close();
},

viewerPage: async ({ browser }, use) => {
const context = await browser.newContext({
storageState: VIEWER_AUTH_FILE,
});
const viewerPage = await context.newPage();
await use(viewerPage);
await context.close();
},

anonPage: async ({ browser }, use) => {
const context = await browser.newContext({
storageState: { cookies: [], origins: [] },
});
const anonPage = await context.newPage();
await use(anonPage);
await context.close();
},

cli: async ({ page }, use) => {
await cliLogin(page);
await use();
await cliLogout();
},
});
Loading
Loading