From 0df1becf5a8222801f547a06ae9917721d88ef12 Mon Sep 17 00:00:00 2001 From: Tanvi Gupta Date: Tue, 19 May 2026 16:21:43 -0700 Subject: [PATCH] feat(js): add playwright+mocha test to capture test context --- js/playwright/capture-context/package.json | 13 +++ js/playwright/capture-context/tests/login.js | 101 +++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 js/playwright/capture-context/package.json create mode 100644 js/playwright/capture-context/tests/login.js diff --git a/js/playwright/capture-context/package.json b/js/playwright/capture-context/package.json new file mode 100644 index 0000000..e0da55f --- /dev/null +++ b/js/playwright/capture-context/package.json @@ -0,0 +1,13 @@ +{ + "name": "capture-context", + "private": true, + "scripts": { + "test": "mocha --timeout 5000 'tests/login.js'" + }, + "devDependencies": { + "@axe-core/watcher": "^4.0.0", + "chai": "^4", + "mocha": "^10.6.0", + "playwright": "^1.45.1" + } +} diff --git a/js/playwright/capture-context/tests/login.js b/js/playwright/capture-context/tests/login.js new file mode 100644 index 0000000..68c0cec --- /dev/null +++ b/js/playwright/capture-context/tests/login.js @@ -0,0 +1,101 @@ +const { assert } = require('chai') +const playwright = require('playwright') +const { + wrapPlaywrightPage, + PlaywrightController, + playwrightConfig +} = require('@axe-core/watcher/playwright') + +/* Get your configuration from environment variables. */ +const { + API_KEY, + PROJECT_ID, + SERVER_URL = 'https://axe.deque.com' +} = process.env + +describe('My Login Application', () => { + let browserContext + let page + let controller + + before(async () => { + browserContext = await playwright.chromium.launchPersistentContext( + '', + playwrightConfig({ + axe: { + apiKey: API_KEY, + projectId: PROJECT_ID, + serverURL: SERVER_URL + }, + //@see: https://playwright.dev/docs/chrome-extensions#headless-mode + headless: false, + args: ['--headless=new'] + }) + ) + }) + + after(async () => { + await browserContext.close() + }) + + // Note: function expression (not arrow) so `this.currentTest` is bound + // to Mocha's Context. Arrow functions would leave it undefined. + beforeEach(async function () { + // Create a fresh page instance for each test. + page = await browserContext.newPage() + + // Initialize the PlaywrightController by passing in the Playwright page. + controller = new PlaywrightController(page) + + // Use the new wrapped Playwright page instance. + page = wrapPlaywrightPage(page, controller) + + // Tell axe Watcher which test each scan in this test belongs to. + controller.setTestContext({ + test_file_path: this.currentTest?.file ?? null, + test_location: this.currentTest?.titlePath() ?? null + }) + }) + + afterEach(async () => { + /* Flush axe-watcher results after each test. */ + await controller.flush() + + // Clear so no stray scan after flush picks up the previous test's context. + controller.setTestContext(null) + + await page.close() + }) + + describe('Login', () => { + describe('with valid credentials', () => { + it('should login', async () => { + await page.goto('https://the-internet.herokuapp.com/login') + + await page.locator('#username').fill('tomsmith') + await page.locator('#password').fill('SuperSecretPassword!') + + await page.locator('button[type="submit"]').click() + + const element = await page.waitForSelector('#flash') + + assert.isNotNull(element) + }) + + it('should be able to logout', async () => { + await page.goto('https://the-internet.herokuapp.com/login') + + await page.locator('#username').fill('tomsmith') + await page.locator('#password').fill('SuperSecretPassword!') + await page.locator('button[type="submit"]').click() + + await page.waitForSelector('#flash') + + // Logout and verify we're back on the login page + await page.locator('a[href="/logout"]').click() + + await page.waitForSelector('#flash') + }) + }) + }) +})