Skip to content
Merged
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
9 changes: 9 additions & 0 deletions e2e/analytics.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,16 @@ import { test, expect, type Page } from '@playwright/test'
// the same convention e2e/visual.spec.ts uses for dashboard screenshots.
const DEMO_ADDRESS = 'GBQ2X7KFY3R4VZ6N5LJ7WQH3M2PD8C9SAUTV4EXAMPLE0WALLET00ADDR'

// The mock streams in lib/mock-data.ts are seeded with startTime offsets
// relative to Date.now() at module-evaluation time (e.g. "now - 90 days").
// Without a frozen clock, which streams fall inside a given range depends on
// exactly when the test happens to run. Freeze the clock with Playwright's
// `page.clock` so the seeded offsets — and therefore the expected counts
// below — are deterministic regardless of the current date.
const FIXED_NOW = new Date('2025-06-15T12:00:00.000Z')

async function withWallet(page: Page, address: string = DEMO_ADDRESS) {
await page.clock.install({ time: FIXED_NOW })
await page.addInitScript((walletAddress) => {
localStorage.setItem('walletId', 'xbull')
;(window as any).xBullSDK = {
Expand Down
22 changes: 20 additions & 2 deletions e2e/contract-integration.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
import { test, expect } from '@playwright/test'
import { test, expect, type Page } from '@playwright/test'

// The create form is wrapped in `RequireWallet`, so without a connected
// wallet it only renders a connect prompt instead of the real form fields.
// Mirrors the helper used in e2e/accessibility.spec.ts.
async function withWallet(page: Page) {
await page.addInitScript(() => {
localStorage.setItem('walletId', 'xbull')
;(window as any).xBullSDK = {
connect: async () => ({
publicKey: 'GA4M5Y74MXREPXU6LGRR7WOC6VLXJBLKJHZBJGDBKOFIP7GBM3MHF3G5',
}),
signXDR: async () => 'AAAAAgAAAAA...dummy-signature...',
}
})
}

test.describe('Contract Integration Tests', () => {
test.describe('Wallet Connection & Dashboard', () => {
Expand Down Expand Up @@ -34,7 +49,7 @@ test.describe('Contract Integration Tests', () => {

test('should display back button on stream detail page', async ({ page }) => {
await page.goto('/app/stream/test-id')
const backBtn = page.locator('text=Dashboard')
const backBtn = page.getByRole('main').getByRole('link', { name: 'Dashboard' })
await expect(backBtn).toBeVisible()
})

Expand All @@ -48,6 +63,7 @@ test.describe('Contract Integration Tests', () => {

test.describe('Create Stream Form Validation', () => {
test('should show create form with recipient field', async ({ page }) => {
await withWallet(page)
await page.goto('/app/create')
// Look for input fields typical of a stream creation form
const inputs = page.locator('input[type="text"], input[type="number"]')
Expand All @@ -69,6 +85,7 @@ test.describe('Contract Integration Tests', () => {
})

test('should handle token selection', async ({ page }) => {
await withWallet(page)
await page.goto('/app/create')
const tokenInputs = page.locator('input, button').filter({ hasText: /XLM|USDC|token/ })
// At least one token selector should be visible
Expand Down Expand Up @@ -209,6 +226,7 @@ test.describe('Contract Integration Tests', () => {
})

test('should have accessible form labels', async ({ page }) => {
await withWallet(page)
await page.goto('/app/create')
const labels = page.locator('label')
const count = await labels.count()
Expand Down
16 changes: 11 additions & 5 deletions e2e/visual.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ test.describe("Dashboard visual states", () => {
test("dashboard connected with streams", async ({ page }) => {
await preparePage(page, { theme: "light", connect: true });
await page.goto("/app");
await expect(page.locator("text=Dashboard")).toBeVisible();
await expect(
page.getByRole("heading", { name: "Dashboard", level: 1 }),
).toBeVisible();
await expect(page.locator("text=New stream")).toBeVisible();
await expect(page).toHaveScreenshot("dashboard-with-streams.png", {
fullPage: true,
Expand All @@ -95,7 +97,9 @@ test.describe("Dashboard visual states", () => {
test("dashboard tabs: receiving and sent", async ({ page }) => {
await preparePage(page, { theme: "light", connect: true });
await page.goto("/app");
await expect(page.locator("text=Dashboard")).toBeVisible();
await expect(
page.getByRole("heading", { name: "Dashboard", level: 1 }),
).toBeVisible();

await page.locator('button:has-text("Receiving")').first().click();
await expect(page.locator("text=Receiving")).toBeVisible();
Expand Down Expand Up @@ -131,8 +135,8 @@ test.describe("Create stream form", () => {
await page.click('button:has-text("Create stream")');
await expect(
page
.locator("text=Review transaction")
.or(page.locator("text=Create stream")),
.getByRole("heading", { name: "Transaction Preview" })
.or(page.getByRole("button", { name: "Create stream" })),
).toBeVisible();
await expect(page).toHaveScreenshot("create-stream-filled.png", {
fullPage: true,
Expand Down Expand Up @@ -252,7 +256,9 @@ test.describe("Wallet and modal dialogs", () => {
await preparePage(page, { theme: "light", connect: true });
await page.goto("/app/stream/1");
await page.locator('button:has-text("Cancel")').first().click();
await expect(page.locator("text=Cancel stream")).toBeVisible();
await expect(
page.getByRole("heading", { name: "Cancel stream" }),
).toBeVisible();
await expect(page).toHaveScreenshot("cancel-dialog.png", {
fullPage: true,
});
Expand Down
Loading