diff --git a/frontend/playwright.config.ts b/frontend/playwright.config.ts index b22d3feef..eafd5667e 100644 --- a/frontend/playwright.config.ts +++ b/frontend/playwright.config.ts @@ -7,11 +7,10 @@ import { defineConfig, devices } from '@playwright/test'; */ export default defineConfig({ testDir: './tests/playwright', - fullyParallel: false, - forbidOnly: !!process.env.CI, - retries: process.env.CI ? 2 : 0, + fullyParallel: true, + retries: 0, workers: 1, - reporter: process.env.CI ? 'html' : 'list', + reporter: 'list', use: { baseURL: 'http://localhost:3333', trace: 'on-first-retry', @@ -33,5 +32,6 @@ export default defineConfig({ command: 'yarn start', url: 'http://localhost:3333', timeout: 120 * 1000, + reuseExistingServer: true, }, }); \ No newline at end of file diff --git a/frontend/tests/playwright/auth-state.json b/frontend/tests/playwright/auth-state.json new file mode 100644 index 000000000..3aa12bc6a --- /dev/null +++ b/frontend/tests/playwright/auth-state.json @@ -0,0 +1,42 @@ +{ + "cookies": [], + "origins": [ + { + "origin": "http://localhost:3333", + "localStorage": [ + { + "name": "__$session-timezone$_local__", + "value": "true" + }, + { + "name": "i18nextLng", + "value": "en" + }, + { + "name": "theme", + "value": "light" + }, + { + "name": "__$global-destinationPath$__", + "value": "/" + }, + { + "name": "__$session-timezone$__", + "value": "{\"label\":\"UTC +02:00\",\"value\":\"UTC+02\"}" + }, + { + "name": "__$session-mouseTrail$__", + "value": "true" + }, + { + "name": "AuthStore", + "value": "{\"authDetails\":\"{\\\"tenants\\\":true,\\\"sso\\\":null,\\\"ssoProvider\\\":null,\\\"enforceSSO\\\":null,\\\"edition\\\":\\\"foss\\\"}\",\"__mps__\":{\"expireInTimestamp\":1748009041183}}" + }, + { + "name": "UserStore", + "value": "{\"siteId\":null,\"tenants\":[],\"jwt\":null,\"spotJwt\":null,\"scopeState\":null,\"onboarding\":false,\"account\":\"{}\"}" + } + ] + } + ] +} \ No newline at end of file diff --git a/frontend/tests/playwright/auth.setup.ts b/frontend/tests/playwright/auth.setup.ts index f3be63728..4c4cf8a44 100644 --- a/frontend/tests/playwright/auth.setup.ts +++ b/frontend/tests/playwright/auth.setup.ts @@ -1,26 +1,38 @@ -import { authStateFile, testUseAuthState } from './helpers'; -import { test } from '@playwright/test'; +import { authStateFile, testUseAuthState } from './helpers'; +import { expect, test as setup } from '@playwright/test'; testUseAuthState(); -test('authenticate', async ({ page }) => { - await page.goto('/'); +setup.beforeEach(async ({ page }) => { + await page.goto('http://localhost:3333'); +}); - try { - const url = page.url(); +setup('authenticate', async ({ page }) => { + await page.goto('/login'); - if (url.includes('login')) { - await page.locator('[data-test-id="login"]').click(); - await page.locator('.ant-input-affix-wrapper').first().click(); - await page.locator('[data-test-id="login"]').fill('andrei@openreplay.com'); - await page.locator('[data-test-id="password"]').click(); - await page.locator('[data-test-id="password"]').fill('Andrey123!'); - await page.locator('[data-test-id="log-button"]').click(); - } - await page.waitForSelector('h1:has-text("Sessions")', { timeout: 10000 }); - } catch (e) {} + try { + const url = page.url(); + console.log('Current URL:', url); - try { - await page.context().storageState({ path: authStateFile }); - } catch {} -}); \ No newline at end of file + if (url.includes('login')) { + console.log('Already on login page, skipping authentication'); + await page.locator('[data-test-id="login"]').click(); + await page.locator('.ant-input-affix-wrapper').first().click(); + await page + .locator('[data-test-id="login"]') + .fill('andrei@openreplay.com'); + await page.locator('[data-test-id="password"]').click(); + await page.locator('[data-test-id="password"]').fill('Andrey123!'); + await page.locator('[data-test-id="log-button"]').click(); + } + await expect(page.getByRole('heading', { name: 'Sessions' })).toBeVisible(); + } catch (e) { + console.error('Error during authentication:', e); + } + + try { + await page.context().storageState({ path: authStateFile }); + } catch (e) { + console.error('Error saving authentication state:', e); + } +}); diff --git a/frontend/tests/playwright/helpers.ts b/frontend/tests/playwright/helpers.ts index 9a05ef0c5..6e4a5a226 100644 --- a/frontend/tests/playwright/helpers.ts +++ b/frontend/tests/playwright/helpers.ts @@ -3,7 +3,7 @@ import { exists } from "i18next"; import { dirname } from "path"; import { test } from "@playwright/test"; -export const authStateFile = 'node_modules/playwright/auth-state.json'; +export const authStateFile = 'tests/playwright/auth-state.json'; mkdirSync(dirname(authStateFile), { recursive: true }); diff --git a/frontend/tests/playwright/session-list.spec.ts b/frontend/tests/playwright/session-list.spec.ts index d006a085a..efad033fc 100644 --- a/frontend/tests/playwright/session-list.spec.ts +++ b/frontend/tests/playwright/session-list.spec.ts @@ -10,4 +10,5 @@ test('test', async ({ page }) => { await page.getByRole('button', { name: 'Android caret-down' }).click(); await page.getByText('OpenReplay Documentation Site').click(); await page.locator('#session-item').first().click(); + await expect(page.locator('#session-item')).toBeVisible(); }); \ No newline at end of file diff --git a/frontend/tests/playwright/test-3.spec.ts b/frontend/tests/playwright/test-3.spec.ts new file mode 100644 index 000000000..d65f82707 --- /dev/null +++ b/frontend/tests/playwright/test-3.spec.ts @@ -0,0 +1,15 @@ +import { test, expect } from '@playwright/test'; + +test('test', async ({ page }) => { + await page.goto('http://localhost:3333/login'); + await page.locator('[data-test-id="login"]').fill('andrei@openreplay.com'); + await page.locator('[data-test-id="password"]').click(); + await page.locator('[data-test-id="password"]').fill('Andrey123!'); + await page.locator('[data-test-id="log-button"]').click(); + await page.getByRole('button', { name: 'Android caret-down' }).click(); + await page.getByRole('menuitem', { name: 'OpenReplay Documentation Site' }).click(); + await page.getByTitle('Past 24 Hours').click(); + await page.getByTitle('Past 30 Days').click(); + await page.getByRole('button', { name: 'Refresh' }).click(); + await page.locator('#session-item').first().click(); +}); \ No newline at end of file diff --git a/tests/playwright/auth-state.json b/tests/playwright/auth-state.json new file mode 100644 index 000000000..66aa3e5ee --- /dev/null +++ b/tests/playwright/auth-state.json @@ -0,0 +1,66 @@ +{ + "cookies": [], + "origins": [ + { + "origin": "http://localhost:3333", + "localStorage": [ + { + "name": "__$session-timezone$_local__", + "value": "true" + }, + { + "name": "i18nextLng", + "value": "en" + }, + { + "name": "theme", + "value": "light" + }, + { + "name": "__$user-gettingStarted$__", + "value": "{\"steps\":[{\"title\":\"🛠️ Install OpenReplay\",\"status\":\"completed\"},{\"title\":\"🕵️ Identify Users\",\"status\":\"completed\"},{\"title\":\"🧑‍💻 Invite Team Members\",\"status\":\"completed\"},{\"title\":\"🔌 Integrations\",\"status\":\"completed\"}],\"status\":\"completed\"}" + }, + { + "name": "__$global-destinationPath$__", + "value": "/" + }, + { + "name": "___$or_spotToken$___", + "value": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjU4LCJ0ZW5hbnRJZCI6MSwiZXhwIjoxNzQ4MDA2MTI2LCJpc3MiOiJPcGVuUmVwbGF5LW9zcyIsImlhdCI6MTc0ODAwNTUyNiwiYXVkIjoic3BvdDpPcGVuUmVwbGF5In0.lwg8ylwBnEdpNxD0-795pwDcPubJRm2z9-_P8LBnI-KtFx8nCBpY5sIvcOwPPh0HYfRKXhHcdA0iu_1oAHB8JQ" + }, + { + "name": "__$session-timezone$__", + "value": "{\"label\":\"UTC +02:00\",\"value\":\"UTC+02\"}" + }, + { + "name": "__$session-mouseTrail$__", + "value": "true" + }, + { + "name": "__openreplay_health_status", + "value": "1748005536080" + }, + { + "name": "__$user-siteId$__", + "value": "109" + }, + { + "name": "__or__langBannerClosed", + "value": "0" + }, + { + "name": "AuthStore", + "value": "{\"authDetails\":\"{\\\"tenants\\\":true,\\\"sso\\\":null,\\\"ssoProvider\\\":null,\\\"enforceSSO\\\":null,\\\"edition\\\":\\\"foss\\\"}\",\"__mps__\":{\"expireInTimestamp\":1748009134445}}" + }, + { + "name": "UserStore", + "value": "{\"siteId\":null,\"tenants\":[],\"jwt\":\"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjU4LCJ0ZW5hbnRJZCI6MSwiZXhwIjoxNzQ4MDkxOTI2LCJpc3MiOiJPcGVuUmVwbGF5LW9zcyIsImlhdCI6MTc0ODAwNTUyNiwiYXVkIjoiZnJvbnQ6T3BlblJlcGxheSJ9.p11bS55aedM9jfVHtBpFEalCpClac337KQNNvDF04WeSUrryLb99n76gyzfi8_gyeUu5UZ6h_eA0Gll5GxITcw\",\"spotJwt\":\"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjU4LCJ0ZW5hbnRJZCI6MSwiZXhwIjoxNzQ4MDA2MTI2LCJpc3MiOiJPcGVuUmVwbGF5LW9zcyIsImlhdCI6MTc0ODAwNTUyNiwiYXVkIjoic3BvdDpPcGVuUmVwbGF5In0.lwg8ylwBnEdpNxD0-795pwDcPubJRm2z9-_P8LBnI-KtFx8nCBpY5sIvcOwPPh0HYfRKXhHcdA0iu_1oAHB8JQ\",\"scopeState\":2,\"onboarding\":false,\"account\":\"{\\\"id\\\":58,\\\"email\\\":\\\"andrei@openreplay.com\\\",\\\"smtp\\\":false,\\\"expirationDate\\\":-1,\\\"permissions\\\":[],\\\"settings\\\":{\\\"modules\\\":[\\\"usability-tests\\\",\\\"feature-flags\\\"]},\\\"iceServers\\\":[],\\\"hasPassword\\\":true,\\\"apiKey\\\":\\\"48Vph82zUEWHmfPSUbgG\\\",\\\"edition\\\":\\\"foss\\\",\\\"optOut\\\":false,\\\"versionNumber\\\":\\\"1.17.0\\\",\\\"name\\\":\\\"Andrei\\\",\\\"createdAt\\\":1652690354756,\\\"admin\\\":true,\\\"superAdmin\\\":false}\"}" + }, + { + "name": "__openreplay_health_response", + "value": "{\"overallHealth\":true,\"healthMap\":{\"databases\":{\"name\":\"Databases\",\"healthOk\":true,\"subservices\":{\"postgres\":{\"health\":true,\"details\":{}}},\"serviceName\":\"databases\"},\"ingestionPipeline\":{\"name\":\"Ingestion Pipeline\",\"healthOk\":true,\"subservices\":{\"redis\":{\"health\":true,\"details\":{}}},\"serviceName\":\"ingestionPipeline\"},\"backendServices\":{\"name\":\"Backend Services\",\"healthOk\":true,\"subservices\":{\"alerts\":{\"health\":true,\"details\":{}},\"assets\":{\"health\":true,\"details\":{}},\"assist\":{\"health\":true,\"details\":{}},\"chalice\":{\"health\":true,\"details\":{}},\"db\":{\"health\":true,\"details\":{}},\"ender\":{\"health\":true,\"details\":{}},\"frontend\":{\"health\":true,\"details\":{}},\"heuristics\":{\"health\":true,\"details\":{}},\"http\":{\"health\":true,\"details\":{}},\"ingress-nginx\":{\"health\":true,\"details\":{}},\"integrations\":{\"health\":true,\"details\":{}},\"sink\":{\"health\":true,\"details\":{}},\"sourcemapreader\":{\"health\":true,\"details\":{}},\"storage\":{\"health\":true,\"details\":{}}},\"serviceName\":\"backendServices\"}},\"details\":{\"numberOfSessionsCaptured\":214690,\"numberOfEventCaptured\":1816886}}" + } + ] + } + ] +} \ No newline at end of file