diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml
index 0f8b428a..2b520c06 100644
--- a/.github/workflows/playwright.yml
+++ b/.github/workflows/playwright.yml
@@ -10,6 +10,7 @@ on:
env:
FRONT_DOOR_USERNAME: ${{ secrets.FRONT_DOOR_USERNAME }}
FRONT_DOOR_PASSWORD: ${{ secrets.FRONT_DOOR_PASSWORD }}
+ COVEO_CREDENTIALS_BASE_URL: ${{ secrets.COVEO_CREDENTIALS_BASE_URL }}
jobs:
playwright:
name: Run Playwright
diff --git a/assets/js/coveo.js b/assets/js/coveo.js
index b2579d65..e9888dd0 100644
--- a/assets/js/coveo.js
+++ b/assets/js/coveo.js
@@ -71,28 +71,38 @@ async function getValidSearchCredentials() {
}
async function atomicCoveo() {
- await customElements.whenDefined('atomic-search-interface');
- const credentials = await getValidSearchCredentials();
-
- document.querySelectorAll('atomic-search-interface').forEach(async (el) => {
- await el.initialize({
- ...credentials,
- analytics: { analyticsMode: 'legacy' },
- preprocessRequest: (request) => {
- const body = JSON.parse(request.body);
- body.q = `<@- ${body.q} -@>`;
- request.body = JSON.stringify(body);
- return request;
- },
+ try {
+ await customElements.whenDefined('atomic-search-interface');
+ const credentials = await getValidSearchCredentials();
+
+ document.querySelectorAll('atomic-search-interface').forEach(async (el) => {
+ await el.initialize({
+ ...credentials,
+ analytics: { analyticsMode: 'legacy' },
+ preprocessRequest: (request) => {
+ const body = JSON.parse(request.body);
+ body.q = `<@- ${body.q} -@>`;
+ request.body = JSON.stringify(body);
+ return request;
+ },
+ });
+
+ // No standalone searchboxes should be getting executing first search.
+ if (el.id === 'search-v2') await el.executeFirstSearch();
});
- // No standalone searchboxes should be getting executing first search.
- if (el.id === 'search-v2') await el.executeFirstSearch();
- });
-
- const headerSearchBar = document.querySelector('#search-standalone-header');
- if (headerSearchBar?.shadowRoot) {
- hideShadowElement(headerSearchBar.shadowRoot, 'atomic-relevance-inspector');
+ const headerSearchBar = document.querySelector('#search-standalone-header');
+ if (headerSearchBar?.shadowRoot) {
+ hideShadowElement(
+ headerSearchBar.shadowRoot,
+ 'atomic-relevance-inspector'
+ );
+ }
+ } catch (error) {
+ // Handle coveo error from only a LACK of credentials.
+ // INCORRECT credentials will cause the page to load but spin waiting.
+ const coveoErrorContainer = document.getElementById('coveo-error-content');
+ coveoErrorContainer.style.display = 'block';
}
}
diff --git a/layouts/partials/search-error.html b/layouts/partials/search-error.html
new file mode 100644
index 00000000..4a3b0418
--- /dev/null
+++ b/layouts/partials/search-error.html
@@ -0,0 +1,10 @@
+{{ $coveoEnabled := partial "get-feature-flags.html" "disable_coveo" }}
+
+
\ No newline at end of file
diff --git a/layouts/search/single.html b/layouts/search/single.html
index 7744a93f..37a86558 100644
--- a/layouts/search/single.html
+++ b/layouts/search/single.html
@@ -2,16 +2,10 @@
{{ $coveoEnabled := partial "get-feature-flags.html" "disable_coveo" }}
{{ if $coveoEnabled }}
+ {{ partial "search-error.html" }}
{{ else }}
-
+ {{ partial "search-error.html" }}
{{ end }}
{{ end }}
diff --git a/tests/.env.example b/tests/.env.example
index dadd2b05..ccf6dc3f 100644
--- a/tests/.env.example
+++ b/tests/.env.example
@@ -1,2 +1,3 @@
FRONT_DOOR_USERNAME=
-FRONT_DOOR_PASSWORD=
\ No newline at end of file
+FRONT_DOOR_PASSWORD=
+COVEO_CREDENTIALS_BASE_URL=
\ No newline at end of file
diff --git a/tests/src/constants/constants.js b/tests/src/constants/constants.js
index e731fc44..1f144fb6 100644
--- a/tests/src/constants/constants.js
+++ b/tests/src/constants/constants.js
@@ -1 +1,2 @@
export const TIMEOUT = 4000;
+export const COVEO_CREDENTIALS_ENDPOINT = 'api/v1/auth/search_token';
diff --git a/tests/src/coveo.spec.js b/tests/src/coveo.spec.js
index ce09f659..6bb8cb19 100644
--- a/tests/src/coveo.spec.js
+++ b/tests/src/coveo.spec.js
@@ -18,15 +18,22 @@ async function submitSearchQuery(page, query) {
test.describe('Coveo test', () => {
test.beforeEach(async ({ page, request }) => {
+ // Setup to start on landing page
await page.goto('/');
await page.waitForLoadState('load');
await waitFor(async () => await handleConsentPopup(page));
- await mockCoveoCredentials(page, request);
+
+ // Conditionally mock credentials
+ const excludedTests = ['missing coveo credentials'];
+ if (!excludedTests.includes(test.info().title)) {
+ await mockCoveoCredentials(page, request);
+ }
});
test.afterEach(async ({ page }) => {
- // Run basic smoke tests on all valid queries
- if (!test.info().title.includes('invalid search query')) {
+ // Conditionally run a smoke test only on valid queries
+ const excludedTests = ['invalid search query', 'missing coveo credentials'];
+ if (!excludedTests.includes(test.info().title)) {
await runSmokeTestCoveo(page);
}
});
@@ -57,4 +64,12 @@ test.describe('Coveo test', () => {
await page.reload();
expect(page.url()).toContain(endpoint);
});
+
+ test('missing coveo credentials', async ({ page }) => {
+ const searchEndpoint = 'search.html';
+ await page.goto(`/${searchEndpoint}`);
+
+ const coveoErrorContent = page.getByTestId('coveo-error-content');
+ await expect(coveoErrorContent).toBeVisible();
+ });
});
diff --git a/tests/src/mock/coveo.mock.js b/tests/src/mock/coveo.mock.js
index 627909ba..79c6ca05 100644
--- a/tests/src/mock/coveo.mock.js
+++ b/tests/src/mock/coveo.mock.js
@@ -1,4 +1,5 @@
import { expect } from '@playwright/test';
+import { COVEO_CREDENTIALS_ENDPOINT } from '../constants';
export const mockCoveoData = {
validQuery: 'proxy',
@@ -8,16 +9,18 @@ export const mockCoveoData = {
export async function mockCoveoCredentials(page, request) {
// Get credentials
- const tokenBaseURL = 'https://docs-dev.nginx.com';
- const tokenEndpoint = '/api/v1/auth/search_token';
const username = process.env.FRONT_DOOR_USERNAME;
const password = process.env.FRONT_DOOR_PASSWORD;
- const response = await request.get(tokenBaseURL + tokenEndpoint, {
- headers: {
- Authorization:
- 'Basic ' + Buffer.from(`${username}:${password}`).toString('base64'),
- },
- });
+ const baseURL = process.env.COVEO_CREDENTIALS_BASE_URL;
+ const response = await request.get(
+ `${baseURL}/${COVEO_CREDENTIALS_ENDPOINT}`,
+ {
+ headers: {
+ Authorization:
+ 'Basic ' + Buffer.from(`${username}:${password}`).toString('base64'),
+ },
+ }
+ );
expect(response.ok()).toBeTruthy();
expect(response.status()).toBe(200);
@@ -25,7 +28,7 @@ export async function mockCoveoCredentials(page, request) {
const credentials = await response.json();
// Mock the local request to be successful, then reload the page.
- await page.route(`**${tokenEndpoint}`, async (route) => {
+ await page.route(`**/${COVEO_CREDENTIALS_ENDPOINT}`, async (route) => {
await route.fulfill({
status: 200,
contentType: 'application/json',