From 83e2d3c4bd11dd0f70a4a6617ae473f43dd5519b Mon Sep 17 00:00:00 2001 From: Adam Raine <6752989+adamraine@users.noreply.github.com> Date: Thu, 3 Feb 2022 10:30:30 -0500 Subject: [PATCH] tests(smoke): test array `_includes` and `lhr.timing` (#13619) --- lighthouse-cli/test/smokehouse/readme.md | 4 +++ .../test/smokehouse/report-assert.js | 36 +++++++++++++++++++ types/smokehouse.d.ts | 3 ++ 3 files changed, 43 insertions(+) diff --git a/lighthouse-cli/test/smokehouse/readme.md b/lighthouse-cli/test/smokehouse/readme.md index 72c7cdf2cf48..0a5875fe5c57 100644 --- a/lighthouse-cli/test/smokehouse/readme.md +++ b/lighthouse-cli/test/smokehouse/readme.md @@ -64,11 +64,15 @@ Individual elements of an array can be asserted by using numeric properties in a However, if an array literal is used as the expectation, an extra condition is enforced that the actual array _must_ have the same length as the provided expected array. +Arrays can be checked against a subset of elements using the special `_includes` property. The value of `_includes` _must_ be an array. Each assertion in `_includes` will remove the matching item from consideration for the rest. + **Examples**: | Actual | Expected | Result | | -- | -- | -- | | `[{url: 'http://badssl.com'}, {url: 'http://example.com'}]` | `{1: {url: 'http://example.com'}}` | ✅ PASS | | `[{timeInMs: 5}, {timeInMs: 15}]` | `{length: 2}` | ✅ PASS | +| `[{timeInMs: 5}, {timeInMs: 15}]` | `{_includes: [{timeInMs: 5}]}` | ✅ PASS | +| `[{timeInMs: 5}, {timeInMs: 15}]` | `{_includes: [{timeInMs: 5}, {timeInMs: 5}]}` | ❌ FAIL | | `[{timeInMs: 5}, {timeInMs: 15}]` | `[{timeInMs: 5}]` | ❌ FAIL | ### Special environment checks diff --git a/lighthouse-cli/test/smokehouse/report-assert.js b/lighthouse-cli/test/smokehouse/report-assert.js index d58b33563faa..88efaf129585 100644 --- a/lighthouse-cli/test/smokehouse/report-assert.js +++ b/lighthouse-cli/test/smokehouse/report-assert.js @@ -111,6 +111,35 @@ function findDifference(path, actual, expected) { const keyPath = path + keyAccessor; const expectedValue = expected[key]; + if (key === '_includes') { + if (!Array.isArray(expectedValue)) throw new Error('Array subset must be array'); + if (!Array.isArray(actual)) { + return { + path, + actual: 'Actual value is not an array', + expected, + }; + } + + const actualCopy = [...actual]; + for (const expectedEntry of expectedValue) { + const matchingIndex = + actualCopy.findIndex(actualEntry => !findDifference(keyPath, actualEntry, expectedEntry)); + if (matchingIndex !== -1) { + actualCopy.splice(matchingIndex, 1); + continue; + } + + return { + path, + actual: 'Item not found in array', + expected: expectedEntry, + }; + } + + continue; + } + const actualValue = actual[key]; const subDifference = findDifference(keyPath, actualValue, expectedValue); @@ -305,6 +334,12 @@ function collateResults(localConsole, actual, expected) { return makeComparison(auditName + ' audit', actualResult, expectedResult); }); + const timingAssertions = []; + if (expected.lhr.timing) { + const comparison = makeComparison('timing', actual.lhr.timing, expected.lhr.timing); + timingAssertions.push(comparison); + } + /** @type {Comparison[]} */ const requestCountAssertion = []; if (expected.networkRequests) { @@ -322,6 +357,7 @@ function collateResults(localConsole, actual, expected) { ...requestCountAssertion, ...artifactAssertions, ...auditAssertions, + ...timingAssertions, ]; } diff --git a/types/smokehouse.d.ts b/types/smokehouse.d.ts index cd02ae67256f..b2bcc364a08f 100644 --- a/types/smokehouse.d.ts +++ b/types/smokehouse.d.ts @@ -20,6 +20,9 @@ declare global { code?: any; message?: any; }; + timing?: { + entries?: any + } } export type ExpectedRunnerResult = {