-
Notifications
You must be signed in to change notification settings - Fork 1
test: add Playwright integration tests for dev-playground #76
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
base: main
Are you sure you want to change the base?
Changes from all commits
3bd97f8
a9f7795
0643065
42893a8
3fd2b21
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| # Playwright | ||
| test-results/ | ||
| playwright-report/ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| # Dev Playground | ||
|
|
||
| Test application showing AppKit capabilities including analytics dashboards, SSE streaming, telemetry, and data visualization. | ||
|
|
||
| ## Development | ||
|
|
||
| ```bash | ||
| # Start development server | ||
| pnpm dev | ||
|
|
||
| # Build for production | ||
| pnpm build | ||
|
|
||
| # Start production server | ||
| pnpm start:local | ||
| ``` | ||
|
|
||
| ## Integration Tests | ||
|
|
||
| Integration tests use Playwright to verify the application works correctly with mocked backend responses. | ||
|
|
||
| **Note:** These are frontend-only integration tests. API calls are intercepted at the browser level and return mock data, so the AppKit backend plugins are not tested. They focus on verifying UI behavior, navigation, data rendering, and client-side interactions. | ||
|
|
||
| ### Running Tests | ||
|
|
||
| ```bash | ||
| # Run all integration tests | ||
| pnpm test:integration | ||
|
|
||
| # Run tests with interactive UI mode (for debugging) | ||
| pnpm test:integration:ui | ||
|
|
||
| # Run tests in headed mode (see the browser) | ||
| pnpm test:integration:headed | ||
|
|
||
| # Run a specific test file | ||
| npx playwright test tests/smoke.spec.ts | ||
|
|
||
| # Run tests matching a pattern | ||
| npx playwright test -g "analytics" | ||
| ``` | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| import { defineConfig, devices } from "@playwright/test"; | ||
|
|
||
| export default defineConfig({ | ||
| testDir: "./tests", | ||
| fullyParallel: true, | ||
| forbidOnly: !!process.env.CI, | ||
| retries: 0, | ||
| workers: process.env.CI ? 1 : undefined, | ||
| reporter: "html", | ||
| use: { | ||
| baseURL: "http://localhost:8000", | ||
| trace: "on-first-retry", | ||
| }, | ||
| projects: [ | ||
| { | ||
| name: "chromium", | ||
| use: { ...devices["Desktop Chrome"] }, | ||
| }, | ||
| ], | ||
| webServer: { | ||
| command: "pnpm dev", | ||
| url: "http://localhost:8000", | ||
| reuseExistingServer: !process.env.CI, | ||
| timeout: 120 * 1000, | ||
| }, | ||
| }); |
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as before: This test already has a value with mocked backend, but it would be multiplied if we converted it to E2E test. That is, we'd mock the SDK on backend, run the |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| import { expect, test } from "@playwright/test"; | ||
| import { | ||
| STRICT_MODE_MULTIPLIER, | ||
| setupMockAPI, | ||
| trackApiCalls, | ||
| waitForChartsToLoad, | ||
| } from "./utils/test-utils"; | ||
|
|
||
| test.describe("Arrow Analytics", () => { | ||
| test.beforeEach(async ({ page }) => { | ||
| await setupMockAPI(page); | ||
| }); | ||
|
|
||
| test("page loads and displays heading", async ({ page }) => { | ||
| await page.goto("/arrow-analytics", { waitUntil: "networkidle" }); | ||
|
|
||
| await expect(page.getByText("Unified Charts API")).toBeVisible(); | ||
| }); | ||
|
|
||
| test("calls expected API endpoints", async ({ page }) => { | ||
| const appsListCalls = trackApiCalls(page, "apps_list"); | ||
| const spendDataCalls = trackApiCalls(page, "spend_data"); | ||
| const topContributorsCalls = trackApiCalls(page, "top_contributors"); | ||
| const heatmapCalls = trackApiCalls(page, "app_activity_heatmap"); | ||
|
|
||
| await page.goto("/arrow-analytics", { waitUntil: "networkidle" }); | ||
| await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight)); | ||
| await waitForChartsToLoad(page); | ||
|
|
||
| expect(appsListCalls.length).toBe(5 * STRICT_MODE_MULTIPLIER); | ||
| expect(spendDataCalls.length).toBe(5 * STRICT_MODE_MULTIPLIER); | ||
| expect(topContributorsCalls.length).toBe(2 * STRICT_MODE_MULTIPLIER); | ||
| expect(heatmapCalls.length).toBe(2 * STRICT_MODE_MULTIPLIER); | ||
| }); | ||
|
|
||
| test("charts render with mock data (no empty states)", async ({ page }) => { | ||
| await page.goto("/arrow-analytics", { waitUntil: "networkidle" }); | ||
| await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight)); | ||
| await waitForChartsToLoad(page); | ||
|
|
||
| const barCharts = page.locator('[data-testid="bar-chart-apps_list"]'); | ||
| expect(await barCharts.count()).toBe(3); | ||
| await expect(barCharts.first().locator("canvas")).toBeVisible(); | ||
|
|
||
| const lineCharts = page.locator('[data-testid="line-chart-spend_data"]'); | ||
| expect(await lineCharts.count()).toBe(3); | ||
| await expect(lineCharts.first().locator("canvas")).toBeVisible(); | ||
|
|
||
| const donutCharts = page.locator( | ||
| '[data-testid="donut-chart-top_contributors"]', | ||
| ); | ||
| expect(await donutCharts.count()).toBe(2); | ||
| await expect(donutCharts.first().locator("canvas")).toBeVisible(); | ||
|
|
||
| const heatmapCharts = page.locator( | ||
| '[data-testid="heatmap-chart-app_activity_heatmap"]', | ||
| ); | ||
| expect(await heatmapCharts.count()).toBe(2); | ||
| await expect(heatmapCharts.first().locator("canvas")).toBeVisible(); | ||
| }); | ||
|
|
||
| test("chart tooltip appears on hover with mock app data", async ({ | ||
| page, | ||
| }) => { | ||
| await page.goto("/arrow-analytics", { waitUntil: "networkidle" }); | ||
| await waitForChartsToLoad(page); | ||
|
|
||
| const barChart = page | ||
| .locator('[data-testid="bar-chart-apps_list"]') | ||
| .first() | ||
| .locator("canvas"); | ||
| await expect(barChart).toBeVisible(); | ||
|
|
||
| const box = await barChart.boundingBox(); | ||
| if (!box) throw new Error("Could not get chart bounding box"); | ||
|
|
||
| const positions = [0.2, 0.35, 0.5, 0.65, 0.8]; | ||
| for (const xRatio of positions) { | ||
| await page.mouse.move( | ||
| box.x + box.width * xRatio, | ||
| box.y + box.height * 0.4, | ||
| ); | ||
|
|
||
| const tooltip = page | ||
| .locator("div") | ||
| .filter({ hasText: /App One|App Two|App Three/ }); | ||
|
|
||
| try { | ||
| await expect(tooltip.first()).toBeVisible({ timeout: 1000 }); | ||
| return; | ||
| } catch {} | ||
| } | ||
|
|
||
| throw new Error( | ||
| "Could not trigger tooltip with any mock app data after trying multiple positions", | ||
| ); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd add a note to ensure the
DATABRICKS_APP_PORTis not overriden in the.envfile - as initially running those tests failed in my case because of that reason.EDIT: We specify
DATABRICKS_APP_PORT=8001in the.env.distso after all maybe we should adjust the default test configuration to point to the app running on 8001 port?JFYI - we specify it to avoid collision with the clean app example and run
pnpm devon the root ofappkitrepo to run all the apps.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@calvarjorge I think you missed that PR, PTAL - let's configure playwright to point to the app working on 8001 port as our
.env.distconfigures, alright?