Co-authored-by: Joe Portner <5295965+jportner@users.noreply.github.com>
This commit is contained in:
parent
88ded09bfa
commit
6be9fbe9c7
|
@ -216,61 +216,51 @@ describe('SavedObjectsClient', () => {
|
|||
`);
|
||||
});
|
||||
|
||||
test('removes duplicates when calling `_bulk_resolve`', async () => {
|
||||
test('handles duplicates correctly', async () => {
|
||||
// Await #resolve call to ensure batchQueue is empty and throttle has reset
|
||||
mockResolvedObjects({ ...doc, type: 'type2' });
|
||||
await savedObjectsClient.resolve('type2', doc.id);
|
||||
http.fetch.mockClear();
|
||||
|
||||
mockResolvedObjects(doc, { ...doc, type: 'some-type', id: 'some-id' }); // the client will only request two objects, so we only mock two results
|
||||
savedObjectsClient.resolve(doc.type, doc.id);
|
||||
savedObjectsClient.resolve('some-type', 'some-id');
|
||||
await savedObjectsClient.resolve(doc.type, doc.id);
|
||||
mockResolvedObjects(doc, { ...doc, type: 'type2' }, { ...doc, type: 'type3' }); // the client will only request three objects, so we only mock three results
|
||||
const call1 = savedObjectsClient.resolve(doc.type, doc.id);
|
||||
const call2 = savedObjectsClient.resolve('type2', doc.id);
|
||||
const call3 = savedObjectsClient.resolve(doc.type, doc.id);
|
||||
const objFromCall4 = await savedObjectsClient.resolve('type3', doc.id);
|
||||
const objFromCall1 = await call1;
|
||||
const objFromCall2 = await call2;
|
||||
const objFromCall3 = await call3;
|
||||
|
||||
// Assertion 1: all calls should return the expected object
|
||||
expect(objFromCall1.saved_object).toEqual(
|
||||
expect.objectContaining({ type: doc.type, id: doc.id, error: undefined })
|
||||
);
|
||||
expect(objFromCall2.saved_object).toEqual(
|
||||
expect.objectContaining({ type: 'type2', id: doc.id, error: undefined })
|
||||
);
|
||||
expect(objFromCall3.saved_object).toEqual(
|
||||
expect.objectContaining({ type: doc.type, id: doc.id, error: undefined })
|
||||
);
|
||||
expect(objFromCall4.saved_object).toEqual(
|
||||
expect.objectContaining({ type: 'type3', id: doc.id, error: undefined })
|
||||
);
|
||||
|
||||
// Assertion 2: requests should be deduplicated (call1 and call3)
|
||||
expect(http.fetch).toHaveBeenCalledTimes(1);
|
||||
expect(http.fetch.mock.calls[0]).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"/api/saved_objects/_bulk_resolve",
|
||||
Object {
|
||||
"body": "[{\\"id\\":\\"AVwSwFxtcMV38qjDZoQg\\",\\"type\\":\\"config\\"},{\\"id\\":\\"some-id\\",\\"type\\":\\"some-type\\"}]",
|
||||
"body": "[{\\"id\\":\\"AVwSwFxtcMV38qjDZoQg\\",\\"type\\":\\"config\\"},{\\"id\\":\\"AVwSwFxtcMV38qjDZoQg\\",\\"type\\":\\"type2\\"},{\\"id\\":\\"AVwSwFxtcMV38qjDZoQg\\",\\"type\\":\\"type3\\"}]",
|
||||
"method": "POST",
|
||||
"query": undefined,
|
||||
},
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
test('resolves with correct object when there are duplicates present', async () => {
|
||||
// Await #resolve call to ensure batchQueue is empty and throttle has reset
|
||||
mockResolvedObjects({ ...doc, type: 'type2' });
|
||||
await savedObjectsClient.resolve('type2', doc.id);
|
||||
http.fetch.mockClear();
|
||||
|
||||
mockResolvedObjects(doc);
|
||||
const call1 = savedObjectsClient.resolve(doc.type, doc.id);
|
||||
const objFromCall2 = await savedObjectsClient.resolve(doc.type, doc.id);
|
||||
const objFromCall1 = await call1;
|
||||
|
||||
expect(objFromCall1.saved_object.type).toBe(doc.type);
|
||||
expect(objFromCall1.saved_object.id).toBe(doc.id);
|
||||
|
||||
expect(objFromCall2.saved_object.type).toBe(doc.type);
|
||||
expect(objFromCall2.saved_object.id).toBe(doc.id);
|
||||
});
|
||||
|
||||
test('do not share instances or references between duplicate callers', async () => {
|
||||
// Await #resolve call to ensure batchQueue is empty and throttle has reset
|
||||
await savedObjectsClient.resolve('type2', doc.id);
|
||||
mockResolvedObjects({ ...doc, type: 'type2' });
|
||||
http.fetch.mockClear();
|
||||
|
||||
mockResolvedObjects(doc);
|
||||
const call1 = savedObjectsClient.resolve(doc.type, doc.id);
|
||||
const objFromCall2 = await savedObjectsClient.resolve(doc.type, doc.id);
|
||||
const objFromCall1 = await call1;
|
||||
|
||||
// Assertion 3: deduplicated requests should not share response object instances or references
|
||||
objFromCall1.saved_object.set('title', 'new title');
|
||||
expect(objFromCall2.saved_object.get('title')).toEqual('Example title');
|
||||
expect(objFromCall3.saved_object.get('title')).toEqual('Example title'); // unchanged
|
||||
});
|
||||
|
||||
test('resolves with ResolvedSimpleSavedObject instance', async () => {
|
||||
|
|
|
@ -168,13 +168,13 @@ const getObjectsToResolve = (queue: BatchResolveQueueEntry[]) => {
|
|||
const responseIndices: number[] = [];
|
||||
const objectsToResolve: ObjectTypeAndId[] = [];
|
||||
const inserted = new Map<string, number>();
|
||||
queue.forEach(({ id, type }, currentIndex) => {
|
||||
queue.forEach(({ id, type }) => {
|
||||
const key = `${type}|${id}`;
|
||||
const indexForTypeAndId = inserted.get(key);
|
||||
if (indexForTypeAndId === undefined) {
|
||||
inserted.set(key, currentIndex);
|
||||
inserted.set(key, objectsToResolve.length);
|
||||
responseIndices.push(objectsToResolve.length);
|
||||
objectsToResolve.push({ id, type });
|
||||
responseIndices.push(currentIndex);
|
||||
} else {
|
||||
responseIndices.push(indexForTypeAndId);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue