Skip to content

Commit 1310faf

Browse files
committed
Combine tests and implement lit tasks for similar features fetch
1 parent f4cd864 commit 1310faf

File tree

6 files changed

+150
-164
lines changed

6 files changed

+150
-164
lines changed

e2e/tests/404.spec.ts

Lines changed: 55 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -52,80 +52,65 @@ test('Bad URL redirection to 404 page', async ({page}) => {
5252
}
5353
});
5454

55-
test('should fetch similar features from API and show results', async ({
55+
async function goTo404Page(page, query: string): Promise<void> {
56+
await page.goto(`${BASE_URL}/features/${query}`);
57+
await expect(page).toHaveURL(
58+
`${BASE_URL}/errors-404/feature-not-found?q=${query}`,
59+
);
60+
61+
const response = await page.context().request.fetch(page.url());
62+
expect(response.status()).toBe(404);
63+
}
64+
65+
async function expectButtons(page, {hasSearch}: {hasSearch: boolean}) {
66+
await expect(page.locator('#error-action-home-btn')).toBeVisible();
67+
await expect(page.locator('#error-action-report')).toBeVisible();
68+
69+
if (hasSearch) {
70+
await expect(page.locator('#error-action-search-btn')).toBeVisible();
71+
} else {
72+
await expect(page.locator('#error-action-search-btn')).toHaveCount(0);
73+
}
74+
}
75+
76+
test('shows similar features and all buttons when results exist', async ({
5677
page,
5778
}) => {
58-
// Test URLs for different feature IDs
59-
const badUrls = [
60-
{badUrl: `${BASE_URL}/features/badID_1234`, query: 'badID_1234'},
61-
{badUrl: `${BASE_URL}/features/g`, query: 'g'}
62-
];
63-
const API_BASE_URL =
64-
'http://localhost:8080/v1/features?q={query}&page_size=5';
79+
const query = 'g';
80+
await goTo404Page(page, query);
6581

66-
for (const {badUrl, query} of badUrls) {
67-
await test.step(`Testing API response for: ${badUrl}`, async () => {
68-
await page.goto(badUrl);
69-
await expect(page).toHaveURL(
70-
'http://localhost:5555/errors-404/feature-not-found?q=' + query,
71-
);
82+
await expect(page.locator('.similar-features-container')).toBeVisible();
83+
await expectButtons(page, {hasSearch: true});
7284

73-
const featurePageResponse = await page
74-
.context()
75-
.request.fetch(page.url());
85+
const similarContainerButton = page.locator('#error-action-search-btn');
86+
const pageContainer = page.locator('.page-container');
7687

77-
// Assert that the response status code is 404
78-
expect(featurePageResponse.status()).toBe(404);
79-
80-
// Mock API response for similar features
81-
const apiUrl = API_BASE_URL.replace('{query}', query);
82-
const response = await page.context().request.get(apiUrl);
83-
expect(response.status()).toBe(200);
84-
85-
const data = await response.json();
86-
const hasResults = Array.isArray(data?.data) && data.data.length > 0;
87-
88-
if (hasResults) {
89-
// Show similar features container
90-
const similarContainer = page.locator('.similar-features-container');
91-
await expect(similarContainer).toBeVisible();
92-
await expect(page.locator('.feature-list li')).toHaveCount(
93-
data.data.length,
94-
);
95-
96-
// ✅ Click first similar feature
97-
const firstFeature = data.data[0];
98-
const firstFeatureLink = page.locator('.feature-list li a').first();
99-
await expect(firstFeatureLink).toHaveText(firstFeature.name);
100-
101-
// Click and wait for navigation
102-
await Promise.all([page.waitForNavigation(), firstFeatureLink.click()]);
103-
104-
await expect(page).toHaveURL(
105-
`${BASE_URL}/features/${firstFeature.feature_id}`,
106-
);
107-
108-
// Go back to error page to test second part
109-
await page.goBack();
110-
111-
// ✅ Click "Search for more similar features" button
112-
const searchButton = page.locator('#error-action-search-btn');
113-
await expect(searchButton).toBeVisible();
114-
115-
await Promise.all([page.waitForNavigation(), searchButton.click()]);
116-
117-
await expect(page).toHaveURL(`${BASE_URL}?q=${query}`);
118-
} else {
119-
// No similar features found
120-
await expect(
121-
page.locator('.similar-features-container'),
122-
).not.toBeVisible();
123-
await expect(page.locator('.error-message')).toContainText(
124-
'No similar features found.',
125-
);
126-
}
127-
});
128-
}
88+
// Snapshot
89+
await expect(pageContainer).toHaveScreenshot(
90+
'not-found-error-page-similar-results.png',
91+
);
92+
93+
// Clicking the search button should redirect to homepage with search
94+
await Promise.all([page.waitForNavigation(), similarContainerButton.click()]);
95+
await expect(page).toHaveURL(`${BASE_URL}?q=${query}`);
96+
});
97+
98+
test('shows only home and report buttons when no similar features found', async ({
99+
page,
100+
}) => {
101+
const query = 'nonexistent-feature';
102+
await goTo404Page(page, query);
103+
104+
await expect(page.locator('.similar-features-container')).toHaveCount(0);
105+
await expectButtons(page, {hasSearch: false});
106+
107+
await expect(page.locator('#error-detailed-message')).toContainText(
108+
`We could not find Feature ID: ${query}`,
109+
);
110+
111+
await expect(page.locator('.error-message')).toContainText(
112+
'No similar features found.',
113+
);
129114
});
130115

131116
test('should allow navigation from 404 page', async ({page}) => {
@@ -150,21 +135,8 @@ test('should allow navigation from 404 page', async ({page}) => {
150135
);
151136
});
152137

153-
test('matches the screenshot', async ({page}) => {
138+
test('matches the screenshot 404 not found page', async ({page}) => {
154139
await page.goto(`${BASE_URL}/bad_url`);
155140
const pageContainer = page.locator('.page-container');
156141
await expect(pageContainer).toHaveScreenshot('not-found-error-page.png');
157142
});
158-
159-
test('matches the screenshot with similar results', async ({page}) => {
160-
await page.goto(`${BASE_URL}/features/g`);
161-
162-
// ✅ Wait for similar results to appear
163-
const similarContainer = page.locator('.similar-features-container');
164-
await expect(similarContainer).toBeVisible({timeout: 5000});
165-
166-
const pageContainer = page.locator('.page-container');
167-
await expect(pageContainer).toHaveScreenshot(
168-
'not-found-error-page-similar-results.png',
169-
);
170-
});
197 Bytes
Loading
707 Bytes
Loading
506 Bytes
Loading

frontend/src/static/js/components/test/webstatus-notfound-error-page.test.ts

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ import {expect, fixture, html} from '@open-wc/testing';
1818
import '../webstatus-not-found-error-page.js';
1919
import {WebstatusNotFoundErrorPage} from '../webstatus-notfound-error-page.js';
2020
import {Task} from '@lit/task';
21+
import {APIClient} from '../../contexts/api-client-context.js';
22+
23+
type SimilarFeature = {name: string; url: string};
2124

2225
const GITHUB_REPO_ISSUE_LINK = 'https://github.com/example/repo/issues';
2326

@@ -66,16 +69,16 @@ describe('webstatus-not-found-error-page', () => {
6669
></webstatus-not-found-error-page>
6770
`);
6871

69-
// Override the _loadingSimilarResults with a fake pending Task
70-
component._loadingSimilarResults = new Task(component, {
71-
args: () => [], // no-op args
72+
// Override the _similarResults with a fake pending Task
73+
component._similarResults = new Task(component, {
74+
args: () => [undefined as unknown as APIClient, 'test-feature'], // no-op args
7275
task: async () => {
7376
return new Promise(() => {}); // never resolves = stays pending
7477
},
7578
});
7679

7780
// Trigger the task manually
78-
component._loadingSimilarResults.run();
81+
component._similarResults.run();
7982
await component.updateComplete;
8083

8184
const loadingMessage =
@@ -87,16 +90,27 @@ describe('webstatus-not-found-error-page', () => {
8790
});
8891

8992
it('renders similar features when API returns results', async () => {
93+
const mockData = [
94+
{name: 'Feature One', url: '/features/dignissimos44'},
95+
{name: 'Feature Two', url: '/features/fugiat37'},
96+
];
97+
9098
const component = await fixture<WebstatusNotFoundErrorPage>(html`
9199
<webstatus-not-found-error-page
92100
.location=${{search: '?q=g'}}
93101
></webstatus-not-found-error-page>
94102
`);
95103

96-
component.similarFeatures = [
97-
{name: 'Feature One', url: '/features/dignissimos44'},
98-
{name: 'Feature Two', url: '/features/fugiat37'},
99-
];
104+
// Patch _similarResults manually
105+
component._similarResults = new Task<[APIClient, string], SimilarFeature[]>(
106+
component,
107+
{
108+
args: () => [undefined as unknown as APIClient, 'g'],
109+
task: async () => mockData,
110+
},
111+
);
112+
113+
component._similarResults.run(); // force task to execute
100114
await component.updateComplete;
101115

102116
const featureList =
@@ -106,25 +120,6 @@ describe('webstatus-not-found-error-page', () => {
106120
expect(featureList?.[1]?.textContent?.trim()).to.equal('Feature Two');
107121
});
108122

109-
it('renders "No similar features found." when API returns no results', async () => {
110-
const component = await fixture<WebstatusNotFoundErrorPage>(html`
111-
<webstatus-not-found-error-page
112-
.location=${{search: '?q=test-feature'}}
113-
></webstatus-not-found-error-page>
114-
`);
115-
116-
component.similarFeatures = [];
117-
await component.updateComplete;
118-
119-
const noResultsMessage = component.shadowRoot?.querySelector(
120-
'.similar-features-container p',
121-
);
122-
expect(noResultsMessage).to.exist;
123-
expect(noResultsMessage?.textContent?.trim()).to.equal(
124-
'No similar features found.',
125-
);
126-
});
127-
128123
it('renders all three buttons when featureId and similar results exist', async () => {
129124
const component = await fixture<WebstatusNotFoundErrorPage>(html`
130125
<webstatus-not-found-error-page

0 commit comments

Comments
 (0)