diff --git a/src/Explorer/Tabs/DocumentsTabV2/DocumentsTabV2Mongo.test.tsx b/src/Explorer/Tabs/DocumentsTabV2/DocumentsTabV2Mongo.test.tsx
new file mode 100644
index 000000000..107407a8f
--- /dev/null
+++ b/src/Explorer/Tabs/DocumentsTabV2/DocumentsTabV2Mongo.test.tsx
@@ -0,0 +1,194 @@
+import { deleteDocument } 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",
+ }),
+ ),
+ deleteDocument: jest.fn(() => Promise.resolve()),
+}));
+
+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(),
+ })),
+ },
+}));
+
+async function waitForComponentToPaint
(wrapper: ReactWrapper
| ShallowWrapper
, 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("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: function (): void {
+ throw new Error("Function not implemented.");
+ },
+ onNewQueryClick: function (source: any, event?: MouseEvent, queryText?: string): void {
+ throw new Error("Function not implemented.");
+ },
+ expandCollection: function (): void {
+ throw new Error("Function not implemented.");
+ },
+ collapseCollection: function (): void {
+ throw new Error("Function not implemented.");
+ },
+ getDatabase: function (): 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();
+ wrapper = await waitForComponentToPaint(wrapper);
+ });
+
+ 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 asks for confirmation", () => {
+ const mockDeleteDocument = deleteDocument as jest.Mock;
+ mockDeleteDocument.mockClear();
+
+ act(() => {
+ useCommandBar
+ .getState()
+ .contextButtons.find((button) => button.id === DELETE_BUTTON_ID)
+ .onCommandClick(undefined);
+ });
+
+ expect(mockDeleteDocument).toHaveBeenCalled();
+ });
+ });
+});