-
-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add Playwright testing framework and initial test setup for bro… #55
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
Draft
clFaster
wants to merge
2
commits into
main
Choose a base branch
from
feat/testing
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| name: Playwright Tests | ||
| on: | ||
| push: | ||
| branches: [ main ] | ||
| pull_request: | ||
| branches: [ main ] | ||
| jobs: | ||
| test: | ||
| timeout-minutes: 60 | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - uses: pnpm/action-setup@v4 | ||
| with: | ||
| version: 10 | ||
|
|
||
| - uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: lts/* | ||
| cache: 'pnpm' | ||
|
|
||
| - name: Install dependencies | ||
| run: pnpm install | ||
|
|
||
| - name: Install Playwright Browsers | ||
| run: pnpm exec playwright install --with-deps | ||
| working-directory: browser | ||
|
|
||
| - name: Run Playwright tests (excluding extension tests that require build) | ||
| run: pnpm test --grep-invert extension | ||
| working-directory: browser | ||
|
|
||
| - uses: actions/upload-artifact@v4 | ||
| if: always() | ||
| with: | ||
| name: playwright-report | ||
| path: browser/playwright-report/ | ||
| retention-days: 30 | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| import { defineConfig, devices } from '@playwright/test'; | ||
|
|
||
| /** | ||
| * Read environment variables from file. | ||
| * https://github.com/motdotla/dotenv | ||
| */ | ||
| // require('dotenv').config(); | ||
|
Check warning on line 7 in browser/playwright.config.ts
|
||
|
|
||
| /** | ||
| * See https://playwright.dev/docs/test-configuration. | ||
| */ | ||
| export default defineConfig({ | ||
| testDir: './tests', | ||
| /* Run tests in files in parallel */ | ||
| fullyParallel: true, | ||
| /* Fail the build on CI if you accidentally left test.only in the source code. */ | ||
| forbidOnly: !!process.env.CI, | ||
| /* Retry on CI only */ | ||
| retries: process.env.CI ? 2 : 0, | ||
| /* Opt out of parallel tests on CI. */ | ||
| workers: process.env.CI ? 1 : undefined, | ||
| /* Reporter to use. See https://playwright.dev/docs/test-reporters */ | ||
| reporter: 'html', | ||
| /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ | ||
| use: { | ||
| /* Base URL to use in actions like `await page.goto('/')`. */ | ||
| // baseURL: 'http://127.0.0.1:3000', | ||
|
|
||
| /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ | ||
| trace: 'on-first-retry', | ||
| }, | ||
|
|
||
| /* Configure projects */ | ||
| projects: [ | ||
| { | ||
| name: 'chromium', | ||
| use: { ...devices['Desktop Chrome'] }, | ||
| } | ||
| ], | ||
|
|
||
| /* Run your local dev server before starting the tests */ | ||
| // webServer: { | ||
| // command: 'npm run start', | ||
| // url: 'http://127.0.0.1:3000', | ||
| // reuseExistingServer: !process.env.CI, | ||
| // }, | ||
| }); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,15 @@ | ||
| import browser from "webextension-polyfill"; | ||
|
|
||
| export const getActiveTab = async () => { | ||
| export const getActiveTab = async (): Promise<string> => { | ||
| const tabs = await browser.tabs.query({ active: true, currentWindow: true }); | ||
| return tabs[0].url; | ||
| const url = tabs[0]?.url; | ||
|
|
||
| // Return URL if found, otherwise check for test fallback | ||
| if (url) { | ||
| return url; | ||
| } | ||
|
|
||
| // Fallback for testing when no active tab is available | ||
| const urlParams = new URLSearchParams(window.location.search); | ||
|
Check warning on line 13 in browser/src/utils/browser-tabs.ts
|
||
| return urlParams.get('url') || "URL not found"; | ||
| }; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| # TapToQR Browser Extension Tests | ||
|
|
||
| This directory contains Playwright tests for the TapToQR browser extension. | ||
|
|
||
| ## Test Structure | ||
|
|
||
| - **example.spec.ts** - Basic smoke tests to verify test environment | ||
| - **qr-data-formatters.spec.ts** - Unit tests for QR data formatting functions (WiFi, Contact, Email, etc.) | ||
| - **qr-generation.spec.ts** - Integration tests for QR code generation library | ||
| - **extension.spec.ts** - End-to-end UI tests for the extension (requires build) | ||
| - **fixtures.ts** - Custom Playwright fixtures for extension testing | ||
|
|
||
| ## Running Tests | ||
|
|
||
| ### All Tests (Unit + Integration, excluding extension tests) | ||
| ```bash | ||
| pnpm test --grep-invert extension | ||
| ``` | ||
|
|
||
| ### All Tests Including Extension Tests | ||
| ```bash | ||
| # Build the extension first | ||
| pnpm build | ||
|
|
||
| # Run all tests | ||
| pnpm test --workers=1 | ||
| ``` | ||
|
|
||
| ### Specific Test File | ||
| ```bash | ||
| pnpm exec playwright test qr-data-formatters.spec.ts | ||
| ``` | ||
|
|
||
| ### With UI Mode (Interactive) | ||
| ```bash | ||
| pnpm exec playwright test --ui | ||
| ``` | ||
|
|
||
| ### Extension Tests Only | ||
| ```bash | ||
| # Build the extension first | ||
| pnpm build | ||
|
|
||
| # Run extension tests | ||
| pnpm test extension.spec.ts --workers=1 | ||
| ``` | ||
|
|
||
| **Note:** Extension tests require: | ||
| 1. The extension to be built first (`pnpm build`) | ||
| 2. Single worker mode (`--workers=1`) to avoid conflicts with browser contexts | ||
| 3. A background service worker in the manifest to get the extension ID | ||
|
|
||
| ## Setup | ||
|
|
||
| Install Playwright browsers (one-time setup): | ||
| ```bash | ||
| pnpm exec playwright install | ||
| ``` | ||
|
|
||
| ## Test Categories | ||
|
|
||
| ### Unit Tests | ||
| Tests that don't require a browser or extension context: | ||
| - Data formatters (19 tests) | ||
| - Utility functions | ||
|
|
||
| ### Integration Tests | ||
| Tests that use the browser but not the extension: | ||
| - QR code generation (7 tests) | ||
| - Library integration | ||
|
|
||
| ### E2E/UI Tests | ||
| Tests that require the built extension (17 tests per project): | ||
| - Extension popup UI (buttons, QR code display, navigation) | ||
| - Extension options page (settings, sliders, checkboxes, save/revert) | ||
| - Custom QR page loading | ||
| - Extension manifest validation | ||
|
|
||
| ## CI/CD | ||
|
|
||
| Tests run automatically on: | ||
| - Pull requests to main/master | ||
| - Pushes to main/master | ||
|
|
||
| The CI workflow excludes extension tests that require the built extension. | ||
|
|
||
| See `.github/workflows/playwright.yml` for CI configuration. | ||
|
|
||
| ## Writing Tests | ||
|
|
||
| ### For Unit Tests | ||
| Use standard Playwright test syntax: | ||
| ```typescript | ||
| import { test, expect } from '@playwright/test'; | ||
|
|
||
| test('my test', () => { | ||
| // test code | ||
| }); | ||
| ``` | ||
|
|
||
| ### For Extension Tests | ||
| Use the custom fixtures that provide the extension context: | ||
| ```typescript | ||
| import { test, expect } from './fixtures'; | ||
|
|
||
| test('extension test', async ({ page, extensionId }) => { | ||
| await page.goto(`chrome-extension://${extensionId}/pages/popup.html`); | ||
| await page.waitForLoadState('networkidle'); | ||
|
|
||
| // Test interactions with the extension UI | ||
| await expect(page.locator('#some-element')).toBeVisible(); | ||
| }); | ||
| ``` | ||
|
|
||
| ## Extension Testing Approach | ||
|
|
||
| Based on [Playwright's Chrome Extensions documentation](https://playwright.dev/docs/chrome-extensions), our tests: | ||
|
|
||
| 1. Launch a persistent browser context with the extension loaded | ||
| 2. Use a background service worker to get the extension ID | ||
| 3. Navigate to extension pages using `chrome-extension://<id>/pages/...` URLs | ||
| 4. Test UI interactions, form submissions, and navigation | ||
| 5. Verify manifest properties and extension configuration | ||
|
|
||
| The extension must have a background service worker defined in the manifest for the tests to work properly. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| import { test, expect } from './fixtures'; | ||
|
|
||
| test.describe('Extension Popup UI', () => { | ||
| test('should load and display QR code with correct URL', async ({ page, extensionId, context }) => { | ||
| // Navigate to a test page first | ||
| const testUrl = 'https://moritzreis.dev'; | ||
|
|
||
| // Open the popup with the URL as a query parameter | ||
| // This simulates what would happen if the popup had access to the active tab | ||
| const popupPage = await context.newPage(); | ||
| await popupPage.goto( | ||
| `chrome-extension://${extensionId}/pages/popup.html?url=${encodeURIComponent(testUrl)}` | ||
| ); | ||
| await popupPage.waitForLoadState('networkidle'); | ||
|
|
||
| // Check that the popup container is visible | ||
| await expect(popupPage.locator('#popup-container')).toBeVisible(); | ||
|
|
||
| // Check that the header is present | ||
| await expect(popupPage.getByText('TapToQR')).toBeVisible(); | ||
|
|
||
| // Check that the QR code SVG is rendered | ||
| const qrCodeContainer = popupPage.locator('svg').first(); | ||
| await expect(qrCodeContainer).toBeVisible(); | ||
|
|
||
| // Verify the QR code was generated (check that there are path elements) | ||
| const paths = popupPage.locator('svg path'); | ||
| await expect(paths.first()).toBeVisible(); | ||
|
|
||
| // Optional: You could decode the QR code to verify it contains the correct URL | ||
| // For now, we verify that the QR code rendered and the correct URL was passed | ||
| const currentUrl = popupPage.url(); | ||
| expect(currentUrl).toContain(encodeURIComponent(testUrl)); | ||
|
|
||
| await popupPage.close(); | ||
| }); | ||
| }); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Check warning
Code scanning / CodeQL
Workflow does not contain permissions Medium
Copilot Autofix
AI 4 months ago
To fix this problem, add a
permissionssection with least-privilege settings. In this workflow, the only needed permission is likelycontents: read, which grants read access to repository contents, enabling actions like checkout and reading code, but preventing pushes or sensitive changes. This can be added either at the root (applies to all jobs) or at thetestjob level. Since there is only one job, adding at the root is clear and future-proof.Change required:
namefield), insert: