Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No longer mark test plan reports with skipped tests as final #833

Merged
merged 11 commits into from
Nov 22, 2023
31 changes: 0 additions & 31 deletions client/components/Reports/Reports.css
Original file line number Diff line number Diff line change
Expand Up @@ -56,36 +56,6 @@
margin-top: 1em;
}

.skipped-tests-heading {
background: #fefbea;
padding: 1.75em 1.75em 1em 1.75em;
border: 1px solid #eddfbe;
border-bottom: 0;
margin-top: 2em;
}

.skipped-tests {
columns: 2;
line-height: 2;
border: 1px solid #eddfbe;
padding: 1.5em 3em;
background: #fdfcf6;
}

.skipped-tests li {
margin-bottom: 0.5em;
border-bottom: 1px solid #eddfbe;
padding-bottom: 0.5em;
margin-right: 3em;
-webkit-column-break-inside: avoid;
page-break-inside: avoid;
break-inside: avoid;
}

.skipped-tests li:last-child {
border-bottom: none;
}

.test-result-heading {
display: flex;
justify-content: space-between;
Expand All @@ -100,7 +70,6 @@
margin-bottom: 0;
}

.skipped-tests-heading h2,
.test-result-heading h2 {
margin-top: 0;
}
Expand Down
26 changes: 0 additions & 26 deletions client/components/Reports/SummarizeTestPlanReport.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
faExternalLinkAlt,
faHome
} from '@fortawesome/free-solid-svg-icons';
import { differenceBy } from 'lodash';
import { convertDateToString } from '../../utils/formatter';
import DisclaimerInfo from '../DisclaimerInfo';
import TestPlanResultsTable from '../common/TestPlanResultsTable';
Expand Down Expand Up @@ -100,11 +99,6 @@ const SummarizeTestPlanReport = ({ testPlanVersion, testPlanReports }) => {
browser
};

