IGNITE-8990 Web Console: Fixed check for unsaved changes logic.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/ee1acb23 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/ee1acb23 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/ee1acb23 Branch: refs/heads/ignite-8446 Commit: ee1acb2366abf2d03fc3c95a79bcad7ae0efcf9d Parents: b77e979 Author: Ilya Borisov <klast...@gmail.com> Authored: Wed Jul 25 15:16:41 2018 +0700 Committer: Alexey Kuznetsov <akuznet...@apache.org> Committed: Wed Jul 25 15:16:41 2018 +0700 ---------------------------------------------------------------------- .../configuration/clusterFormChangeDetection.js | 56 ++++++++++++++++++++ modules/web-console/e2e/testcafe/helpers.js | 4 +- modules/web-console/e2e/testcafe/package.json | 2 +- .../PageConfigurationAdvancedCluster.js | 21 ++++++-- .../page-models/PageConfigurationOverview.js | 10 ++-- .../pageConfigurationAdvancedIGFS.js | 4 +- .../pageConfigurationAdvancedModels.js | 6 +-- .../components/cluster-edit-form/controller.js | 6 ++- .../page-configure/components/fakeUICanExit.js | 27 ++++++++-- .../components/fakeUICanExit.spec.js | 32 +++++++++++ 10 files changed, 146 insertions(+), 22 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/ee1acb23/modules/web-console/e2e/testcafe/fixtures/configuration/clusterFormChangeDetection.js ---------------------------------------------------------------------- diff --git a/modules/web-console/e2e/testcafe/fixtures/configuration/clusterFormChangeDetection.js b/modules/web-console/e2e/testcafe/fixtures/configuration/clusterFormChangeDetection.js new file mode 100644 index 0000000..a862172 --- /dev/null +++ b/modules/web-console/e2e/testcafe/fixtures/configuration/clusterFormChangeDetection.js @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {dropTestDB, insertTestUser, resolveUrl} from '../../environment/envtools'; +import {createRegularUser} from '../../roles'; +import {PageConfigurationOverview} from '../../page-models/PageConfigurationOverview'; +import {PageConfigurationAdvancedCluster} from '../../page-models/PageConfigurationAdvancedCluster'; +import {advancedNavButton} from '../../components/pageConfiguration'; +import {pageAdvancedConfiguration} from '../../components/pageAdvancedConfiguration'; +import {confirmation} from '../../components/confirmation'; +import {scrollIntoView} from '../../helpers'; + +const regularUser = createRegularUser(); + +fixture('Cluster configuration form change detection') + .before(async() => { + await dropTestDB(); + await insertTestUser(); + }) + .beforeEach(async(t) => { + await t.useRole(regularUser); + }) + .after(dropTestDB); + +test('New cluster change detection', async(t) => { + const overview = new PageConfigurationOverview(); + const advanced = new PageConfigurationAdvancedCluster(); + + await t + .navigateTo(resolveUrl(`/configuration/overview`)) + .click(overview.createClusterConfigButton) + .click(advancedNavButton) + .click(advanced.sections.connectorConfiguration.panel.heading); + + await scrollIntoView.with({dependencies: {el: advanced.sections.connectorConfiguration.panel.heading}})(); + + await t + .click(advanced.sections.connectorConfiguration.inputs.enable.control) + .click(advanced.saveButton) + .click(pageAdvancedConfiguration.cachesNavButton) + .expect(confirmation.body.exists).notOk(`Doesn't show changes confiramtion after saving new cluster`); +}); http://git-wip-us.apache.org/repos/asf/ignite/blob/ee1acb23/modules/web-console/e2e/testcafe/helpers.js ---------------------------------------------------------------------- diff --git a/modules/web-console/e2e/testcafe/helpers.js b/modules/web-console/e2e/testcafe/helpers.js index fc68f93..908bd6e 100644 --- a/modules/web-console/e2e/testcafe/helpers.js +++ b/modules/web-console/e2e/testcafe/helpers.js @@ -34,4 +34,6 @@ const getLocationPathname = ClientFunction(() => Promise.resolve(location.pathna */ const isVisible = (node) => !!node.getBoundingClientRect().width; -module.exports = { mouseenterTrigger, getLocationPathname, isVisible }; +const scrollIntoView = ClientFunction(() => el().scrollIntoView()); + +module.exports = { mouseenterTrigger, getLocationPathname, isVisible, scrollIntoView }; http://git-wip-us.apache.org/repos/asf/ignite/blob/ee1acb23/modules/web-console/e2e/testcafe/package.json ---------------------------------------------------------------------- diff --git a/modules/web-console/e2e/testcafe/package.json b/modules/web-console/e2e/testcafe/package.json index 5a4926d..220003a 100644 --- a/modules/web-console/e2e/testcafe/package.json +++ b/modules/web-console/e2e/testcafe/package.json @@ -33,7 +33,7 @@ "objectid": "3.2.1", "path": "0.12.7", "sinon": "2.3.8", - "testcafe": "0.19.0", + "testcafe": "0.20.5", "testcafe-angular-selectors": "0.3.0", "testcafe-reporter-teamcity": "1.0.9", "type-detect": "4.0.3", http://git-wip-us.apache.org/repos/asf/ignite/blob/ee1acb23/modules/web-console/e2e/testcafe/page-models/PageConfigurationAdvancedCluster.js ---------------------------------------------------------------------- diff --git a/modules/web-console/e2e/testcafe/page-models/PageConfigurationAdvancedCluster.js b/modules/web-console/e2e/testcafe/page-models/PageConfigurationAdvancedCluster.js index 0f62707..70f714e 100644 --- a/modules/web-console/e2e/testcafe/page-models/PageConfigurationAdvancedCluster.js +++ b/modules/web-console/e2e/testcafe/page-models/PageConfigurationAdvancedCluster.js @@ -15,14 +15,27 @@ * limitations under the License. */ -import {Selector, t} from 'testcafe' +import {Selector, t} from 'testcafe'; +import {PanelCollapsible} from '../components/PanelCollapsible'; +import {FormField} from '../components/FormField'; export class PageConfigurationAdvancedCluster { constructor() { - this._selector = Selector('page-configure-advanced-cluster') - this.saveButton = Selector('.pc-form-actions-panel .btn-ignite').withText('Save') + this._selector = Selector('page-configure-advanced-cluster'); + + this.saveButton = Selector('.pc-form-actions-panel .btn-ignite').withText('Save'); + + this.sections = { + connectorConfiguration: { + panel: new PanelCollapsible('Connector configuration'), + inputs: { + enable: new FormField({id: 'restEnabledInput'}) + } + } + }; } + async save() { - await t.click(this.saveButton) + await t.click(this.saveButton); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/ee1acb23/modules/web-console/e2e/testcafe/page-models/PageConfigurationOverview.js ---------------------------------------------------------------------- diff --git a/modules/web-console/e2e/testcafe/page-models/PageConfigurationOverview.js b/modules/web-console/e2e/testcafe/page-models/PageConfigurationOverview.js index 34a6486..652b50f 100644 --- a/modules/web-console/e2e/testcafe/page-models/PageConfigurationOverview.js +++ b/modules/web-console/e2e/testcafe/page-models/PageConfigurationOverview.js @@ -15,17 +15,17 @@ * limitations under the License. */ -import {Selector, t} from 'testcafe' -import {Table} from '../components/Table' -import {confirmation} from '../components/confirmation' -import {successNotification} from '../components/notifications' +import {Selector, t} from 'testcafe'; +import {Table} from '../components/Table'; +import {confirmation} from '../components/confirmation'; +import {successNotification} from '../components/notifications'; export class PageConfigurationOverview { constructor() { this.createClusterConfigButton = Selector('.btn-ignite').withText('Create Cluster Configuration'); this.importFromDBButton = Selector('.btn-ignite').withText('Import from Database'); this.clustersTable = new Table(Selector('pc-items-table')); - this.pageHeader = Selector('.pc-page-header') + this.pageHeader = Selector('.pc-page-header'); } async removeAllItems() { await t.click(this.clustersTable.allItemsCheckbox); http://git-wip-us.apache.org/repos/asf/ignite/blob/ee1acb23/modules/web-console/e2e/testcafe/page-models/pageConfigurationAdvancedIGFS.js ---------------------------------------------------------------------- diff --git a/modules/web-console/e2e/testcafe/page-models/pageConfigurationAdvancedIGFS.js b/modules/web-console/e2e/testcafe/page-models/pageConfigurationAdvancedIGFS.js index f3ac35c..8225f7e 100644 --- a/modules/web-console/e2e/testcafe/page-models/pageConfigurationAdvancedIGFS.js +++ b/modules/web-console/e2e/testcafe/page-models/pageConfigurationAdvancedIGFS.js @@ -15,7 +15,7 @@ * limitations under the License. */ -import {Selector} from 'testcafe' -import {isVisible} from '../helpers' +import {Selector} from 'testcafe'; +import {isVisible} from '../helpers'; export const createIGFSButton = Selector('pc-items-table footer-slot .link-success').filter(isVisible); http://git-wip-us.apache.org/repos/asf/ignite/blob/ee1acb23/modules/web-console/e2e/testcafe/page-models/pageConfigurationAdvancedModels.js ---------------------------------------------------------------------- diff --git a/modules/web-console/e2e/testcafe/page-models/pageConfigurationAdvancedModels.js b/modules/web-console/e2e/testcafe/page-models/pageConfigurationAdvancedModels.js index 196ac3c..c9b64b9 100644 --- a/modules/web-console/e2e/testcafe/page-models/pageConfigurationAdvancedModels.js +++ b/modules/web-console/e2e/testcafe/page-models/pageConfigurationAdvancedModels.js @@ -15,9 +15,9 @@ * limitations under the License. */ -import {Selector} from 'testcafe' -import {FormField} from '../components/FormField' -import {isVisible} from '../helpers' +import {Selector} from 'testcafe'; +import {FormField} from '../components/FormField'; +import {isVisible} from '../helpers'; export const createModelButton = Selector('pc-items-table footer-slot .link-success').filter(isVisible); export const general = { http://git-wip-us.apache.org/repos/asf/ignite/blob/ee1acb23/modules/web-console/frontend/app/components/page-configure-advanced/components/cluster-edit-form/controller.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/page-configure-advanced/components/cluster-edit-form/controller.js b/modules/web-console/frontend/app/components/page-configure-advanced/components/cluster-edit-form/controller.js index 8459cdd..cd8d3e4 100644 --- a/modules/web-console/frontend/app/components/page-configure-advanced/components/cluster-edit-form/controller.js +++ b/modules/web-console/frontend/app/components/page-configure-advanced/components/cluster-edit-form/controller.js @@ -29,8 +29,12 @@ export default class ClusterEditFormController { onSave; static $inject = ['IgniteLegacyUtils', 'IgniteEventGroups', 'IgniteConfirm', 'IgniteVersion', '$scope', 'Clusters', 'IgniteFormUtils']; + /** + * @param {import('app/services/Clusters').default} Clusters + */ constructor(IgniteLegacyUtils, IgniteEventGroups, IgniteConfirm, IgniteVersion, $scope, Clusters, IgniteFormUtils) { - Object.assign(this, {IgniteLegacyUtils, IgniteEventGroups, IgniteConfirm, IgniteVersion, $scope, Clusters, IgniteFormUtils}); + Object.assign(this, {IgniteLegacyUtils, IgniteEventGroups, IgniteConfirm, IgniteVersion, $scope, IgniteFormUtils}); + this.Clusters = Clusters; } $onDestroy() { http://git-wip-us.apache.org/repos/asf/ignite/blob/ee1acb23/modules/web-console/frontend/app/components/page-configure/components/fakeUICanExit.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/page-configure/components/fakeUICanExit.js b/modules/web-console/frontend/app/components/page-configure/components/fakeUICanExit.js index c0837ed..246562f 100644 --- a/modules/web-console/frontend/app/components/page-configure/components/fakeUICanExit.js +++ b/modules/web-console/frontend/app/components/page-configure/components/fakeUICanExit.js @@ -15,25 +15,42 @@ * limitations under the License. */ -class FakeUiCanExitController { +export class FakeUiCanExitController { static $inject = ['$element', '$transitions']; static CALLBACK_NAME = 'uiCanExit'; + + /** @type {string} Name of state to listen exit from */ + fromState; + + /** + * @param {JQLite} $element + * @param {import('@uirouter/angularjs').TransitionService} $transitions + */ constructor($element, $transitions) { - Object.assign(this, {$element, $transitions}); + this.$element = $element; + this.$transitions = $transitions; } + $onInit() { const data = this.$element.data(); const {CALLBACK_NAME} = this.constructor; + const controllerWithCallback = Object.keys(data) .map((key) => data[key]) .find((controller) => controller[CALLBACK_NAME]); - if (!controllerWithCallback) return; - const off = this.$transitions.onBefore({from: this.fromState}, (...args) => { + + if (!controllerWithCallback) + return; + + this.off = this.$transitions.onBefore({from: this.fromState}, (...args) => { return controllerWithCallback[CALLBACK_NAME](...args); }); } + $onDestroy() { - if (this.off) this.off(); + if (this.off) + this.off(); + this.$element = null; } } http://git-wip-us.apache.org/repos/asf/ignite/blob/ee1acb23/modules/web-console/frontend/app/components/page-configure/components/fakeUICanExit.spec.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/components/page-configure/components/fakeUICanExit.spec.js b/modules/web-console/frontend/app/components/page-configure/components/fakeUICanExit.spec.js new file mode 100644 index 0000000..7d21eba --- /dev/null +++ b/modules/web-console/frontend/app/components/page-configure/components/fakeUICanExit.spec.js @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {spy} from 'sinon'; +import {assert} from 'chai'; +import {FakeUiCanExitController} from './fakeUICanExit'; + +suite('Page configuration fakeUIcanExit directive', () => { + test('It unsubscribes from state events when destroyed', () => { + const $element = {data: () => [{uiCanExit: () => {}}]}; + const off = spy(); + const $transitions = {onBefore: () => off}; + const i = new FakeUiCanExitController($element, $transitions); + i.$onInit(); + i.$onDestroy(); + assert.ok(off.calledOnce, 'Calls off when destroyed'); + }); +});