Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
PLAYWRIGHT_USERNAME=
PLAYWRIGHT_PASSWORD=
7 changes: 3 additions & 4 deletions .github/workflows/e2etest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,11 @@ jobs:
node-version: lts/*
- name: Install dependencies
run: npm ci
- name: Setup credentials
run: mkdir -p playwright/.auth
- name: Import Credentials
run: echo "${{ secrets.TEST_ACCOUNT_CREDS }}" | base64 --decode > playwright/.auth/creds.json
- name: Run Playwright tests
run: npm run e2e -- --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
env:
PLAYWRIGHT_USERNAME: ${{ secrets.TEST_ACCOUNT_USERNAME }}
PLAYWRIGHT_PASSWORD: ${{ secrets.TEST_ACCOUNT_PASSWORD }}
- uses: actions/upload-artifact@v7
if: ${{ !cancelled() }}
with:
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.

*.ts.*
.env
# compiled output
/dist
/tmp
Expand Down Expand Up @@ -57,4 +58,4 @@ docs/
/test-results/
/playwright-report/
/playwright/.cache/
playwright/
playwright/
43 changes: 23 additions & 20 deletions e2e/auth.setup.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,31 @@
import { expect, test as setup } from '@playwright/test';
import path from 'path';
import fs from 'fs';
import { chromium, expect } from '@playwright/test';
import dotenv from 'dotenv';
import { overrideUserCookieHeaders } from 'e2e/helpers';

async function globalSetup() {
// const { baseURL } = config.projects[0].use;
const browser = await chromium.launch();
const page = await browser.newPage();
console.log('Running auth setup function');
dotenv.config({ quiet: true });

// import { username, password } from '../playwright/.auth/creds.json';
const authFile = path.join(__dirname, '../playwright/.auth/user.json');
const credsFile = path.join(__dirname, '../playwright/.auth/creds.json');
setup('authenticate', async ({ page }) => {
let userData = {};
try {
const data = fs.readFileSync(credsFile, 'utf8');
userData = JSON.parse(data);
} catch (_e) {
console.error('Error reading or parsing auth JSON file.');
return;
}
await page.goto('https://search.asf.alaska.edu');
const popupPromise = page.waitForEvent('popup');

if (!process.env['PLAYWRIGHT_USERNAME']) {
console.log('No credentials defined: Some tests may fail');
return;
}
console.log('Signing in');
await page.getByRole('button', { name: 'Sign In' }).click();
const popup = await popupPromise;
await popup.getByLabel('username').fill(userData['username']);
await popup.getByLabel('password').fill(userData['password']);
await popup.getByLabel('username').fill(process.env['PLAYWRIGHT_USERNAME']);
await popup.getByLabel('password').fill(process.env['PLAYWRIGHT_PASSWORD']);
await overrideUserCookieHeaders(page);
await popup.getByRole('button', { name: 'Log in' }).click();
await expect(page.getByRole('button', { name: 'Sign In' })).toHaveCount(0);
console.log('Sign in successfull');
await page.context().storageState({ path: 'playwright/.auth/user.json' });
await browser.close();
}

await page.context().storageState({ path: authFile });
});
export default globalSetup;
16 changes: 16 additions & 0 deletions e2e/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,19 @@ export async function waitForASFAPIResponse(page: Page) {
response.url().includes('output=jsonlite2'),
);
}

export async function overrideUserCookieHeaders(page: Page) {
await page.route('**appdata-**/info/cookie', async (route) => {
const response = await route.fetch();
const url = new URL(page.url()).origin;
await route.fulfill({
response,
headers: {
...response.headers(),
'Access-Control-Allow-Origin': url,
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': '*',
},
});
});
}
11 changes: 11 additions & 0 deletions e2e/pages/auth.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { test as base, Page } from '@playwright/test';
import { overrideUserCookieHeaders } from 'e2e/helpers';

export const test = base.extend<{ loggedInPage: Page }>({
loggedInPage: async ({ page }, use) => {
await overrideUserCookieHeaders(page);

await use(page);
},
});
export { expect } from '@playwright/test';
9 changes: 9 additions & 0 deletions e2e/profile/test.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { test, expect } from 'e2e/pages/auth.page';

test('Profile: Logged In', { tag: '@auth' }, async ({ loggedInPage }) => {
loggedInPage.goto('/');

await expect(
loggedInPage.getByRole('button', { name: 'automatedtesting_fullaccess' }),
).toBeVisible();
});
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
"@vitest/coverage-v8": "^4.0.17",
"angular-eslint": "21.3.1",
"csv-parse": "^6.2.1",
"dotenv": "^17.4.2",
"esbuild": "^0.28.0",
"eslint": "^9.35.0",
"eslint-config-prettier": "^10.1.8",
Expand Down
27 changes: 16 additions & 11 deletions playwright.config.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
import { defineConfig, devices } from '@playwright/test';

/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();

/**
* See https://playwright.dev/docs/test-configuration.
*/
Expand Down Expand Up @@ -35,31 +29,42 @@ export default defineConfig({
maxDiffPixelRatio: 0.2,
},
},

globalSetup: './e2e/auth.setup',
/* Configure projects for major browsers */
projects: [
{ name: 'setup', testMatch: /.*\.setup\.ts/ },

{
name: 'chromium',
use: {
...devices['Desktop Chrome'],
viewport: { width: 1920, height: 1080 },
timezoneId: 'America/New_York',
bypassCSP: true,
// storageState: 'playwright/.auth/user.json',
// TODO: this makes all tests authenticated, we probably want to define test suites that use authentication instead of general projects
},
grepInvert: /@auth/,
},

{
name: 'firefox',
use: {
...devices['Desktop Firefox'],
viewport: { width: 1920, height: 1080 },
timezoneId: 'America/New_York',
bypassCSP: true,
},
grepInvert: /@auth/,
},

{
name: 'chromium-auth',
use: {
...devices['Desktop Chrome'],
trace: 'off',
storageState: 'playwright/.auth/user.json',
viewport: { width: 1920, height: 1080 },
timezoneId: 'America/New_York',
bypassCSP: true,
},
grep: /@auth/,
},

// {
Expand Down
Loading