diff --git a/desktop/plugins/public/network/__tests__/datastorage.node.tsx b/desktop/plugins/public/network/__tests__/datastorage.node.tsx new file mode 100644 index 00000000000..557713ef73f --- /dev/null +++ b/desktop/plugins/public/network/__tests__/datastorage.node.tsx @@ -0,0 +1,70 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +import {createDataSource} from 'flipper-plugin'; +import {RequestDataDB} from '../RequestDataDB'; +import {createRequestFromRequestInfo} from '../index'; + +import {decodeBody} from '../utils'; + +import {Request} from '../types'; +import {Base64} from 'js-base64'; + +// IndexedDB polyfill +global.structuredClone = (val) => (val ? JSON.parse(JSON.stringify(val)) : val); +require('fake-indexeddb/auto'); + +const firstRequest = { + id: '17', + timestamp: 1234567890, + method: 'GET', + url: 'https://fbflipper.com/', + headers: [{key: 'Content-Type', value: 'text/plain'}], + data: undefined, +}; + +const secondRequest = { + id: '17', + timestamp: 1234567890, + method: 'GET', // same as before + url: 'https://fallback.fbflipper.com/', // changed from before + headers: [{key: 'Content-Type', value: 'text/plain'}], + data: Base64.encode('hello world'), // new field (not stored in DataSource) +}; + +test('DataSource handles updates', () => { + const requests = createDataSource([], { + key: 'id', + indices: [['method'], ['status']], + }); + const customColumns = []; + + requests.upsert(createRequestFromRequestInfo(firstRequest, customColumns)); + requests.upsert(createRequestFromRequestInfo(secondRequest, customColumns)); + + const result = requests.getById('17'); + expect(result?.method).toEqual('GET'); + expect(result?.url).toEqual('https://fallback.fbflipper.com/'); +}); + +test('RequestDataDB handles updates', async () => { + const db = new RequestDataDB(); + + db.storeRequestData( + firstRequest.id, + decodeBody(firstRequest.headers, firstRequest.data), + ); + db.storeRequestData( + secondRequest.id, + decodeBody(secondRequest.headers, secondRequest.data), + ); + + const result = await db.getRequestData('17'); + expect(result).toEqual('hello world'); +}); diff --git a/desktop/plugins/public/network/index.tsx b/desktop/plugins/public/network/index.tsx index 8ed54aa20fd..a42c5dac855 100644 --- a/desktop/plugins/public/network/index.tsx +++ b/desktop/plugins/public/network/index.tsx @@ -170,13 +170,10 @@ export function plugin(client: PluginClient) { }); client.onMessage('newRequest', (data) => { - // Some network stacks may send duplicate data, so we filter them out. - if (requests.has(data.id)) { - console.warn(`Ignoring duplicate request with id ${data.id}:`, data); - } else { - requests.append(createRequestFromRequestInfo(data, customColumns.get())); - db.storeRequestData(data.id, decodeBody(data.headers, data.data)); - } + // Network stacks might emit newRequest multiple times with incremental + // data, hence the upsert. + requests.upsert(createRequestFromRequestInfo(data, customColumns.get())); + db.storeRequestData(data.id, decodeBody(data.headers, data.data)); }); function storeResponse(response: ResponseInfo) { @@ -542,7 +539,7 @@ function showCustomColumnDialog( renderReactRoot((unmount) => ); } -function createRequestFromRequestInfo( +export function createRequestFromRequestInfo( data: RequestInfo, customColumns: CustomColumnConfig[], ): Request {