mirror of
https://github.com/nasa/openmct.git
synced 2024-12-24 23:36:41 +00:00
178 lines
7.5 KiB
JavaScript
178 lines
7.5 KiB
JavaScript
/*****************************************************************************
|
|
* Open MCT, Copyright (c) 2014-2024, 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 template is to be used when creating new test suites. It will be kept up to date with the latest improvements
|
|
* made by the Open MCT team. It will also follow our best pratices as those evolve. Please use this structure as a _reference_ and clear
|
|
* or update any references when creating a new test suite!
|
|
*
|
|
* To illustrate current best practices, we've included a mocked up test suite for Renaming a Timer domain object.
|
|
*
|
|
* Demonstrated:
|
|
* - Using appActions to leverage existing functions
|
|
* - Structure
|
|
* - @unstable annotation
|
|
* - await, expect, test, describe syntax
|
|
* - Writing a custom function for a test suite
|
|
* - Test stub for unfinished test coverage (test.fixme)
|
|
*
|
|
* The structure should follow
|
|
* 1. imports
|
|
* 2. test.describe()
|
|
* 3. -> test1
|
|
* -> test2
|
|
* -> test3(stub)
|
|
* 4. Any custom functions
|
|
*/
|
|
|
|
// Structure: Some standard Imports. Please update the required pathing.
|
|
import { createDomainObjectWithDefaults } from '../../appActions.js';
|
|
import { expect, test } from '../../pluginFixtures.js';
|
|
|
|
/**
|
|
* Structure:
|
|
* Try to keep a single describe block per logical groups of tests.
|
|
* If your test runtime exceeds 5 minutes or 500 lines, it's likely that it will need to be split.
|
|
*
|
|
* Annotations:
|
|
* Please use the @unstable tag at the end of the test title so that our automation can pick it up
|
|
* as a part of our test promotion pipeline.
|
|
*/
|
|
test.describe('Renaming Timer Object', () => {
|
|
// Top-level declaration of the Timer object created in beforeEach().
|
|
// We can then use this throughout the entire test suite.
|
|
let timer;
|
|
test.beforeEach(async ({ page }) => {
|
|
// Open a browser, navigate to the main page, and wait until all network events to resolve
|
|
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
|
|
|
// We provide some helper functions in appActions like `createDomainObjectWithDefaults()`.
|
|
// This example will create a Timer object with default properties, under the root folder:
|
|
timer = await createDomainObjectWithDefaults(page, { type: 'Timer' });
|
|
|
|
// Assert the object to be created and check its name in the title
|
|
await expect(page.locator('.l-browse-bar__object-name')).toContainText(timer.name);
|
|
});
|
|
|
|
/**
|
|
* Make sure to use testcase names which are descriptive and easy to understand.
|
|
* A good testcase name concisely describes the test's goal(s) and should give
|
|
* some hint as to what went wrong if the test fails.
|
|
*/
|
|
test('An existing Timer object can be renamed via the 3dot actions menu', async ({ page }) => {
|
|
const newObjectName = 'Renamed Timer';
|
|
|
|
// We've created an example of a shared function which pases the page and newObjectName values
|
|
await renameTimerFrom3DotMenu(page, timer.url, newObjectName);
|
|
|
|
// Assert that the name has changed in the browser bar to the value we assigned above
|
|
await expect(page.locator('.l-browse-bar__object-name')).toContainText(newObjectName);
|
|
});
|
|
|
|
test('An existing Timer object can be renamed twice', async ({ page }) => {
|
|
const newObjectName = 'Renamed Timer';
|
|
const newObjectName2 = 'Re-Renamed Timer';
|
|
|
|
await renameTimerFrom3DotMenu(page, timer.url, newObjectName);
|
|
|
|
// Assert that the name has changed in the browser bar to the value we assigned above
|
|
await expect(page.locator('.l-browse-bar__object-name')).toContainText(newObjectName);
|
|
|
|
// Rename the Timer object again
|
|
await renameTimerFrom3DotMenu(page, timer.url, newObjectName2);
|
|
|
|
// Assert that the name has changed in the browser bar to the second value
|
|
await expect(page.locator('.l-browse-bar__object-name')).toContainText(newObjectName2);
|
|
});
|
|
|
|
/**
|
|
* If you run out of time to write new tests, please stub in the missing tests
|
|
* in-place with a test.fixme and BDD-style test steps.
|
|
* Someone will carry the baton!
|
|
*/
|
|
test.fixme('Can Rename Timer Object from Tree', async ({ page }) => {
|
|
//Create a new object
|
|
//Copy this object
|
|
//Delete first object
|
|
//Expect copied object to persist
|
|
});
|
|
});
|
|
|
|
/**
|
|
* The next most important concept in our testing is working with telemetry objects. Telemetry is at the core of Open MCT
|
|
* and we have developed a great pattern for working with it.
|
|
*/
|
|
test.describe('Advanced: Working with telemetry objects', () => {
|
|
let displayLayout;
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
|
|
|
// Create a Display Layout with a meaningful name
|
|
displayLayout = await createDomainObjectWithDefaults(page, {
|
|
type: 'Display Layout',
|
|
name: 'Display Layout with Embedded SWG'
|
|
});
|
|
// Create Telemetry object within the parent object created above
|
|
await createDomainObjectWithDefaults(page, {
|
|
type: 'Sine Wave Generator',
|
|
name: 'Telemetry',
|
|
parent: displayLayout.uuid //reference the display layout in the creation process
|
|
});
|
|
});
|
|
test('Can directly navigate to a Display Layout with embedded telemetry', async ({ page }) => {
|
|
//Now you can directly navigate to the displayLayout created in the beforeEach with the embedded telemetry
|
|
await page.goto(displayLayout.url);
|
|
//Expect the created Telemetry Object to be visible when directly navigating to the displayLayout
|
|
await expect(page.getByTitle('Sine')).toBeVisible();
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Structure:
|
|
* Custom functions should be declared last.
|
|
* We are leaning on JSDoc pretty heavily to describe functionality. It is not required, but highly recommended.
|
|
*/
|
|
|
|
/**
|
|
* This is an example of a function which is shared between testcases in this test suite. When refactoring, we'll be looking
|
|
* for common functionality which makes sense to generalize for the entire test framework.
|
|
* @param {import('@playwright/test').Page} page
|
|
* @param {string} timerUrl The URL of the timer object to be renamed
|
|
* @param {string} newNameForTimer New name for object
|
|
*/
|
|
async function renameTimerFrom3DotMenu(page, timerUrl, newNameForTimer) {
|
|
// Navigate to the timer object
|
|
await page.goto(timerUrl);
|
|
|
|
// Click on 3 Dot Menu
|
|
await page.locator('button[title="More actions"]').click();
|
|
|
|
// Click text=Edit Properties...
|
|
await page.locator('text=Edit Properties...').click();
|
|
|
|
// Rename the timer object
|
|
await page.locator('text=Properties Title Notes >> input[type="text"]').fill(newNameForTimer);
|
|
|
|
// Click Ok button to Save
|
|
await page.locator('button:has-text("OK")').click();
|
|
}
|