Compare commits
	
		
			8 Commits
		
	
	
		
			release/2.
			...
			timestrip-
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 2f79adcb88 | ||
|   | 92112cf8a2 | ||
|   | 56159843a2 | ||
|   | 93a81a1369 | ||
|   | 482d8f392c | ||
|   | 67234c70a4 | ||
|   | e9680e975f | ||
|   | e691a89682 | 
							
								
								
									
										2
									
								
								.github/workflows/e2e-pr.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/e2e-pr.yml
									
									
									
									
										vendored
									
									
								
							| @@ -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 | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/e2e-visual.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/e2e-visual.yml
									
									
									
									
										vendored
									
									
								
							| @@ -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 | ||||
|   | ||||
							
								
								
									
										161
									
								
								e2e/tests/example/generator/SinewaveLimitProvider.e2e.spec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								e2e/tests/example/generator/SinewaveLimitProvider.e2e.spec.js
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
|             } | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										46
									
								
								e2e/tests/plugins/notebook/notebook.e2e.spec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								e2e/tests/plugins/notebook/notebook.e2e.spec.js
									
									
									
									
									
										Normal file
									
								
							| @@ -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 Notebooks. | ||||
| */ | ||||
|  | ||||
| const { test, expect } = require('@playwright/test'); | ||||
|  | ||||
| test.describe('Notebook CRUD Operations', () => { | ||||
|     test.fixme('Can create a Notebook Object', async ({ page }) => { | ||||
|         //Create domain object | ||||
|     }); | ||||
|     test.fixme('Can update a Notebook Object', 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('Can view a perviously created Notebook Object', async ({ page }) => { | ||||
|         // Create 2 objects with hierarchy | ||||
|         // Export as JSON | ||||
|         // Verify Hiearchy | ||||
|     }); | ||||
|     test.fixme('Can Delete a Notebook Object', async ({ page }) => { | ||||
|         // Other than non-persistible objects | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										114
									
								
								e2e/tests/plugins/notebook/notebookTesting.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								e2e/tests/plugins/notebook/notebookTesting.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,114 @@ | ||||
|     Notebook Testing: | ||||
| ## Useful commands: | ||||
| 1.  - To check default notebook: | ||||
|     `JSON.parse(localStorage.getItem('notebook-storage'));` | ||||
| 1.  - Clear default notebook: | ||||
|     `localStorage.setItem('notebook-storage', null);` | ||||
|  | ||||
| ## I. Default Notebook: | ||||
| 1. Make sure there is no default notebook | ||||
|     `localStorage.setItem('notebook-storage', null);` | ||||
| 2. Check for default notebook is null | ||||
|     `JSON.parse(localStorage.getItem('notebook-storage'));` | ||||
| 3. Create 2 notebooks, add entry into first one to make it default now add entry to other one. Verify by icon change and using following | ||||
|     1. `JSON.parse(localStorage.getItem('notebook-storage'));` | ||||
|     2. There is default icon on notebook inside tree and main view after notebook name | ||||
|     3. Inside default notebook, default section and page has deafult icon. | ||||
| 4. Delete default notebook and check for default notebook is null and default icons are removed. | ||||
|     `JSON.parse(localStorage.getItem('notebook-storage'));` | ||||
|  | ||||
| ## II. Sections and Pages: | ||||
| 1.  - Newly created notebook should have one Section and one page, 'Unnamed Section'/'Unnamed Page' | ||||
|  | ||||
| ### - Sections: | ||||
| 1.  - Rename existing section '1 Section' and '1 Page' | ||||
|     - click 'add section' new section - should be added 'Unnamed Section' with new page 'Unnamed Page' | ||||
| 1.  - Delete existing section | ||||
|     - new 'Unnamed Section' automatically gets created. | ||||
| 1.  - Have 5 total sections without a default section/page | ||||
|     - select 3nd section then delete 4th section | ||||
|     - 3rd is still selected | ||||
| 1.  -  Have 5 total sections without a default section/page | ||||
|     - select 3rd section then delete 3rd section | ||||
|     - 1st is now selected | ||||
| 1.  - Have 5 total sections with a 3rd section as default section | ||||
|     - select 2nd section then delete 2nd section | ||||
|     - 3rd (default) is now selected | ||||
| 1.  - Have 5 total sections with a 3rd section as default section | ||||
|     - select 3rd section then delete 3rd section | ||||
|     - 1st is now selected and there is no default notebook | ||||
|  | ||||
| ### - Pages: | ||||
| 1.  - Delete existing page | ||||
|     - new 'Unnamed Page' automatically gets created | ||||
| 1.  - Have 5 total pages without a default page | ||||
|     - select 3nd page then delete 4th page | ||||
|     - 3rd is still selected | ||||
| 1.  - Have 5 total pages without a default page | ||||
|     - select 3rd page then delete 3rd page | ||||
|     - 1st is now selected | ||||
| 1.  - Have 5 total pages with a 3rd page as default page | ||||
|     - select 2nd page then delete 2nd page | ||||
|     - 3rd (default) is now selected | ||||
| 1.  - Have 5 total pages with a 3rd page as default page | ||||
|     - select 3rd page then delete 3rd page | ||||
|     - 1st is now selected and there is no default notebook | ||||
|  | ||||
| ## III. Entries: | ||||
| 1.  - Add new entry into page should create entry and focus on it | ||||
| 1.  - Drag and drop any telmetry object on 'drop object' | ||||
|     - new entry gets created with telemtry object | ||||
| 1.  - Add new entry into page | ||||
|     - drop any telmetry object on this entry | ||||
|     - telmetry object appears inside this entry | ||||
| 1.  - Add new entry into page, enter text | ||||
|     - navigate away and return | ||||
|     - edit entry text | ||||
|     - navigate away and return back | ||||
|     - confirm text is correct | ||||
| 1.  - delete previously created entry | ||||
|  | ||||
| ## IV: Snapshot Menu: | ||||
| 1.  - There should be no default notebook | ||||
|     - Clear default notebook if exists using `localStorage.setItem('notebook-storage', null);` | ||||
|     - refresh page | ||||
|     - Click on 'Notebook Snaphot Menu' | ||||
|     - Following popup option should be there | ||||
|         1. save to Notebook Snapshots | ||||
| 1.  - Check for default notebook if there is one, else add some entry into one of notebook to make it default | ||||
|     - Click on 'Notebook Snaphot Menu' | ||||
|     - Following popup options should be there | ||||
|         1. save to Default Notebook | ||||
|         1. save to Notebook Snapshots | ||||
| 1.  - Select any telemetry object eg: SWG | ||||
|     - From 'Notebook Snaphot Menu' click on 'save to Default Notebook' | ||||
|     - Navigate to default notebook - section - page and verify that SWG snaphot has been added with correct details | ||||
|  | ||||
| ## V: Snapshot container: | ||||
| 1.  - Select any telemetry object eg: SWG | ||||
|     - Click on 'Notebook Snaphot Menu' | ||||
|     - from popup options click on 'save to Notebook Snapshots' | ||||
|     - Snapshots indicator should blink, click on it to view snapshots | ||||
|     - drag and drop snapshot on droppable area for new enrty | ||||
|     - this should create a new entry with given snaphot has been added to it | ||||
| 1.  - Select any telemetry object eg: SWG | ||||
|     - Click on 'Notebook Snaphot Menu' | ||||
|     - from popup options click on 'save to Notebook Snapshots' | ||||
|     - Snapshots indicator should blink, click on it to view snapshots | ||||
|     - goto any notebook with pre exisintg entry (if not create new entry) | ||||
|     - drag and drop snapshot on exisintg entry | ||||
|     - this should add a given snaphot inside that entry | ||||
|  | ||||
| ## VI: Embeds: | ||||
| 1.  - Add SWG using snapshot to notebook | ||||
|     - Go to that entry | ||||
|     - click on thumbnail image | ||||
|     - should open image with PNG, JPG and Annotate buttons | ||||
|     - verify they all work as intended | ||||
| 1.  - Add SWG using snapshot to notebook | ||||
|     - note down start and end time on time conductor and Fixed Timestamp/Local Clock | ||||
|     - Go to that entry | ||||
|     - change start and end time on time conductor if Local Clock | ||||
|     - click on embed Name/Text | ||||
|     - should take to that object | ||||
|     - also verify that start and end time on time conductor (also should automatically switch to Fixed timestamp)*/ | ||||
							
								
								
									
										69
									
								
								e2e/tests/plugins/timeConductor/timeConductor.e2e.spec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								e2e/tests/plugins/timeConductor/timeConductor.e2e.spec.js
									
									
									
									
									
										Normal file
									
								
							| @@ -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(); | ||||
|     }); | ||||
| }); | ||||
							
								
								
									
										126
									
								
								e2e/tests/visual/default.visual.spec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								e2e/tests/visual/default.visual.spec.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,126 @@ | ||||
| /***************************************************************************** | ||||
|  * 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. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| /* | ||||
| Collection of Visual Tests set to run in a default context. The tests within this suite | ||||
| are only meant to run against openmct's app.js started by `npm run start` within the | ||||
| `./e2e/playwright-visual.config.js` file. | ||||
|  | ||||
| These should only use functional expect statements to verify assumptions about the state | ||||
| in a test and not for functional verification of correctness. Visual tests are not supposed | ||||
| to "fail" on assertions. Instead, they should be used to detect changes between builds or branches. | ||||
|  | ||||
| Note: Larger testsuite sizes are OK due to the setup time associated with these tests. | ||||
| */ | ||||
|  | ||||
| const { test, expect } = require('@playwright/test'); | ||||
| const percySnapshot = require('@percy/playwright'); | ||||
| const path = require('path'); | ||||
| const sinon = require('sinon'); | ||||
|  | ||||
| const VISUAL_GRACE_PERIOD = 5 * 1000; //Lets the application "simmer" before the snapshot is taken | ||||
|  | ||||
| // // Snippet from https://github.com/microsoft/playwright/issues/6347#issuecomment-965887758 | ||||
| // //Will replace with cy.clock() equivalent | ||||
| test.beforeEach(async ({ context }) => { | ||||
|     await context.addInitScript({ | ||||
|         // eslint-disable-next-line no-undef | ||||
|         path: path.join(__dirname, '../../..', './node_modules/sinon/pkg/sinon.js') | ||||
|     }); | ||||
|     await context.addInitScript(() => { | ||||
|         window.__clock = sinon.useFakeTimers({ | ||||
|             now: 1483228800000, | ||||
|             shouldAdvanceTime: true | ||||
|         }); //Set browser clock to UNIX Epoch | ||||
|     }); | ||||
| }); | ||||
|  | ||||
| test('Visual - Display layout items view', async ({ page }) => { | ||||
|     //Go to baseURL | ||||
|     await page.goto('/', { waitUntil: 'networkidle' }); | ||||
|  | ||||
|     await page.evaluate(() => window.__clock.tick(1000)); | ||||
|  | ||||
|     //Click the Create button | ||||
|     await page.click('button:has-text("Create")'); | ||||
|  | ||||
|     // Click text=Display Layout | ||||
|     await page.click('text=Display Layout'); | ||||
|  | ||||
|     // Click text=OK | ||||
|     await page.click('text=OK'); | ||||
|  | ||||
|     // Take a snapshot of the newly created Display Layout object | ||||
|     await page.waitForTimeout(VISUAL_GRACE_PERIOD); | ||||
|     await percySnapshot(page, 'Default Display Layout'); | ||||
|  | ||||
|     // Click text=Snapshot Save and Finish Editing Save and Continue Editing >> button >> nth=1 | ||||
|     await page.locator('text=Snapshot Save and Finish Editing Save and Continue Editing >> button').nth(1).click(); | ||||
|  | ||||
|     // Click text=Save and Finish Editing | ||||
|     await page.locator('text=Save and Finish Editing').click(); | ||||
|  | ||||
|     //Click the Create button | ||||
|     await page.click('button:has-text("Create")'); | ||||
|  | ||||
|     // Click text=Sine Wave Generator | ||||
|     await page.click('text=Sine Wave Generator'); | ||||
|  | ||||
|     // Click text=Save In Open MCT No items >> input[type="search"] | ||||
|     await page.locator('text=Save In Open MCT No items >> input[type="search"]').click(); | ||||
|  | ||||
|     // Fill text=Save In Open MCT No items >> input[type="search"] | ||||
|     await page.locator('text=Save In Open MCT No items >> input[type="search"]').fill('Unnamed Display Layout'); | ||||
|  | ||||
|     // Click text=OK Cancel | ||||
|     await page.locator('text=OK Cancel').click(); | ||||
|  | ||||
|     // Click text=OK | ||||
|     await page.click('text=OK'); | ||||
|  | ||||
|     // Take a snapshot of the newly created Display Layout object | ||||
|     await page.waitForTimeout(VISUAL_GRACE_PERIOD); | ||||
|     await percySnapshot(page, 'Default Sine Wave Generator'); | ||||
|  | ||||
| }); | ||||
|  | ||||
| test.skip('Visual - Timestrip', async ({ page }) => { | ||||
|     //Go to baseURL | ||||
|     await page.goto('/', { waitUntil: 'networkidle' }); | ||||
|  | ||||
|     //Click the Create button | ||||
|     await page.click('button:has-text("Create")'); | ||||
|  | ||||
|     // Click li:has-text("Example Imagery") | ||||
|     await page.locator('li:has-text("Example Imagery")').click(); | ||||
|  | ||||
|     // Fill input[type="number"] | ||||
|     //await page.locator('input[type="number"]').fill('500'); | ||||
|  | ||||
|     // Click text=OK | ||||
|     await page.locator('text=OK').click(); | ||||
|  | ||||
|     await page.pause(); | ||||
|     //  | ||||
|     await page.waitForTimeout(VISUAL_GRACE_PERIOD); | ||||
|     await percySnapshot(page, 'Default Timestrip created'); | ||||
| }); | ||||
| @@ -40,7 +40,7 @@ const sinon = require('sinon'); | ||||
| const VISUAL_GRACE_PERIOD = 5 * 1000; //Lets the application "simmer" before the snapshot is taken
 | ||||
| 
 | ||||
| // Snippet from https://github.com/microsoft/playwright/issues/6347#issuecomment-965887758
 | ||||
| // Will replace with cy.clock() equivalent
 | ||||
| //Will replace with cy.clock() equivalent
 | ||||
| test.beforeEach(async ({ context }) => { | ||||
|     await context.addInitScript({ | ||||
|         // eslint-disable-next-line no-undef
 | ||||
| @@ -112,28 +112,48 @@ test('Visual - Default Condition Widget', async ({ page }) => { | ||||
|     await percySnapshot(page, 'Default Condition Widget'); | ||||
| }); | ||||
| 
 | ||||
| test.skip('Visual - Display layout items view', async ({ page }) => { | ||||
| 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(); | ||||
| 
 | ||||
|     //Click the Create button
 | ||||
|     await page.click('button:has-text("Create")'); | ||||
|     let startDate = 'xxxx-01-01 01:00:00.000Z'; | ||||
|     startDate = year + startDate.substring(4); | ||||
| 
 | ||||
|     // Click text=Display Layout
 | ||||
|     await page.click('text=Display Layout'); | ||||
|     let endDate = 'xxxx-01-01 02:00:00.000Z'; | ||||
|     endDate = year + endDate.substring(4); | ||||
| 
 | ||||
|     // Click text=OK
 | ||||
|     await page.click('text=OK'); | ||||
|     await page.locator('input[type="text"]').nth(1).fill(endDate.toString()); | ||||
|     await page.locator('input[type="text"]').first().fill(startDate.toString()); | ||||
| 
 | ||||
|     // Take a snapshot of the newly created Display Layout object
 | ||||
|     //  verify no error msg
 | ||||
|     await page.waitForTimeout(VISUAL_GRACE_PERIOD); | ||||
|     await percySnapshot(page, 'Default Display Layout'); | ||||
|     await percySnapshot(page, 'Default Time conductor'); | ||||
| 
 | ||||
|     // Click text=Snapshot Save and Finish Editing Save and Continue Editing >> button >> nth=1
 | ||||
|     await page.locator('text=Snapshot Save and Finish Editing Save and Continue Editing >> button').nth(1).click(); | ||||
|     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(); | ||||
| 
 | ||||
|     // Click text=Save and Finish Editing
 | ||||
|     await page.locator('text=Save and Finish Editing').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")'); | ||||
| @@ -141,20 +161,35 @@ test.skip('Visual - Display layout items view', async ({ page }) => { | ||||
|     // Click text=Sine Wave Generator
 | ||||
|     await page.click('text=Sine Wave Generator'); | ||||
| 
 | ||||
|     // Click text=Save In Open MCT No items >> input[type="search"]
 | ||||
|     await page.locator('text=Save In Open MCT No items >> input[type="search"]').click(); | ||||
|     await page.waitForTimeout(VISUAL_GRACE_PERIOD); | ||||
|     await percySnapshot(page, 'Default Sine Wave Generator Form'); | ||||
| 
 | ||||
|     // Fill text=Save In Open MCT No items >> input[type="search"]
 | ||||
|     await page.locator('text=Save In Open MCT No items >> input[type="search"]').fill('Unnamed Display Layout'); | ||||
|     await page.locator('.field.control.l-input-sm input').first().click(); | ||||
|     await page.locator('.field.control.l-input-sm input').first().fill(''); | ||||
| 
 | ||||
|     // Click text=OK Cancel
 | ||||
|     await page.locator('text=OK Cancel').click(); | ||||
|     // Validate red x mark
 | ||||
|     await page.waitForTimeout(VISUAL_GRACE_PERIOD); | ||||
|     await percySnapshot(page, 'removed amplitude property value'); | ||||
| }); | ||||
| 
 | ||||
| test.only('Visual - Timestrip', async ({ page }) => { | ||||
|     //Go to baseURL
 | ||||
|     await page.goto('/', { waitUntil: 'networkidle' }); | ||||
| 
 | ||||
|     //Click the Create button
 | ||||
|     await page.click('button:has-text("Create")'); | ||||
| 
 | ||||
|     // Click li:has-text("Example Imagery")
 | ||||
|     await page.locator('li:has-text("Example Imagery")').click(); | ||||
| 
 | ||||
|     // Fill input[type="number"]
 | ||||
|     //await page.locator('input[type="number"]').fill('500');
 | ||||
| 
 | ||||
|     // Click text=OK
 | ||||
|     await page.click('text=OK'); | ||||
|     await page.locator('text=OK').click(); | ||||
| 
 | ||||
|     // Take a snapshot of the newly created Display Layout object
 | ||||
|     await page.pause(); | ||||
|     // 
 | ||||
|     await page.waitForTimeout(VISUAL_GRACE_PERIOD); | ||||
|     await percySnapshot(page, 'Default Sine Wave Generator'); | ||||
| 
 | ||||
|     await percySnapshot(page, 'Default Timestrip created'); | ||||
| }); | ||||
							
								
								
									
										38
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								package.json
									
									
									
									
									
								
							| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "openmct", | ||||
|   "version": "2.0.1", | ||||
|   "version": "2.0.1-SNAPSHOT", | ||||
|   "description": "The Open MCT core platform", | ||||
|   "devDependencies": { | ||||
|     "@braintree/sanitize-url": "6.0.0", | ||||
| @@ -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", | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -15,8 +15,7 @@ export default function (folderName, couchPlugin, searchFilter) { | ||||
|                     return Promise.resolve({ | ||||
|                         identifier, | ||||
|                         type: 'folder', | ||||
|                         name: folderName || "CouchDB Documents", | ||||
|                         location: 'ROOT' | ||||
|                         name: folderName || "CouchDB Documents" | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|   | ||||
| @@ -85,8 +85,7 @@ describe('the plugin', function () { | ||||
|             expect(object).toEqual({ | ||||
|                 identifier, | ||||
|                 type: 'folder', | ||||
|                 name: 'CouchDB Documents', | ||||
|                 location: 'ROOT' | ||||
|                 name: "CouchDB Documents" | ||||
|             }); | ||||
|         }); | ||||
|     }); | ||||
|   | ||||
| @@ -166,7 +166,7 @@ export default { | ||||
|     }, | ||||
|     computed: { | ||||
|         gridSize() { | ||||
|             return this.domainObject.configuration.layoutGrid.map(Number); | ||||
|             return this.domainObject.configuration.layoutGrid; | ||||
|         }, | ||||
|         layoutItems() { | ||||
|             return this.domainObject.configuration.items; | ||||
|   | ||||
| @@ -43,7 +43,7 @@ | ||||
|         <template v-for="(container, index) in containers"> | ||||
|             <drop-hint | ||||
|                 v-if="index === 0 && containers.length > 1" | ||||
|                 :key="`hint-top-${container.id}`" | ||||
|                 :key="index" | ||||
|                 class="c-fl-frame__drop-hint" | ||||
|                 :index="-1" | ||||
|                 :allow-drop="allowContainerDrop" | ||||
| @@ -51,7 +51,7 @@ | ||||
|             /> | ||||
|  | ||||
|             <container-component | ||||
|                 :key="`component-${container.id}`" | ||||
|                 :key="container.id" | ||||
|                 class="c-fl__container" | ||||
|                 :index="index" | ||||
|                 :container="container" | ||||
| @@ -66,7 +66,7 @@ | ||||
|  | ||||
|             <resize-handle | ||||
|                 v-if="index !== (containers.length - 1)" | ||||
|                 :key="`handle-${container.id}`" | ||||
|                 :key="index" | ||||
|                 :index="index" | ||||
|                 :orientation="rowsLayout ? 'vertical' : 'horizontal'" | ||||
|                 :is-editing="isEditing" | ||||
| @@ -77,7 +77,7 @@ | ||||
|  | ||||
|             <drop-hint | ||||
|                 v-if="containers.length > 1" | ||||
|                 :key="`hint-bottom-${container.id}`" | ||||
|                 :key="index" | ||||
|                 class="c-fl-frame__drop-hint" | ||||
|                 :index="index" | ||||
|                 :allow-drop="allowContainerDrop" | ||||
|   | ||||
| @@ -90,17 +90,6 @@ export default class LinkAction { | ||||
|  | ||||
|     validate(currentParent) { | ||||
|         return (data) => { | ||||
|  | ||||
|             // default current parent to ROOT, if it's undefined, then it's a root level item | ||||
|             if (currentParent === undefined) { | ||||
|                 currentParent = { | ||||
|                     identifier: { | ||||
|                         key: 'ROOT', | ||||
|                         namespace: '' | ||||
|                     } | ||||
|                 }; | ||||
|             } | ||||
|  | ||||
|             const parentCandidate = data.value[0]; | ||||
|             const currentParentKeystring = this.openmct.objects.makeKeyString(currentParent.identifier); | ||||
|             const parentCandidateKeystring = this.openmct.objects.makeKeyString(parentCandidate.identifier); | ||||
|   | ||||
| @@ -92,33 +92,23 @@ export default class RemoveAction { | ||||
|             this.openmct.editor.save(); | ||||
|         } | ||||
|  | ||||
|         if (!this.isAlias(child, parent)) { | ||||
|         const parentKeyString = this.openmct.objects.makeKeyString(parent.identifier); | ||||
|         const isAlias = parentKeyString !== child.location; | ||||
|  | ||||
|         if (!isAlias) { | ||||
|             this.openmct.objects.mutate(child, 'location', null); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     isAlias(child, parent) { | ||||
|         if (parent === undefined) { | ||||
|             // then it's a root item, not an alias | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         const parentKeyString = this.openmct.objects.makeKeyString(parent.identifier); | ||||
|         const childLocation = child.location; | ||||
|  | ||||
|         return childLocation !== parentKeyString; | ||||
|     } | ||||
|  | ||||
|     appliesTo(objectPath) { | ||||
|         const parent = objectPath[1]; | ||||
|         const parentType = parent && this.openmct.types.get(parent.type); | ||||
|         const child = objectPath[0]; | ||||
|         const locked = child.locked ? child.locked : parent && parent.locked; | ||||
|         const isEditing = this.openmct.editor.isEditing(); | ||||
|         const isPersistable = this.openmct.objects.isPersistable(child.identifier); | ||||
|         const isAlias = this.isAlias(child, parent); | ||||
|         let parent = objectPath[1]; | ||||
|         let parentType = parent && this.openmct.types.get(parent.type); | ||||
|         let child = objectPath[0]; | ||||
|         let locked = child.locked ? child.locked : parent && parent.locked; | ||||
|         let isEditing = this.openmct.editor.isEditing(); | ||||
|         let isPersistable = this.openmct.objects.isPersistable(child.identifier); | ||||
|  | ||||
|         if (locked || (!isPersistable && !isAlias)) { | ||||
|         if (locked || !isPersistable) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -31,11 +31,9 @@ | ||||
| > | ||||
|     <div class="c-conductor__time-bounds"> | ||||
|         <conductor-inputs-fixed v-if="isFixed" | ||||
|                                 :input-bounds="viewBounds" | ||||
|                                 @updated="saveFixedOffsets" | ||||
|         /> | ||||
|         <conductor-inputs-realtime v-else | ||||
|                                    :input-bounds="viewBounds" | ||||
|                                    @updated="saveClockOffsets" | ||||
|         /> | ||||
|         <ConductorModeIcon class="c-conductor__mode-icon" /> | ||||
|   | ||||
| @@ -71,12 +71,6 @@ export default { | ||||
|             default() { | ||||
|                 return undefined; | ||||
|             } | ||||
|         }, | ||||
|         inputBounds: { | ||||
|             type: Object, | ||||
|             default() { | ||||
|                 return undefined; | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     data() { | ||||
| @@ -104,12 +98,6 @@ export default { | ||||
|     watch: { | ||||
|         keyString() { | ||||
|             this.setTimeContext(); | ||||
|         }, | ||||
|         inputBounds: { | ||||
|             handler(newBounds) { | ||||
|                 this.handleNewBounds(newBounds); | ||||
|             }, | ||||
|             deep: true | ||||
|         } | ||||
|     }, | ||||
|     mounted() { | ||||
| @@ -265,6 +253,8 @@ export default { | ||||
|                 input.title = ''; | ||||
|             } | ||||
|  | ||||
|             this.$refs.fixedDeltaInput.reportValidity(); | ||||
|  | ||||
|             return validationResult.valid; | ||||
|         }, | ||||
|         startDateSelected(date) { | ||||
|   | ||||
| @@ -21,7 +21,7 @@ | ||||
|             ref="startOffset" | ||||
|             class="c-button c-conductor__delta-button" | ||||
|             title="Set the time offset after now" | ||||
|             @click.prevent.stop="showTimePopupStart" | ||||
|             @click.prevent="showTimePopupStart" | ||||
|         > | ||||
|             {{ offsets.start }} | ||||
|         </button> | ||||
| @@ -60,7 +60,7 @@ | ||||
|             ref="endOffset" | ||||
|             class="c-button c-conductor__delta-button" | ||||
|             title="Set the time offset preceding now" | ||||
|             @click.prevent.stop="showTimePopupEnd" | ||||
|             @click.prevent="showTimePopupEnd" | ||||
|         > | ||||
|             {{ offsets.end }} | ||||
|         </button> | ||||
| @@ -86,12 +86,6 @@ export default { | ||||
|             default() { | ||||
|                 return undefined; | ||||
|             } | ||||
|         }, | ||||
|         inputBounds: { | ||||
|             type: Object, | ||||
|             default() { | ||||
|                 return undefined; | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     data() { | ||||
| @@ -124,12 +118,6 @@ export default { | ||||
|     watch: { | ||||
|         keyString() { | ||||
|             this.setTimeContext(); | ||||
|         }, | ||||
|         inputBounds: { | ||||
|             handler(newBounds) { | ||||
|                 this.handleNewBounds(newBounds); | ||||
|             }, | ||||
|             deep: true | ||||
|         } | ||||
|     }, | ||||
|     mounted() { | ||||
|   | ||||
| @@ -122,9 +122,6 @@ | ||||
|         flex: 1 1 auto; | ||||
|         height: 0; // Chrome 73 overflow bug fix | ||||
|         overflow: auto; | ||||
|         //To accommodate independent time conductor controls | ||||
|         display: flex; | ||||
|         flex-direction: column; | ||||
|  | ||||
|         .u-fills-container { | ||||
|             // Expand component types that fill a container | ||||
|   | ||||
		Reference in New Issue
	
	Block a user