Skip to content

Commit ad30a0e

Browse files
ozyxakhenry
andauthored
feat(Fault Management): allow fault providers to define shelve durations (#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]>
1 parent 29f1956 commit ad30a0e

File tree

11 files changed

+360
-379
lines changed

11 files changed

+360
-379
lines changed

.circleci/config.yml

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,45 @@ commands:
3737
ls -latR >> /tmp/artifacts/dir.txt
3838
- store_artifacts:
3939
path: /tmp/artifacts/
40+
download_verify_codecov_cli:
41+
description: 'Download and verify Codecov CLI'
42+
steps:
43+
- run:
44+
name: Download and verify Codecov CLI
45+
command: |
46+
# Download Codecov CLI
47+
curl -Os https://cli.codecov.io/latest/linux/codecov
48+
49+
# Import Codecov's GPG key
50+
curl https://keybase.io/codecovsecurity/pgp_keys.asc | gpg --no-default-keyring --keyring trustedkeys.gpg --import
51+
52+
# Download and verify the SHA256SUM and its signature
53+
curl -Os https://cli.codecov.io/latest/linux/codecov.SHA256SUM
54+
curl -Os https://cli.codecov.io/latest/linux/codecov.SHA256SUM.sig
55+
gpgv codecov.SHA256SUM.sig codecov.SHA256SUM
56+
57+
# Verify the checksum
58+
shasum -a 256 -c codecov.SHA256SUM
59+
60+
# Make the codecov executable
61+
[[ $EUID -ne 0 ]] && sudo chmod +x codecov || chmod +x codecov
62+
./codecov --help
4063
generate_e2e_code_cov_report:
4164
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"
4265
parameters:
4366
suite:
4467
type: string
4568
steps:
4669
- run: npm run cov:e2e:report || true
47-
- run: npm run cov:e2e:<<parameters.suite>>:publish
70+
- download_verify_codecov_cli
71+
- run:
72+
name: Upload coverage report to Codecov
73+
command: |
74+
./codecov --verbose upload-process --disable-search \
75+
-t $CODECOV_TOKEN \
76+
-n 'e2e-<<parameters.suite>>'-${CIRCLE_WORKFLOW_ID} \
77+
-F e2e-<<parameters.suite>> \
78+
-f ./coverage/e2e/lcov.info
4879
jobs:
4980
npm-audit:
5081
parameters:
@@ -81,7 +112,15 @@ jobs:
81112
mkdir -p dist/reports/tests/
82113
TESTFILES=$(circleci tests glob "src/**/*Spec.js")
83114
echo "$TESTFILES" | circleci tests run --command="xargs npm run test" --verbose
84-
- run: npm run cov:unit:publish
115+
- download_verify_codecov_cli
116+
- run:
117+
name: Upload coverage report to Codecov
118+
command: |
119+
./codecov --verbose upload-process --disable-search \
120+
-t $CODECOV_TOKEN \
121+
-n 'unit-test'-${CIRCLE_WORKFLOW_ID} \
122+
-F unit \
123+
-f ./coverage/unit/lcov.info
85124
- store_test_results:
86125
path: dist/reports/tests/
87126
- store_artifacts:

.github/workflows/e2e-couchdb.yml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,18 @@ jobs:
5151
env:
5252
COMMIT_INFO_SHA: ${{github.event.pull_request.head.sha }}
5353
run: npm run test:e2e:couchdb
54+
55+
- name: Generate Code Coverage Report
56+
run: npm run cov:e2e:report
5457

5558
- name: Publish Results to Codecov.io
56-
env:
57-
SUPER_SECRET: ${{ secrets.CODECOV_TOKEN }}
58-
run: npm run cov:e2e:full:publish
59+
uses: codecov/codecov-action@v4
60+
with:
61+
token: ${{ secrets.CODECOV_TOKEN }}
62+
files: ./coverage/e2e/lcov.info
63+
flags: e2e-full
64+
fail_ci_if_error: true
65+
verbose: true
5966

6067
- name: Archive test results
6168
if: success() || failure()

e2e/helper/faultUtils.js

Lines changed: 47 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { expect } from '../pluginFixtures.js';
2525

2626
/**
2727
* @param {import('@playwright/test').Page} page
28+
* @returns {Promise<void>}
2829
*/
2930
export async function navigateToFaultManagementWithExample(page) {
3031
await page.addInitScript({
@@ -36,6 +37,7 @@ export async function navigateToFaultManagementWithExample(page) {
3637

3738
/**
3839
* @param {import('@playwright/test').Page} page
40+
* @returns {Promise<void>}
3941
*/
4042
export async function navigateToFaultManagementWithStaticExample(page) {
4143
await page.addInitScript({
@@ -47,6 +49,7 @@ export async function navigateToFaultManagementWithStaticExample(page) {
4749

4850
/**
4951
* @param {import('@playwright/test').Page} page
52+
* @returns {Promise<void>}
5053
*/
5154
export async function navigateToFaultManagementWithoutExample(page) {
5255
await page.addInitScript({
@@ -58,6 +61,7 @@ export async function navigateToFaultManagementWithoutExample(page) {
5861

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

7882
/**
7983
* @param {import('@playwright/test').Page} page
84+
* @param {number} rowNumber
85+
* @returns {Promise<void>}
8086
*/
8187
export async function acknowledgeFault(page, rowNumber) {
8288
await openFaultRowMenu(page, rowNumber);
@@ -86,6 +92,8 @@ export async function acknowledgeFault(page, rowNumber) {
8692

8793
/**
8894
* @param {import('@playwright/test').Page} page
95+
* @param {...number} nums
96+
* @returns {Promise<void>}
8997
*/
9098
export async function shelveMultipleFaults(page, ...nums) {
9199
const selectRows = nums.map((num) => {
@@ -99,57 +107,52 @@ export async function shelveMultipleFaults(page, ...nums) {
99107

100108
/**
101109
* @param {import('@playwright/test').Page} page
110+
* @param {...number} nums
111+
* @returns {Promise<void>}
102112
*/
103113
export async function acknowledgeMultipleFaults(page, ...nums) {
104114
const selectRows = nums.map((num) => {
105115
return selectFaultItem(page, num);
106116
});
107117
await Promise.all(selectRows);
108118

109-
await page.locator('button:has-text("Acknowledge")').click();
119+
await page.getByLabel('Acknowledge selected faults').click();
110120
await page.getByLabel('Save').click();
111121
}
112122

113123
/**
114124
* @param {import('@playwright/test').Page} page
125+
* @param {number} rowNumber
126+
* @returns {Promise<void>}
115127
*/
116128
export async function shelveFault(page, rowNumber) {
117129
await openFaultRowMenu(page, rowNumber);
118-
await page.locator('.c-menu >> text="Shelve"').click();
119-
// Click [aria-label="Save"]
130+
await page.getByLabel('Shelve', { exact: true }).click();
120131
await page.getByLabel('Save').click();
121132
}
122133

123134
/**
124135
* @param {import('@playwright/test').Page} page
125-
*/
126-
export async function changeViewTo(page, view) {
127-
await page.locator('.c-fault-mgmt__search-row select').first().selectOption(view);
128-
}
129-
130-
/**
131-
* @param {import('@playwright/test').Page} page
136+
* @param {'severity' | 'newest-first' | 'oldest-first'} sort
137+
* @returns {Promise<void>}
132138
*/
133139
export async function sortFaultsBy(page, sort) {
134-
await page.locator('.c-fault-mgmt__list-header-sortButton select').selectOption(sort);
135-
}
136-
137-
/**
138-
* @param {import('@playwright/test').Page} page
139-
*/
140-
export async function enterSearchTerm(page, term) {
141-
await page.locator('.c-fault-mgmt-search [aria-label="Search Input"]').fill(term);
140+
await page.getByTitle('Sort By').getByRole('combobox').selectOption(sort);
142141
}
143142

144143
/**
145144
* @param {import('@playwright/test').Page} page
145+
* @param {'acknowledged' | 'shelved' | 'standard view'} view
146+
* @returns {Promise<void>}
146147
*/
147-
export async function clearSearch(page) {
148-
await enterSearchTerm(page, '');
148+
export async function changeViewTo(page, view) {
149+
await page.getByTitle('View Filter').getByRole('combobox').selectOption(view);
149150
}
150151

151152
/**
152153
* @param {import('@playwright/test').Page} page
154+
* @param {number} rowNumber
155+
* @returns {Promise<void>}
153156
*/
154157
export async function selectFaultItem(page, rowNumber) {
155158
await page
@@ -165,116 +168,80 @@ export async function selectFaultItem(page, rowNumber) {
165168

166169
/**
167170
* @param {import('@playwright/test').Page} page
168-
*/
169-
export async function getHighestSeverity(page) {
170-
const criticalCount = await page.locator('[title=CRITICAL]').count();
171-
const warningCount = await page.locator('[title=WARNING]').count();
172-
173-
if (criticalCount > 0) {
174-
return 'CRITICAL';
175-
} else if (warningCount > 0) {
176-
return 'WARNING';
177-
}
178-
179-
return 'WATCH';
180-
}
181-
182-
/**
183-
* @param {import('@playwright/test').Page} page
184-
*/
185-
export async function getLowestSeverity(page) {
186-
const warningCount = await page.locator('[title=WARNING]').count();
187-
const watchCount = await page.locator('[title=WATCH]').count();
188-
189-
if (watchCount > 0) {
190-
return 'WATCH';
191-
} else if (warningCount > 0) {
192-
return 'WARNING';
193-
}
194-
195-
return 'CRITICAL';
196-
}
197-
198-
/**
199-
* @param {import('@playwright/test').Page} page
200-
*/
201-
export async function getFaultResultCount(page) {
202-
const count = await page.locator('.c-faults-list-view-item-body > .c-fault-mgmt__list').count();
203-
204-
return count;
205-
}
206-
207-
/**
208-
* @param {import('@playwright/test').Page} page
171+
* @param {number} rowNumber
172+
* @returns {import('@playwright/test').Locator}
209173
*/
210174
export function getFault(page, rowNumber) {
211-
const fault = page.locator(
212-
`.c-faults-list-view-item-body > .c-fault-mgmt__list >> nth=${rowNumber - 1}`
213-
);
175+
const fault = page.getByLabel('Fault triggered at').nth(rowNumber - 1);
214176

215177
return fault;
216178
}
217179

218180
/**
219181
* @param {import('@playwright/test').Page} page
182+
* @param {string} name
183+
* @returns {import('@playwright/test').Locator}
220184
*/
221185
export function getFaultByName(page, name) {
222-
const fault = page.locator(`.c-fault-mgmt__list-faultname:has-text("${name}")`);
186+
const fault = page.getByLabel('Fault triggered at').filter({
187+
hasText: name
188+
});
223189

224190
return fault;
225191
}
226192

227193
/**
228194
* @param {import('@playwright/test').Page} page
195+
* @param {number} rowNumber
196+
* @returns {Promise<string>}
229197
*/
230198
export async function getFaultName(page, rowNumber) {
231199
const faultName = await page
232-
.locator(`.c-fault-mgmt__list-faultname >> nth=${rowNumber - 1}`)
200+
.getByLabel('Fault name', { exact: true })
201+
.nth(rowNumber - 1)
233202
.textContent();
234203

235204
return faultName;
236205
}
237206

238207
/**
239208
* @param {import('@playwright/test').Page} page
240-
*/
241-
export async function getFaultSeverity(page, rowNumber) {
242-
const faultSeverity = await page
243-
.locator(`.c-faults-list-view-item-body .c-fault-mgmt__list-severity >> nth=${rowNumber - 1}`)
244-
.getAttribute('title');
245-
246-
return faultSeverity;
247-
}
248-
249-
/**
250-
* @param {import('@playwright/test').Page} page
209+
* @param {number} rowNumber
210+
* @returns {Promise<string>}
251211
*/
252212
export async function getFaultNamespace(page, rowNumber) {
253213
const faultNamespace = await page
254-
.locator(`.c-fault-mgmt__list-path >> nth=${rowNumber - 1}`)
214+
.getByLabel('Fault namespace')
215+
.nth(rowNumber - 1)
255216
.textContent();
256217

257218
return faultNamespace;
258219
}
259220

260221
/**
261222
* @param {import('@playwright/test').Page} page
223+
* @param {number} rowNumber
224+
* @returns {Promise<string>}
262225
*/
263226
export async function getFaultTriggerTime(page, rowNumber) {
264227
const faultTriggerTime = await page
265-
.locator(`.c-fault-mgmt__list-trigTime >> nth=${rowNumber - 1} >> .c-fault-mgmt-item__value`)
228+
.getByLabel('Last Trigger Time')
229+
.nth(rowNumber - 1)
266230
.textContent();
267231

268232
return faultTriggerTime.toString().trim();
269233
}
270234

271235
/**
272236
* @param {import('@playwright/test').Page} page
237+
* @param {number} rowNumber
238+
* @returns {Promise<void>}
273239
*/
274240
export async function openFaultRowMenu(page, rowNumber) {
275241
// select
276242
await page
277-
.getByLabel('Disposition actions')
243+
.getByLabel('Fault triggered at')
278244
.nth(rowNumber - 1)
245+
.getByLabel('Disposition Actions')
279246
.click();
280247
}

0 commit comments

Comments
 (0)