Skip to content

Commit 94e1703

Browse files
committed
added tests
1 parent a8c26c1 commit 94e1703

File tree

3 files changed

+62
-29
lines changed

3 files changed

+62
-29
lines changed

special-pages/pages/new-tab/app/activity/BurnProvider.js

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { useContext, useEffect } from 'preact/hooks';
33
import { ActivityApiContext, ActivityServiceContext } from './ActivityProvider';
44
import { ACTION_BURN } from './constants.js';
55
import { batch, signal, useSignal } from '@preact/signals';
6+
import { useEnv } from '../../../../shared/components/EnvironmentProvider.js';
67

78
export const ActivityBurningSignalContext = createContext({
89
/** @type {import("@preact/signals").Signal<string[]>} */
@@ -20,6 +21,7 @@ export function BurnProvider({ children }) {
2021
const exiting = useSignal(/** @type {string[]} */ ([]));
2122
const { didClick: originalDidClick } = useContext(ActivityApiContext);
2223
const service = useContext(ActivityServiceContext);
24+
const { isReducedMotion } = useEnv();
2325

2426
async function didClick(e) {
2527
const button = /** @type {HTMLButtonElement|null} */ (e.target?.closest(`button[value][data-action="${ACTION_BURN}"]`));
@@ -41,8 +43,8 @@ export function BurnProvider({ children }) {
4143
// mark this item as burning - this will prevent further events until we're done
4244
burning.value = burning.value.concat(value);
4345

44-
// wait for either the animation to be finished, or the document visibility changed
45-
const feSignals = any(animationExit(), didChangeDocumentVisibility());
46+
// wait for a signal from the FE that we can continue
47+
const feSignals = any(reducedMotion(isReducedMotion), animationExit(), didChangeDocumentVisibility());
4648

4749
// the signal from native that burning was complete
4850
const nativeSignal = didCompleteNatively(service);
@@ -102,11 +104,21 @@ function toPromise(fn) {
102104
});
103105
}
104106

107+
function reducedMotion(isReducedMotion) {
108+
console.log('+[reducedMotion] setup');
109+
return (subject) => {
110+
if (isReducedMotion) {
111+
console.log(' .next() [reducedMotion] setup');
112+
subject.next();
113+
}
114+
};
115+
}
116+
105117
function animationExit() {
106118
return (subject) => {
107119
console.log('+[didExit] setup');
108120
const handler = () => {
109-
console.log(' -> [didExit] resolve .next()');
121+
console.log(' .next() -> [didExit]');
110122
subject.next();
111123
};
112124
window.addEventListener('done-exiting', handler, { once: true });
@@ -121,7 +133,7 @@ function timer(ms) {
121133
return (subject) => {
122134
console.log('+[timer] setup');
123135
const int = setTimeout(() => {
124-
console.log(' -> [timer] .next()');
136+
console.log(' .next() -> [timer]');
125137
return subject.next();
126138
}, ms);
127139
return () => {
@@ -135,7 +147,7 @@ function didCompleteNatively(service) {
135147
return (subject) => {
136148
console.log('+[didCompleteNatively] setup');
137149
const unsub = service?.onBurnComplete(() => {
138-
console.log(' -> [didCompleteNatively] .next()');
150+
console.log(' .next() -> [didCompleteNatively] ');
139151
subject.next();
140152
});
141153
return () => {
@@ -147,72 +159,72 @@ function didCompleteNatively(service) {
147159

148160
function didChangeDocumentVisibility() {
149161
return (subject) => {
150-
console.log('+[didChangeVisibilty] setup');
162+
console.log('+[didChangeVisibility] setup');
151163
const handler = () => {
152-
console.log(' -> [didChangeVisibilty] resolve .next()');
164+
console.log(' .next() -> [didChangeVisibility] resolve ');
153165
return subject.next(document.visibilityState);
154166
};
155167
document.addEventListener('visibilitychange', handler, { once: true });
156168
return () => {
157-
console.log('-[didChangeVisibilty] teardown');
169+
console.log('-[didChangeVisibility] teardown');
158170
window.removeEventListener('visibilitychange', handler);
159171
};
160172
};
161173
}
162174

163175
function any(...fns) {
164176
return (subject) => {
165-
const work = fns.map((factory) => {
177+
const jobs = fns.map((factory) => {
166178
const subject = {
167179
/** @type {any} */
168180
next: undefined,
169181
};
170182
const promise = new Promise((resolve) => (subject.next = resolve));
171183
const cleanup = factory(subject);
172184
return {
173-
promise: promise,
174-
cleanup: cleanup,
185+
promise,
186+
cleanup,
175187
};
176188
});
177189

178-
Promise.any(work.map((x) => x.promise))
190+
Promise.any(jobs.map((x) => x.promise))
179191
// eslint-disable-next-line promise/prefer-await-to-then
180192
.then((d) => subject.next(d))
181193
// eslint-disable-next-line promise/prefer-await-to-then
182194
.catch(console.error);
183195

184196
return () => {
185-
for (const workItem of work) {
186-
workItem.cleanup();
197+
for (const job of jobs) {
198+
job.cleanup?.();
187199
}
188200
};
189201
};
190202
}
191203

192204
function all(...fns) {
193205
return (subject) => {
194-
const work = fns.map((factory) => {
206+
const jobs = fns.map((factory) => {
195207
const subject = {
196208
/** @type {any} */
197209
next: undefined,
198210
};
199211
const promise = new Promise((resolve) => (subject.next = resolve));
200212
const cleanup = factory(subject);
201213
return {
202-
promise: promise,
203-
cleanup: cleanup,
214+
promise,
215+
cleanup,
204216
};
205217
});
206218

207-
Promise.all(work.map((x) => x.promise))
219+
Promise.all(jobs.map((x) => x.promise))
208220
// eslint-disable-next-line promise/prefer-await-to-then
209221
.then((d) => subject.next(d))
210222
// eslint-disable-next-line promise/prefer-await-to-then
211223
.catch(console.error);
212224

213225
return () => {
214-
for (const workItem of work) {
215-
workItem.cleanup();
226+
for (const job of jobs) {
227+
job.cleanup?.();
216228
}
217229
};
218230
};

special-pages/pages/new-tab/app/activity/integration-tests/activity.page.js

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
import { activityMocks } from '../mocks/activity.mocks.js';
22
import { expect } from '@playwright/test';
33

4+
/**
5+
* @typedef {import('../../../types/new-tab.js').NewTabMessages['subscriptions']['subscriptionEvent']} SubscriptionEventNames
6+
*/
7+
8+
/**
9+
* @param {SubscriptionEventNames} n
10+
*/
11+
const sub = (n) => n;
12+
413
export class ActivityPage {
514
/**
615
* @param {import("@playwright/test").Page} page
@@ -120,7 +129,13 @@ export class ActivityPage {
120129
};
121130
}, response);
122131

132+
// control: ensure we have 5 first
133+
await expect(this.context().getByTestId('ActivityItem')).toHaveCount(5);
134+
135+
// burn 1 item in the list
123136
await this.context().getByRole('button', { name: 'Clear browsing history and data for example.com' }).click();
137+
138+
// assert the confirm was sent
124139
const result = await this.ntp.mocks.waitForCallCount({ method: 'activity_confirmBurn', count: 1 });
125140
expect(result[0].payload).toMatchObject({
126141
context: 'specialPages',
@@ -130,12 +145,17 @@ export class ActivityPage {
130145
url: 'https://example.com',
131146
},
132147
});
133-
const animResult = await this.ntp.mocks.waitForCallCount({ method: 'activity_burnAnimationComplete', count: 1 });
134-
expect(animResult[0].payload).toMatchObject({
135-
context: 'specialPages',
136-
featureName: 'newTabPage',
137-
method: 'activity_burnAnimationComplete',
138-
});
148+
149+
// simulate a small delay from native
150+
await page.waitForTimeout(50);
151+
152+
// deliver both updates from native
153+
const nextData = activityMocks.few.activity.filter((x) => x.url !== 'https://example.com');
154+
await this.ntp.mocks.simulateSubscriptionMessage(sub('activity_onDataUpdate'), { activity: nextData });
155+
await this.ntp.mocks.simulateSubscriptionMessage(sub('activity_onBurnComplete'), {});
156+
157+
// now assert only 4 items are there
158+
await expect(this.context().getByTestId('ActivityItem')).toHaveCount(4);
139159
}
140160

141161
async removesItem() {

special-pages/pages/new-tab/app/activity/mocks/activity.mock-transport.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,17 +104,18 @@ export function activityMockTransport() {
104104
}
105105
}
106106

107-
if (response.action === 'burn') {
107+
if (response.action === 'burn' && !window.__playwright_01) {
108108
setTimeout(() => {
109109
const cb = subs.get('activity_onDataUpdate');
110-
console.log('wills send new data for', url);
110+
console.log('will send updated data after 500ms', url);
111111
const next = activityMocks.few.activity.filter((x) => x.url !== url);
112112
cb?.({ activity: next });
113113
}, 500);
114114
setTimeout(() => {
115115
const cb = subs.get('activity_onBurnComplete');
116+
console.log('will send updated data after 600ms', url);
116117
cb?.();
117-
}, 550);
118+
}, 600);
118119
}
119120

120121
return Promise.resolve(response);

0 commit comments

Comments
 (0)