mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-27 12:51:41 +00:00
With this change TabsBase objects will retain a reference to the TabsManager they belong to, so they can ask it if they're the active tab or not. This removes the possibility for bugs like activating an unmanaged tab, or having more than one active tab, etc.
254 lines
10 KiB
TypeScript
254 lines
10 KiB
TypeScript
import { shallow } from "enzyme";
|
|
import ko from "knockout";
|
|
import React from "react";
|
|
import { updateCollection } from "../../../Common/dataAccess/updateCollection";
|
|
import { updateOffer } from "../../../Common/dataAccess/updateOffer";
|
|
import * as DataModels from "../../../Contracts/DataModels";
|
|
import * as ViewModels from "../../../Contracts/ViewModels";
|
|
import { updateUserContext } from "../../../UserContext";
|
|
import Explorer from "../../Explorer";
|
|
import { CollectionSettingsTabV2 } from "../../Tabs/SettingsTabV2";
|
|
import { SettingsComponent, SettingsComponentProps, SettingsComponentState } from "./SettingsComponent";
|
|
import { isDirty, TtlType } from "./SettingsUtils";
|
|
import { collection } from "./TestUtils";
|
|
jest.mock("../../../Common/dataAccess/getIndexTransformationProgress", () => ({
|
|
getIndexTransformationProgress: jest.fn().mockReturnValue(undefined),
|
|
}));
|
|
jest.mock("../../../Common/dataAccess/updateCollection", () => ({
|
|
updateCollection: jest.fn().mockReturnValue({
|
|
id: undefined,
|
|
defaultTtl: undefined,
|
|
indexingPolicy: undefined,
|
|
conflictResolutionPolicy: undefined,
|
|
changeFeedPolicy: undefined,
|
|
analyticalStorageTtl: undefined,
|
|
geospatialConfig: undefined,
|
|
indexes: [],
|
|
}),
|
|
}));
|
|
jest.mock("../../../Common/dataAccess/updateOffer", () => ({
|
|
updateOffer: jest.fn().mockReturnValue({} as DataModels.Offer),
|
|
}));
|
|
|
|
describe("SettingsComponent", () => {
|
|
const baseProps: SettingsComponentProps = {
|
|
settingsTab: new CollectionSettingsTabV2({
|
|
collection: collection,
|
|
tabKind: ViewModels.CollectionTabKind.CollectionSettingsV2,
|
|
title: "Scale & Settings",
|
|
tabPath: "",
|
|
node: undefined,
|
|
hashLocation: "settings",
|
|
onUpdateTabsButtons: undefined,
|
|
}),
|
|
};
|
|
|
|
it("renders", () => {
|
|
const wrapper = shallow(<SettingsComponent {...baseProps} />);
|
|
expect(wrapper).toMatchSnapshot();
|
|
});
|
|
|
|
it("dirty value enables save button and discard button", () => {
|
|
const wrapper = shallow(<SettingsComponent {...baseProps} />);
|
|
const settingsComponentInstance = wrapper.instance() as SettingsComponent;
|
|
expect(settingsComponentInstance.isSaveSettingsButtonEnabled()).toEqual(false);
|
|
expect(settingsComponentInstance.isDiscardSettingsButtonEnabled()).toEqual(false);
|
|
wrapper.setState({ isScaleSaveable: true, isScaleDiscardable: true });
|
|
wrapper.update();
|
|
expect(settingsComponentInstance.isSaveSettingsButtonEnabled()).toEqual(true);
|
|
expect(settingsComponentInstance.isDiscardSettingsButtonEnabled()).toEqual(true);
|
|
wrapper.setState({
|
|
isScaleSaveable: false,
|
|
isScaleDiscardable: false,
|
|
isSubSettingsSaveable: true,
|
|
isSubSettingsDiscardable: true,
|
|
});
|
|
wrapper.update();
|
|
expect(settingsComponentInstance.isSaveSettingsButtonEnabled()).toEqual(true);
|
|
expect(settingsComponentInstance.isDiscardSettingsButtonEnabled()).toEqual(true);
|
|
wrapper.setState({ isSubSettingsSaveable: false, isSubSettingsDiscardable: false, isIndexingPolicyDirty: true });
|
|
wrapper.update();
|
|
expect(settingsComponentInstance.isSaveSettingsButtonEnabled()).toEqual(true);
|
|
expect(settingsComponentInstance.isDiscardSettingsButtonEnabled()).toEqual(true);
|
|
wrapper.setState({ isIndexingPolicyDirty: false, isConflictResolutionDirty: true });
|
|
wrapper.update();
|
|
expect(settingsComponentInstance.isSaveSettingsButtonEnabled()).toEqual(true);
|
|
expect(settingsComponentInstance.isDiscardSettingsButtonEnabled()).toEqual(true);
|
|
});
|
|
|
|
it("auto pilot helper functions pass on correct value", () => {
|
|
const newCollection = { ...collection };
|
|
newCollection.offer = ko.observable<DataModels.Offer>({
|
|
autoscaleMaxThroughput: 10000,
|
|
manualThroughput: undefined,
|
|
minimumThroughput: 400,
|
|
id: "test",
|
|
offerReplacePending: false,
|
|
});
|
|
|
|
const props = { ...baseProps };
|
|
props.settingsTab.collection = newCollection;
|
|
|
|
const wrapper = shallow(<SettingsComponent {...props} />);
|
|
const settingsComponentInstance = wrapper.instance() as SettingsComponent;
|
|
expect(settingsComponentInstance.hasProvisioningTypeChanged()).toEqual(false);
|
|
wrapper.setState({
|
|
userCanChangeProvisioningTypes: true,
|
|
isAutoPilotSelected: true,
|
|
wasAutopilotOriginallySet: false,
|
|
autoPilotThroughput: 1000,
|
|
});
|
|
wrapper.update();
|
|
expect(settingsComponentInstance.hasProvisioningTypeChanged()).toEqual(true);
|
|
});
|
|
|
|
it("shouldShowKeyspaceSharedThroughputMessage", () => {
|
|
let settingsComponentInstance = new SettingsComponent(baseProps);
|
|
expect(settingsComponentInstance.shouldShowKeyspaceSharedThroughputMessage()).toEqual(false);
|
|
|
|
const newContainer = new Explorer();
|
|
updateUserContext({
|
|
databaseAccount: {
|
|
properties: {
|
|
capabilities: [{ name: "EnableCassandra" }],
|
|
},
|
|
} as DataModels.DatabaseAccount,
|
|
});
|
|
|
|
const newCollection = { ...collection };
|
|
newCollection.container = newContainer;
|
|
const newDatabase = {
|
|
nodeKind: undefined,
|
|
rid: undefined,
|
|
container: newContainer,
|
|
self: undefined,
|
|
id: undefined,
|
|
collections: undefined,
|
|
offer: undefined,
|
|
isDatabaseExpanded: undefined,
|
|
isDatabaseShared: ko.computed(() => true),
|
|
selectedSubnodeKind: undefined,
|
|
selectDatabase: undefined,
|
|
expandDatabase: undefined,
|
|
collapseDatabase: undefined,
|
|
loadCollections: undefined,
|
|
findCollectionWithId: undefined,
|
|
openAddCollection: undefined,
|
|
readSettings: undefined,
|
|
onSettingsClick: undefined,
|
|
loadOffer: undefined,
|
|
getPendingThroughputSplitNotification: undefined,
|
|
} as ViewModels.Database;
|
|
newCollection.getDatabase = () => newDatabase;
|
|
newCollection.offer = ko.observable(undefined);
|
|
|
|
const props = { ...baseProps };
|
|
props.settingsTab.collection = newCollection;
|
|
|
|
settingsComponentInstance = new SettingsComponent(props);
|
|
expect(settingsComponentInstance.shouldShowKeyspaceSharedThroughputMessage()).toEqual(true);
|
|
});
|
|
|
|
it("hasConflictResolution", () => {
|
|
let settingsComponentInstance = new SettingsComponent(baseProps);
|
|
expect(settingsComponentInstance.hasConflictResolution()).toEqual(undefined);
|
|
|
|
const newContainer = new Explorer();
|
|
newContainer.databaseAccount = ko.observable({
|
|
id: undefined,
|
|
name: undefined,
|
|
location: undefined,
|
|
type: undefined,
|
|
kind: undefined,
|
|
tags: undefined,
|
|
properties: {
|
|
documentEndpoint: undefined,
|
|
tableEndpoint: undefined,
|
|
gremlinEndpoint: undefined,
|
|
cassandraEndpoint: undefined,
|
|
enableMultipleWriteLocations: true,
|
|
},
|
|
});
|
|
const newCollection = { ...collection };
|
|
newCollection.container = newContainer;
|
|
newCollection.conflictResolutionPolicy = ko.observable({
|
|
mode: DataModels.ConflictResolutionMode.Custom,
|
|
conflictResolutionProcedure: undefined,
|
|
} as DataModels.ConflictResolutionPolicy);
|
|
|
|
const props = { ...baseProps };
|
|
props.settingsTab.collection = newCollection;
|
|
|
|
settingsComponentInstance = new SettingsComponent(props);
|
|
expect(settingsComponentInstance.hasConflictResolution()).toEqual(true);
|
|
});
|
|
|
|
it("save calls updateCollection, updateMongoDBCollectionThroughRP and updateOffer", async () => {
|
|
const wrapper = shallow(<SettingsComponent {...baseProps} />);
|
|
wrapper.setState({ isSubSettingsSaveable: true, isScaleSaveable: true, isMongoIndexingPolicySaveable: true });
|
|
wrapper.update();
|
|
const settingsComponentInstance = wrapper.instance() as SettingsComponent;
|
|
settingsComponentInstance.mongoDBCollectionResource = {
|
|
id: "id",
|
|
};
|
|
await settingsComponentInstance.onSaveClick();
|
|
expect(updateCollection).toBeCalled();
|
|
expect(updateOffer).toBeCalled();
|
|
});
|
|
|
|
it("revert resets state values", async () => {
|
|
const wrapper = shallow(<SettingsComponent {...baseProps} />);
|
|
wrapper.setState({ timeToLive: TtlType.OnNoDefault, throughput: 10 });
|
|
wrapper.update();
|
|
let state = wrapper.state() as SettingsComponentState;
|
|
expect(isDirty(state.timeToLive, state.timeToLiveBaseline)).toEqual(true);
|
|
expect(isDirty(state.throughput, state.throughputBaseline)).toEqual(true);
|
|
|
|
const settingsComponentInstance = wrapper.instance() as SettingsComponent;
|
|
settingsComponentInstance.onRevertClick();
|
|
state = wrapper.state() as SettingsComponentState;
|
|
expect(isDirty(state.timeToLive, state.timeToLiveBaseline)).toEqual(false);
|
|
expect(isDirty(state.throughput, state.throughputBaseline)).toEqual(false);
|
|
});
|
|
|
|
it("getAnalyticalStorageTtl", () => {
|
|
const newCollection = { ...collection };
|
|
newCollection.analyticalStorageTtl = ko.observable(10);
|
|
const props = { ...baseProps };
|
|
props.settingsTab.collection = newCollection;
|
|
const wrapper = shallow(<SettingsComponent {...props} />);
|
|
const settingsComponentInstance = wrapper.instance() as SettingsComponent;
|
|
expect(settingsComponentInstance.getAnalyticalStorageTtl()).toEqual(10);
|
|
wrapper.setState({ analyticalStorageTtlSelection: TtlType.Off });
|
|
wrapper.update();
|
|
expect(settingsComponentInstance.getAnalyticalStorageTtl()).toEqual(-1);
|
|
});
|
|
|
|
it("getUpdatedConflictResolutionPolicy", () => {
|
|
const wrapper = shallow(<SettingsComponent {...baseProps} />);
|
|
const conflictResolutionPolicyPath = "/_ts";
|
|
const conflictResolutionPolicyProcedure = "sample_sproc";
|
|
const expectSprocPath =
|
|
"/dbs/" + collection.databaseId + "/colls/" + collection.id() + "/sprocs/" + conflictResolutionPolicyProcedure;
|
|
|
|
wrapper.setState({
|
|
conflictResolutionPolicyMode: DataModels.ConflictResolutionMode.LastWriterWins,
|
|
conflictResolutionPolicyPath: conflictResolutionPolicyPath,
|
|
});
|
|
wrapper.update();
|
|
const settingsComponentInstance = wrapper.instance() as SettingsComponent;
|
|
let conflictResolutionPolicy = settingsComponentInstance.getUpdatedConflictResolutionPolicy();
|
|
expect(conflictResolutionPolicy.mode).toEqual(DataModels.ConflictResolutionMode.LastWriterWins);
|
|
expect(conflictResolutionPolicy.conflictResolutionPath).toEqual(conflictResolutionPolicyPath);
|
|
|
|
wrapper.setState({
|
|
conflictResolutionPolicyMode: DataModels.ConflictResolutionMode.Custom,
|
|
conflictResolutionPolicyProcedure: conflictResolutionPolicyProcedure,
|
|
});
|
|
wrapper.update();
|
|
conflictResolutionPolicy = settingsComponentInstance.getUpdatedConflictResolutionPolicy();
|
|
expect(conflictResolutionPolicy.mode).toEqual(DataModels.ConflictResolutionMode.Custom);
|
|
expect(conflictResolutionPolicy.conflictResolutionProcedure).toEqual(expectSprocPath);
|
|
});
|
|
});
|