mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-04-08 02:42:08 +01:00
* Upgrade typescript to 4.9.5 * Fix compile issue and put back files in tsconfig.strict.json * Update test snapshots * Fix jest tests by upgrading jest and other related packages. * Attempt to fix playwright test * Revert "Attempt to fix playwright test" This reverts commit 8293f34c9ce3901eb160a56526c59e3d3e1e343e. * 2nd attempt to fix example test * fix waitFor in playwright * Remove unused describe section * Attempt to fix e2e test * Revert "Attempt to fix e2e test" This reverts commit 9745bcd2efccf92e33e62e4563349cb76e6236de. * Upgrade playwright to latest * Revert "Upgrade playwright to latest" This reverts commit e2ea1d01895f9db157a92a5167a7865b7cc43266. * Error test on e2e * Revert "Error test on e2e" This reverts commit 124e3764f72fff70df9cc1a2e93d12faa7b507e9. * Try to select dropdown item by xpath selector * Revert "Try to select dropdown item by xpath selector" This reverts commit 8eb42a64e23cee589a7c0a809c039ecc7867b7ba. * Attempt to wait until page is fully loaded * Revert "Attempt to wait until page is fully loaded" This reverts commit bb43fcea6e71e593f7d1a3e374e9f1d57052ab70. * Use playwright selectOption to select dropdown option * Revert "Use playwright selectOption to select dropdown option" This reverts commit daa8cd09304f68093df2d94f4bd1139cb367465a. * Select dropdown option with playwright api instead of manual click * c7ab4c7ecf7b05f32a85568bce1a667ad8c62703Revert "Select dropdown option with playwright api instead of manual click" This reverts commit c7ab4c7ecf7b05f32a85568bce1a667ad8c62703. * Wait for 5s after dropdown click * Revert "Wait for 5s after dropdown click" This reverts commit 847e9ad33fbfac99a947fc088e1c8c1c14c57853. * Try forcing click * Revert "Try forcing click" This reverts commit 29b9fa1bda18dd3aba7853b20c6215d971bc826a. * Force click on the dropdown and set viewport size bigger. * Force click on the dropdown and set viewport size bigger. * try force clicking option * Skip container test on webkit * Add branded browsers to e2e tests --------- Co-authored-by: Ashley Stanton-Nurse <ashleyst@microsoft.com>
603 lines
21 KiB
TypeScript
603 lines
21 KiB
TypeScript
import { CapabilityNames } from "Common/Constants";
|
|
import { Platform, updateConfigContext } from "ConfigContext";
|
|
import { TreeNode } from "Explorer/Controls/TreeComponent/TreeNodeComponent";
|
|
import Explorer from "Explorer/Explorer";
|
|
import { useCommandBar } from "Explorer/Menus/CommandBar/CommandBarComponentAdapter";
|
|
import { useNotebook } from "Explorer/Notebook/useNotebook";
|
|
import { DeleteDatabaseConfirmationPanel } from "Explorer/Panes/DeleteDatabaseConfirmationPanel";
|
|
import TabsBase from "Explorer/Tabs/TabsBase";
|
|
import StoredProcedure from "Explorer/Tree/StoredProcedure";
|
|
import Trigger from "Explorer/Tree/Trigger";
|
|
import UserDefinedFunction from "Explorer/Tree/UserDefinedFunction";
|
|
import {
|
|
createDatabaseTreeNodes,
|
|
createResourceTokenTreeNodes,
|
|
createSampleDataTreeNodes,
|
|
} from "Explorer/Tree/treeNodeUtil";
|
|
import { useDatabases } from "Explorer/useDatabases";
|
|
import { useSelectedNode } from "Explorer/useSelectedNode";
|
|
import { updateUserContext } from "UserContext";
|
|
import PromiseSource from "Utils/PromiseSource";
|
|
import { useSidePanel } from "hooks/useSidePanel";
|
|
import { useTabs } from "hooks/useTabs";
|
|
import ko from "knockout";
|
|
import * as DataModels from "../../Contracts/DataModels";
|
|
import * as ViewModels from "../../Contracts/ViewModels";
|
|
|
|
jest.mock("Explorer/Explorer", () => {
|
|
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
|
|
class MockExplorer {
|
|
onNewCollectionClicked = jest.fn();
|
|
}
|
|
|
|
return MockExplorer;
|
|
});
|
|
|
|
jest.mock("Explorer/Tree/StoredProcedure", () => {
|
|
let counter = 0;
|
|
class MockStoredProcedure {
|
|
id: () => string;
|
|
open = jest.fn();
|
|
delete = jest.fn();
|
|
constructor() {
|
|
this.id = () => `mockSproc${counter}`;
|
|
counter++;
|
|
}
|
|
}
|
|
|
|
return MockStoredProcedure;
|
|
});
|
|
|
|
jest.mock("Explorer/Tree/UserDefinedFunction", () => {
|
|
let counter = 0;
|
|
class MockUserDefinedFunction {
|
|
id: () => string;
|
|
open = jest.fn();
|
|
delete = jest.fn();
|
|
constructor() {
|
|
this.id = () => `mockUdf${counter}`;
|
|
counter++;
|
|
}
|
|
}
|
|
|
|
return MockUserDefinedFunction;
|
|
});
|
|
|
|
jest.mock("Explorer/Tree/Trigger", () => {
|
|
let counter = 0;
|
|
class MockTrigger {
|
|
id: () => string;
|
|
open = jest.fn();
|
|
delete = jest.fn();
|
|
constructor() {
|
|
this.id = () => `mockTrigger${counter}`;
|
|
counter++;
|
|
}
|
|
}
|
|
|
|
return MockTrigger;
|
|
});
|
|
|
|
jest.mock("Common/DatabaseAccountUtility", () => {
|
|
return {
|
|
isPublicInternetAccessAllowed: () => true,
|
|
};
|
|
});
|
|
|
|
// Defining this value outside the mock, AND prefixing the name with 'mock' is required by Jest's mocking logic.
|
|
let nextTabIndex = 1;
|
|
class MockTab extends TabsBase {
|
|
constructor(tabOptions: Pick<ViewModels.TabOptions, "tabKind"> & Partial<ViewModels.TabOptions>) {
|
|
super({
|
|
title: `Mock Tab ${nextTabIndex}`,
|
|
tabPath: `mockTabs/tab${nextTabIndex}`,
|
|
...tabOptions,
|
|
} as ViewModels.TabOptions);
|
|
nextTabIndex++;
|
|
}
|
|
|
|
onActivate = jest.fn();
|
|
}
|
|
|
|
/** A basic test collection that can be expanded on in tests. */
|
|
const baseCollection = {
|
|
container: new Explorer(),
|
|
databaseId: "testDatabase",
|
|
id: ko.observable<string>("testCollection"),
|
|
defaultTtl: ko.observable<number>(5),
|
|
analyticalStorageTtl: ko.observable<number>(undefined),
|
|
selectedSubnodeKind: ko.observable<ViewModels.CollectionTabKind>(),
|
|
indexingPolicy: ko.observable<DataModels.IndexingPolicy>({
|
|
automatic: true,
|
|
indexingMode: "consistent",
|
|
includedPaths: [],
|
|
excludedPaths: [],
|
|
}),
|
|
uniqueKeyPolicy: {} as DataModels.UniqueKeyPolicy,
|
|
usageSizeInKB: ko.observable(100),
|
|
offer: ko.observable<DataModels.Offer>({
|
|
autoscaleMaxThroughput: undefined,
|
|
manualThroughput: 10000,
|
|
minimumThroughput: 6000,
|
|
id: "offer",
|
|
offerReplacePending: false,
|
|
}),
|
|
conflictResolutionPolicy: ko.observable<DataModels.ConflictResolutionPolicy>(
|
|
{} as DataModels.ConflictResolutionPolicy,
|
|
),
|
|
changeFeedPolicy: ko.observable<DataModels.ChangeFeedPolicy>({} as DataModels.ChangeFeedPolicy),
|
|
geospatialConfig: ko.observable<DataModels.GeospatialConfig>({} as DataModels.GeospatialConfig),
|
|
getDatabase: () => {},
|
|
partitionKey: {
|
|
paths: [],
|
|
kind: "hash",
|
|
version: 2,
|
|
},
|
|
storedProcedures: ko.observableArray([]),
|
|
userDefinedFunctions: ko.observableArray([]),
|
|
triggers: ko.observableArray([]),
|
|
partitionKeyProperties: ["testPartitionKey"],
|
|
readSettings: () => {},
|
|
isCollectionExpanded: ko.observable(true),
|
|
onSettingsClick: jest.fn(),
|
|
onDocumentDBDocumentsClick: jest.fn(),
|
|
onNewQueryClick: jest.fn(),
|
|
onConflictsClick: jest.fn(),
|
|
onSchemaAnalyzerClick: jest.fn(),
|
|
} as unknown as ViewModels.Collection;
|
|
|
|
/** A basic test database that can be expanded on in tests */
|
|
const baseDatabase = {
|
|
container: new Explorer(),
|
|
id: ko.observable<string>("testDatabase"),
|
|
collections: ko.observableArray<ViewModels.Collection>([]),
|
|
isDatabaseShared: ko.pureComputed(() => false),
|
|
isDatabaseExpanded: ko.observable(true),
|
|
selectedSubnodeKind: ko.observable<ViewModels.CollectionTabKind>(),
|
|
expandDatabase: jest.fn().mockResolvedValue({}),
|
|
collapseDatabase: jest.fn(),
|
|
onSettingsClick: jest.fn(),
|
|
} as unknown as ViewModels.Database;
|
|
|
|
/** Configures app state so that useSelectedNode.getState().isDataNodeSelected() returns true for the provided arguments. */
|
|
function selectDataNode(
|
|
node: ViewModels.Database | ViewModels.CollectionBase,
|
|
subnodeKind?: ViewModels.CollectionTabKind,
|
|
) {
|
|
useSelectedNode.getState().setSelectedNode(node);
|
|
|
|
if (subnodeKind !== undefined) {
|
|
node.selectedSubnodeKind(subnodeKind);
|
|
useTabs.getState().activateNewTab(new MockTab({ tabKind: subnodeKind, node }));
|
|
}
|
|
}
|
|
|
|
describe("createSampleDataTreeNodes", () => {
|
|
let sampleDataResourceTokenCollection: ViewModels.Collection;
|
|
let nodes: TreeNode[];
|
|
|
|
beforeEach(() => {
|
|
jest.resetAllMocks();
|
|
const collection = { ...baseCollection };
|
|
useDatabases.setState({ sampleDataResourceTokenCollection: collection });
|
|
useSelectedNode.setState({ selectedNode: undefined });
|
|
|
|
sampleDataResourceTokenCollection = collection;
|
|
nodes = createSampleDataTreeNodes(sampleDataResourceTokenCollection);
|
|
});
|
|
|
|
it("creates the expected tree nodes", () => {
|
|
expect(nodes).toMatchSnapshot();
|
|
});
|
|
});
|
|
|
|
describe("createResourceTokenTreeNodes", () => {
|
|
let resourceTokenCollection: ViewModels.Collection;
|
|
let nodes: TreeNode[];
|
|
|
|
beforeEach(() => {
|
|
jest.resetAllMocks();
|
|
const collection = { ...baseCollection };
|
|
useDatabases.setState({ resourceTokenCollection: collection });
|
|
useSelectedNode.setState({ selectedNode: undefined });
|
|
|
|
resourceTokenCollection = collection;
|
|
nodes = createResourceTokenTreeNodes(resourceTokenCollection);
|
|
});
|
|
|
|
it("returns an empty node when collection is undefined or null", () => {
|
|
const snapshot = `
|
|
[
|
|
{
|
|
"children": [],
|
|
"isExpanded": true,
|
|
"label": "",
|
|
},
|
|
]
|
|
`;
|
|
expect(createResourceTokenTreeNodes(undefined)).toMatchInlineSnapshot(snapshot);
|
|
expect(createResourceTokenTreeNodes(null)).toMatchInlineSnapshot(snapshot);
|
|
});
|
|
|
|
it("creates the expected tree nodes", () => {
|
|
expect(nodes).toMatchSnapshot();
|
|
});
|
|
});
|
|
|
|
describe("createDatabaseTreeNodes", () => {
|
|
let explorer: Explorer;
|
|
let standardDb: ViewModels.Database;
|
|
let sharedDb: ViewModels.Database;
|
|
let giganticDb: ViewModels.Database;
|
|
let standardCollection: ViewModels.Collection;
|
|
let sampleItemsCollection: ViewModels.Collection;
|
|
let schemaCollection: ViewModels.Collection;
|
|
let conflictsCollection: ViewModels.Collection;
|
|
let sproc: StoredProcedure;
|
|
let udf: UserDefinedFunction;
|
|
let trigger: Trigger;
|
|
let refreshActiveTab: (comparator: (tab: TabsBase) => boolean) => void;
|
|
|
|
beforeEach(() => {
|
|
jest.resetAllMocks();
|
|
explorer = new Explorer();
|
|
standardDb = {
|
|
...baseDatabase,
|
|
id: ko.observable("standardDb"),
|
|
container: explorer,
|
|
} as ViewModels.Database;
|
|
sharedDb = {
|
|
...baseDatabase,
|
|
id: ko.observable("sharedDatabase"),
|
|
container: explorer,
|
|
isDatabaseShared: ko.pureComputed(() => true),
|
|
} as ViewModels.Database;
|
|
giganticDb = {
|
|
...baseDatabase,
|
|
id: ko.observable("giganticDatabase"),
|
|
container: explorer,
|
|
collectionsContinuationToken: "continuationToken",
|
|
} as ViewModels.Database;
|
|
|
|
standardCollection = {
|
|
...baseCollection,
|
|
id: ko.observable("standardCollection"),
|
|
container: explorer,
|
|
databaseId: standardDb.id(),
|
|
} as ViewModels.Collection;
|
|
|
|
// These classes are mocked, so the constructor args don't matter
|
|
sproc = new StoredProcedure(explorer, standardCollection, {} as never);
|
|
standardCollection.storedProcedures = ko.pureComputed(() => [sproc]);
|
|
udf = new UserDefinedFunction(explorer, standardCollection, {} as never);
|
|
standardCollection.userDefinedFunctions = ko.pureComputed(() => [udf]);
|
|
trigger = new Trigger(explorer, standardCollection, {} as never);
|
|
standardCollection.triggers = ko.pureComputed(() => [trigger]);
|
|
|
|
sampleItemsCollection = {
|
|
...baseCollection,
|
|
id: ko.observable("sampleItemsCollection"),
|
|
container: explorer,
|
|
databaseId: sharedDb.id(),
|
|
isSampleCollection: true,
|
|
} as ViewModels.Collection;
|
|
|
|
schemaCollection = {
|
|
...baseCollection,
|
|
id: ko.observable("schemaCollection"),
|
|
container: explorer,
|
|
databaseId: sharedDb.id(),
|
|
analyticalStorageTtl: ko.observable<number>(5),
|
|
schema: {
|
|
fields: [
|
|
{
|
|
path: "address.street",
|
|
dataType: { name: "string" },
|
|
hasNulls: false,
|
|
},
|
|
{
|
|
path: "address.line2",
|
|
dataType: { name: "string" },
|
|
hasNulls: true,
|
|
},
|
|
{
|
|
path: "address.zip",
|
|
dataType: { name: "number" },
|
|
hasNulls: false,
|
|
},
|
|
{
|
|
path: "orderId",
|
|
dataType: { name: "string" },
|
|
hasNulls: false,
|
|
},
|
|
],
|
|
} as unknown,
|
|
} as ViewModels.Collection;
|
|
|
|
conflictsCollection = {
|
|
...baseCollection,
|
|
id: ko.observable("conflictsCollection"),
|
|
rawDataModel: {
|
|
conflictResolutionPolicy: {
|
|
mode: "Custom",
|
|
conflictResolutionPath: "path",
|
|
conflictResolutionProcedure: "proc",
|
|
},
|
|
},
|
|
} as ViewModels.Collection;
|
|
|
|
standardDb.collections = ko.observableArray([standardCollection, conflictsCollection]);
|
|
sharedDb.collections = ko.observableArray([sampleItemsCollection]);
|
|
giganticDb.collections = ko.observableArray([schemaCollection]);
|
|
|
|
useDatabases.setState({
|
|
databases: [standardDb, sharedDb, giganticDb],
|
|
updateDatabase: jest.fn(),
|
|
});
|
|
useSelectedNode.setState({ selectedNode: undefined });
|
|
|
|
refreshActiveTab = jest.fn();
|
|
});
|
|
|
|
describe("using NoSQL API on Hosted Platform", () => {
|
|
let nodes: TreeNode[];
|
|
beforeEach(() => {
|
|
updateConfigContext({
|
|
platform: Platform.Hosted,
|
|
});
|
|
updateUserContext({
|
|
databaseAccount: {
|
|
properties: {
|
|
capabilities: [],
|
|
},
|
|
} as never,
|
|
});
|
|
nodes = createDatabaseTreeNodes(explorer, false, useDatabases.getState().databases, refreshActiveTab);
|
|
});
|
|
|
|
it("creates expected tree", () => {
|
|
expect(nodes).toMatchSnapshot();
|
|
});
|
|
});
|
|
|
|
it.each<[string, Platform, boolean, Partial<DataModels.DatabaseAccountExtendedProperties>]>([
|
|
["the SQL API, on Fabric", Platform.Fabric, false, { capabilities: [], enableMultipleWriteLocations: true }],
|
|
["the SQL API, on Portal", Platform.Portal, false, { capabilities: [], enableMultipleWriteLocations: true }],
|
|
[
|
|
"the Cassandra API, serverless, on Hosted",
|
|
Platform.Hosted,
|
|
false,
|
|
{
|
|
capabilities: [
|
|
{ name: CapabilityNames.EnableCassandra, description: "" },
|
|
{ name: CapabilityNames.EnableServerless, description: "" },
|
|
],
|
|
},
|
|
],
|
|
[
|
|
"the Mongo API, with Notebooks and Phoenix features, on Emulator",
|
|
Platform.Emulator,
|
|
true,
|
|
{
|
|
capabilities: [{ name: CapabilityNames.EnableMongo, description: "" }],
|
|
},
|
|
],
|
|
])("generates the correct tree structure for %s", (_, platform, isNotebookEnabled, dbAccountProperties) => {
|
|
useNotebook.setState({ isPhoenixFeatures: isNotebookEnabled });
|
|
updateConfigContext({ platform });
|
|
updateUserContext({
|
|
databaseAccount: {
|
|
properties: {
|
|
enableMultipleWriteLocations: true,
|
|
...dbAccountProperties,
|
|
},
|
|
} as unknown as DataModels.DatabaseAccount,
|
|
});
|
|
const nodes = createDatabaseTreeNodes(
|
|
explorer,
|
|
isNotebookEnabled,
|
|
useDatabases.getState().databases,
|
|
refreshActiveTab,
|
|
);
|
|
expect(nodes).toMatchSnapshot();
|
|
});
|
|
|
|
// The above tests focused on the tree structure. The below tests focus on some core behaviors of the nodes.
|
|
// They are not exhaustive, because exhaustive tests here require a lot of mocking and can become very brittle.
|
|
// The goal is to cover some key behaviors like loading child nodes, opening tabs/side panels, etc.
|
|
|
|
it("adds new collections to database as they appear", () => {
|
|
const nodes = createDatabaseTreeNodes(explorer, false, useDatabases.getState().databases, refreshActiveTab);
|
|
const giganticDbNode = nodes.find((node) => node.label === giganticDb.id());
|
|
expect(giganticDbNode).toBeDefined();
|
|
expect(giganticDbNode.children.map((node) => node.label)).toStrictEqual(["schemaCollection", "load more"]);
|
|
|
|
giganticDb.collections.push({
|
|
...baseCollection,
|
|
id: ko.observable("addedCollection"),
|
|
});
|
|
|
|
expect(giganticDbNode.children.map((node) => node.label)).toStrictEqual([
|
|
"schemaCollection",
|
|
"addedCollection",
|
|
"load more",
|
|
]);
|
|
});
|
|
|
|
describe("the database node", () => {
|
|
let nodes: TreeNode[];
|
|
let standardDbNode: TreeNode;
|
|
let sharedDbNode: TreeNode;
|
|
let giganticDbNode: TreeNode;
|
|
|
|
beforeEach(() => {
|
|
updateConfigContext({ platform: Platform.Hosted });
|
|
updateUserContext({
|
|
databaseAccount: {
|
|
properties: {
|
|
capabilities: [],
|
|
},
|
|
} as unknown as DataModels.DatabaseAccount,
|
|
});
|
|
nodes = createDatabaseTreeNodes(explorer, false, useDatabases.getState().databases, refreshActiveTab);
|
|
standardDbNode = nodes.find((node) => node.label === standardDb.id());
|
|
sharedDbNode = nodes.find((node) => node.label === sharedDb.id());
|
|
giganticDbNode = nodes.find((node) => node.label === giganticDb.id());
|
|
});
|
|
|
|
it("loads child nodes when expanded", async () => {
|
|
// Temporarily clear the child nodes to trigger the loading behavior
|
|
standardDbNode.children = [];
|
|
|
|
const expanding = new PromiseSource();
|
|
let expandCalled = false;
|
|
standardDb.expandDatabase = () => {
|
|
expandCalled = true;
|
|
return expanding.promise;
|
|
};
|
|
|
|
standardDbNode.onExpanded();
|
|
expect(useSelectedNode.getState().selectedNode).toBe(standardDb);
|
|
expect(standardDbNode.isLoading).toStrictEqual(true);
|
|
expect(expandCalled).toStrictEqual(true);
|
|
|
|
await expanding.resolveAndWait();
|
|
|
|
expect(standardDbNode.isLoading).toStrictEqual(false);
|
|
expect(useCommandBar.getState().contextButtons).toStrictEqual([]);
|
|
expect(refreshActiveTab).toHaveBeenCalled();
|
|
expect(useDatabases.getState().updateDatabase).toHaveBeenCalledWith(standardDb);
|
|
});
|
|
|
|
it("opens a New Container panel when 'New Container' option in context menu is clicked", () => {
|
|
const newContainerMenuItem = standardDbNode.contextMenu.find((item) => item.label === "New Container");
|
|
newContainerMenuItem.onClick();
|
|
expect(explorer.onNewCollectionClicked).toHaveBeenCalled();
|
|
});
|
|
|
|
it("opens a Delete Database panel when 'Delete Database' option in context menu is clicked", () => {
|
|
const deleteDatabaseMenuItem = standardDbNode.contextMenu.find((item) => item.label === "Delete Database");
|
|
deleteDatabaseMenuItem.onClick();
|
|
expect(useSidePanel.getState().headerText).toStrictEqual("Delete Database");
|
|
expect(useSidePanel.getState().panelContent.type).toStrictEqual(DeleteDatabaseConfirmationPanel);
|
|
});
|
|
|
|
describe("the Scale subnode", () => {
|
|
let scaleNode: TreeNode;
|
|
beforeEach(() => {
|
|
scaleNode = sharedDbNode.children.find((node) => node.label === "Scale");
|
|
});
|
|
|
|
it("is selected when Scale tab is open", () => {
|
|
expect(scaleNode.isSelected()).toStrictEqual(false);
|
|
selectDataNode(sharedDb, ViewModels.CollectionTabKind.DatabaseSettingsV2);
|
|
expect(scaleNode.isSelected()).toStrictEqual(true);
|
|
});
|
|
|
|
it("opens settings tab when clicked", () => {
|
|
expect(sharedDb.onSettingsClick).not.toHaveBeenCalled();
|
|
scaleNode.onClick();
|
|
expect(sharedDb.onSettingsClick).toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe("the load more node", () => {
|
|
it("loads more collections when clicked", async () => {
|
|
const loadCollections = new PromiseSource();
|
|
let loadCalled = false;
|
|
giganticDb.loadCollections = () => {
|
|
loadCalled = true;
|
|
return loadCollections.promise;
|
|
};
|
|
|
|
const loadMoreNode = giganticDbNode.children.find((node) => node.label === "load more");
|
|
loadMoreNode.onClick();
|
|
expect(loadCalled).toStrictEqual(true);
|
|
await loadCollections.resolveAndWait();
|
|
expect(useDatabases.getState().updateDatabase).toHaveBeenCalledWith(giganticDb);
|
|
});
|
|
});
|
|
|
|
describe("the Collection subnode", () => {
|
|
let standardCollectionNode: TreeNode;
|
|
beforeEach(() => {
|
|
standardCollectionNode = standardDbNode.children.find((node) => node.label === standardCollection.id());
|
|
});
|
|
|
|
it.each([
|
|
[
|
|
"for SQL API",
|
|
() => updateUserContext({ databaseAccount: { properties: {} } as unknown as DataModels.DatabaseAccount }),
|
|
],
|
|
[
|
|
"for Gremlin API",
|
|
() =>
|
|
updateUserContext({
|
|
databaseAccount: {
|
|
properties: { capabilities: [{ name: CapabilityNames.EnableGremlin, description: "" }] },
|
|
} as unknown as DataModels.DatabaseAccount,
|
|
}),
|
|
],
|
|
])("loads sprocs/udfs/triggers when expanded, %s", async () => {
|
|
standardCollection.loadStoredProcedures = jest.fn(() => Promise.resolve());
|
|
standardCollection.loadUserDefinedFunctions = jest.fn(() => Promise.resolve());
|
|
standardCollection.loadTriggers = jest.fn(() => Promise.resolve());
|
|
|
|
await standardCollectionNode.onExpanded();
|
|
|
|
expect(standardCollection.loadStoredProcedures).toHaveBeenCalled();
|
|
expect(standardCollection.loadUserDefinedFunctions).toHaveBeenCalled();
|
|
expect(standardCollection.loadTriggers).toHaveBeenCalled();
|
|
});
|
|
|
|
it.each([
|
|
["in Fabric", () => updateConfigContext({ platform: Platform.Fabric })],
|
|
[
|
|
"for Cassandra API",
|
|
() =>
|
|
updateUserContext({
|
|
databaseAccount: {
|
|
properties: { capabilities: [{ name: CapabilityNames.EnableCassandra, description: "" }] },
|
|
} as unknown as DataModels.DatabaseAccount,
|
|
}),
|
|
],
|
|
[
|
|
"for Mongo API",
|
|
() =>
|
|
updateUserContext({
|
|
databaseAccount: {
|
|
properties: { capabilities: [{ name: CapabilityNames.EnableMongo, description: "" }] },
|
|
} as unknown as DataModels.DatabaseAccount,
|
|
}),
|
|
],
|
|
[
|
|
"for Tables API",
|
|
() =>
|
|
updateUserContext({
|
|
databaseAccount: {
|
|
properties: { capabilities: [{ name: CapabilityNames.EnableTable, description: "" }] },
|
|
} as unknown as DataModels.DatabaseAccount,
|
|
}),
|
|
],
|
|
])("does not load sprocs/udfs/triggers when expanded, %s", async (_, setup) => {
|
|
setup();
|
|
|
|
// Rebuild the nodes after changing the user/config context.
|
|
nodes = createDatabaseTreeNodes(explorer, false, useDatabases.getState().databases, refreshActiveTab);
|
|
standardDbNode = nodes.find((node) => node.label === standardDb.id());
|
|
standardCollectionNode = standardDbNode.children.find((node) => node.label === standardCollection.id());
|
|
|
|
standardCollection.loadStoredProcedures = jest.fn(() => Promise.resolve());
|
|
standardCollection.loadUserDefinedFunctions = jest.fn(() => Promise.resolve());
|
|
standardCollection.loadTriggers = jest.fn(() => Promise.resolve());
|
|
|
|
await standardCollectionNode.onExpanded();
|
|
|
|
expect(standardCollection.loadStoredProcedures).not.toHaveBeenCalled();
|
|
expect(standardCollection.loadUserDefinedFunctions).not.toHaveBeenCalled();
|
|
expect(standardCollection.loadTriggers).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
});
|
|
});
|