Skip to content

Commit

Permalink
feat(Fault Management): allow fault providers to define shelve durati…
Browse files Browse the repository at this point in the history
…ons (#7849)

* refactor: clean up FaultManagementView code

* feat: providers can now provide "Shelve Duration" options

* fix(exampleFaultSource): support `getShelveDurations`

* a11y: aria label for fault management list item

* a11y(FaultManagement): more labels

* refactor: eliminate some faultUtils and refactor locator() out of tests

* docs: add some more docs to fault management api

* refactor: make for loop more readable

* test: use static faults when testing

* fix: set a timestamp for static faults and subtract so we get faults in order

* refactor: autoformat

* chore: add missing copyright header

* fix: use as default parameter to get value as method is called

* refactor: make magic number a const

* fix(codecov): use codecov github action to upload

* fix: generate the report

* build: update circleci yml to use codecov orb

* build: remove codecov scripts and package

* build: don't use the orb because things can't be easy

- nasa org disallows "third party" orbs

* build: only use `sudo` if we ain't da root user

---------

Co-authored-by: Andrew Henry <[email protected]>
  • Loading branch information
ozyx and akhenry authored Oct 1, 2024
1 parent 29f1956 commit ad30a0e
Show file tree
Hide file tree
Showing 11 changed files with 360 additions and 379 deletions.
43 changes: 41 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,45 @@ commands:
ls -latR >> /tmp/artifacts/dir.txt
- store_artifacts:
path: /tmp/artifacts/
download_verify_codecov_cli:
description: 'Download and verify Codecov CLI'
steps:
- run:
name: Download and verify Codecov CLI
command: |
# Download Codecov CLI
curl -Os https://cli.codecov.io/latest/linux/codecov
# Import Codecov's GPG key
curl https://keybase.io/codecovsecurity/pgp_keys.asc | gpg --no-default-keyring --keyring trustedkeys.gpg --import
# Download and verify the SHA256SUM and its signature
curl -Os https://cli.codecov.io/latest/linux/codecov.SHA256SUM
curl -Os https://cli.codecov.io/latest/linux/codecov.SHA256SUM.sig
gpgv codecov.SHA256SUM.sig codecov.SHA256SUM
# Verify the checksum
shasum -a 256 -c codecov.SHA256SUM
# Make the codecov executable
[[ $EUID -ne 0 ]] && sudo chmod +x codecov || chmod +x codecov
./codecov --help
generate_e2e_code_cov_report:
description: "Generate e2e code coverage artifacts and publish to codecov.io. Needed to that we can ignore the exit code status of the npm run test"
parameters:
suite:
type: string
steps:
- run: npm run cov:e2e:report || true
- run: npm run cov:e2e:<<parameters.suite>>:publish
- download_verify_codecov_cli
- run:
name: Upload coverage report to Codecov
command: |
./codecov --verbose upload-process --disable-search \
-t $CODECOV_TOKEN \
-n 'e2e-<<parameters.suite>>'-${CIRCLE_WORKFLOW_ID} \
-F e2e-<<parameters.suite>> \
-f ./coverage/e2e/lcov.info
jobs:
npm-audit:
parameters:
Expand Down Expand Up @@ -81,7 +112,15 @@ jobs:
mkdir -p dist/reports/tests/
TESTFILES=$(circleci tests glob "src/**/*Spec.js")
echo "$TESTFILES" | circleci tests run --command="xargs npm run test" --verbose
- run: npm run cov:unit:publish
- download_verify_codecov_cli
- run:
name: Upload coverage report to Codecov
command: |
./codecov --verbose upload-process --disable-search \
-t $CODECOV_TOKEN \
-n 'unit-test'-${CIRCLE_WORKFLOW_ID} \
-F unit \
-f ./coverage/unit/lcov.info
- store_test_results:
path: dist/reports/tests/
- store_artifacts:
Expand Down
13 changes: 10 additions & 3 deletions .github/workflows/e2e-couchdb.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,18 @@ jobs:
env:
COMMIT_INFO_SHA: ${{github.event.pull_request.head.sha }}
run: npm run test:e2e:couchdb

- name: Generate Code Coverage Report
run: npm run cov:e2e:report

- name: Publish Results to Codecov.io
env:
SUPER_SECRET: ${{ secrets.CODECOV_TOKEN }}
run: npm run cov:e2e:full:publish
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage/e2e/lcov.info
flags: e2e-full
fail_ci_if_error: true
verbose: true

- name: Archive test results
if: success() || failure()
Expand Down
127 changes: 47 additions & 80 deletions e2e/helper/faultUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { expect } from '../pluginFixtures.js';

/**
* @param {import('@playwright/test').Page} page
* @returns {Promise<void>}
*/
export async function navigateToFaultManagementWithExample(page) {
await page.addInitScript({
Expand All @@ -36,6 +37,7 @@ export async function navigateToFaultManagementWithExample(page) {

/**
* @param {import('@playwright/test').Page} page
* @returns {Promise<void>}
*/
export async function navigateToFaultManagementWithStaticExample(page) {
await page.addInitScript({
Expand All @@ -47,6 +49,7 @@ export async function navigateToFaultManagementWithStaticExample(page) {

/**
* @param {import('@playwright/test').Page} page
* @returns {Promise<void>}
*/
export async function navigateToFaultManagementWithoutExample(page) {
await page.addInitScript({
Expand All @@ -58,6 +61,7 @@ export async function navigateToFaultManagementWithoutExample(page) {

/**
* @param {import('@playwright/test').Page} page
* @returns {Promise<void>}
*/
async function navigateToFaultItemInTree(page) {
await page.goto('./', { waitUntil: 'domcontentloaded' });
Expand All @@ -77,6 +81,8 @@ async function navigateToFaultItemInTree(page) {

/**
* @param {import('@playwright/test').Page} page
* @param {number} rowNumber
* @returns {Promise<void>}
*/
export async function acknowledgeFault(page, rowNumber) {
await openFaultRowMenu(page, rowNumber);
Expand All @@ -86,6 +92,8 @@ export async function acknowledgeFault(page, rowNumber) {

/**
* @param {import('@playwright/test').Page} page
* @param {...number} nums
* @returns {Promise<void>}
*/
export async function shelveMultipleFaults(page, ...nums) {
const selectRows = nums.map((num) => {
Expand All @@ -99,57 +107,52 @@ export async function shelveMultipleFaults(page, ...nums) {

/**
* @param {import('@playwright/test').Page} page
* @param {...number} nums
* @returns {Promise<void>}
*/
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.getByLabel('Acknowledge selected faults').click();
await page.getByLabel('Save').click();
}

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

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

/**
* @param {import('@playwright/test').Page} page
* @param {'severity' | 'newest-first' | 'oldest-first'} sort
* @returns {Promise<void>}
*/
export async function sortFaultsBy(page, sort) {
await page.locator('.c-fault-mgmt__list-header-sortButton select').selectOption(sort);
}

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

/**
* @param {import('@playwright/test').Page} page
* @param {'acknowledged' | 'shelved' | 'standard view'} view
* @returns {Promise<void>}
*/
export async function clearSearch(page) {
await enterSearchTerm(page, '');
export async function changeViewTo(page, view) {
await page.getByTitle('View Filter').getByRole('combobox').selectOption(view);
}

/**
* @param {import('@playwright/test').Page} page
* @param {number} rowNumber
* @returns {Promise<void>}
*/
export async function selectFaultItem(page, rowNumber) {
await page
Expand All @@ -165,116 +168,80 @@ export async function selectFaultItem(page, rowNumber) {

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

if (criticalCount > 0) {
return 'CRITICAL';
} else if (warningCount > 0) {
return 'WARNING';
}

return 'WATCH';
}

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

if (watchCount > 0) {
return 'WATCH';
} else if (warningCount > 0) {
return 'WARNING';
}

return 'CRITICAL';
}

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

return count;
}

/**
* @param {import('@playwright/test').Page} page
* @param {number} rowNumber
* @returns {import('@playwright/test').Locator}
*/
export function getFault(page, rowNumber) {
const fault = page.locator(
`.c-faults-list-view-item-body > .c-fault-mgmt__list >> nth=${rowNumber - 1}`
);
const fault = page.getByLabel('Fault triggered at').nth(rowNumber - 1);

return fault;
}

/**
* @param {import('@playwright/test').Page} page
* @param {string} name
* @returns {import('@playwright/test').Locator}
*/
export function getFaultByName(page, name) {
const fault = page.locator(`.c-fault-mgmt__list-faultname:has-text("${name}")`);
const fault = page.getByLabel('Fault triggered at').filter({
hasText: name
});

return fault;
}

/**
* @param {import('@playwright/test').Page} page
* @param {number} rowNumber
* @returns {Promise<string>}
*/
export async function getFaultName(page, rowNumber) {
const faultName = await page
.locator(`.c-fault-mgmt__list-faultname >> nth=${rowNumber - 1}`)
.getByLabel('Fault name', { exact: true })
.nth(rowNumber - 1)
.textContent();

return faultName;
}

/**
* @param {import('@playwright/test').Page} page
*/
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');

return faultSeverity;
}

/**
* @param {import('@playwright/test').Page} page
* @param {number} rowNumber
* @returns {Promise<string>}
*/
export async function getFaultNamespace(page, rowNumber) {
const faultNamespace = await page
.locator(`.c-fault-mgmt__list-path >> nth=${rowNumber - 1}`)
.getByLabel('Fault namespace')
.nth(rowNumber - 1)
.textContent();

return faultNamespace;
}

/**
* @param {import('@playwright/test').Page} page
* @param {number} rowNumber
* @returns {Promise<string>}
*/
export async function getFaultTriggerTime(page, rowNumber) {
const faultTriggerTime = await page
.locator(`.c-fault-mgmt__list-trigTime >> nth=${rowNumber - 1} >> .c-fault-mgmt-item__value`)
.getByLabel('Last Trigger Time')
.nth(rowNumber - 1)
.textContent();

return faultTriggerTime.toString().trim();
}

/**
* @param {import('@playwright/test').Page} page
* @param {number} rowNumber
* @returns {Promise<void>}
*/
export async function openFaultRowMenu(page, rowNumber) {
// select
await page
.getByLabel('Disposition actions')
.getByLabel('Fault triggered at')
.nth(rowNumber - 1)
.getByLabel('Disposition Actions')
.click();
}
Loading

0 comments on commit ad30a0e

Please sign in to comment.