// `fetchMLDataBatch`, against a server that sends one file's ML data. // // ML data that decrypts and gunzips but is not a JSON object is reported with // the reason, as ML data that does not parse is, and is never returned as a // payload: the library would fail to store it. import { gzipSync } from "node:zlib"; import sodium from "libsodium-wrappers-sumo"; import { beforeAll, describe, expect, it } from "vitest"; import { ApiClient } from "../../src/api/client.js"; import { encryptBlob, init, toBase64 } from "../../src/crypto/index.js"; import { fetchMLDataBatch } from "../../src/mldata-fetch.js"; beforeAll(async () => { await init(); await sodium.ready; }); // Fetch the ML data of file 1 from a server that sends `json`, gzipped and // encrypted with the file's key. const fetchServing = async (json: string) => { const key = sodium.crypto_secretstream_xchacha20poly1305_keygen(); const { header, ciphertext } = encryptBlob( new Uint8Array(gzipSync(json)), key, ); const data = [ { fileID: 1, encryptedData: toBase64(ciphertext), decryptionHeader: toBase64(header), }, ]; const api = new ApiClient({ fetch: async () => new Response(JSON.stringify({ data }), { headers: { "content-type": "application/json" }, }), }); return fetchMLDataBatch(api, [1], new Map([[1, key]])); }; describe("fetchMLDataBatch", () => { it.each(["null", "5", "[]"])( "gives a reason for ML data that is %s", async (json) => { const { payloads, errors } = await fetchServing(json); expect(payloads.size).toBe(0); expect(errors.get(1)).toEqual(new Error("not a JSON object")); }, ); });