diff --git a/src/collections/deserialize/index.ts b/src/collections/deserialize/index.ts index 5ad7489e..97723179 100644 --- a/src/collections/deserialize/index.ts +++ b/src/collections/deserialize/index.ts @@ -533,7 +533,10 @@ export class Deserialize { objects: verbose ? reply.objects.map((obj) => { return { - id: stringify(obj.uuid), + // stringify() throws on anything but a 16-byte uuid; the server + // can omit the uuid on a BatchDeleteObject, so guard it here + // instead of letting an opaque TypeError escape. + id: obj.uuid.length === 16 ? stringify(obj.uuid) : undefined, successful: obj.successful, error: obj.error, }; diff --git a/src/collections/deserialize/unit.test.ts b/src/collections/deserialize/unit.test.ts new file mode 100644 index 00000000..19581ff8 --- /dev/null +++ b/src/collections/deserialize/unit.test.ts @@ -0,0 +1,30 @@ +import { v4 } from 'uuid'; +import { describe, expect, it } from 'vitest'; +import { BatchDeleteReply } from '../../proto/v1/batch_delete.js'; +import { Deserialize } from './index.js'; + +describe('Unit testing of Deserialize.deleteMany', () => { + const baseReply = (uuid: Uint8Array): BatchDeleteReply => ({ + took: 0, + failed: 0, + matches: 1, + successful: 1, + objects: [{ uuid, successful: true, error: '' }], + }); + + it('should stringify a well-formed 16-byte uuid', () => { + const id = v4(); + const uuid = Uint8Array.from(Buffer.from(id.replace(/-/g, ''), 'hex')); + + const result = Deserialize.deleteMany(baseReply(uuid), true); + + expect(result.objects![0].id).toBe(id); + }); + + it('should return an undefined id instead of throwing when the server omits the uuid', () => { + const result = Deserialize.deleteMany(baseReply(new Uint8Array(0)), true); + + expect(result.objects![0].id).toBeUndefined(); + expect(result.objects![0].successful).toBe(true); + }); +}); diff --git a/src/collections/types/data.ts b/src/collections/types/data.ts index 0a4d33be..763ab3a7 100644 --- a/src/collections/types/data.ts +++ b/src/collections/types/data.ts @@ -9,7 +9,8 @@ export type DataObject = { }; export type DeleteManyObject = { - id: string; + /** Undefined when the server returned no uuid for this object. */ + id?: string; successful: boolean; error?: string; }; diff --git a/test/collections/journey.test.ts b/test/collections/journey.test.ts index 11d01222..094bdd83 100644 --- a/test/collections/journey.test.ts +++ b/test/collections/journey.test.ts @@ -13,7 +13,7 @@ describe('Journey testing of the client using a WCD cluster', () => { dateOfBirth: Date; }; - afterAll(() => client.collections.delete(collectionName)); + afterAll(() => client?.collections.delete(collectionName)); beforeAll(async () => { client = await weaviate.connectToWeaviateCloud(