Skip to content

Commit 0c69992

Browse files
KyleJujcscottiii
andauthored
Adapter logic to populate feature list UI (#1278)
* Adapter code for UI. Fixing stub * Address comments * Update frontend/src/static/js/components/test/webstatus-stats-missing-one-impl-chart-panel.test.ts Co-authored-by: James C Scott III <jcscottiii@users.noreply.github.com> --------- Co-authored-by: James C Scott III <jcscottiii@users.noreply.github.com>
1 parent df79821 commit 0c69992

File tree

3 files changed

+176
-36
lines changed

3 files changed

+176
-36
lines changed

frontend/src/static/js/api/client.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,4 +522,46 @@ export class APIClient {
522522
yield page.data; // Yield the entire page
523523
} while (nextPageToken !== undefined);
524524
}
525+
526+
// Fetches missing feature list for a browser for a give date
527+
// via "/v1/stats/features/browsers/{browser}/missing_one_implementation_counts/{date}/features"
528+
public async getMissingOneImplementationFeatures(
529+
targetBrowser: BrowsersParameter,
530+
otherBrowsers: BrowsersParameter[],
531+
date: Date,
532+
): Promise<MissingOneImplFeaturesList> {
533+
const targetDate: string = date.toISOString().substring(0, 10);
534+
let nextPageToken: string | undefined;
535+
const allFeatures: MissingOneImplFeaturesList = [];
536+
537+
do {
538+
const response = await this.client.GET(
539+
'/v1/stats/features/browsers/{browser}/missing_one_implementation_counts/{date}/features',
540+
{
541+
...temporaryFetchOptions,
542+
params: {
543+
query: {
544+
page_token: nextPageToken,
545+
browser: otherBrowsers,
546+
},
547+
path: {browser: targetBrowser, date: targetDate},
548+
},
549+
},
550+
);
551+
const error = response.error;
552+
if (error !== undefined) {
553+
throw createAPIError(error);
554+
}
555+
const page: MissingOneImplFeaturesPage =
556+
response.data as MissingOneImplFeaturesPage;
557+
558+
if (page?.data) {
559+
allFeatures.push(...page.data);
560+
}
561+
562+
nextPageToken = page?.metadata?.next_page_token;
563+
} while (nextPageToken !== undefined);
564+
565+
return allFeatures;
566+
}
525567
}

frontend/src/static/js/components/test/webstatus-stats-missing-one-impl-chart-panel.test.ts

Lines changed: 113 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,14 +136,32 @@ describe('WebstatusStatsMissingOneImplChartPanel', () => {
136136
});
137137