const skippedTests = differenceBy(
testPlanReport.runnableTests,
testPlanReport.finalizedTestResults,
testOrTestResult => testOrTestResult.test?.id ?? testOrTestResult.id
);
return (
<Container id="main" as="main" tabIndex="-1">
<Helmet>
Expand Down Expand Up @@ -269,26 +263,6 @@ const SummarizeTestPlanReport = ({ testPlanVersion, testPlanReports }) => {
</Fragment>
);
})}
{skippedTests.length ? (
Copy link
Contributor

@howard-e howard-e Nov 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's great getting rid of these lines!

<Fragment>
<div className="skipped-tests-heading">
<h2 id="skipped-tests" tabIndex="-1">
Skipped Tests
</h2>
<p>
The following tests have been skipped in this test
run:
</p>
</div>
<ol className="skipped-tests">
{skippedTests.map(test => (
<li key={test.id}>
<a href={test.renderedUrl}>{test.title}</a>
</li>
))}
</ol>
</Fragment>
) : null}
</Container>
);
};
Expand Down
18 changes: 0 additions & 18 deletions client/components/Reports/SummarizeTestPlanVersion.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import { Helmet } from 'react-helmet';
import { differenceBy } from 'lodash';
import getMetrics from './getMetrics';
import { getTestPlanTargetTitle, getTestPlanVersionTitle } from './getTitles';
import { Breadcrumb, Button, Container, Table } from 'react-bootstrap';
Expand Down Expand Up @@ -86,12 +85,6 @@ const SummarizeTestPlanVersion = ({ testPlanVersion, testPlanReports }) => {

{testPlanReports.map(testPlanReport => {
if (testPlanReport.status === 'DRAFT') return null;
const skippedTests = differenceBy(
testPlanReport.runnableTests,
testPlanReport.finalizedTestResults,
testOrTestResult =>
testOrTestResult.test?.id ?? testOrTestResult.id
);
const overallMetrics = getMetrics({ testPlanReport });

const { at, browser } = testPlanReport;
Expand Down Expand Up @@ -124,17 +117,6 @@ const SummarizeTestPlanVersion = ({ testPlanVersion, testPlanReports }) => {
View Complete Results
</Button>
</LinkContainer>
{skippedTests.length ? (
<Link
to={
`/report/${testPlanVersion.id}` +
`/targets/${testPlanReport.id}` +
`#skipped-tests`
}
>
{skippedTests.length} Tests Were Skipped
</Link>
) : null}
<Table
className="mt-3"
bordered
Expand Down
8 changes: 7 additions & 1 deletion client/components/TestQueueRow/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,11 @@ const TestQueueRow = ({
'completed'
].join('-');

const completedAllTests = testPlanReport.draftTestPlanRuns.every(
testPlanRun =>
testPlanRun.testResultsLength === testPlanReport.runnableTestsLength
);

return (
<LoadingStatus message={loadingMessage}>
<tr className="test-queue-run-row">
Expand Down Expand Up @@ -494,7 +499,8 @@ const TestQueueRow = ({
!testPlanReport.conflictsLength &&
testPlanReport.draftTestPlanRuns.length &&
testPlanReport.draftTestPlanRuns[0]
.testResultsLength ? (
.testResultsLength &&
completedAllTests ? (
<>
<Button
ref={updateTestPlanStatusButtonRef}
Expand Down
2 changes: 1 addition & 1 deletion client/components/TestRun/TestRun.css
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ button.test-navigator-toggle:focus {
left: 4px;
}

.test-name-wrapper.skipped .progress-indicator {
.test-name-wrapper .progress-indicator {
background: White;
border: 2px dashed black;
}
Expand Down
63 changes: 63 additions & 0 deletions server/migrations/20231031162340-verifyNoSkippedTests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
'use strict';

/** @type {import('sequelize-cli').Migration} */
module.exports = {
async up(queryInterface /* , Sequelize */) {
return queryInterface.sequelize.transaction(async transaction => {
const [rows] = await queryInterface.sequelize.query(
`
SELECT
"TestPlanReport".id,
"TestPlanReport"."atId",
"TestPlanRun"."testResults",
"TestPlanVersion".tests
FROM
"TestPlanReport"
INNER JOIN "TestPlanVersion" ON "TestPlanVersion".id = "TestPlanReport"."testPlanVersionId"
INNER JOIN "TestPlanRun" ON "TestPlanReport".id = "TestPlanRun"."testPlanReportId"
WHERE
"TestPlanReport"."markedFinalAt" IS NOT NULL
`,
{ transaction }
);

const dataById = {};
rows.forEach(({ id, atId, testResults, tests }) => {
if (dataById[id]) {
dataById[id].runLengths.push(testResults.length);
} else {
const runnableTestsLength = tests.filter(test =>
test.atIds.includes(atId)
).length;
dataById[id] = {
id,
runnableTestsLength,
runLengths: [testResults.length]
};
}
});

for (const data of Object.values(dataById)) {
const isComplete = data.runLengths.every(
runLength => runLength === data.runnableTestsLength
);
if (!isComplete) {
console.info(`Found incomplete report ${data.id}`); // eslint-disable-line
// Since final test plan reports can
// no longer have skipped tests, we should
// move them to the test queue where incomplete
// runs are still supported.
await queryInterface.sequelize.query(
`
UPDATE "TestPlanReport" SET "markedFinalAt" = NULL WHERE id = ?
`,
{
replacements: [data.id],
transaction
}
);
}
}
});
}
};
27 changes: 8 additions & 19 deletions server/resolvers/TestPlanReport/finalizedTestResultsResolver.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,20 @@
const testResultsResolver = require('../TestPlanRun/testResultsResolver');
const deepCustomMerge = require('../../util/deepCustomMerge');

/**
* Completed test results sourced from all the report's runs. The runs must be
* merged because each run might have skipped different tests.
*/
const finalizedTestResultsResolver = async (testPlanReport, _, context) => {
if (!testPlanReport.testPlanRuns.length) {
return null;
}

let merged = [];
// Since conflicts are now resolved, all testPlanRuns are interchangeable.
const testPlanRun = testPlanReport.testPlanRuns[0];

for (let i = 0; i < testPlanReport.testPlanRuns.length; i += 1) {
merged = deepCustomMerge(
merged,
testPlanReport.testPlanRuns[i].testResults.filter(
testResult => !!testResult.completedAt
),
{
identifyArrayItem: item =>
item.testId ?? item.scenarioId ?? item.assertionId
}
);
}
return testResultsResolver(
{ testPlanReport, testResults: merged },
{
testPlanReport,
testResults: testPlanRun.testResults.filter(
testResult => !!testResult.completedAt
)
},
null,
context
);
Expand Down
18 changes: 10 additions & 8 deletions server/resolvers/TestPlanReportOperations/markAsFinalResolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const {
getTestPlanReportById,
updateTestPlanReport
} = require('../../models/services/TestPlanReportService');
const finalizedTestResultsResolver = require('../TestPlanReport/finalizedTestResultsResolver');
const runnableTestsResolver = require('../TestPlanReport/runnableTestsResolver');
const populateData = require('../../services/PopulatedData/populateData');
const conflictsResolver = require('../TestPlanReport/conflictsResolver');

Expand All @@ -27,15 +27,17 @@ const markAsFinalResolver = async (
);
}

const finalizedTestResults = await finalizedTestResultsResolver(
testPlanReport,
null,
context
const runnableTests = runnableTestsResolver(testPlanReport);

const hasIncompleteTestRuns = testPlanReport.testPlanRuns.find(
testPlanRun => {
return testPlanRun.testResults.length !== runnableTests.length;
}
);
if (!finalizedTestResults || !finalizedTestResults.length) {

if (hasIncompleteTestRuns) {
throw new Error(
'Cannot mark test plan report as final because there are no ' +
'completed test results'
'Cannot mark test plan report as final because not all testers have completed their test runs.'
);
}

Expand Down
9 changes: 1 addition & 8 deletions server/resolvers/testPlanReportsResolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,6 @@ const testPlanReportsResolver = async (
attributes: testPlanReportAttributes
} = retrieveAttributes('testPlanReport', TEST_PLAN_REPORT_ATTRIBUTES, info);

const { attributes: testPlanRunAttributes } = retrieveAttributes(
'draftTestPlanRuns',
TEST_PLAN_RUN_ATTRIBUTES,
info,
true
);

const { attributes: testPlanVersionAttributes } = retrieveAttributes(
'testPlanVersion',
TEST_PLAN_VERSION_ATTRIBUTES,
Expand Down Expand Up @@ -64,7 +57,7 @@ const testPlanReportsResolver = async (
null,
where,
testPlanReportAttributes,
testPlanRunAttributes,
TEST_PLAN_RUN_ATTRIBUTES,
testPlanVersionAttributes,
null,
null,
Expand Down
6 changes: 3 additions & 3 deletions server/scripts/populate-test-data/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const populateTestDatabase = async () => {

await populateFakeTestResults(4, [
'completeAndPassing',
null,
'completeAndPassing',
'completeAndFailingDueToIncorrectAssertions',
'completeAndFailingDueToNoOutputAssertions',
'completeAndFailingDueToUnexpectedBehaviors',
Expand All @@ -78,7 +78,7 @@ const populateTestDatabase = async () => {

await populateFakeTestResults(5, [
'completeAndPassing',
null,
'completeAndPassing',
'completeAndFailingDueToIncorrectAssertions',
'completeAndPassing',
'completeAndFailingDueToNoOutputAssertions',
Expand All @@ -89,7 +89,7 @@ const populateTestDatabase = async () => {

await populateFakeTestResults(6, [
'completeAndPassing',
null,
'completeAndPassing',
'completeAndFailingDueToIncorrectAssertions',
'completeAndPassing',
'completeAndFailingDueToIncorrectAssertions',
Expand Down
Loading
Loading