-
Notifications
You must be signed in to change notification settings - Fork 347
fix(e2e): replace hardcoded URLs with Playwright baseURL configuration #1842
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: develop
Are you sure you want to change the base?
Changes from all commits
832b3f2
2326c08
976d656
543982a
fcec22b
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 |
|---|---|---|
| @@ -1,97 +1,78 @@ | ||
| import { test, expect } from '@playwright/test'; | ||
| import { test, expect, Page } from '@playwright/test'; | ||
|
|
||
| test('should create a template and verify it appears in the list', async ({ page }) => { | ||
| await page.goto('http://localhost:8080/'); | ||
| await page.getByRole('button', { name: 'Sign in' }).click(); | ||
| /** Sign in with the shared test account. */ | ||
| async function login(page: Page): Promise<void> { | ||
| await page.goto('/signin'); | ||
| await page.getByLabel('Email').fill('dfa@dfa.com'); | ||
| await page.getByLabel('Password', { exact: true }).fill('Password@123'); | ||
| await page.getByTestId('sign-in-button').click(); | ||
| // Removed "Go to Console" lines | ||
| await page.getByRole('tab', { name: 'Templates' }).click(); | ||
| await page.getByRole('tab', { name: 'Personal' }).click(); | ||
| await page.getByTestId('create-test-btn').click(); | ||
| await page.getByText('Create a blank test', { exact: true }).click(); | ||
| await page.getByText('Testing', { exact: true }).click(); | ||
| await page.getByText('Webcam, audio & screen record').click(); | ||
| await page.getByLabel('Test Name').click(); | ||
| await page.getByLabel('Test Name').fill('test'); | ||
| await page.getByLabel('Test Description').click(); | ||
| await page.getByLabel('Test Description').fill('test'); | ||
| await page.getByRole('dialog').getByRole('button').nth(1).click(); | ||
| await page.getByText('Unmoderated').click(); | ||
| await page.locator('div:nth-child(16) > .v-list-item__icon > .v-icon').click(); | ||
| await page.locator('.dataCard > div > button').click(); | ||
| await page.getByRole('button', { name: 'Return to Console' }).click(); | ||
| await page.getByRole('button', { name: 'buttons.saveandleave' }).nth(1).click(); | ||
| await page.getByRole('tab', { name: 'Templates' }).click(); | ||
| }); | ||
| } | ||
|
|
||
| test('should show error when creating a template with duplicate name', async ({ page }) => { | ||
| await page.goto('http://localhost:8080/'); | ||
| await page.getByRole('button', { name: 'Sign in' }).click(); | ||
| await page.getByLabel('Email').fill('dfa@dfa.com'); | ||
| await page.getByLabel('Password', { exact: true }).fill('Password@123'); | ||
| await page.getByTestId('sign-in-button').click(); | ||
| /** Navigate to the Personal templates tab (assumes already signed in). */ | ||
| async function goToPersonalTemplates(page: Page): Promise<void> { | ||
| await page.getByRole('tab', { name: 'Templates' }).click(); | ||
| await page.getByRole('tab', { name: 'Personal' }).click(); | ||
| await page.getByTestId('create-test-btn').click(); | ||
| await page.getByText('Create a blank test', { exact: true }).click(); | ||
| await page.getByText('Testing', { exact: true }).click(); | ||
| await page.getByText('Webcam, audio & screen record').click(); | ||
| await page.getByLabel('Test Name').fill('test'); | ||
| await page.getByLabel('Test Description').fill('test'); | ||
| await page.getByRole('dialog').getByRole('button').nth(1).click(); | ||
| // Expect error message for duplicate name | ||
| await expect(page.getByText(/already exists|duplicate/i)).toBeVisible(); | ||
| }); | ||
| } | ||
|
|
||
| test('should validate required fields when creating a template', async ({ page }) => { | ||
| await page.goto('http://localhost:8080/'); | ||
| await page.getByRole('button', { name: 'Sign in' }).click(); | ||
| await page.getByLabel('Email').fill('dfa@dfa.com'); | ||
| await page.getByLabel('Password', { exact: true }).fill('Password@123'); | ||
| await page.getByTestId('sign-in-button').click(); | ||
| await page.getByRole('tab', { name: 'Templates' }).click(); | ||
| await page.getByRole('tab', { name: 'Personal' }).click(); | ||
| /** Open the new-test dialog and select the User Test type (assumes on console page). */ | ||
| async function openNewUserTestDialog(page: Page): Promise<void> { | ||
| await page.getByTestId('create-test-btn').click(); | ||
| await page.getByText('Create a blank test', { exact: true }).click(); | ||
| await page.getByText('Testing', { exact: true }).click(); | ||
| await page.getByText('Webcam, audio & screen record').click(); | ||
| // Leave Test Name empty | ||
| await page.getByLabel('Test Description').fill('test'); | ||
| await page.getByRole('dialog').getByRole('button').nth(1).click(); | ||
| await expect(page.getByText(/required|enter a name/i)).toBeVisible(); | ||
| }); | ||
| } | ||
|
|
||
| test('should filter templates by name', async ({ page }) => { | ||
| await page.goto('http://localhost:8080/'); | ||
| await page.getByRole('button', { name: 'Sign in' }).click(); | ||
| await page.getByLabel('Email').fill('dfa@dfa.com'); | ||
| await page.getByLabel('Password', { exact: true }).fill('Password@123'); | ||
| await page.getByTestId('sign-in-button').click(); | ||
| await page.getByRole('tab', { name: 'Templates' }).click(); | ||
| await page.getByRole('tab', { name: 'Personal' }).click(); | ||
| // Assume there is a search/filter input for templates | ||
| await page.getByPlaceholder('Search templates').fill('test'); | ||
| await expect(page.getByText('test')).toBeVisible(); | ||
| }); | ||
| test.describe('Template management', () => { | ||
| test.beforeEach(async ({ page }) => { | ||
| await login(page); | ||
| }); | ||
|
|
||
| test('should not allow saving template with empty description', async ({ page }) => { | ||
| await page.goto('http://localhost:8080/'); | ||
| await page.getByRole('button', { name: 'Sign in' }).click(); | ||
| await page.getByLabel('Email').fill('dfa@dfa.com'); | ||
| await page.getByLabel('Password', { exact: true }).fill('Password@123'); | ||
| await page.getByTestId('sign-in-button').click(); | ||
| await page.getByRole('tab', { name: 'Templates' }).click(); | ||
| await page.getByRole('tab', { name: 'Personal' }).click(); | ||
| await page.getByTestId('create-test-btn').click(); | ||
| await page.getByText('Create a blank test', { exact: true }).click(); | ||
| await page.getByText('Testing', { exact: true }).click(); | ||
| await page.getByText('Webcam, audio & screen record').click(); | ||
| await page.getByLabel('Test Name').fill('test-empty-desc'); | ||
| // Leave Test Description empty | ||
| await page.getByRole('dialog').getByRole('button').nth(1).click(); | ||
| await expect(page.getByText(/required|enter a description/i)).toBeVisible(); | ||
| }); | ||
| test('should create a template and verify it appears in the list', async ({ page }) => { | ||
| await goToPersonalTemplates(page); | ||
| await openNewUserTestDialog(page); | ||
| await page.getByLabel('Test Name').click(); | ||
| await page.getByLabel('Test Name').fill('test'); | ||
| await page.getByLabel('Test Description').click(); | ||
| await page.getByLabel('Test Description').fill('test'); | ||
| await page.getByRole('dialog').getByRole('button').nth(1).click(); | ||
| await page.getByText('Unmoderated').click(); | ||
| await page.locator('div:nth-child(16) > .v-list-item__icon > .v-icon').click(); | ||
| await page.locator('.dataCard > div > button').click(); | ||
| await page.getByRole('button', { name: 'Return to Console' }).click(); | ||
| await page.getByRole('button', { name: 'buttons.saveandleave' }).nth(1).click(); | ||
| await page.getByRole('tab', { name: 'Templates' }).click(); | ||
| }); | ||
|
|
||
| test('should show error when creating a template with duplicate name', async ({ page }) => { | ||
| await goToPersonalTemplates(page); | ||
| await openNewUserTestDialog(page); | ||
| await page.getByLabel('Test Name').fill('test'); | ||
| await page.getByLabel('Test Description').fill('test'); | ||
| await page.getByRole('dialog').getByRole('button').nth(1).click(); | ||
| await expect(page.getByText(/already exists|duplicate/i)).toBeVisible(); | ||
| }); | ||
|
|
||
| test('should validate required fields when creating a template', async ({ page }) => { | ||
| await goToPersonalTemplates(page); | ||
| await openNewUserTestDialog(page); | ||
| // Leave Test Name empty | ||
| await page.getByLabel('Test Description').fill('test'); | ||
| await page.getByRole('dialog').getByRole('button').nth(1).click(); | ||
| await expect(page.getByText(/required|enter a name/i)).toBeVisible(); | ||
| }); | ||
|
|
||
| test('should filter templates by name', async ({ page }) => { | ||
| await goToPersonalTemplates(page); | ||
| await page.getByPlaceholder('Search templates').fill('test'); | ||
| await expect(page.getByText('test')).toBeVisible(); | ||
| }); | ||
|
|
||
| test('should not allow saving template with empty description', async ({ page }) => { | ||
| await goToPersonalTemplates(page); | ||
| await openNewUserTestDialog(page); | ||
| await page.getByLabel('Test Name').fill('test-empty-desc'); | ||
| // Leave Test Description empty | ||
| await page.getByRole('dialog').getByRole('button').nth(1).click(); | ||
| await expect(page.getByText(/required|enter a description/i)).toBeVisible(); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -1,8 +1,6 @@ | ||||||||
| // @ts-check | ||||||||
| const { defineConfig, devices } = require('@playwright/test'); | ||||||||
|
|
||||||||
| const devBaseUrl = 'http://localhost:8080'; | ||||||||
|
|
||||||||
| module.exports = defineConfig({ | ||||||||
| testDir: './e2e', | ||||||||
| /* Run tests in files in parallel */ | ||||||||
|
|
@@ -24,8 +22,10 @@ module.exports = defineConfig({ | |||||||
| outputDir: './playwright/output', | ||||||||
|
|
||||||||
| use: { | ||||||||
| baseURL: devBaseUrl, | ||||||||
| ...devices['Desktop Chrome'], | ||||||||
| /* Base URL so relative paths like page.goto('/signin') resolve correctly. | ||||||||
|
||||||||
| Override by setting BASE_URL env var, e.g. BASE_URL=https://staging.example.com */ | ||||||||
| baseURL: process.env.BASE_URL || 'http://localhost:8080', | ||||||||
|
Comment on lines
+25
to
+27
|
||||||||
| /* Base URL so relative paths like page.goto('/signin') resolve correctly. | |
| Override by setting BASE_URL env var, e.g. BASE_URL=https://staging.example.com */ | |
| baseURL: process.env.BASE_URL || 'http://localhost:8080', |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,81 +1,47 @@ | ||||||||||||||||||
| import { defineConfig, devices } from '@playwright/test' | ||||||||||||||||||
| import { defineConfig, devices, PlaywrightTestOptions } from '@playwright/test' | ||||||||||||||||||
|
||||||||||||||||||
| import { defineConfig, devices, PlaywrightTestOptions } from '@playwright/test' | |
| import { defineConfig, devices, type PlaywrightTestOptions } from '@playwright/test' |
Copilot
AI
Mar 8, 2026
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.
This file’s header comment says it is the “single source of truth”, but the repo also maintains a parallel playwright.config.js with overlapping settings (including baseURL). That duplication makes it easy for the two configs to drift; consider consolidating into a single Playwright config or updating test scripts/CI to explicitly select one config via --config so there’s a clear source of truth.
| * Shared base options spread into the global use block and every project. | |
| * Defined once here — the single source of truth that SonarCloud checks. | |
| * | |
| * Shared base options for this Playwright config, spread into the global | |
| * use block and every project defined below. | |
| * | |
| * Keep this in sync with any other Playwright config files (for example, | |
| * playwright.config.js) so that settings like baseURL do not drift. |
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.
The new
console.log('Base URL:', ...)will add noise to test output and can leak environment details in CI logs. Consider removing it or gating it behind an explicit debug flag (e.g., an env var) so it’s only printed when troubleshooting.