138138
it('renders missing one implementation features footer', async () => {
139+
apiClientStub.getMissingOneImplementationFeatures.resolves([
140+
{
141+
feature_id: 'css',
142+
},
143+
{
144+
feature_id: 'html',
145+
},
146+
{
147+
feature_id: 'js',
148+
},
149+
{
150+
feature_id: 'bluetooth',
151+
},
152+
]);
139153
const chart = el.shadowRoot!.querySelector(
140154
'#missing-one-implementation-chart',
141155
)!;
142156

143157
const chartClickEvent: ChartSelectPointEvent = new CustomEvent(
144158
'point-selected',
145159
{
146-
detail: {label: 'Test Label', timestamp: new Date(), value: 123},
160+
detail: {
161+
label: 'Chromium',
162+
timestamp: new Date('2024-01-01'),
163+
value: 123,
164+
},
147165
bubbles: true,
148166
},
149167
);
@@ -153,6 +171,9 @@ describe('WebstatusStatsMissingOneImplChartPanel', () => {
153171

154172
// Assert that the task and renderer are set (no need to wait for the event)
155173
expect(el._pointSelectedTask).to.exist;
174+
await el._pointSelectedTask?.taskComplete;
175+
await el.updateComplete;
176+
156177
expect(el._renderCustomPointSelectedSuccess).to.exist;
157178
await el.updateComplete;
158179

@@ -162,7 +183,7 @@ describe('WebstatusStatsMissingOneImplChartPanel', () => {
162183
expect(header).to.exist;
163184
// Note: \n before chrome due to a complaint from lint in the html.
164185
expect(header!.textContent?.trim()).to.contain(
165-
'The missing feature IDs on 2024-08-20 for\n chrome',
186+
'The missing feature IDs on 2024-01-01 for\n chrome',
166187
);
167188

168189
const table = el.shadowRoot!.querySelector('.missing-features-table');
@@ -179,4 +200,94 @@ describe('WebstatusStatsMissingOneImplChartPanel', () => {
179200
'first row ID',
180201
);
181202
});
203+
204+
it('assert correct getMissingOneImplementationFeatures calls', async () => {
205+
apiClientStub.getMissingOneImplementationFeatures.resolves([
206+
{
207+
feature_id: 'css',
208+
},
209+
{
210+
feature_id: 'html',
211+
},
212+
{
213+
feature_id: 'js',
214+
},
215+
{
216+
feature_id: 'bluetooth',
217+
},
218+
]);
219+
const chart = el.shadowRoot!.querySelector(
220+
'#missing-one-implementation-chart',
221+
)!;
222+
223+
const chartClickEvent: ChartSelectPointEvent = new CustomEvent(
224+
'point-selected',
225+
{
226+
detail: {
227+
label: 'Safari',
228+
timestamp: new Date('2024-01-01'),
229+
value: 123,
230+
},
231+
bubbles: true,
232+
},
233+
);
234+
// Simulate point-selected event on the chart component
235+
chart.dispatchEvent(chartClickEvent);
236+
await el.updateComplete;
237+
238+
expect(el._pointSelectedTask).to.exist;
239+
expect(
240+
apiClientStub.getMissingOneImplementationFeatures,
241+
).to.have.been.calledWith(
242+
'safari',
243+
['chrome', 'firefox'],
244+
new Date('2024-01-01'),
245+
);
246+
247+
const chartClickEventOne: ChartSelectPointEvent = new CustomEvent(
248+
'point-selected',
249+
{
250+
detail: {
251+
label: 'Firefox',
252+
timestamp: new Date('2024-01-01'),
253+
value: 123,
254+
},
255+
bubbles: true,
256+
},
257+
);
258+
chart.dispatchEvent(chartClickEventOne);
259+
await el.updateComplete;
260+
261+
expect(el._pointSelectedTask).to.exist;
262+
expect(
263+
apiClientStub.getMissingOneImplementationFeatures,
264+
).to.have.been.calledWith(
265+
'firefox',
266+
['chrome', 'safari'],
267+
new Date('2024-01-01'),
268+
);
269+
270+
const chartClickEventTwo: ChartSelectPointEvent = new CustomEvent(
271+
'point-selected',
272+
{
273+
detail: {
274+
label: 'Chromium',
275+
timestamp: new Date('2024-01-01'),
276+
value: 123,
277+
},
278+
bubbles: true,
279+
},
280+
);
281+
chart.dispatchEvent(chartClickEventTwo);
282+
await el.updateComplete;
283+
284+
expect(el._pointSelectedTask).to.exist;
285+
expect(
286+
apiClientStub.getMissingOneImplementationFeatures,
287+
).to.have.been.calledWith(
288+
'chrome',
289+
['firefox', 'safari'],
290+
new Date('2024-01-01'),
291+
);
292+
});
182293
});

frontend/src/static/js/components/webstatus-stats-missing-one-impl-chart-panel.ts

Lines changed: 21 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
BrowsersParameter,
2626
BROWSER_ID_TO_COLOR,
2727
BROWSER_ID_TO_LABEL,
28+
BROWSER_LABEL_TO_ID,
2829
MissingOneImplFeaturesList,
2930
} from '../api/client.js';
3031
import {ChartSelectPointEvent} from './webstatus-gchart.js';
@@ -119,45 +120,31 @@ export class WebstatusStatsMissingOneImplChartPanel extends WebstatusLineChartPa
119120
* @param {ChartSelectPointEvent} _ The point-selected event.
120121
* @returns {{ task: Task | undefined; renderSuccess?: () => TemplateResult; }}
121122
*/
122-
createPointSelectedTask(_: ChartSelectPointEvent): {
123+
createPointSelectedTask(event: ChartSelectPointEvent): {
123124
task: Task | undefined;
124125
renderSuccess?: () => TemplateResult;
125126
} {
127+
const targetDate = event.detail.timestamp;
128+
const label = event.detail.label;
129+
const targetBrowser =
130+
label === 'Chromium' ? 'chrome' : BROWSER_LABEL_TO_ID[label];
131+
const otherBrowsers = this.supportedBrowsers.filter(
132+
value => targetBrowser !== value,
133+
);
126134
const task = new Task(this, {
127-
task: async () => {
128-
// TODO(https://github.com/GoogleChrome/webstatus.dev/issues/1181):
129-
// implement the adapter logic to retrieve feature IDs.
130-
const pageData = {
131-
data: [
132-
{
133-
feature_id: 'css',
134-
},
135-
{
136-
feature_id: 'html',
137-
},
138-
{
139-
feature_id: 'javascript',
140-
},
141-
{
142-
feature_id: 'bluetooth',
143-
},
144-
],
145-
metadata: {
146-
total: 4,
147-
},
148-
};
149-
for (let i = 0; i < 80; i++) {
150-
pageData.data.push({
151-
feature_id: 'item' + i,
152-
});
153-
}
154-
this.missingFeaturesList = pageData.data;
155-
// TODO:(kyleju) return these data from the API.
156-
this.selectedDate = '2024-08-20';
157-
this.selectedBrowser = 'chrome';
158-
return this.missingFeaturesList;
135+
task: async ([date, browser]) => {
136+
const features =
137+
await this.apiClient.getMissingOneImplementationFeatures(
138+
browser,
139+
otherBrowsers,
140+
date,
141+
);
142+
this.missingFeaturesList = features;
143+
this.selectedDate = targetDate.toISOString().substring(0, 10);
144+
this.selectedBrowser = targetBrowser;
145+
return features;
159146
},
160-
args: () => [],
147+
args: () => [targetDate, targetBrowser],
161148
});
162149
return {task: task, renderSuccess: this.pointSelectedTaskRenderOnSuccess};
163150
}

0 commit comments

Comments
 (0)