From 6ecfe1da9884c11a925f912da5589b6139e57c8d Mon Sep 17 00:00:00 2001 From: Paul Clue <67766160+Paul-Clue@users.noreply.github.com> Date: Wed, 10 Jan 2024 10:13:04 -0500 Subject: [PATCH] Remove test plan report update modal --- .../TestPlanUpdater/TestPlanUpdaterModal.css | 95 ---- .../TestPlanUpdater/TestPlanUpdaterModal.jsx | 520 ------------------ client/components/TestPlanUpdater/index.js | 3 - client/components/TestPlanUpdater/queries.js | 201 ------- client/components/TestQueueRow/index.jsx | 13 +- 5 files changed, 1 insertion(+), 831 deletions(-) delete mode 100644 client/components/TestPlanUpdater/TestPlanUpdaterModal.css delete mode 100644 client/components/TestPlanUpdater/TestPlanUpdaterModal.jsx delete mode 100644 client/components/TestPlanUpdater/index.js delete mode 100644 client/components/TestPlanUpdater/queries.js diff --git a/client/components/TestPlanUpdater/TestPlanUpdaterModal.css b/client/components/TestPlanUpdater/TestPlanUpdaterModal.css deleted file mode 100644 index 8da3c7fb8..000000000 --- a/client/components/TestPlanUpdater/TestPlanUpdaterModal.css +++ /dev/null @@ -1,95 +0,0 @@ -.cancel-button { - width: 100%; - justify-self: end; -} - -.completion-alert { - margin-bottom: 0em; -} - -.backup-checkbox { - grid-column: 1/2; -} - -.loading-spinner { - align-self: center; - margin: 40px 0; -} - -.loading-spinner-modal { - height: 250px; -} - -.results-spinner-container { - display: flex; - justify-content: center; -} - -@media (min-width: 768px) { - .modal-50w { - min-width: 50%; - } -} - -.new-version { - grid-column: 1/3; - margin-bottom: 1em; -} - -.side-button-container { - display: grid; - grid-template-columns: 1fr 1fr; - grid-gap: 0.5em; -} - -.side-button-container.no-backup { - grid-column: 2/3; -} - -.submit-button { - width: 100%; - white-space: pre; - justify-self: end; -} - -.submit-buttons-row { - align-items: center; - display: grid; - grid-template-columns: 1fr 1fr; - width: 100%; -} - -@media (max-width: 767px) { - .submit-buttons-row { - grid-template-columns: 1fr; - gap: 0.5em; - } -} - -.trash-icon { - margin-right: 0 !important; -} - -.version-info-wrapper { - display: grid; - grid-template-columns: repeat(2, 1fr); - grid-gap: 1em; -} - -.current-version { - grid-column: 1/3; -} - -.version-info-label { - background: #f5f8fa; - border: 1px solid #d2d5d9; - width: 100%; - text-align: center; - padding: 0.5em 0.75em; - border-radius: 3px; - font-size: 0.9em; -} - -.version-select { - margin-bottom: 1em; -} diff --git a/client/components/TestPlanUpdater/TestPlanUpdaterModal.jsx b/client/components/TestPlanUpdater/TestPlanUpdaterModal.jsx deleted file mode 100644 index 2ed715182..000000000 --- a/client/components/TestPlanUpdater/TestPlanUpdaterModal.jsx +++ /dev/null @@ -1,520 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import PropTypes from 'prop-types'; -import { useApolloClient } from '@apollo/client'; -import { Alert, Modal, Button, Form } from 'react-bootstrap'; -import { gitUpdatedDateToString } from '../../utils/gitUtils'; -import hash from 'object-hash'; -import { omit } from 'lodash'; -import { - CREATE_TEST_PLAN_REPORT_MUTATION, - CREATE_TEST_PLAN_RUN_MUTATION, - CREATE_TEST_RESULT_MUTATION, - DELETE_TEST_PLAN_REPORT, - SAVE_TEST_RESULT_MUTATION, - SUBMIT_TEST_RESULT_MUTATION, - TEST_PLAN_ID_QUERY, - VERSION_QUERY -} from './queries'; -import './TestPlanUpdaterModal.css'; -import '../TestRun/TestRun.css'; -import LoadingSpinner from '../LoadingSpinner/LoadingSpinner'; - -const toSentence = array => { - // https://stackoverflow.com/a/24376930/3888572 - return array.join(', ').replace(/,\s([^,]+)$/, ' and $1'); -}; - -const TestPlanUpdaterModal = ({ - show, - handleClose, - testPlanReportId, - triggerTestPlanReportUpdate -}) => { - const loadInitialData = async ({ client, testPlanReportId }) => { - const { data: currentReportData } = await client.query({ - query: TEST_PLAN_ID_QUERY, - variables: { testPlanReportId } - }); - const testPlanId = - currentReportData?.testPlanReport?.testPlanVersion?.testPlan?.id; - - if (!testPlanId) - throw new Error( - `Could not find test plan report with id "${testPlanReportId}"` - ); - - setCurrentReportData(currentReportData); - - const latestTestPlanVersionId = - currentReportData.testPlanReport.testPlanVersion.testPlan - .latestTestPlanVersion.id; - const atId = currentReportData.testPlanReport.at.id; - - const { data: versionData } = await client.query({ - query: VERSION_QUERY, - variables: { - testPlanReportId, - testPlanVersionId: latestTestPlanVersionId, - atId - } - }); - setVersionData(versionData); - }; - - const compareTestContent = (currentTests, newTests) => { - const hashTest = test => hash(omit(test, ['id'])); - const hashTests = tests => { - return Object.fromEntries( - tests.map(test => [hashTest(test), test]) - ); - }; - - const currentTestsByHash = hashTests(currentTests); - const newTestsByHash = hashTests(newTests); - - const testsToDelete = []; - const currentTestIdsToNewTestIds = {}; - Object.entries(currentTestsByHash).forEach(([hash, currentTest]) => { - const newTest = newTestsByHash[hash]; - if (!newTest) { - testsToDelete.push(currentTest); - return; - } - currentTestIdsToNewTestIds[currentTest.id] = newTest.id; - }); - - return { testsToDelete, currentTestIdsToNewTestIds }; - }; - - const client = useApolloClient(); - const [currentReportData, setCurrentReportData] = useState(); - const [versionData, setVersionData] = useState(); - const [showModalData, setShowModalData] = useState(true); - const [loadingSpinnerProgress, setLoadingSpinnerProgress] = useState({ - visible: false, - numerator: null, - denominator: null - }); - const [alertCompletion, setAlertCompletion] = useState({ - message: null, - success: false, - visible: false - }); - const [backupChecked, setBackupChecked] = useState(false); - const [newReport, setNewReport] = useState(); - const [closeButton, setCloseButton] = useState(false); - - useEffect(() => { - loadInitialData({ client, testPlanReportId }); - }, []); - - if (!currentReportData) { - return ( - - - Test Plan Updater - - - - ); - } - - const { - testPlanReport: { - id: currentReportId, - at: { id: atId, name: atName }, - browser: { id: browserId, name: browserName }, - testPlanVersion - } - } = currentReportData; - - const { - testPlan: { latestTestPlanVersion } - } = testPlanVersion; - - const newTestPlanVersionId = versionData?.testPlanVersion.id; - let runsWithResults; - let allTestResults; - let copyableTestResults; - let testsToDelete; - let currentTestIdsToNewTestIds; - if (versionData) { - const { testPlanReport, testPlanVersion: newTestPlanVersion } = - versionData; - runsWithResults = testPlanReport.draftTestPlanRuns.filter( - testPlanRun => testPlanRun.testResults.length - ); - allTestResults = runsWithResults.flatMap( - testPlanRun => testPlanRun.testResults - ); - - ({ testsToDelete, currentTestIdsToNewTestIds } = compareTestContent( - allTestResults.map(testResult => testResult.test), - newTestPlanVersion.tests - )); - - copyableTestResults = allTestResults.filter( - testResult => currentTestIdsToNewTestIds[testResult.test.id] - ); - } - - const copyTestResult = (testResultSkeleton, testResult) => { - return { - id: testResultSkeleton.id, - atVersionId: testResultSkeleton.atVersion.id, - browserVersionId: testResultSkeleton.browserVersion.id, - scenarioResults: testResultSkeleton.scenarioResults.map( - (scenarioResultSkeleton, index) => { - const scenarioResult = testResult.scenarioResults[index]; - return { - id: scenarioResultSkeleton.id, - output: scenarioResult.output, - assertionResults: - scenarioResultSkeleton.assertionResults.map( - ( - assertionResultSkeleton, - assertionResultIndex - ) => { - const assertionResult = - scenarioResult.assertionResults[ - assertionResultIndex - ]; - return { - id: assertionResultSkeleton.id, - passed: assertionResult.passed - }; - } - ), - unexpectedBehaviors: scenarioResult.unexpectedBehaviors - }; - } - ) - }; - }; - - const createNewReportWithData = async () => { - setShowModalData(false); - const { data: newReportData } = await client.mutate({ - mutation: CREATE_TEST_PLAN_REPORT_MUTATION, - variables: { - input: { - testPlanVersionId: newTestPlanVersionId, - atId: atId, - browserId: browserId - } - } - }); - - const { - testPlanReport: { id: newReportId } - } = newReportData.findOrCreateTestPlanReport.populatedData; - - const created = newReportData.findOrCreateTestPlanReport.created; - const reportIsNew = !!created.find(item => item.testPlanReport.id); - if (!reportIsNew) { - setAlertCompletion({ - message: - 'Aborting because a report already exists and continuing would overwrite its data.', - success: false, - visible: true - }); - setCloseButton(true); - return; - } - - setNewReport(created.find(item => item.testPlanReport.id)); - - for (const testPlanRun of runsWithResults) { - const { data: runData } = await client.mutate({ - mutation: CREATE_TEST_PLAN_RUN_MUTATION, - variables: { - testPlanReportId: newReportId, - testerUserId: testPlanRun.tester.id - } - }); - - // Set the number of created runs - setLoadingSpinnerProgress(prevState => ({ - visible: true, - numerator: prevState.numerator + 1, - denominator: runsWithResults.length + copyableTestResults.length - })); - - const testPlanRunId = - runData.testPlanReport.assignTester.testPlanRun.id; - - for (const testResult of testPlanRun.testResults) { - const testId = currentTestIdsToNewTestIds[testResult.test.id]; - const atVersionId = testResult.atVersion.id; - const browserVersionId = testResult.browserVersion.id; - if (!testId) continue; - - const { data: testResultData } = await client.mutate({ - mutation: CREATE_TEST_RESULT_MUTATION, - variables: { - testPlanRunId, - testId, - atVersionId, - browserVersionId - } - }); - - const testResultSkeleton = - testResultData.testPlanRun.findOrCreateTestResult - .testResult; - - const copiedTestResultInput = copyTestResult( - testResultSkeleton, - testResult - ); - - const saveMutation = testResult.completedAt - ? SUBMIT_TEST_RESULT_MUTATION - : SAVE_TEST_RESULT_MUTATION; - - const { data: savedData } = await client.mutate({ - mutation: saveMutation, - variables: { - testResultId: copiedTestResultInput.id, - testResultInput: copiedTestResultInput - } - }); - - if (savedData.errors) throw savedData.errors; - - // Set the number of created results - setLoadingSpinnerProgress(prevState => ({ - ...prevState, - numerator: prevState.numerator + 1 - })); - } - } - - setLoadingSpinnerProgress(prevState => ({ - ...prevState, - visible: false - })); - - if (backupChecked) { - setAlertCompletion({ - message: 'Completed without errors.', - success: true, - visible: true - }); - setCloseButton(true); - return; - } - - await deleteOldTestPlanReport(currentReportId); - }; - - const deleteOldTestPlanReport = async safeToDeleteReportId => { - await client.mutate({ - mutation: DELETE_TEST_PLAN_REPORT, - variables: { - testPlanReportId: safeToDeleteReportId - } - }); - setAlertCompletion({ - visible: true, - success: true, - message: 'Completed without errors.' - }); - setCloseButton(true); - }; - - const closeAndReload = async () => { - if (newReport) { - await triggerTestPlanReportUpdate(newReport.testPlanReport.id); - } - handleClose(); - }; - - return ( - - - Test Plan Updater - - {showModalData && ( - <> - -
-
- Test Plan: {testPlanVersion.title} -
-
- AT and Browser: {atName} with{' '} - {browserName} -
-
- Current version:{' '} - {gitUpdatedDateToString( - testPlanVersion.updatedAt - )}{' '} - {testPlanVersion.gitMessage} ( - {testPlanVersion.gitSha.substring(0, 7)}) -
-
- Latest version: - {gitUpdatedDateToString( - latestTestPlanVersion.updatedAt - )}{' '} - {latestTestPlanVersion.gitMessage} ( - {latestTestPlanVersion.gitSha.substring(0, 7)}) -
-
-
- {(() => { - if (!runsWithResults?.length) { - return ( -
- -
- ); - } - const testers = runsWithResults.map( - testPlanRun => testPlanRun.tester.username - ); - - let deletionNote; - if (!testsToDelete.length) { - deletionNote = ( - <> - All test results can be copied from - the old report to the new report. - - ); - } else { - deletionNote = ( - <> - Note that {testsToDelete.length}{' '} - {testsToDelete.length === 1 - ? 'test differs' - : 'tests differ'}{' '} - between the old and new versions and - cannot be automatically copied. - - ); - } - - return ( - - Found {allTestResults.length} partial or - completed test{' '} - {allTestResults.length === 1 - ? 'result' - : 'results'}{' '} - for{' '} - {testers.length > 1 - ? 'testers' - : 'tester'}{' '} - {toSentence(testers)}. {deletionNote} - - ); - })()} -
-
- -
- {testsToDelete?.length > 0 && ( - - - { - setBackupChecked( - !backupChecked - ); - }} - checked={backupChecked} - /> - Keep older versions of test plan and - results - - - )} -
0 - ? 'side-button-container' - : 'side-button-container no-backup' - } - > - - -
-
-
- - )} - {loadingSpinnerProgress.visible && ( - - )} - {alertCompletion.visible && ( - <> - - - {alertCompletion.message} - - - - )} - {!showModalData && ( - - {closeButton && ( - - )} - - )} -
- ); -}; - -TestPlanUpdaterModal.propTypes = { - show: PropTypes.bool, - isAdmin: PropTypes.bool, - details: PropTypes.object, - handleClose: PropTypes.func, - handleAction: PropTypes.func, - testPlanReportId: PropTypes.string, - triggerTestPlanReportUpdate: PropTypes.func -}; - -export default TestPlanUpdaterModal; diff --git a/client/components/TestPlanUpdater/index.js b/client/components/TestPlanUpdater/index.js deleted file mode 100644 index ff6bc5a8e..000000000 --- a/client/components/TestPlanUpdater/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import TestPlanUpdaterModal from './TestPlanUpdaterModal'; - -export default TestPlanUpdaterModal; diff --git a/client/components/TestPlanUpdater/queries.js b/client/components/TestPlanUpdater/queries.js deleted file mode 100644 index 4ece2f33d..000000000 --- a/client/components/TestPlanUpdater/queries.js +++ /dev/null @@ -1,201 +0,0 @@ -import { gql } from '@apollo/client'; - -export const TEST_PLAN_ID_QUERY = gql` - query TestPlanIdQuery($testPlanReportId: ID!) { - testPlanReport(id: $testPlanReportId) { - id - at { - name - id - } - browser { - id - name - } - testPlanVersion { - id - testPlan { - id - latestTestPlanVersion { - id - gitSha - gitMessage - updatedAt - } - } - title - gitMessage - gitSha - updatedAt - } - } - } -`; - -export const VERSION_QUERY = gql` - fragment TestFragment on Test { - __typename - id - title - ats { - id - } - atMode - scenarios(atId: $atId) { - commands { - text - } - } - assertions { - priority - text - } - } - - query LatestVersionQuery( - $testPlanReportId: ID! - $testPlanVersionId: ID! - $atId: ID! - ) { - testPlanReport(id: $testPlanReportId) { - id - draftTestPlanRuns { - tester { - id - username - } - testResults { - test { - ...TestFragment - } - atVersion { - id - } - browserVersion { - id - } - completedAt - scenarioResults { - output - assertionResults { - passed - } - unexpectedBehaviors { - id - otherUnexpectedBehaviorText - } - } - } - } - } - testPlanVersion(id: $testPlanVersionId) { - id - tests { - ...TestFragment - } - } - } -`; - -export const CREATE_TEST_PLAN_REPORT_MUTATION = gql` - mutation CreateTestPlanReportMutation($input: TestPlanReportInput!) { - findOrCreateTestPlanReport(input: $input) { - populatedData { - testPlanReport { - id - } - } - created { - locationOfData - testPlanReport { - id - } - } - } - } -`; - -export const CREATE_TEST_PLAN_RUN_MUTATION = gql` - mutation CreateTestPlanRunMutation( - $testPlanReportId: ID! - $testerUserId: ID! - ) { - testPlanReport(id: $testPlanReportId) { - assignTester(userId: $testerUserId) { - testPlanRun { - id - } - } - } - } -`; - -export const CREATE_TEST_RESULT_MUTATION = gql` - mutation CreateTestResultMutation( - $testPlanRunId: ID! - $testId: ID! - $atVersionId: ID! - $browserVersionId: ID! - ) { - testPlanRun(id: $testPlanRunId) { - findOrCreateTestResult( - testId: $testId - atVersionId: $atVersionId - browserVersionId: $browserVersionId - ) { - testResult { - id - atVersion { - id - } - browserVersion { - id - } - scenarioResults { - id - assertionResults { - id - } - unexpectedBehaviors { - id - } - } - } - } - } - } -`; - -export const SAVE_TEST_RESULT_MUTATION = gql` - mutation SaveTestResultMutation( - $testResultId: ID! - $testResultInput: TestResultInput! - ) { - testResult(id: $testResultId) { - saveTestResult(input: $testResultInput) { - locationOfData - } - } - } -`; - -export const SUBMIT_TEST_RESULT_MUTATION = gql` - mutation SubmitTestResultMutation( - $testResultId: ID! - $testResultInput: TestResultInput! - ) { - testResult(id: $testResultId) { - submitTestResult(input: $testResultInput) { - locationOfData - } - } - } -`; - -export const DELETE_TEST_PLAN_REPORT = gql` - mutation DeleteTestPlanReport($testPlanReportId: ID!) { - testPlanReport(id: $testPlanReportId) { - deleteTestPlanReport - } - } -`; diff --git a/client/components/TestQueueRow/index.jsx b/client/components/TestQueueRow/index.jsx index 1f517d651..2d2a63682 100644 --- a/client/components/TestQueueRow/index.jsx +++ b/client/components/TestQueueRow/index.jsx @@ -19,7 +19,6 @@ import { REMOVE_TESTER_MUTATION, REMOVE_TESTER_RESULTS_MUTATION } from '../TestQueue/queries'; -import TestPlanUpdaterModal from '../TestPlanUpdater/TestPlanUpdaterModal'; import BasicThemedModal from '../common/BasicThemedModal'; import { LoadingStatus, useTriggerLoad } from '../common/LoadingStatus'; import './TestQueueRow.css'; @@ -60,14 +59,11 @@ const TestQueueRow = ({ const [removeTester] = useMutation(REMOVE_TESTER_MUTATION); const [removeTesterResults] = useMutation(REMOVE_TESTER_RESULTS_MUTATION); - const [showTestPlanUpdaterModal, setShowTestPlanUpdaterModal] = - useState(false); const [testPlanReport, setTestPlanReport] = useState(testPlanReportData); const [isLoading, setIsLoading] = useState(false); const { id, isAdmin, isTester, isVendor, username } = user; const { - id: testPlanReportId, testPlanVersion, draftTestPlanRuns, runnableTestsLength = 0 @@ -609,14 +605,7 @@ const TestQueueRow = ({ )} - {showTestPlanUpdaterModal && ( - setShowTestPlanUpdaterModal(false)} - testPlanReportId={testPlanReportId} - triggerTestPlanReportUpdate={triggerTestPlanReportUpdate} - /> - )} + {showThemedModal && (