mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-19 17:01:13 +00:00
Initial Move from Azure DevOps to GitHub
This commit is contained in:
266
src/Explorer/Graph/GraphExplorerComponent/GremlinClient.test.ts
Normal file
266
src/Explorer/Graph/GraphExplorerComponent/GremlinClient.test.ts
Normal file
@@ -0,0 +1,266 @@
|
||||
import * as sinon from "sinon";
|
||||
import { GremlinClient, GremlinClientParameters } from "./GremlinClient";
|
||||
import { NotificationConsoleUtils } from "../../../Utils/NotificationConsoleUtils";
|
||||
import { 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, "logConsoleMessage");
|
||||
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, "logConsoleMessage");
|
||||
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, "logConsoleMessage");
|
||||
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
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user