From 8d721dbda3a28cd9af445b0bb3266179962f07c5 Mon Sep 17 00:00:00 2001 From: munderseth Date: Wed, 3 Jun 2026 08:31:19 -0700 Subject: [PATCH] Simplify setup; example login spec --- .env.example | 3 +- .github/workflows/ci.yml | 6 +++- README.md | 50 ++++++++++----------------- package.json | 7 ++-- playwright.config.js | 40 +++++++-------------- tests/components/checks/login.spec.js | 12 +++++++ tests/components/login-component.js | 42 ++++++++++++++++++++++ tests/hello-world.spec.js | 3 +- 8 files changed, 96 insertions(+), 67 deletions(-) create mode 100644 tests/components/checks/login.spec.js create mode 100644 tests/components/login-component.js diff --git a/.env.example b/.env.example index ae1d7bd..f21c3c7 100644 --- a/.env.example +++ b/.env.example @@ -1 +1,2 @@ -BASE_URL=https://example.com \ No newline at end of file +BASE_URL=https://s2testorg.stridespace.com +PASSWORD=testuser \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bee3913..0c00808 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,16 +31,20 @@ jobs: run: npx playwright install --with-deps chromium - name: Run Playwright tests + env: + BASE_URL: ${{ vars.BASE_URL }} + PASSWORD: ${{ secrets.PASSWORD }} run: npm test - name: Setup Testspace client + if: always() uses: testspace-com/setup-testspace@v1 with: domain: samples.stridespace.com - name: Publish results to Testspace - run: testspace test-results/junit/results.xml if: always() + run: testspace test-results/junit/results.xml - name: Upload JUnit report if: always() diff --git a/README.md b/README.md index 110c767..0dcaac0 100644 --- a/README.md +++ b/README.md @@ -13,36 +13,40 @@ Minimal Playwright setup for JavaScript-based browser scenarios with: - Node.js 20+ - npm 10+ -## Initial setup +## Getting started -If starting from an empty folder, create a project manifest: +Clone the repo and install dependencies: ```bash -npm init -y +npm install ``` -Install project dependencies: +Install the browser: ```bash -npm install --save-dev @playwright/test dotenv +npx playwright install chromium ``` -Optional: create a local environment file from the example: +Copy the environment file and set `BASE_URL` to your target server: ```bash cp .env.example .env ``` -Install the browser used by this starter project: +Run the hello-world verification test: ```bash -npx playwright install chromium +npm run test:hello ``` -Run the hello-world verification test: +## Starting from scratch + +If you are creating a new project rather than cloning this one: ```bash -npm run test:hello +npm init -y +npm install --save-dev @playwright/test dotenv +npx playwright install chromium ``` ## Running tests @@ -59,24 +63,12 @@ Run a single file directly: npx playwright test tests/hello-world.spec.js ``` -Run headed mode: - -```bash -npm run test:headed -``` - -Run with Playwright UI mode: +Run with Playwright UI mode (interactive, useful for debugging): ```bash npm run test:ui ``` -Run in debug mode: - -```bash -npm run test:debug -``` - ## Reports Every test run writes: @@ -120,22 +112,18 @@ CI publishes: ## Changing the target URL -The sample test uses `BASE_URL` and defaults to `https://example.com`. - -You can store it in a `.env` file: +`BASE_URL` must be set before running tests. Set it in your `.env` file: ```bash -BASE_URL=https://example.com +BASE_URL=https://your-server.example.com ``` -Example: +Or pass it inline: ```bash -BASE_URL=https://playwright.dev npm run test:hello +BASE_URL=https://your-server.example.com npm test ``` -If you change `BASE_URL`, update the sample assertions to match that page. - ## Project structure ```text diff --git a/package.json b/package.json index ecb0659..cde5096 100644 --- a/package.json +++ b/package.json @@ -5,12 +5,9 @@ "description": "Starter setup for running JavaScript Playwright scenarios with HTML and JUnit reporting.", "scripts": { "test": "playwright test", - "test:headed": "playwright test --headed", - "test:ui": "playwright test --ui", - "test:debug": "playwright test --debug", "test:hello": "playwright test tests/hello-world.spec.js", - "report:html": "playwright show-report playwright-report", - "install:browsers": "playwright install chromium" + "test:ui": "playwright test --ui", + "report:html": "playwright show-report playwright-report" }, "devDependencies": { "@playwright/test": "^1.60.0", diff --git a/playwright.config.js b/playwright.config.js index b80e667..9158571 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -1,41 +1,27 @@ require('dotenv').config(); -const { defineConfig, devices } = require('@playwright/test'); -const isWSL = !!process.env.WSL_DISTRO_NAME; +if (!process.env.BASE_URL) { + throw new Error('BASE_URL is not set. Copy .env.example to .env and update BASE_URL.'); +} + +const { defineConfig } = require('@playwright/test'); module.exports = defineConfig({ testDir: './tests', - timeout: 30_000, - fullyParallel: true, - forbidOnly: !!process.env.CI, - retries: process.env.CI ? 2 : 0, - workers: process.env.CI ? 1 : undefined, + timeout: 60000, + retries: 0, + workers: 1, reporter: [ ['list'], ['html', { outputFolder: 'playwright-report', open: 'never' }], ['junit', { outputFile: 'test-results/junit/results.xml' }] ], use: { - baseURL: process.env.BASE_URL || 'https://example.com', - trace: 'on-first-retry', - screenshot: 'only-on-failure', - video: 'retain-on-failure' + baseURL: process.env.BASE_URL, + browserName: 'chromium', + headless: !!process.env.CI, + viewport: { width: 1280, height: 720 }, + ignoreHTTPSErrors: true, }, - projects: [ - { - name: 'chromium', - use: { - ...devices['Desktop Chrome'], - launchOptions: { - args: [ - '--window-position=80,80', - '--window-size=1440,900', - '--start-maximized', - ...(isWSL ? ['--ozone-platform=x11', '--disable-gpu'] : []) - ] - } - } - } - ], outputDir: 'test-results/artifacts' }); \ No newline at end of file diff --git a/tests/components/checks/login.spec.js b/tests/components/checks/login.spec.js new file mode 100644 index 0000000..a21d55f --- /dev/null +++ b/tests/components/checks/login.spec.js @@ -0,0 +1,12 @@ +const { test, expect } = require('@playwright/test'); +const { loginComponent } = require('../login-component'); + +test.describe("login", () => { + test("login", async ({ page }) => { + // TODO: Add structured test cases in the Validation panel to generate test stubs here. + process.env.BASE_URL = process.env.BASE_URL || 'https://s2testorg.stridespace.com'; + process.env.PASSWORD = process.env.PASSWORD || ''; + await loginComponent(page); + // Add assertions here + }); +}); diff --git a/tests/components/login-component.js b/tests/components/login-component.js new file mode 100644 index 0000000..b565bc2 --- /dev/null +++ b/tests/components/login-component.js @@ -0,0 +1,42 @@ +/** + * Component: login + * Description: Component to login into Testspace + * + * Steps: + * 1. Navigate to $env.BASE_URL + * 2. Click on username or email address + * 3. Enter 'testuser' in username or email address + * 4. Press Tab on username or email address + * 5. Enter password + * 6. Click on "SUBMIT" + * 7. Submit signin form + */ +async function loginComponent(page) { + const BASE_URL = process.env.BASE_URL; + if (!BASE_URL) throw new Error('Environment variable BASE_URL is required but not defined'); + const PASSWORD = process.env.PASSWORD; + if (!PASSWORD) throw new Error('Environment variable PASSWORD is required but not defined'); + + // Step 1: Navigate to $env.BASE_URL + await page.goto(BASE_URL); + + // Step 2: Click on username or email address + // Step 3: Enter 'testuser' in username or email address + await page.getByPlaceholder('username or email address').fill('testuser'); + + // Step 4: Press Tab on username or email address + await page.getByPlaceholder('username or email address').press('Tab'); + + // Step 5: Enter password + await page.getByPlaceholder('password').fill(PASSWORD); + + // Step 6: Click on "SUBMIT" + // Step 7: Submit signin form + await page.getByRole('button', { name: 'Submit', exact: true }).click(); + // Form uses data-remote="true" (Rails UJS); Turbolinks follows the redirect as a top-level + // navigation. Wait for the browser to leave the signin subdomain, then land on BASE_URL. + await page.waitForURL(url => !url.hostname.startsWith('signin.'), { timeout: 30000 }); + await page.goto(BASE_URL); +} + +module.exports = { loginComponent }; diff --git a/tests/hello-world.spec.js b/tests/hello-world.spec.js index e5c510c..b0bee20 100644 --- a/tests/hello-world.spec.js +++ b/tests/hello-world.spec.js @@ -2,6 +2,5 @@ const { test, expect } = require('@playwright/test'); test('hello world smoke test', async ({ page }) => { await page.goto('/'); - await expect(page).toHaveTitle(/Example Domain/); - await expect(page.getByRole('heading', { name: 'Example Domain' })).toBeVisible(); + await expect(page).toHaveTitle(/.+/); }); \ No newline at end of file