2020-11-03 13:40:44 -08:00

267 lines
8.3 KiB
TypeScript

import * as sinon from "sinon";
import { GremlinClient, GremlinClientParameters } from "./GremlinClient";
import * as NotificationConsoleUtils from "../../../Utils/NotificationConsoleUtils";
import * as Logger from "../../../Common/Logger";
describe("Gremlin Client", () => {
const emptyParams: GremlinClientParameters = {
endpoint: null,
collectionId: null,
databaseId: null,
masterKey: null,
maxResultSize: 10000
};
it("should use databaseId, collectionId and masterKey to authenticate", () => {
const collectionId = "collectionId";
const databaseId = "databaseId";
const masterKey = "masterKey";
const gremlinClient = new GremlinClient();
gremlinClient.initialize({
endpoint: null,
collectionId,
databaseId,
masterKey,
maxResultSize: 0
});
// User must includes these values
expect(gremlinClient.client.params.user.indexOf(collectionId)).not.toBe(-1);
expect(gremlinClient.client.params.user.indexOf(databaseId)).not.toBe(-1);
expect(gremlinClient.client.params.password).toEqual(masterKey);
});
it("should aggregate RU charges across multiple responses", done => {
const gremlinClient = new GremlinClient();
const ru1 = 1;
const ru2 = 2;
const ru3 = 3;
const requestId = "id";
gremlinClient.initialize(emptyParams);
sinon.stub(gremlinClient.client, "executeGremlinQuery").callsFake((query: string): string => requestId);
gremlinClient
.execute("fake query")
.then(result => expect(result.totalRequestCharge).toBe(ru1 + ru2 + ru3))
.finally(done);
gremlinClient.client.params.progressCallback({
data: ["data1"],
requestCharge: ru1,
requestId: requestId
});
gremlinClient.client.params.progressCallback({
data: ["data2"],
requestCharge: ru2,
requestId: requestId
});
gremlinClient.client.params.successCallback({
data: ["data3"],
requestCharge: ru3,
requestId: requestId
});
});
it("should keep track of pending requests", () => {
const gremlinClient = new GremlinClient();
const fakeRequestIds = ["id1", "id2", "id3"];
gremlinClient.initialize(emptyParams);
sinon.stub(gremlinClient.client, "executeGremlinQuery").callsFake((query: string): string => fakeRequestIds.pop());
gremlinClient.execute("fake query");
gremlinClient.execute("fake query");
gremlinClient.execute("fake query");
expect(gremlinClient.pendingResults.size()).toBe(3);
});
it("should clean up pending request ids after success", async () => {
const gremlinClient = new GremlinClient();
const ru1 = 1;
gremlinClient.initialize(emptyParams);
sinon.stub(gremlinClient.client, "executeGremlinQuery").callsFake((query: string): string => {
const requestId = "id";
setTimeout(() => {
gremlinClient.client.params.successCallback({
data: ["data1"],
requestCharge: ru1,
requestId: requestId
});
}, 0);
return requestId;
});
await gremlinClient.execute("fake query");
expect(gremlinClient.pendingResults.size()).toBe(0);
});
it("should log and display error out on unknown requestId", () => {
const gremlinClient = new GremlinClient();
const logConsoleSpy = sinon.spy(NotificationConsoleUtils, "logConsoleError");
const logErrorSpy = sinon.spy(Logger, "logError");
gremlinClient.initialize(emptyParams);
sinon.stub(gremlinClient.client, "executeGremlinQuery").callsFake((query: string): string => "requestId");
gremlinClient.execute("fake query");
gremlinClient.client.params.successCallback({
data: ["data1"],
requestCharge: 1,
requestId: "unknownId"
});
expect(logConsoleSpy.called).toBe(true);
expect(logErrorSpy.called).toBe(true);
logConsoleSpy.restore();
logErrorSpy.restore();
});
it("should not display RU if null or undefined", () => {
const emptyResult = "";
expect(GremlinClient.getRequestChargeString(null)).toEqual(emptyResult);
expect(GremlinClient.getRequestChargeString(undefined)).toEqual(emptyResult);
expect(GremlinClient.getRequestChargeString(123)).not.toEqual(emptyResult);
expect(GremlinClient.getRequestChargeString("123")).not.toEqual(emptyResult);
});
it("should not aggregate RU if not a number and reset totalRequestCharge to undefined", done => {
const logConsoleSpy = sinon.spy(NotificationConsoleUtils, "logConsoleError");
const logErrorSpy = sinon.spy(Logger, "logError");
const gremlinClient = new GremlinClient();
const ru1 = 123;
const ru2 = "should be a number";
const requestId = "id";
gremlinClient.initialize(emptyParams);
sinon.stub(gremlinClient.client, "executeGremlinQuery").callsFake((query: string): string => requestId);
gremlinClient
.execute("fake query")
.then(
result => {
try {
expect(result.totalRequestCharge).toBe(undefined);
expect(logConsoleSpy.called).toBe(true);
expect(logErrorSpy.called).toBe(true);
done();
} catch (e) {
done(e);
}
},
error => done.fail(error)
)
.finally(() => {
logConsoleSpy.restore();
logErrorSpy.restore();
});
gremlinClient.client.params.progressCallback({
data: ["data1"],
requestCharge: ru1,
requestId: requestId
});
gremlinClient.client.params.successCallback({
data: ["data2"],
requestCharge: ru2 as any,
requestId: requestId
});
});
it("should not aggregate RU if undefined and reset totalRequestCharge to undefined", done => {
const logConsoleSpy = sinon.spy(NotificationConsoleUtils, "logConsoleError");
const logErrorSpy = sinon.spy(Logger, "logError");
const gremlinClient = new GremlinClient();
const ru1 = 123;
const ru2: number = undefined;
const requestId = "id";
gremlinClient.initialize(emptyParams);
sinon.stub(gremlinClient.client, "executeGremlinQuery").callsFake((query: string): string => requestId);
gremlinClient
.execute("fake query")
.then(
result => {
try {
expect(result.totalRequestCharge).toBe(undefined);
expect(logConsoleSpy.called).toBe(true);
expect(logErrorSpy.called).toBe(true);
done();
} catch (e) {
done(e);
}
},
error => done.fail(error)
)
.finally(() => {
logConsoleSpy.restore();
logErrorSpy.restore();
});
gremlinClient.client.params.progressCallback({
data: ["data1"],
requestCharge: ru1,
requestId: requestId
});
gremlinClient.client.params.successCallback({
data: ["data2"],
requestCharge: ru2,
requestId: requestId
});
});
it("should track RUs even on failure", done => {
const gremlinClient = new GremlinClient();
const requestId = "id";
const RU = 1234;
const error = "Some error";
gremlinClient.initialize(emptyParams);
sinon.stub(gremlinClient.client, "executeGremlinQuery").callsFake((query: string): string => requestId);
const abortPendingRequestSpy = sinon.spy(gremlinClient, "abortPendingRequest");
gremlinClient.execute("fake query").then(
result => done.fail(`Unexpectedly succeeded with ${result}`),
error => {
try {
expect(abortPendingRequestSpy.calledWith(requestId, error, RU)).toBe(true);
done();
} catch (e) {
done(e);
}
}
);
gremlinClient.client.params.failureCallback(
{
data: null,
requestCharge: RU,
requestId: requestId
},
error
);
});
it("should abort all pending requests if requestId from failure response", done => {
const gremlinClient = new GremlinClient();
const requestId = "id";
const error = "Some error";
gremlinClient.initialize(emptyParams);
sinon.stub(gremlinClient.client, "executeGremlinQuery").callsFake((query: string): string => requestId);
gremlinClient.execute("fake query").finally(() => {
try {
expect(gremlinClient.pendingResults.size()).toBe(0);
done();
} catch (e) {
done(e);
}
});
gremlinClient.client.params.failureCallback(
{
data: null,
requestCharge: undefined,
requestId: undefined
},
error
);
});
});