import { shallow } from "enzyme"; import React from "react"; import { SettingsComponentProps, SettingsComponent, SettingsComponentState } from "./SettingsComponent"; import * as ViewModels from "../../../Contracts/ViewModels"; import SettingsTabV2 from "../../Tabs/SettingsTabV2"; import { collection } from "./TestUtils"; import * as DataModels from "../../../Contracts/DataModels"; import ko from "knockout"; import { TtlType, isDirty } from "./SettingsUtils"; import Explorer from "../../Explorer"; jest.mock("../../../Common/dataAccess/getIndexTransformationProgress", () => ({ getIndexTransformationProgress: jest.fn().mockReturnValue(undefined) })); import { updateCollection, updateMongoDBCollectionThroughRP } from "../../../Common/dataAccess/updateCollection"; jest.mock("../../../Common/dataAccess/updateCollection", () => ({ updateCollection: jest.fn().mockReturnValue({ id: undefined, defaultTtl: undefined, indexingPolicy: undefined, conflictResolutionPolicy: undefined, changeFeedPolicy: undefined, analyticalStorageTtl: undefined, geospatialConfig: undefined } as DataModels.Collection), updateMongoDBCollectionThroughRP: jest.fn().mockReturnValue({ id: undefined, shardKey: undefined, indexes: [], analyticalStorageTtl: undefined } as MongoDBCollectionResource) })); import { updateOffer } from "../../../Common/dataAccess/updateOffer"; import { MongoDBCollectionResource } from "../../../Utils/arm/generatedClients/2020-04-01/types"; import Q from "q"; jest.mock("../../../Common/dataAccess/updateOffer", () => ({ updateOffer: jest.fn().mockReturnValue({} as DataModels.Offer) })); describe("SettingsComponent", () => { const baseProps: SettingsComponentProps = { settingsTab: new SettingsTabV2({ collection: collection, tabKind: ViewModels.CollectionTabKind.SettingsV2, title: "Scale & Settings", tabPath: "", node: undefined, hashLocation: "settings", isActive: ko.observable(false), onUpdateTabsButtons: undefined, getPendingNotification: Q.Promise(() => { return; }) }) }; it("renders", () => { const wrapper = shallow(); expect(wrapper).toMatchSnapshot(); }); it("dirty value enables save button and discard button", () => { const wrapper = shallow(); 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({ autoscaleMaxThroughput: 10000, manualThroughput: undefined, minimumThroughput: 400, id: "test", offerReplacePending: false }); const props = { ...baseProps }; props.settingsTab.collection = newCollection; const wrapper = shallow(); 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(); newContainer.isPreferredApiCassandra = ko.computed(() => true); 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, onDeleteDatabaseContextMenuClick: undefined, readSettings: undefined, onSettingsClick: undefined, loadOffer: 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(); 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(updateMongoDBCollectionThroughRP).toBeCalled(); expect(updateOffer).toBeCalled(); }); it("revert resets state values", async () => { const wrapper = shallow(); 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(); 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(); 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); }); });