Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nasa/openmct.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Bell <scott@traclabs.com>2022-03-18 16:27:14 +0300
committerGitHub <noreply@github.com>2022-03-18 16:27:14 +0300
commit918ec3759fb633cf8180bfb56e69dea86f579a0a (patch)
tree18f17681134a3206c8594264b905c45407ea55b9
parent55b3b3bba99b7ca23cb406a9f307129d745a4515 (diff)
parent492ff2fa64274b1cf711e7eea0ec0aef9b258df8 (diff)
Merge branch 'master' into mct4879mct4879
-rw-r--r--.github/workflows/e2e-pr.yml2
-rw-r--r--.github/workflows/e2e-visual.yml2
-rw-r--r--e2e/tests/example/generator/SinewaveLimitProvider.e2e.spec.js161
-rw-r--r--e2e/tests/moveObjects.e2e.spec.js42
-rw-r--r--e2e/tests/persistence/addNoneditableObject.js27
-rw-r--r--e2e/tests/persistence/persistability.e2e.spec.js77
-rw-r--r--e2e/tests/plugins/ExportAsJSON/exportAsJson.e2e.spec.js48
-rw-r--r--e2e/tests/plugins/ImportAsJSON/importAsJson.e2e.spec.js46
-rw-r--r--e2e/tests/plugins/timeConductor/timeConductor.e2e.spec.js69
-rw-r--r--e2e/tests/visual/default.spec.js60
-rw-r--r--package.json36
-rw-r--r--src/api/forms/components/controls/NumberField.vue10
-rw-r--r--src/api/forms/components/controls/TextAreaField.vue9
-rw-r--r--src/api/forms/components/controls/TextField.vue9
-rw-r--r--src/plugins/timeConductor/ConductorInputsFixed.vue2
15 files changed, 574 insertions, 26 deletions
diff --git a/.github/workflows/e2e-pr.yml b/.github/workflows/e2e-pr.yml
index a79ae472e..ce279307b 100644
--- a/.github/workflows/e2e-pr.yml
+++ b/.github/workflows/e2e-pr.yml
@@ -30,7 +30,7 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: '16'
- - run: npx playwright install-deps
+ - run: npx playwright@1.19.2 install
- run: npm install
- run: npm run test:e2e:full
- name: Archive test results
diff --git a/.github/workflows/e2e-visual.yml b/.github/workflows/e2e-visual.yml
index 26163895e..28653e7c9 100644
--- a/.github/workflows/e2e-visual.yml
+++ b/.github/workflows/e2e-visual.yml
@@ -17,7 +17,7 @@ jobs:
- uses: actions/setup-node@v3
with:
node-version: '16'
- - run: npx playwright install-deps
+ - run: npx playwright@1.19.2 install
- run: npm install
- name: Run the e2e visual tests
run: npm run test:e2e:visual
diff --git a/e2e/tests/example/generator/SinewaveLimitProvider.e2e.spec.js b/e2e/tests/example/generator/SinewaveLimitProvider.e2e.spec.js
new file mode 100644
index 000000000..fc8101c9e
--- /dev/null
+++ b/e2e/tests/example/generator/SinewaveLimitProvider.e2e.spec.js
@@ -0,0 +1,161 @@
+/*****************************************************************************
+ * Open MCT, Copyright (c) 2014-2022, United States Government
+ * as represented by the Administrator of the National Aeronautics and Space
+ * Administration. All rights reserved.
+ *
+ * Open MCT is licensed 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.
+ *
+ * Open MCT includes source code licensed under additional open source
+ * licenses. See the Open Source Licenses file (LICENSES.md) included with
+ * this source code distribution or the Licensing information page available
+ * at runtime from the About dialog for additional information.
+ *****************************************************************************/
+
+/*
+This test suite is dedicated to tests which verify the basic operations surrounding conditionSets.
+*/
+
+const { test, expect } = require('@playwright/test');
+
+test.describe('Sine Wave Generator', () => {
+ test('Create new Sine Wave Generator Object and validate create Form Logic', async ({ page }) => {
+ //Go to baseURL
+ await page.goto('/', { waitUntil: 'networkidle' });
+
+ //Click the Create button
+ await page.click('button:has-text("Create")');
+
+ // Click Sine Wave Generator
+ await page.click('text=Sine Wave Generator');
+
+ // Verify that the each required field has required indicator
+ // Title
+ await expect(page.locator('.c-form-row__state-indicator').first()).toHaveClass(['c-form-row__state-indicator req']);
+
+ // Verify that the Notes row does not have a required indicator
+ await expect(page.locator('.c-form__section div:nth-child(3) .form-row .c-form-row__state-indicator')).not.toContain('.req');
+
+ // Period
+ await expect(page.locator('.c-form__section div:nth-child(4) .form-row .c-form-row__state-indicator')).toHaveClass(['c-form-row__state-indicator req']);
+
+ // Amplitude
+ await expect(page.locator('.c-form__section div:nth-child(5) .form-row .c-form-row__state-indicator')).toHaveClass(['c-form-row__state-indicator req']);
+
+ // Offset
+ await expect(page.locator('.c-form__section div:nth-child(6) .form-row .c-form-row__state-indicator')).toHaveClass(['c-form-row__state-indicator req']);
+
+ // Data Rate
+ await expect(page.locator('.c-form__section div:nth-child(7) .form-row .c-form-row__state-indicator')).toHaveClass(['c-form-row__state-indicator req']);
+
+ // Phase
+ await expect(page.locator('.c-form__section div:nth-child(8) .form-row .c-form-row__state-indicator')).toHaveClass(['c-form-row__state-indicator req']);
+
+ // Randomness
+ await expect(page.locator('.c-form__section div:nth-child(9) .form-row .c-form-row__state-indicator')).toHaveClass(['c-form-row__state-indicator req']);
+
+ // Verify that by removing value from required text field shows invalid indicator
+ await page.locator('text=Properties Title Notes Period Amplitude Offset Data Rate (hz) Phase (radians) Ra >> input[type="text"]').fill('');
+ await expect(page.locator('.c-form-row__state-indicator').first()).toHaveClass(['c-form-row__state-indicator req invalid']);
+
+ // Verify that by adding value to empty required text field changes invalid to valid indicator
+ await page.locator('text=Properties Title Notes Period Amplitude Offset Data Rate (hz) Phase (radians) Ra >> input[type="text"]').fill('non empty');
+ await expect(page.locator('.c-form-row__state-indicator').first()).toHaveClass(['c-form-row__state-indicator req valid']);
+
+ // Verify that by removing value from required number field shows invalid indicator
+ await page.locator('.field.control.l-input-sm input').first().fill('');
+ await expect(page.locator('.c-form__section div:nth-child(4) .form-row .c-form-row__state-indicator')).toHaveClass(['c-form-row__state-indicator req invalid']);
+
+ // Verify that by adding value to empty required number field changes invalid to valid indicator
+ await page.locator('.field.control.l-input-sm input').first().fill('3');
+ await expect(page.locator('.c-form__section div:nth-child(4) .form-row .c-form-row__state-indicator')).toHaveClass(['c-form-row__state-indicator req valid']);
+
+ // Verify that can change value of number field by up/down arrows keys
+ // Click .field.control.l-input-sm input >> nth=0
+ await page.locator('.field.control.l-input-sm input').first().click();
+ // Press ArrowUp 3 times to change value from 3 to 6
+ await page.locator('.field.control.l-input-sm input').first().press('ArrowUp');
+ await page.locator('.field.control.l-input-sm input').first().press('ArrowUp');
+ await page.locator('.field.control.l-input-sm input').first().press('ArrowUp');
+
+ const value = await page.locator('.field.control.l-input-sm input').first().inputValue();
+ await expect(value).toBe('6');
+
+ // Click .c-form-row__state-indicator.grows
+ await page.locator('.c-form-row__state-indicator.grows').click();
+
+ // Click text=Properties Title Notes Period Amplitude Offset Data Rate (hz) Phase (radians) Ra >> input[type="text"]
+ await page.locator('text=Properties Title Notes Period Amplitude Offset Data Rate (hz) Phase (radians) Ra >> input[type="text"]').click();
+
+ // Click .c-form-row__state-indicator >> nth=0
+ await page.locator('.c-form-row__state-indicator').first().click();
+
+ // Fill text=Properties Title Notes Period Amplitude Offset Data Rate (hz) Phase (radians) Ra >> input[type="text"]
+ await page.locator('text=Properties Title Notes Period Amplitude Offset Data Rate (hz) Phase (radians) Ra >> input[type="text"]').fill('New Sine Wave Generator');
+
+ // Double click div:nth-child(4) .form-row .c-form-row__controls
+ await page.locator('div:nth-child(4) .form-row .c-form-row__controls').dblclick();
+
+ // Click .field.control.l-input-sm input >> nth=0
+ await page.locator('.field.control.l-input-sm input').first().click();
+
+ // Click div:nth-child(4) .form-row .c-form-row__state-indicator
+ await page.locator('div:nth-child(4) .form-row .c-form-row__state-indicator').click();
+
+ // Click .field.control.l-input-sm input >> nth=0
+ await page.locator('.field.control.l-input-sm input').first().click();
+
+ // Click .field.control.l-input-sm input >> nth=0
+ await page.locator('.field.control.l-input-sm input').first().click();
+
+ // Click div:nth-child(5) .form-row .c-form-row__controls .form-control .field input
+ await page.locator('div:nth-child(5) .form-row .c-form-row__controls .form-control .field input').click();
+
+ // Click div:nth-child(5) .form-row .c-form-row__controls .form-control .field input
+ await page.locator('div:nth-child(5) .form-row .c-form-row__controls .form-control .field input').click();
+
+ // Click div:nth-child(5) .form-row .c-form-row__controls .form-control .field input
+ await page.locator('div:nth-child(5) .form-row .c-form-row__controls .form-control .field input').click();
+
+ // Click div:nth-child(6) .form-row .c-form-row__controls .form-control .field input
+ await page.locator('div:nth-child(6) .form-row .c-form-row__controls .form-control .field input').click();
+
+ // Double click div:nth-child(7) .form-row .c-form-row__controls .form-control .field input
+ await page.locator('div:nth-child(7) .form-row .c-form-row__controls .form-control .field input').dblclick();
+
+ // Click div:nth-child(7) .form-row .c-form-row__state-indicator
+ await page.locator('div:nth-child(7) .form-row .c-form-row__state-indicator').click();
+
+ // Click div:nth-child(7) .form-row .c-form-row__controls .form-control .field input
+ await page.locator('div:nth-child(7) .form-row .c-form-row__controls .form-control .field input').click();
+
+ // Fill div:nth-child(7) .form-row .c-form-row__controls .form-control .field input
+ await page.locator('div:nth-child(7) .form-row .c-form-row__controls .form-control .field input').fill('3');
+
+ //Click text=OK
+ await Promise.all([
+ page.waitForNavigation(),
+ page.click('text=OK')
+ ]);
+
+ // Verify that the Sine Wave Generator is displayed and correct
+ // Verify object properties
+ await expect(page.locator('.l-browse-bar__object-name')).toContainText('New Sine Wave Generator');
+
+ // Verify canvas rendered
+ await page.locator('canvas').nth(1).click({
+ position: {
+ x: 341,
+ y: 28
+ }
+ });
+ });
+});
diff --git a/e2e/tests/moveObjects.e2e.spec.js b/e2e/tests/moveObjects.e2e.spec.js
new file mode 100644
index 000000000..26ffdcdff
--- /dev/null
+++ b/e2e/tests/moveObjects.e2e.spec.js
@@ -0,0 +1,42 @@
+/*****************************************************************************
+ * Open MCT, Copyright (c) 2014-2022, United States Government
+ * as represented by the Administrator of the National Aeronautics and Space
+ * Administration. All rights reserved.
+ *
+ * Open MCT is licensed 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.
+ *
+ * Open MCT includes source code licensed under additional open source
+ * licenses. See the Open Source Licenses file (LICENSES.md) included with
+ * this source code distribution or the Licensing information page available
+ * at runtime from the About dialog for additional information.
+ *****************************************************************************/
+
+/*
+This test suite is dedicated to tests which verify the basic operations surrounding moving objects.
+*/
+
+const { test, expect } = require('@playwright/test');
+
+test.describe('Move item tests', () => {
+ test.fixme('Create a basic object and verify that it can be moved to another Folder', async ({ page }) => {
+ //Create and save Folder
+ //Create and save Domain Object
+ //Verify that the newly created domain object can be moved to Folder from Step 1.
+ //Verify that newly moved object appears in the correct point in Tree
+ //Verify that newly moved object appears correctly in Inspector panel
+ });
+ test.fixme('Create a basic object and verify that it cannot be moved to object without Composition Provider', async ({ page }) => {
+ //Create and save Telemetry Object
+ //Create and save Domain Object
+ //Verify that the newly created domain object cannot be moved to Telemetry Object from step 1.
+ });
+});
diff --git a/e2e/tests/persistence/addNoneditableObject.js b/e2e/tests/persistence/addNoneditableObject.js
new file mode 100644
index 000000000..55da25358
--- /dev/null
+++ b/e2e/tests/persistence/addNoneditableObject.js
@@ -0,0 +1,27 @@
+(function () {
+ document.addEventListener('DOMContentLoaded', () => {
+ const PERSISTENCE_KEY = 'persistence-tests';
+ const openmct = window.openmct;
+
+ openmct.objects.addRoot({
+ namespace: PERSISTENCE_KEY,
+ key: PERSISTENCE_KEY
+ });
+
+ openmct.objects.addProvider(PERSISTENCE_KEY, {
+ get(identifier) {
+ if (identifier.key !== PERSISTENCE_KEY) {
+ return undefined;
+ } else {
+ return Promise.resolve({
+ identifier,
+ type: 'folder',
+ name: 'Persistence Testing',
+ location: 'ROOT',
+ composition: []
+ });
+ }
+ }
+ });
+ });
+}());
diff --git a/e2e/tests/persistence/persistability.e2e.spec.js b/e2e/tests/persistence/persistability.e2e.spec.js
new file mode 100644
index 000000000..56e48e658
--- /dev/null
+++ b/e2e/tests/persistence/persistability.e2e.spec.js
@@ -0,0 +1,77 @@
+/*****************************************************************************
+ * Open MCT, Copyright (c) 2014-2022, United States Government
+ * as represented by the Administrator of the National Aeronautics and Space
+ * Administration. All rights reserved.
+ *
+ * Open MCT is licensed 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.
+ *
+ * Open MCT includes source code licensed under additional open source
+ * licenses. See the Open Source Licenses file (LICENSES.md) included with
+ * this source code distribution or the Licensing information page available
+ * at runtime from the About dialog for additional information.
+ *****************************************************************************/
+
+/*
+This test suite is dedicated to tests which verify the basic operations surrounding conditionSets.
+*/
+
+const { test, expect } = require('@playwright/test');
+const path = require('path');
+
+// https://github.com/nasa/openmct/issues/4323#issuecomment-1067282651
+
+test.describe('Persistence operations', () => {
+ // add non persistable root item
+ test.beforeEach(async ({ page }) => {
+ // eslint-disable-next-line no-undef
+ await page.addInitScript({ path: path.join(__dirname, 'addNoneditableObject.js') });
+ });
+
+ test('Persistability should be respected in the create form location field', async ({ page }) => {
+ // Go to baseURL
+ await page.goto('/', { waitUntil: 'networkidle' });
+
+ // Click the Create button
+ await page.click('button:has-text("Create")');
+
+ // Click text=Condition Set
+ await page.click('text=Condition Set');
+
+ // Click form[name="mctForm"] >> text=Persistence Testing
+ await page.locator('form[name="mctForm"] >> text=Persistence Testing').click();
+
+ // Check that "OK" button is disabled
+ const okButton = page.locator('button:has-text("OK")');
+ await expect(okButton).toBeDisabled();
+ });
+ test('Non-persistable objects should not show persistence related actions', async ({ page }) => {
+ // Go to baseURL
+ await page.goto('/', { waitUntil: 'networkidle' });
+
+ // Click text=Persistence Testing >> nth=0
+ await page.locator('text=Persistence Testing').first().click({
+ button: 'right'
+ });
+
+ const menuOptions = page.locator('.c-menu ul');
+
+ await expect.soft(menuOptions).toContainText(['Open In New Tab', 'View', 'Create Link']);
+ await expect(menuOptions).not.toContainText(['Move', 'Duplicate', 'Remove', 'Add New Folder', 'Edit Properties...', 'Export as JSON', 'Import from JSON']);
+ });
+ test.fixme('Cannot move a previously created domain object to non-peristable boject in Move Modal', async ({ page }) => {
+ //Create a domain object
+ //Save Domain object
+ //Move Object and verify that cannot select non-persistable object
+ //Move Object to My Items
+ //Verify successful move
+ });
+});
diff --git a/e2e/tests/plugins/ExportAsJSON/exportAsJson.e2e.spec.js b/e2e/tests/plugins/ExportAsJSON/exportAsJson.e2e.spec.js
new file mode 100644
index 000000000..96c41c463
--- /dev/null
+++ b/e2e/tests/plugins/ExportAsJSON/exportAsJson.e2e.spec.js
@@ -0,0 +1,48 @@
+/*****************************************************************************
+ * Open MCT, Copyright (c) 2014-2022, United States Government
+ * as represented by the Administrator of the National Aeronautics and Space
+ * Administration. All rights reserved.
+ *
+ * Open MCT is licensed 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.
+ *
+ * Open MCT includes source code licensed under additional open source
+ * licenses. See the Open Source Licenses file (LICENSES.md) included with
+ * this source code distribution or the Licensing information page available
+ * at runtime from the About dialog for additional information.
+ *****************************************************************************/
+
+/*
+This test suite is dedicated to tests which verify the basic operations surrounding exportAsJSON.
+*/
+
+const { test, expect } = require('@playwright/test');
+
+test.describe('ExportAsJSON', () => {
+ test.fixme('Create a basic object and verify that it can be exported as JSON from Tree', async ({ page }) => {
+ //Create domain object
+ //Save Domain Object
+ //Verify that the newly created domain object can be exported as JSON from the Tree
+ });
+ test.fixme('Create a basic object and verify that it can be exported as JSON from 3 dot menu', async ({ page }) => {
+ //Create domain object
+ //Save Domain Object
+ //Verify that the newly created domain object can be exported as JSON from the 3 dot menu
+ });
+ test.fixme('Verify that a nested Object can be exported as JSON', async ({ page }) => {
+ // Create 2 objects with hierarchy
+ // Export as JSON
+ // Verify Hiearchy
+ });
+ test.fixme('Verify that the ExportAsJSON dropdown does not appear for the item X', async ({ page }) => {
+ // Other than non-persistible objects
+ });
+});
diff --git a/e2e/tests/plugins/ImportAsJSON/importAsJson.e2e.spec.js b/e2e/tests/plugins/ImportAsJSON/importAsJson.e2e.spec.js
new file mode 100644
index 000000000..7c8d0ab64
--- /dev/null
+++ b/e2e/tests/plugins/ImportAsJSON/importAsJson.e2e.spec.js
@@ -0,0 +1,46 @@
+/*****************************************************************************
+ * Open MCT, Copyright (c) 2014-2022, United States Government
+ * as represented by the Administrator of the National Aeronautics and Space
+ * Administration. All rights reserved.
+ *
+ * Open MCT is licensed 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.
+ *
+ * Open MCT includes source code licensed under additional open source
+ * licenses. See the Open Source Licenses file (LICENSES.md) included with
+ * this source code distribution or the Licensing information page available
+ * at runtime from the About dialog for additional information.
+ *****************************************************************************/
+
+/*
+This test suite is dedicated to tests which verify the basic operations surrounding importAsJSON.
+*/
+
+const { test, expect } = require('@playwright/test');
+
+test.describe('ExportAsJSON', () => {
+ test.fixme('Verify that domain object can be importAsJSON from Tree', async ({ page }) => {
+ //Verify that an testdata JSON file can be imported from Tree
+ //Verify correctness of imported domain object
+ });
+ test.fixme('Verify that domain object can be importAsJSON from 3 dot menu on folder', async ({ page }) => {
+ //Verify that an testdata JSON file can be imported from 3 dot menu on folder domain object
+ //Verify correctness of imported domain object
+ });
+ test.fixme('Verify that a nested Objects can be importAsJSON', async ({ page }) => {
+ // Testdata with hierarchy
+ // ImportAsJSON on Tree
+ // Verify Hierarchy
+ });
+ test.fixme('Verify that the ImportAsJSON dropdown does not appear for the item X', async ({ page }) => {
+ // Other than non-persistible objects
+ });
+});
diff --git a/e2e/tests/plugins/timeConductor/timeConductor.e2e.spec.js b/e2e/tests/plugins/timeConductor/timeConductor.e2e.spec.js
new file mode 100644
index 000000000..70fc8bae2
--- /dev/null
+++ b/e2e/tests/plugins/timeConductor/timeConductor.e2e.spec.js
@@ -0,0 +1,69 @@
+/*****************************************************************************
+ * Open MCT, Copyright (c) 2014-2022, United States Government
+ * as represented by the Administrator of the National Aeronautics and Space
+ * Administration. All rights reserved.
+ *
+ * Open MCT is licensed 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.
+ *
+ * Open MCT includes source code licensed under additional open source
+ * licenses. See the Open Source Licenses file (LICENSES.md) included with
+ * this source code distribution or the Licensing information page available
+ * at runtime from the About dialog for additional information.
+ *****************************************************************************/
+
+const { test, expect } = require('@playwright/test');
+
+test.describe('Time counductor operations', () => {
+ test('validate start time does not exceeds end time', async ({ page }) => {
+ //Go to baseURL
+ await page.goto('/', { waitUntil: 'networkidle' });
+ const year = new Date().getFullYear();
+
+ let startDate = 'xxxx-01-01 01:00:00.000Z';
+ startDate = year + startDate.substring(4);
+
+ let endDate = 'xxxx-01-01 02:00:00.000Z';
+ endDate = year + endDate.substring(4);
+
+ const startTimeLocator = page.locator('input[type="text"]').first();
+ const endTimeLocator = page.locator('input[type="text"]').nth(1);
+
+ // Click start time
+ await startTimeLocator.click();
+
+ // Click end time
+ await endTimeLocator.click();
+
+ await endTimeLocator.fill(endDate.toString());
+ await startTimeLocator.fill(startDate.toString());
+
+ // invalid start date
+ startDate = (year + 1) + startDate.substring(4);
+ await startTimeLocator.fill(startDate.toString());
+ await endTimeLocator.click();
+
+ const startDateValidityStatus = await startTimeLocator.evaluate((element) => element.checkValidity());
+ expect(startDateValidityStatus).not.toBeTruthy();
+
+ // fix to valid start date
+ startDate = (year - 1) + startDate.substring(4);
+ await startTimeLocator.fill(startDate.toString());
+
+ // invalid end date
+ endDate = (year - 2) + endDate.substring(4);
+ await endTimeLocator.fill(endDate.toString());
+ await startTimeLocator.click();
+
+ const endDateValidityStatus = await endTimeLocator.evaluate((element) => element.checkValidity());
+ expect(endDateValidityStatus).not.toBeTruthy();
+ });
+});
diff --git a/e2e/tests/visual/default.spec.js b/e2e/tests/visual/default.spec.js
index 60bd8052f..2ad857f92 100644
--- a/e2e/tests/visual/default.spec.js
+++ b/e2e/tests/visual/default.spec.js
@@ -111,3 +111,63 @@ test('Visual - Default Condition Widget', async ({ page }) => {
await page.waitForTimeout(VISUAL_GRACE_PERIOD);
await percySnapshot(page, 'Default Condition Widget');
});
+
+test('Visual - Time Conductor start time is less than end time', async ({ page }) => {
+ //Go to baseURL
+ await page.goto('/', { waitUntil: 'networkidle' });
+ const year = new Date().getFullYear();
+
+ let startDate = 'xxxx-01-01 01:00:00.000Z';
+ startDate = year + startDate.substring(4);
+
+ let endDate = 'xxxx-01-01 02:00:00.000Z';
+ endDate = year + endDate.substring(4);
+
+ await page.locator('input[type="text"]').nth(1).fill(endDate.toString());
+ await page.locator('input[type="text"]').first().fill(startDate.toString());
+
+ // verify no error msg
+ await page.waitForTimeout(VISUAL_GRACE_PERIOD);
+ await percySnapshot(page, 'Default Time conductor');
+
+ startDate = (year + 1) + startDate.substring(4);
+ await page.locator('input[type="text"]').first().fill(startDate.toString());
+ await page.locator('input[type="text"]').nth(1).click();
+
+ // verify error msg for start time (unable to capture snapshot of popup)
+ await page.waitForTimeout(VISUAL_GRACE_PERIOD);
+ await percySnapshot(page, 'Start time error');
+
+ startDate = (year - 1) + startDate.substring(4);
+ await page.locator('input[type="text"]').first().fill(startDate.toString());
+
+ endDate = (year - 2) + endDate.substring(4);
+ await page.locator('input[type="text"]').nth(1).fill(endDate.toString());
+
+ await page.locator('input[type="text"]').first().click();
+
+ // verify error msg for end time (unable to capture snapshot of popup)
+ await page.waitForTimeout(VISUAL_GRACE_PERIOD);
+ await percySnapshot(page, 'End time error');
+});
+
+test('Visual - Sine Wave Generator Form', async ({ page }) => {
+ //Go to baseURL
+ await page.goto('/', { waitUntil: 'networkidle' });
+
+ //Click the Create button
+ await page.click('button:has-text("Create")');
+
+ // Click text=Sine Wave Generator
+ await page.click('text=Sine Wave Generator');
+
+ await page.waitForTimeout(VISUAL_GRACE_PERIOD);
+ await percySnapshot(page, 'Default Sine Wave Generator Form');
+
+ await page.locator('.field.control.l-input-sm input').first().click();
+ await page.locator('.field.control.l-input-sm input').first().fill('');
+
+ // Validate red x mark
+ await page.waitForTimeout(VISUAL_GRACE_PERIOD);
+ await percySnapshot(page, 'removed amplitude property value');
+});
diff --git a/package.json b/package.json
index 8a3938b86..fadea1347 100644
--- a/package.json
+++ b/package.json
@@ -30,7 +30,7 @@
"html-loader": "0.5.5",
"html2canvas": "1.4.1",
"imports-loader": "0.8.0",
- "istanbul-instrumenter-loader": "^3.0.1",
+ "istanbul-instrumenter-loader": "3.0.1",
"jasmine-core": "4.0.0",
"jsdoc": "3.5.5",
"karma": "6.3.15",
@@ -43,36 +43,36 @@
"karma-junit-reporter": "2.0.1",
"karma-sourcemap-loader": "0.3.8",
"karma-spec-reporter": "0.0.33",
- "karma-webpack": "^5.0.0",
- "location-bar": "^3.0.1",
- "lodash": "^4.17.12",
+ "karma-webpack": "5.0.0",
+ "location-bar": "3.0.1",
+ "lodash": "4.17.12",
"mini-css-extract-plugin": "2.4.5",
"moment": "2.29.1",
- "moment-duration-format": "^2.2.2",
+ "moment-duration-format": "2.2.2",
"moment-timezone": "0.5.28",
- "node-bourbon": "^4.2.3",
- "painterro": "^1.2.56",
- "plotly.js-basic-dist": "^2.5.0",
- "plotly.js-gl2d-dist": "^2.5.0",
- "printj": "^1.2.1",
- "raw-loader": "^0.5.1",
- "request": "^2.69.0",
+ "node-bourbon": "4.2.3",
+ "painterro": "1.2.56",
+ "plotly.js-basic-dist": "2.5.0",
+ "plotly.js-gl2d-dist": "2.5.0",
+ "printj": "1.2.1",
+ "raw-loader": "0.5.1",
+ "request": "2.69.0",
"resolve-url-loader": "4.0.0",
"sass": "1.49.0",
"sass-loader": "12.4.0",
"sinon": "13.0.1",
"style-loader": "^1.0.1",
- "uuid": "^3.3.3",
+ "uuid": "3.3.3",
"vue": "2.6.14",
"vue-eslint-parser": "8.2.0",
"vue-loader": "15.9.8",
"vue-template-compiler": "2.6.14",
"webpack": "5.68.0",
"webpack-cli": "4.9.2",
- "webpack-dev-middleware": "^3.1.3",
- "webpack-hot-middleware": "^2.22.3",
+ "webpack-dev-middleware": "3.7.3",
+ "webpack-hot-middleware": "2.22.3",
"webpack-merge": "5.8.0",
- "zepto": "^1.2.0"
+ "zepto": "1.2.0"
},
"scripts": {
"clean": "rm -rf ./dist ./node_modules; rm package-lock.json",
@@ -88,8 +88,8 @@
"test:debug": "cross-env NODE_ENV=debug karma start --no-single-run",
"test:coverage": "cross-env NODE_OPTIONS=\"--max_old_space_size=4096\" COVERAGE=true karma start --single-run",
"test:coverage:firefox": "cross-env NODE_OPTIONS=\"--max_old_space_size=4096\" karma start --single-run --browsers=FirefoxHeadless",
- "test:e2e:ci": "npx playwright test --config=e2e/playwright-ci.config.js --project=chrome smoke default condition.e2e",
- "test:e2e:local": "npx playwright test --config=e2e/playwright-local.config.js",
+ "test:e2e:ci": "npx playwright test --config=e2e/playwright-ci.config.js --project=chrome smoke default condition timeConductor",
+ "test:e2e:local": "npx playwright test --config=e2e/playwright-local.config.js --project=chrome",
"test:e2e:visual": "percy exec --config ./e2e/.percy.yml -- npx playwright test --config=e2e/playwright-visual.config.js default",
"test:e2e:full": "npx playwright test --config=e2e/playwright-ci.config.js",
"test:watch": "cross-env NODE_OPTIONS=\"--max_old_space_size=4096\" karma start --no-single-run",
diff --git a/src/api/forms/components/controls/NumberField.vue b/src/api/forms/components/controls/NumberField.vue
index 6a8bfef5e..77a27795b 100644
--- a/src/api/forms/components/controls/NumberField.vue
+++ b/src/api/forms/components/controls/NumberField.vue
@@ -30,13 +30,15 @@
:min="model.min"
:max="model.max"
:step="model.step"
- @blur="blur()"
+ @input="updateText()"
>
</span>
</span>
</template>
<script>
+import { throttle } from 'lodash';
+
export default {
props: {
model: {
@@ -49,8 +51,12 @@ export default {
field: this.model.value
};
},
+ mounted() {
+ this.updateText = throttle(this.updateText.bind(this), 200);
+ },
methods: {
- blur() {
+ updateText() {
+ console.log('updateText', this.field);
const data = {
model: this.model,
value: this.field
diff --git a/src/api/forms/components/controls/TextAreaField.vue b/src/api/forms/components/controls/TextAreaField.vue
index f3a724c78..8b0dad0b8 100644
--- a/src/api/forms/components/controls/TextAreaField.vue
+++ b/src/api/forms/components/controls/TextAreaField.vue
@@ -28,7 +28,7 @@
<textarea v-model="field"
type="text"
:size="model.size"
- @blur="blur()"
+ @input="updateText()"
>
</textarea>
</span>
@@ -36,6 +36,8 @@
</template>
<script>
+import { throttle } from 'lodash';
+
export default {
props: {
model: {
@@ -48,8 +50,11 @@ export default {
field: this.model.value
};
},
+ mounted() {
+ this.updateText = throttle(this.updateText.bind(this), 500);
+ },
methods: {
- blur() {
+ updateText() {
const data = {
model: this.model,
value: this.field
diff --git a/src/api/forms/components/controls/TextField.vue b/src/api/forms/components/controls/TextField.vue
index b13c133c2..939e42375 100644
--- a/src/api/forms/components/controls/TextField.vue
+++ b/src/api/forms/components/controls/TextField.vue
@@ -28,13 +28,15 @@
<input v-model="field"
type="text"
:size="model.size"
- @blur="blur()"
+ @input="updateText()"
>
</span>
</span>
</template>
<script>
+import { throttle } from 'lodash';
+
export default {
props: {
model: {
@@ -47,8 +49,11 @@ export default {
field: this.model.value
};
},
+ mounted() {
+ this.updateText = throttle(this.updateText.bind(this), 500);
+ },
methods: {
- blur() {
+ updateText() {
const data = {
model: this.model,
value: this.field
diff --git a/src/plugins/timeConductor/ConductorInputsFixed.vue b/src/plugins/timeConductor/ConductorInputsFixed.vue
index a14a3ef96..8e3bddd3b 100644
--- a/src/plugins/timeConductor/ConductorInputsFixed.vue
+++ b/src/plugins/timeConductor/ConductorInputsFixed.vue
@@ -253,6 +253,8 @@ export default {
input.title = '';
}
+ this.$refs.fixedDeltaInput.reportValidity();
+
return validationResult.valid;
},
startDateSelected(date) {