Skip to content

Commit 3e52910

Browse files
authored
Tests: Add coveo e2e tests (#437)
1 parent 826f3f3 commit 3e52910

File tree

11 files changed

+151
-5
lines changed

11 files changed

+151
-5
lines changed

.github/workflows/playwright.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ on:
77
- 'main'
88
pull_request:
99

10+
env:
11+
FRONT_DOOR_USERNAME: ${{ secrets.FRONT_DOOR_USERNAME }}
12+
FRONT_DOOR_PASSWORD: ${{ secrets.FRONT_DOOR_PASSWORD }}
1013
jobs:
1114
playwright:
1215
name: Run Playwright

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*.key
55
*~
66
\#*
7+
.env
78

89
# OS Specific #
910
###############
@@ -34,6 +35,7 @@ exampleSite/hugo
3435
/coverage
3536
*/test-results
3637
*/playwright-report
38+
*.bkp
3739

3840
# Biome
3941
biome.rb

layouts/partials/coveo-atomic.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<atomic-search-interface id="search-v2">
1+
<atomic-search-interface id="search-v2" data-testid="search-results-page">
22
<atomic-search-layout>
33
<!-- Search/Metadata Section -->
44
<atomic-layout-section section="search">

tests/.env.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
FRONT_DOOR_USERNAME=
2+
FRONT_DOOR_PASSWORD=

tests/package-lock.json

Lines changed: 15 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22
"name": "nginx-docs-theme-test",
33
"version": "1.0.0",
44
"private": "true",
5+
"scripts": {
6+
"test": "playwright test --workers 6"
7+
},
58
"devDependencies": {
6-
"@playwright/test": "1.48.0"
9+
"@playwright/test": "1.48.0",
10+
"dotenv": "^17.2.3"
711
}
812
}

tests/playwright.config.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
import { defineConfig, devices } from '@playwright/test';
2+
import dotenv from 'dotenv';
23

34
const BASE_URL = 'http://127.0.0.1';
45
const PORT = 1313;
6+
7+
dotenv.config({ quiet: true });
8+
59
export default defineConfig({
610
testDir: './src',
711
fullyParallel: true,
812
workers: 1,
913
outputDir: './test-results',
1014
snapshotPathTemplate: '{testDir}/__screenshots__/{testFilePath}/{arg}{ext}',
11-
reporter: [['html', { outputFolder: './playwright-report' }]],
15+
reporter: [['html', { open: 'never', outputFolder: './playwright-report' }]],
1216
use: {
1317
baseURL: `${BASE_URL}:${PORT}`,
1418
screenshots: 'only-on-failure',
@@ -29,9 +33,10 @@ export default defineConfig({
2933
},
3034
],
3135
webServer: {
32-
command: `cd ../exampleSite && hugo mod get && hugo --gc --config hugo.toml,hugo.test.toml && hugo serve --port ${PORT} --config hugo.toml,hugo.test.toml`,
36+
command: `cd ../exampleSite && sed -i.bkp 's/disable_coveo = .*/disable_coveo = false/' hugo.toml && hugo mod get && hugo --gc --config hugo.toml,hugo.test.toml && hugo serve --port ${PORT} --config hugo.toml,hugo.test.toml`,
3337
url: `${BASE_URL}:${PORT}`,
3438
stdout: 'ignore',
39+
reuseExistingServer: !process.env.CI,
3540
},
3641
expect: {
3742
toHaveScreenshot: {

tests/src/coveo.spec.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { expect, test } from '@playwright/test';
2+
import { mockCoveoCredentials, mockCoveoData } from './mock';
3+
import {
4+
buildURLFragment,
5+
handleConsentPopup,
6+
runSmokeTestCoveo,
7+
waitFor,
8+
} from './utils';
9+
10+
async function submitSearchQuery(page, query) {
11+
const headerSearchBarContainer = page.getByTestId('header__search');
12+
const searchBar = headerSearchBarContainer.locator('[part="textarea"]');
13+
await searchBar.fill(query);
14+
await page.keyboard.press('Enter');
15+
await page.waitForURL(`**/search.html#q=${query}`);
16+
await page.waitForSelector('#search-v2');
17+
}
18+
19+
test.describe('Coveo test', () => {
20+
test.beforeEach(async ({ page, request }) => {
21+
await page.goto('/');
22+
await page.waitForLoadState('load');
23+
await waitFor(async () => await handleConsentPopup(page));
24+
await mockCoveoCredentials(page, request);
25+
});
26+
27+
test.afterEach(async ({ page }) => {
28+
// Run basic smoke tests on all valid queries
29+
if (!test.info().title.includes('invalid search query')) {
30+
await runSmokeTestCoveo(page);
31+
}
32+
});
33+
34+
test('valid search query', async ({ page }) => {
35+
await submitSearchQuery(page, mockCoveoData.validQuery);
36+
});
37+
38+
test('invalid search query', async ({ page }) => {
39+
await submitSearchQuery(page, mockCoveoData.invalidQuery);
40+
const resultsPage = page.getByTestId('search-results-page');
41+
const main = resultsPage.locator('atomic-layout-section[section="main"]');
42+
const noResultsMessage = main.locator('[part="no-results"]');
43+
await expect(noResultsMessage).toBeVisible();
44+
});
45+
46+
test('inbound link do not reset URL', async ({ page }) => {
47+
// Use ONLY generic filters. Do not add any product specific filters, particularly from the facet.
48+
// If these basic filters work, then its safe to assume, adding facet filters will not reset the URL.
49+
const endpoint = `/search.html#q=${mockCoveoData.validQuery}${buildURLFragment(mockCoveoData.filters)}`;
50+
await page.goto(endpoint);
51+
await page.waitForSelector('#search-v2');
52+
53+
// should retain the same link instead of resetting
54+
expect(page.url()).toContain(endpoint);
55+
56+
// reloading should retain the same link instead of resetting
57+
await page.reload();
58+
expect(page.url()).toContain(endpoint);
59+
});
60+
});

tests/src/mock/coveo.mock.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { expect } from '@playwright/test';
2+
3+
export const mockCoveoData = {
4+
validQuery: 'proxy',
5+
invalidQuery: 'abcdefghijkl',
6+
filters: ['numberOfResults=100', 'sortCriteria=date descending'],
7+
};
8+
9+
export async function mockCoveoCredentials(page, request) {
10+
// Get credentials
11+
const tokenBaseURL = 'https://docs-dev.nginx.com';
12+
const tokenEndpoint = '/api/v1/auth/search_token';
13+
const username = process.env.FRONT_DOOR_USERNAME;
14+
const password = process.env.FRONT_DOOR_PASSWORD;
15+
const response = await request.get(tokenBaseURL + tokenEndpoint, {
16+
headers: {
17+
Authorization:
18+
'Basic ' + Buffer.from(`${username}:${password}`).toString('base64'),
19+
},
20+
});
21+
22+
expect(response.ok()).toBeTruthy();
23+
expect(response.status()).toBe(200);
24+
25+
const credentials = await response.json();
26+
27+
// Mock the local request to be successful, then reload the page.
28+
await page.route(`**${tokenEndpoint}`, async (route) => {
29+
await route.fulfill({
30+
status: 200,
31+
contentType: 'application/json',
32+
body: JSON.stringify(credentials),
33+
});
34+
});
35+
await page.reload();
36+
}

tests/src/mock/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './coveo.mock';

0 commit comments

Comments
 (0)