diff --git a/src/Typesense/Documents.ts b/src/Typesense/Documents.ts index cd1b6460..6cad53f4 100644 --- a/src/Typesense/Documents.ts +++ b/src/Typesense/Documents.ts @@ -1,7 +1,7 @@ import type { ReadStream } from "fs"; import ApiCall from "./ApiCall"; import Configuration from "./Configuration"; -import { ImportError } from "./Errors"; +import { ImportError, RequestMalformed } from "./Errors"; import { SearchOnlyDocuments } from "./SearchOnlyDocuments"; // Todo: use generic to extract filter_by values @@ -388,6 +388,9 @@ export default class Documents ): Promise { let documentsInJSONLFormat; if (Array.isArray(documents)) { + if (documents.length === 0) { + throw new RequestMalformed("No documents provided"); + } try { documentsInJSONLFormat = documents .map((document) => JSON.stringify(document)) @@ -410,6 +413,9 @@ export default class Documents } } else { documentsInJSONLFormat = documents; + if (isEmptyString(documentsInJSONLFormat)) { + throw new RequestMalformed("No documents provided"); + } } const resultsInJSONLFormat = await this.apiCall.performRequest( @@ -514,3 +520,7 @@ export default class Documents }); } } + +function isEmptyString(str: string | null | undefined): boolean { + return str == null || str === "" || str.length === 0; +} diff --git a/test/Typesense/Documents.spec.js b/test/Typesense/Documents.spec.js index 6b9c0032..c09a324f 100644 --- a/test/Typesense/Documents.spec.js +++ b/test/Typesense/Documents.spec.js @@ -436,6 +436,65 @@ describe("Documents", function () { }); describe(".import", function () { + context("when an empty array of documents is passed", function () { + it("throws RequestMalformed error", function (done) { + documents + .import([]) + .then(() => { + done(new Error("Expected import to throw RequestMalformed error")); + }) + .catch((error) => { + expect(error.constructor.name).to.eq("RequestMalformed"); + expect(error.message).to.eq("No documents provided"); + done(); + }); + }); + }); + + context("when an empty string is passed", function () { + it("throws RequestMalformed error", function (done) { + documents + .import("") + .then(() => { + done(new Error("Expected import to throw RequestMalformed error")); + }) + .catch((error) => { + expect(error.constructor.name).to.eq("RequestMalformed"); + expect(error.message).to.eq("No documents provided"); + done(); + }); + }); + }); + + context("when null is passed as JSONL string", function () { + it("throws RequestMalformed error", function (done) { + documents + .import(null) + .then(() => { + done(new Error("Expected import to throw RequestMalformed error")); + }) + .catch((error) => { + expect(error.constructor.name).to.eq("RequestMalformed"); + expect(error.message).to.eq("No documents provided"); + done(); + }); + }); + }); + + context("when undefined is passed as JSONL string", function () { + it("throws RequestMalformed error", function (done) { + documents + .import(undefined) + .then(() => { + done(new Error("Expected import to throw RequestMalformed error")); + }) + .catch((error) => { + expect(error.constructor.name).to.eq("RequestMalformed"); + expect(error.message).to.eq("No documents provided"); + done(); + }); + }); + }); context("when a query paramater is passed", function () { it("passes the query parameter to the API", function (done) { mockAxios