Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
haisamido authored Mar 7, 2024
2 parents 45ea2ee + ab49f3f commit a616d03
Show file tree
Hide file tree
Showing 26 changed files with 1,060 additions and 749 deletions.
2 changes: 2 additions & 0 deletions e2e/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ Current list of test tags:
|`@unstable` | A new test or test which is known to be flaky.|
|`@2p` | Indicates that multiple users are involved, or multiple tabs/pages are used. Useful for testing multi-user interactivity.|
|`@generatedata` | Indicates that a test is used to generate testdata or test the generated test data. Usually to be associated with localstorage, but this may grow over time.|
|`@clock` | A test which modifies the clock. These have expanded out of the visual tests and into the functional tests.

### Continuous Integration

Expand Down Expand Up @@ -447,6 +448,7 @@ By adhering to this principle, we can create tests that are both robust and refl
- Utilize `percyCSS` to ignore time-based elements. For more details, consult our [percyCSS file](./.percy.ci.yml).
- Use Open MCT's fixed-time mode unless explicitly testing realtime clock
- Employ the `createExampleTelemetryObject` appAction to source telemetry and specify a `name` to avoid autogenerated names.
- Avoid creating objects with a time component like timers and clocks.
5. **Hide the Tree and Inspector**: Generally, your test will not require comparisons involving the tree and inspector. These aspects are covered in component-specific tests (explained below). To exclude them from the comparison by default, navigate to the root of the main view with the tree and inspector hidden:
- `await page.goto('./#/browse/mine?hideTree=true&hideInspector=true')`
Expand Down
100 changes: 42 additions & 58 deletions e2e/helper/faultUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@
*****************************************************************************/
import { fileURLToPath } from 'url';

import { expect } from '../pluginFixtures.js';

