Spaces:
Paused
Paused
| /** | |
| * @license | |
| * Copyright 2024 Google LLC | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| import { expect, use } from "chai"; | |
| import { match, restore, stub } from "sinon"; | |
| import * as sinonChai from "sinon-chai"; | |
| import * as chaiAsPromised from "chai-as-promised"; | |
| import { DEFAULT_API_VERSION, DEFAULT_BASE_URL } from "../requests/request"; | |
| import { FilesRequestUrl, makeServerRequest } from "./request"; | |
| import { RpcTask } from "./constants"; | |
| import { GoogleGenerativeAIFetchError } from "../errors"; | |
| use(sinonChai); | |
| use(chaiAsPromised); | |
| describe("Files API - request methods", () => { | |
| afterEach(() => { | |
| restore(); | |
| }); | |
| describe("FilesRequestUrl", () => { | |
| it("includes task, apiVersion, baseURL, upload if upload task", async () => { | |
| const url = new FilesRequestUrl(RpcTask.UPLOAD, "key", {}); | |
| expect(url.toString()).to.include("/upload"); | |
| expect(url.toString()).to.not.include("key"); | |
| expect(url.toString()).to.include(DEFAULT_API_VERSION); | |
| expect(url.toString()).to.include(DEFAULT_BASE_URL); | |
| }); | |
| it("includes task, apiVersion, baseURL, no upload if non-upload task", async () => { | |
| const url = new FilesRequestUrl(RpcTask.GET, "key", {}); | |
| expect(url.toString()).to.not.include("/upload"); | |
| expect(url.toString()).to.not.include("key"); | |
| expect(url.toString()).to.include(DEFAULT_API_VERSION); | |
| expect(url.toString()).to.include(DEFAULT_BASE_URL); | |
| }); | |
| it("gets custom apiVersion", async () => { | |
| const url = new FilesRequestUrl(RpcTask.GET, "key", { | |
| apiVersion: "v2beta", | |
| }); | |
| expect(url.toString()).to.include("/v2beta/files"); | |
| }); | |
| it("custom baseUrl", async () => { | |
| const url = new FilesRequestUrl(RpcTask.GET, "key", { | |
| baseUrl: "http://my.staging.website", | |
| }); | |
| expect(url.toString()).to.include("http://my.staging.website"); | |
| }); | |
| it("adds params", async () => { | |
| const url = new FilesRequestUrl(RpcTask.GET, "key", {}); | |
| url.appendParam("param1", "value1"); | |
| expect(url.toString()).to.include("?param1=value1"); | |
| }); | |
| it("adds path segments", async () => { | |
| const url = new FilesRequestUrl(RpcTask.GET, "key", {}); | |
| url.appendPath("newpath"); | |
| expect(url.toString()).to.match(/\/newpath$/); | |
| }); | |
| }); | |
| describe("makeFilesRequest", () => { | |
| it("upload - ok", async () => { | |
| const fetchStub = stub().resolves({ | |
| ok: true, | |
| } as Response); | |
| const url = new FilesRequestUrl(RpcTask.UPLOAD, "key"); | |
| const headers = new Headers(); | |
| const response = await makeServerRequest( | |
| url, | |
| headers, | |
| new Blob(), | |
| fetchStub as typeof fetch, | |
| ); | |
| expect(fetchStub).to.be.calledWith(match.string, { | |
| method: "POST", | |
| headers: match.instanceOf(Headers), | |
| body: match.instanceOf(Blob), | |
| }); | |
| expect(response.ok).to.be.true; | |
| }); | |
| it("error with timeout", async () => { | |
| const fetchStub = stub().resolves({ | |
| ok: false, | |
| status: 500, | |
| statusText: "AbortError", | |
| } as Response); | |
| const url = new FilesRequestUrl(RpcTask.GET, "key", { timeout: 0 }); | |
| const headers = new Headers(); | |
| try { | |
| await makeServerRequest( | |
| url, | |
| headers, | |
| new Blob(), | |
| fetchStub as typeof fetch, | |
| ); | |
| } catch (e) { | |
| expect((e as GoogleGenerativeAIFetchError).message).to.include( | |
| "500 AbortError", | |
| ); | |
| expect((e as GoogleGenerativeAIFetchError).status).to.equal(500); | |
| expect((e as GoogleGenerativeAIFetchError).statusText).to.equal( | |
| "AbortError", | |
| ); | |
| } | |
| expect(fetchStub).to.be.calledOnce; | |
| }); | |
| it("Network error, no response.json()", async () => { | |
| const fetchStub = stub().resolves({ | |
| ok: false, | |
| status: 500, | |
| statusText: "Server Error", | |
| } as Response); | |
| const url = new FilesRequestUrl(RpcTask.GET, "key"); | |
| const headers = new Headers(); | |
| try { | |
| await makeServerRequest( | |
| url, | |
| headers, | |
| new Blob(), | |
| fetchStub as typeof fetch, | |
| ); | |
| } catch (e) { | |
| expect((e as GoogleGenerativeAIFetchError).message).to.include( | |
| "500 Server Error", | |
| ); | |
| expect((e as GoogleGenerativeAIFetchError).status).to.equal(500); | |
| expect((e as GoogleGenerativeAIFetchError).statusText).to.equal( | |
| "Server Error", | |
| ); | |
| } | |
| expect(fetchStub).to.be.calledOnce; | |
| }); | |
| it("Network error, includes response.json()", async () => { | |
| const fetchStub = stub().resolves({ | |
| ok: false, | |
| status: 500, | |
| statusText: "Server Error", | |
| json: () => Promise.resolve({ error: { message: "extra info" } }), | |
| } as Response); | |
| const url = new FilesRequestUrl(RpcTask.GET, "key"); | |
| const headers = new Headers(); | |
| try { | |
| await makeServerRequest( | |
| url, | |
| headers, | |
| new Blob(), | |
| fetchStub as typeof fetch, | |
| ); | |
| } catch (e) { | |
| expect((e as GoogleGenerativeAIFetchError).message).to.match( | |
| /500 Server Error.+extra info/, | |
| ); | |
| expect((e as GoogleGenerativeAIFetchError).status).to.equal(500); | |
| expect((e as GoogleGenerativeAIFetchError).statusText).to.equal( | |
| "Server Error", | |
| ); | |
| } | |
| expect(fetchStub).to.be.calledOnce; | |
| }); | |
| it("Network error, includes response.json() and details", async () => { | |
| const fetchStub = stub().resolves({ | |
| ok: false, | |
| status: 500, | |
| statusText: "Server Error", | |
| json: () => | |
| Promise.resolve({ | |
| error: { | |
| message: "extra info", | |
| details: [ | |
| { | |
| "@type": "type.googleapis.com/google.rpc.DebugInfo", | |
| detail: | |
| "[ORIGINAL ERROR] generic::invalid_argument: invalid status photos.thumbnailer.Status.Code::5: Source image 0 too short", | |
| }, | |
| ], | |
| }, | |
| }), | |
| } as Response); | |
| const url = new FilesRequestUrl(RpcTask.GET, "key"); | |
| const headers = new Headers(); | |
| try { | |
| await makeServerRequest( | |
| url, | |
| headers, | |
| new Blob(), | |
| fetchStub as typeof fetch, | |
| ); | |
| } catch (e) { | |
| expect((e as GoogleGenerativeAIFetchError).message).to.match( | |
| /500 Server Error.*extra info.*generic::invalid_argument/, | |
| ); | |
| expect((e as GoogleGenerativeAIFetchError).status).to.equal(500); | |
| expect((e as GoogleGenerativeAIFetchError).statusText).to.equal( | |
| "Server Error", | |
| ); | |
| expect( | |
| (e as GoogleGenerativeAIFetchError).errorDetails[0].detail, | |
| ).to.include("generic::invalid_argument"); | |
| } | |
| expect(fetchStub).to.be.calledOnce; | |
| }); | |
| }); | |
| }); | |