Files
cosmos-explorer/src/Explorer/Tabs/DocumentsTabV2/DocumentsTabV2Mongo.test.tsx
BChoudhury-ms 76e63818d3 Enable RBAC support for MongoDB and Cassandra APIs (#2198)
* enable RBAC support for Mongo & Cassandra API

* fix formatting issue

* Handling AAD integration for Mongo Shell

* remove empty aadToken error

* fix formatting issue

* added environment specific scope endpoints
2025-09-19 01:25:35 +05:30

211 lines
6.7 KiB
TypeScript

import { deleteDocuments } from "Common/MongoProxyClient";
import { Platform, updateConfigContext } from "ConfigContext";
import { EditorReactProps } from "Explorer/Controls/Editor/EditorReact";
import { useCommandBar } from "Explorer/Menus/CommandBar/CommandBarComponentAdapter";
import {
DELETE_BUTTON_ID,
DISCARD_BUTTON_ID,
DocumentsTabComponent,
IDocumentsTabComponentProps,
NEW_DOCUMENT_BUTTON_ID,
SAVE_BUTTON_ID,
UPDATE_BUTTON_ID,
buildQuery,
} from "Explorer/Tabs/DocumentsTabV2/DocumentsTabV2";
import { ReactWrapper, ShallowWrapper, mount } from "enzyme";
import * as ko from "knockout";
import React from "react";
import { act } from "react-dom/test-utils";
import * as ViewModels from "../../../Contracts/ViewModels";
import Explorer from "../../Explorer";
jest.requireActual("Explorer/Controls/Editor/EditorReact");
const PROPERTY_VALUE = "__SOME_PROPERTY_VALUE__";
jest.mock("Common/MongoProxyClient", () => ({
queryDocuments: jest.fn(() =>
Promise.resolve({
continuationToken: "",
documents: [
{
_rid: "_rid",
_self: "_self",
_etag: "etag",
_ts: 1234,
id: "id",
},
],
headers: {},
}),
),
readDocument: jest.fn(() =>
Promise.resolve({
_rid: "_rid1",
_self: "_self1",
_etag: "etag1",
property: PROPERTY_VALUE,
_ts: 5678,
id: "id1",
}),
),
deleteDocuments: jest.fn(() => Promise.resolve({ deleteCount: 0, isAcknowledged: true })),
ThrottlingError: Error,
useMongoProxyEndpoint: jest.fn(() => true),
}));
jest.mock("Explorer/Controls/Editor/EditorReact", () => ({
EditorReact: (props: EditorReactProps) => <>{props.content}</>,
}));
jest.mock("Explorer/Controls/Dialog", () => ({
useDialog: {
getState: jest.fn(() => ({
showOkCancelModalDialog: (title: string, subText: string, okLabel: string, onOk: () => void) => onOk(),
showOkModalDialog: () => {},
})),
},
}));
// Added as recent change to @azure/core-util would cause randomUUID() to throw an error during jest tests.
// TODO: when not using beta version of @azure/cosmos sdk try removing this
jest.mock("@azure/core-util", () => ({
...jest.requireActual("@azure/core-util"),
randomUUID: jest.fn(),
}));
async function waitForComponentToPaint<P = unknown>(wrapper: ReactWrapper<P> | ShallowWrapper<P>, amount = 0) {
let newWrapper;
await act(async () => {
await new Promise((resolve) => setTimeout(resolve, amount));
newWrapper = wrapper.update();
});
return newWrapper;
}
describe("Documents tab (Mongo API)", () => {
describe("buildQuery", () => {
it("should generate the right select query for SQL API", () => {
expect(buildQuery(true, "")).toContain("{}");
});
});
describe("Command bar buttons", () => {
const createMockProps = (): IDocumentsTabComponentProps => ({
isPreferredApiMongoDB: true,
documentIds: [],
collection: {
id: ko.observable<string>("foo"),
container: new Explorer(),
partitionKey: {
kind: "Hash",
paths: ["/pkey"],
version: 2,
},
partitionKeyProperties: ["pkey"],
partitionKeyPropertyHeaders: ["/pkey"],
databaseId: "databaseId",
self: "self",
rawDataModel: undefined,
selectedSubnodeKind: undefined,
children: undefined,
isCollectionExpanded: undefined,
onDocumentDBDocumentsClick: (): void => {
throw new Error("Function not implemented.");
},
onNewQueryClick: (): void => {
throw new Error("Function not implemented.");
},
expandCollection: (): void => {
throw new Error("Function not implemented.");
},
collapseCollection: (): void => {
throw new Error("Function not implemented.");
},
getDatabase: (): ViewModels.Database => {
throw new Error("Function not implemented.");
},
nodeKind: "nodeKind",
rid: "rid",
},
partitionKey: undefined,
onLoadStartKey: 0,
tabTitle: "",
onExecutionErrorChange: (isExecutionError: boolean): void => {
isExecutionError;
},
onIsExecutingChange: (isExecuting: boolean): void => {
isExecuting;
},
isTabActive: true,
});
let wrapper: ReactWrapper;
beforeEach(async () => {
updateConfigContext({ platform: Platform.Hosted });
const props: IDocumentsTabComponentProps = createMockProps();
wrapper = mount(<DocumentsTabComponent {...props} />);
// Wait for all pending promises
await act(async () => {
await new Promise((resolve) => setTimeout(resolve, 100));
});
// Wait for any async operations to complete
wrapper = await waitForComponentToPaint(wrapper, 100);
}, 10000);
afterEach(() => {
wrapper.unmount();
});
it("renders by default the first document", async () => {
expect(wrapper.findWhere((node) => node.text().includes(PROPERTY_VALUE)).exists()).toBeTruthy();
});
it("default buttons", async () => {
expect(useCommandBar.getState().contextButtons.find((button) => button.id === UPDATE_BUTTON_ID)).toBeDefined();
expect(useCommandBar.getState().contextButtons.find((button) => button.id === DISCARD_BUTTON_ID)).toBeDefined();
expect(useCommandBar.getState().contextButtons.find((button) => button.id === DELETE_BUTTON_ID)).toBeDefined();
});
it("clicking on New Document should show editor with new document", () => {
act(() => {
useCommandBar
.getState()
.contextButtons.find((button) => button.id === NEW_DOCUMENT_BUTTON_ID)
.onCommandClick(undefined);
});
expect(wrapper.findWhere((node) => node.text().includes("replace_with_new_document_id")).exists()).toBeTruthy();
});
it("clicking on New Document should show Save and Discard buttons", () => {
act(() => {
useCommandBar
.getState()
.contextButtons.find((button) => button.id === NEW_DOCUMENT_BUTTON_ID)
.onCommandClick(undefined);
});
expect(useCommandBar.getState().contextButtons.find((button) => button.id === SAVE_BUTTON_ID)).toBeDefined();
expect(useCommandBar.getState().contextButtons.find((button) => button.id === DISCARD_BUTTON_ID)).toBeDefined();
});
it("clicking Delete Document eventually calls delete client api", () => {
const mockDeleteDocuments = deleteDocuments as jest.Mock;
mockDeleteDocuments.mockClear();
act(() => {
useCommandBar
.getState()
.contextButtons.find((button) => button.id === DELETE_BUTTON_ID)
.onCommandClick(undefined);
});
expect(mockDeleteDocuments).toHaveBeenCalled();
});
});
});