/**
* @param {import('@playwright/test').Page} page
*/
async function navigateToFaultManagementWithExample(page) {
export async function navigateToFaultManagementWithExample(page) {
await page.addInitScript({
path: fileURLToPath(new URL('./addInitExampleFaultProvider.js', import.meta.url))
});
Expand All @@ -35,7 +37,7 @@ async function navigateToFaultManagementWithExample(page) {
/**
* @param {import('@playwright/test').Page} page
*/
async function navigateToFaultManagementWithStaticExample(page) {
export async function navigateToFaultManagementWithStaticExample(page) {
await page.addInitScript({
path: fileURLToPath(new URL('./addInitExampleFaultProviderStatic.js', import.meta.url))
});
Expand All @@ -46,7 +48,7 @@ async function navigateToFaultManagementWithStaticExample(page) {
/**
* @param {import('@playwright/test').Page} page
*/
async function navigateToFaultManagementWithoutExample(page) {
export async function navigateToFaultManagementWithoutExample(page) {
await page.addInitScript({
path: fileURLToPath(new URL('./addInitFaultManagementPlugin.js', import.meta.url))
});
Expand All @@ -57,7 +59,7 @@ async function navigateToFaultManagementWithoutExample(page) {
/**
* @param {import('@playwright/test').Page} page
*/
async function navigateToFaultItemInTree(page) {
export async function navigateToFaultItemInTree(page) {
await page.goto('./', { waitUntil: 'networkidle' });

const faultManagementTreeItem = page
Expand All @@ -75,88 +77,95 @@ async function navigateToFaultItemInTree(page) {
/**
* @param {import('@playwright/test').Page} page
*/
async function acknowledgeFault(page, rowNumber) {
export async function acknowledgeFault(page, rowNumber) {
await openFaultRowMenu(page, rowNumber);
await page.locator('.c-menu >> text="Acknowledge"').click();
// Click [aria-label="Save"]
await page.locator('[aria-label="Save"]').click();
await page.getByLabel('Acknowledge', { exact: true }).click();
await page.getByLabel('Save').click();
}

/**
* @param {import('@playwright/test').Page} page
*/
async function shelveMultipleFaults(page, ...nums) {
export async function shelveMultipleFaults(page, ...nums) {
const selectRows = nums.map((num) => {
return selectFaultItem(page, num);
});
await Promise.all(selectRows);

await page.locator('button:has-text("Shelve")').click();
await page.locator('[aria-label="Save"]').click();
await page.getByLabel('Shelve selected faults').click();
await page.getByLabel('Save').click();
}

/**
* @param {import('@playwright/test').Page} page
*/
async function acknowledgeMultipleFaults(page, ...nums) {
export async function acknowledgeMultipleFaults(page, ...nums) {
const selectRows = nums.map((num) => {
return selectFaultItem(page, num);
});
await Promise.all(selectRows);

await page.locator('button:has-text("Acknowledge")').click();
await page.locator('[aria-label="Save"]').click();
await page.getByLabel('Save').click();
}

/**
* @param {import('@playwright/test').Page} page
*/
async function shelveFault(page, rowNumber) {
export async function shelveFault(page, rowNumber) {
await openFaultRowMenu(page, rowNumber);
await page.locator('.c-menu >> text="Shelve"').click();
// Click [aria-label="Save"]
await page.locator('[aria-label="Save"]').click();
await page.getByLabel('Save').click();
}

/**
* @param {import('@playwright/test').Page} page
*/
async function changeViewTo(page, view) {
export async function changeViewTo(page, view) {
await page.locator('.c-fault-mgmt__search-row select').first().selectOption(view);
}

/**
* @param {import('@playwright/test').Page} page
*/
async function sortFaultsBy(page, sort) {
export async function sortFaultsBy(page, sort) {
await page.locator('.c-fault-mgmt__list-header-sortButton select').selectOption(sort);
}

/**
* @param {import('@playwright/test').Page} page
*/
async function enterSearchTerm(page, term) {
export async function enterSearchTerm(page, term) {
await page.locator('.c-fault-mgmt-search [aria-label="Search Input"]').fill(term);
}

/**
* @param {import('@playwright/test').Page} page
*/
async function clearSearch(page) {
export async function clearSearch(page) {
await enterSearchTerm(page, '');
}

/**
* @param {import('@playwright/test').Page} page
*/
async function selectFaultItem(page, rowNumber) {
await page.locator(`.c-fault-mgmt-item > input >> nth=${rowNumber - 1}`).check();
export async function selectFaultItem(page, rowNumber) {
await page
.getByLabel('Select fault')
.nth(rowNumber - 1)
.check({
// Need force here because checkbox state is changed by an event emitted by the checkbox
// eslint-disable-next-line playwright/no-force-option
force: true
});
await expect(page.getByLabel('Select fault').nth(rowNumber - 1)).toBeChecked();
}

/**
* @param {import('@playwright/test').Page} page
*/
async function getHighestSeverity(page) {
export async function getHighestSeverity(page) {
const criticalCount = await page.locator('[title=CRITICAL]').count();
const warningCount = await page.locator('[title=WARNING]').count();

Expand All @@ -172,7 +181,7 @@ async function getHighestSeverity(page) {
/**
* @param {import('@playwright/test').Page} page
*/
async function getLowestSeverity(page) {
export async function getLowestSeverity(page) {
const warningCount = await page.locator('[title=WARNING]').count();
const watchCount = await page.locator('[title=WATCH]').count();

Expand All @@ -188,7 +197,7 @@ async function getLowestSeverity(page) {
/**
* @param {import('@playwright/test').Page} page
*/
async function getFaultResultCount(page) {
export async function getFaultResultCount(page) {
const count = await page.locator('.c-faults-list-view-item-body > .c-fault-mgmt__list').count();

return count;
Expand All @@ -197,7 +206,7 @@ async function getFaultResultCount(page) {
/**
* @param {import('@playwright/test').Page} page
*/
function getFault(page, rowNumber) {
export function getFault(page, rowNumber) {
const fault = page.locator(
`.c-faults-list-view-item-body > .c-fault-mgmt__list >> nth=${rowNumber - 1}`
);
Expand All @@ -208,7 +217,7 @@ function getFault(page, rowNumber) {
/**
* @param {import('@playwright/test').Page} page
*/
function getFaultByName(page, name) {
export function getFaultByName(page, name) {
const fault = page.locator(`.c-fault-mgmt__list-faultname:has-text("${name}")`);

return fault;
Expand All @@ -217,7 +226,7 @@ function getFaultByName(page, name) {
/**
* @param {import('@playwright/test').Page} page
*/
async function getFaultName(page, rowNumber) {
export async function getFaultName(page, rowNumber) {
const faultName = await page
.locator(`.c-fault-mgmt__list-faultname >> nth=${rowNumber - 1}`)
.textContent();
Expand All @@ -228,7 +237,7 @@ async function getFaultName(page, rowNumber) {
/**
* @param {import('@playwright/test').Page} page
*/
async function getFaultSeverity(page, rowNumber) {
export async function getFaultSeverity(page, rowNumber) {
const faultSeverity = await page
.locator(`.c-faults-list-view-item-body .c-fault-mgmt__list-severity >> nth=${rowNumber - 1}`)
.getAttribute('title');
Expand All @@ -239,7 +248,7 @@ async function getFaultSeverity(page, rowNumber) {
/**
* @param {import('@playwright/test').Page} page
*/
async function getFaultNamespace(page, rowNumber) {
export async function getFaultNamespace(page, rowNumber) {
const faultNamespace = await page
.locator(`.c-fault-mgmt__list-path >> nth=${rowNumber - 1}`)
.textContent();
Expand All @@ -250,7 +259,7 @@ async function getFaultNamespace(page, rowNumber) {
/**
* @param {import('@playwright/test').Page} page
*/
async function getFaultTriggerTime(page, rowNumber) {
export async function getFaultTriggerTime(page, rowNumber) {
const faultTriggerTime = await page
.locator(`.c-fault-mgmt__list-trigTime >> nth=${rowNumber - 1} >> .c-fault-mgmt-item__value`)
.textContent();
Expand All @@ -261,35 +270,10 @@ async function getFaultTriggerTime(page, rowNumber) {
/**
* @param {import('@playwright/test').Page} page
*/
async function openFaultRowMenu(page, rowNumber) {
export async function openFaultRowMenu(page, rowNumber) {
// select
await page
.locator(`.c-fault-mgmt-item > .c-fault-mgmt__list-action-button >> nth=${rowNumber - 1}`)
.getByLabel('Disposition actions')
.nth(rowNumber - 1)
.click();
}

export {
acknowledgeFault,
acknowledgeMultipleFaults,
changeViewTo,
clearSearch,
enterSearchTerm,
getFault,
getFaultByName,
getFaultName,
getFaultNamespace,
getFaultResultCount,
getFaultSeverity,
getFaultTriggerTime,
getHighestSeverity,
getLowestSeverity,
navigateToFaultItemInTree,
navigateToFaultManagementWithExample,
navigateToFaultManagementWithoutExample,
navigateToFaultManagementWithStaticExample,
openFaultRowMenu,
selectFaultItem,
shelveFault,
shelveMultipleFaults,
sortFaultsBy
};
65 changes: 65 additions & 0 deletions e2e/helper/planningUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/

import { createDomainObjectWithDefaults, createPlanFromJSON } from '../appActions.js';
import { expect } from '../pluginFixtures.js';

/**
Expand Down Expand Up @@ -142,6 +143,18 @@ export function getLatestEndTime(planJson) {
return Math.max(...activities.map((activity) => activity.end));
}

/**
*
* @param {object} planJson
* @returns {object}
*/
export function getFirstActivity(planJson) {
const groups = Object.keys(planJson);
const firstGroupKey = groups[0];
const firstGroupItems = planJson[firstGroupKey];
return firstGroupItems[0];
}

/**
* Uses the Open MCT API to set the status of a plan to 'draft'.
* @param {import('@playwright/test').Page} page
Expand Down Expand Up @@ -172,3 +185,55 @@ export async function addPlanGetInterceptor(page) {
});
});
}

/**
* Create a Plan from JSON and add it to a Timelist and Navigate to the Plan view
* @param {import('@playwright/test').Page} page
*/
export async function createTimelistWithPlanAndSetActivityInProgress(page, planJson) {
await page.goto('./', { waitUntil: 'domcontentloaded' });

const timelist = await createDomainObjectWithDefaults(page, {
name: 'Time List',
type: 'Time List'
});

await createPlanFromJSON(page, {
name: 'Test Plan',
json: planJson,
parent: timelist.uuid
});

// Ensure that all activities are shown in the expanded view
const groups = Object.keys(planJson);
const firstGroupKey = groups[0];
const firstGroupItems = planJson[firstGroupKey];
const firstActivityForPlan = firstGroupItems[0];
const lastActivity = firstGroupItems[firstGroupItems.length - 1];
const startBound = firstActivityForPlan.start;
const endBound = lastActivity.end;

// Switch to fixed time mode with all plan events within the bounds
await page.goto(
`${timelist.url}?tc.mode=fixed&tc.startBound=${startBound}&tc.endBound=${endBound}&tc.timeSystem=utc&view=timelist.view`
);

// Change the object to edit mode
await page.getByRole('button', { name: 'Edit Object' }).click();

// Find the display properties section in the inspector
await page.getByRole('tab', { name: 'View Properties' }).click();
// Switch to expanded view and save the setting
await page.getByLabel('Display Style').selectOption({ label: 'Expanded' });

// Click on the "Save" button
await page.getByRole('button', { name: 'Save' }).click();
await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click();

const anActivity = page.getByRole('row').nth(0);

// Set the activity to in progress
await anActivity.click();
await page.getByRole('tab', { name: 'Activity' }).click();
await page.getByLabel('Activity Status', { exact: true }).selectOption({ label: 'In progress' });
}
2 changes: 1 addition & 1 deletion e2e/tests/framework/generateLocalStorageData.e2e.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import { expect, test } from '../../pluginFixtures.js';

const overlayPlotName = 'Overlay Plot with Telemetry Object';

test.describe('Generate Visual Test Data @localStorage @generatedata', () => {
test.describe('Generate Visual Test Data @localStorage @generatedata @clock', () => {
test.use({
clockOptions: {
now: MISSION_TIME,
Expand Down
Loading

0 comments on commit a616d03

Please sign in to comment.