Skip to content

Commit f68d4c9

Browse files
adhorodyskiclaude
andcommitted
Fix ESLint no-unsafe-type-assertion in SequentialQueue test
The test needed a MockFetch-typed handle (pause/resume) for the new disk-write-failure cases. Casting global.fetch to MockFetch tripped @typescript-eslint/no-unsafe-type-assertion in CI. Expose createGlobalFetchMock() returning MockFetch directly (the mock is already built as MockFetch internally), and keep getGlobalFetchMock as a thin typeof-fetch wrapper so existing callers are unaffected. The test now gets a fresh, typed mock per test with no type assertion. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 6944ea4 commit f68d4c9

2 files changed

Lines changed: 19 additions & 15 deletions

File tree

tests/unit/SequentialQueueTest.ts

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import * as SequentialQueue from '../../src/libs/Network/SequentialQueue';
88
import * as RequestModule from '../../src/libs/Request';
99
import type Request from '../../src/types/onyx/Request';
1010
import type {AnyRequest, ConflictActionData} from '../../src/types/onyx/Request';
11+
import type {MockFetch} from '../utils/TestHelper';
1112
import * as TestHelper from '../utils/TestHelper';
1213
import waitForBatchedUpdates from '../utils/waitForBatchedUpdates';
1314

@@ -16,13 +17,15 @@ const request: Request<'userMetadata'> = {
1617
successData: [{key: 'userMetadata', onyxMethod: 'set', value: {accountID: 1234}}],
1718
failureData: [{key: 'userMetadata', onyxMethod: 'set', value: {}}],
1819
};
20+
let mockFetch: MockFetch;
1921
beforeAll(() => {
2022
Onyx.init({
2123
keys: ONYXKEYS,
2224
});
2325
});
2426
beforeEach(() => {
25-
global.fetch = TestHelper.getGlobalFetchMock();
27+
mockFetch = TestHelper.createGlobalFetchMock();
28+
global.fetch = mockFetch;
2629
return Onyx.clear()
2730
.then(() => SequentialQueue.clearQueueFlushedData())
2831
.then(waitForBatchedUpdates);
@@ -77,10 +80,9 @@ describe('SequentialQueue', () => {
7780
it('should not block the queue when a disk write fails during persist', async () => {
7881
// If a conflict-resolution disk write rejects (storage full / corruption), push() must not throw
7982
// or strand isReadyPromise — the request should still flush and waitForIdle() should resolve.
80-
const mockedFetch = global.fetch as ReturnType<typeof TestHelper.getGlobalFetchMock> & {pause: () => void; resume: () => Promise<void>};
8183
const originalSet = Onyx.set.bind(Onyx);
8284

83-
mockedFetch.pause();
85+
mockFetch.pause();
8486
try {
8587
await SequentialQueue.push({command: 'OpenReport'}); // occupies ongoingRequest
8688
await waitForBatchedUpdates();
@@ -105,7 +107,7 @@ describe('SequentialQueue', () => {
105107
setMock.mockRestore();
106108
}
107109
} finally {
108-
await mockedFetch.resume();
110+
await mockFetch.resume();
109111
}
110112

111113
// The queue still drains and READs unblock — a hang here would fail the test by timing out.
@@ -170,8 +172,7 @@ describe('SequentialQueue', () => {
170172
// The conflict checker on push 2 inspects the persisted queue (which excludes the
171173
// ongoing request), so it cannot find a 'ReconnectApp' to replace and falls back
172174
// to 'push'. The new request is therefore added to the queue.
173-
const mockedFetch = global.fetch as ReturnType<typeof TestHelper.getGlobalFetchMock> & {pause: () => void; resume: () => Promise<void>};
174-
mockedFetch.pause();
175+
mockFetch.pause();
175176
try {
176177
await SequentialQueue.push(request);
177178
await waitForBatchedUpdates();
@@ -194,13 +195,12 @@ describe('SequentialQueue', () => {
194195
// The new request is in the persisted queue with the expected accountID.
195196
expect(getAll().some((r) => r.data?.accountID === 56789)).toBe(true);
196197
} finally {
197-
await mockedFetch.resume();
198+
await mockFetch.resume();
198199
}
199200
});
200201

201202
it('should replace request in queue while a similar one is ongoing', async () => {
202-
const mockedFetch = global.fetch as ReturnType<typeof TestHelper.getGlobalFetchMock> & {pause: () => void; resume: () => Promise<void>};
203-
mockedFetch.pause();
203+
mockFetch.pause();
204204
try {
205205
await SequentialQueue.push(request);
206206
await waitForBatchedUpdates();
@@ -234,13 +234,12 @@ describe('SequentialQueue', () => {
234234

235235
expect(getLength()).toBe(2);
236236
} finally {
237-
await mockedFetch.resume();
237+
await mockFetch.resume();
238238
}
239239
});
240240

241241
it('should replace request in queue while a similar one is ongoing and keep the same index', async () => {
242-
const mockedFetch = global.fetch as ReturnType<typeof TestHelper.getGlobalFetchMock> & {pause: () => void; resume: () => Promise<void>};
243-
mockedFetch.pause();
242+
mockFetch.pause();
244243
try {
245244
// First push moves into `ongoingRequest`; subsequent pushes stack in the queue.
246245
await SequentialQueue.push({command: 'OpenReport'});
@@ -270,7 +269,7 @@ describe('SequentialQueue', () => {
270269
expect(getOngoingRequest()?.command).toBe('OpenReport');
271270
expect(persistedRequests.at(0)?.data?.accountID).toBe(56789);
272271
} finally {
273-
await mockedFetch.resume();
272+
await mockFetch.resume();
274273
}
275274
});
276275

tests/utils/TestHelper.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ function signOutTestUser() {
217217
* - fail() - start returning a failure response
218218
* - success() - go back to returning a success response
219219
*/
220-
function getGlobalFetchMock(mockResponse?: Partial<Response>): typeof fetch {
220+
function createGlobalFetchMock(mockResponse?: Partial<Response>): MockFetch {
221221
let queue: QueueItem[] = [];
222222
// eslint-disable-next-line @typescript-eslint/no-explicit-any
223223
let responses = new Map<string, (params: any) => OnyxResponse<any>>();
@@ -280,7 +280,11 @@ function getGlobalFetchMock(mockResponse?: Partial<Response>): typeof fetch {
280280
mockFetch.mockAPICommand = <TCommand extends ApiCommand>(command: TCommand, responseHandler: (params: ApiRequestCommandParameters[TCommand]) => OnyxResponse<any>): void => {
281281
responses.set(command, responseHandler);
282282
};
283-
return mockFetch as typeof fetch;
283+
return mockFetch;
284+
}
285+
286+
function getGlobalFetchMock(mockResponse?: Partial<Response>): typeof fetch {
287+
return createGlobalFetchMock(mockResponse);
284288
}
285289

286290
function setupGlobalFetchMock(): MockFetch {
@@ -394,6 +398,7 @@ export {
394398
buildTestReportComment,
395399
getFetchMockCalls,
396400
getGlobalFetchMock,
401+
createGlobalFetchMock,
397402
setPersonalDetails,
398403
signInWithTestUser,
399404
signOutTestUser,

0 commit comments

Comments
 (0)