diff --git a/client/components/DataManagement/DataManagementRow/index.jsx b/client/components/DataManagement/DataManagementRow/index.jsx index 40d3cf8cf..981c89e05 100644 --- a/client/components/DataManagement/DataManagementRow/index.jsx +++ b/client/components/DataManagement/DataManagementRow/index.jsx @@ -19,6 +19,11 @@ import VersionString from '../../common/VersionString'; import PhasePill from '../../common/PhasePill'; import { differenceBy, uniq as unique, uniqBy as uniqueBy } from 'lodash'; import { getVersionData } from '../utils'; +import { + AtPropType, + TestPlanPropType, + TestPlanVersionPropType +} from '../../common/proptypes'; const StatusCell = styled.div` display: flex; @@ -1089,32 +1094,16 @@ const DataManagementRow = ({ DataManagementRow.propTypes = { isAdmin: PropTypes.bool, - ats: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string, - name: PropTypes.string - }) - ), - testPlan: PropTypes.shape({ - id: PropTypes.string, - title: PropTypes.string, - directory: PropTypes.string - }).isRequired, + ats: PropTypes.arrayOf(AtPropType), + testPlan: TestPlanPropType.isRequired, testPlanVersions: PropTypes.arrayOf( PropTypes.shape({ - id: PropTypes.string, + ...TestPlanVersionPropType, + // Optional in this component title: PropTypes.string, - phase: PropTypes.string, - gitSha: PropTypes.string, - testPlan: PropTypes.shape({ - directory: PropTypes.string - }), - updatedAt: PropTypes.string, - draftPhaseReachedAt: PropTypes.string, - candidatePhaseReachedAt: PropTypes.string, - recommendedPhaseReachedAt: PropTypes.string + isRequired: PropTypes.bool }) - ).isRequired, + ), tableRowIndex: PropTypes.number.isRequired, setTestPlanVersions: PropTypes.func }; diff --git a/client/components/ManageBotRunDialog/MarkBotRunFinishedButton/index.jsx b/client/components/ManageBotRunDialog/MarkBotRunFinishedButton/index.jsx index bcec9dd67..6a8fdec5d 100644 --- a/client/components/ManageBotRunDialog/MarkBotRunFinishedButton/index.jsx +++ b/client/components/ManageBotRunDialog/MarkBotRunFinishedButton/index.jsx @@ -10,6 +10,7 @@ import { LoadingStatus, useTriggerLoad } from '../../common/LoadingStatus'; import { useTestPlanRunValidatedAssertionCounts } from '../../../hooks/useTestPlanRunValidatedAssertionCounts'; import BasicModal from '../../common/BasicModal'; import { useTestPlanRunIsFinished } from '../../../hooks/useTestPlanRunIsFinished'; +import { TestPlanRunPropType } from '../../common/proptypes'; const MarkBotRunFinishedButton = ({ testPlanRun, onClick = () => {} }) => { const { @@ -86,7 +87,7 @@ const MarkBotRunFinishedButton = ({ testPlanRun, onClick = () => {} }) => { }; MarkBotRunFinishedButton.propTypes = { - testPlanRun: PropTypes.object.isRequired, + testPlanRun: TestPlanRunPropType.isRequired, onClick: PropTypes.func }; diff --git a/client/components/ManageBotRunDialog/RetryCanceledCollectionsButton/index.jsx b/client/components/ManageBotRunDialog/RetryCanceledCollectionsButton/index.jsx index a842b8142..947b480dd 100644 --- a/client/components/ManageBotRunDialog/RetryCanceledCollectionsButton/index.jsx +++ b/client/components/ManageBotRunDialog/RetryCanceledCollectionsButton/index.jsx @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import { Button } from 'react-bootstrap'; import { useMutation } from '@apollo/client'; import { RETRY_CANCELED_COLLECTIONS } from '../queries'; +import { CollectionJobPropType } from '../../common/proptypes'; const RetryCanceledCollectionsButton = ({ collectionJob, @@ -33,16 +34,7 @@ const RetryCanceledCollectionsButton = ({ }; RetryCanceledCollectionsButton.propTypes = { - collectionJob: PropTypes.shape({ - id: PropTypes.string, - status: PropTypes.oneOf([ - 'QUEUED', - 'RUNNING', - 'CANCELLED', - 'COMPLETED', - 'ERROR' - ]) - }), + collectionJob: CollectionJobPropType, onClick: PropTypes.func }; diff --git a/client/components/ManageBotRunDialog/StopRunningCollectionButton/index.jsx b/client/components/ManageBotRunDialog/StopRunningCollectionButton/index.jsx index b985996fd..a1fa69c61 100644 --- a/client/components/ManageBotRunDialog/StopRunningCollectionButton/index.jsx +++ b/client/components/ManageBotRunDialog/StopRunningCollectionButton/index.jsx @@ -4,6 +4,7 @@ import { Button } from 'react-bootstrap'; import { useMutation } from '@apollo/client'; import { CANCEL_COLLECTION_JOB } from '../queries'; import { LoadingStatus, useTriggerLoad } from '../../common/LoadingStatus'; +import { CollectionJobPropType } from '../../common/proptypes'; const StopRunningCollectionButton = ({ collectionJob, onClick = () => {} }) => { if (!collectionJob) { @@ -44,16 +45,7 @@ const StopRunningCollectionButton = ({ collectionJob, onClick = () => {} }) => { }; StopRunningCollectionButton.propTypes = { - collectionJob: PropTypes.shape({ - id: PropTypes.string, - status: PropTypes.oneOf([ - 'QUEUED', - 'RUNNING', - 'CANCELLED', - 'COMPLETED', - 'ERROR' - ]).isRequired - }), + collectionJob: CollectionJobPropType, onClick: PropTypes.func }; diff --git a/client/components/ManageBotRunDialog/WithButton.jsx b/client/components/ManageBotRunDialog/WithButton.jsx index ea6f9018a..1eac6318a 100644 --- a/client/components/ManageBotRunDialog/WithButton.jsx +++ b/client/components/ManageBotRunDialog/WithButton.jsx @@ -5,6 +5,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faRobot } from '@fortawesome/free-solid-svg-icons'; import ManageBotRunDialog from '.'; import { useTestPlanRunIsFinished } from '../../hooks/useTestPlanRunIsFinished'; +import { TestPlanRunPropType, UserPropType } from '../common/proptypes'; const ManageBotRunDialogWithButton = ({ testPlanRun, @@ -49,10 +50,10 @@ const ManageBotRunDialogWithButton = ({ }; ManageBotRunDialogWithButton.propTypes = { - testPlanRun: PropTypes.object.isRequired, + testPlanRun: TestPlanRunPropType.isRequired, testPlanReportId: PropTypes.string.isRequired, runnableTestsLength: PropTypes.number.isRequired, - testers: PropTypes.array.isRequired, + testers: PropTypes.arrayOf(UserPropType).isRequired, onChange: PropTypes.func.isRequired }; diff --git a/client/components/ManageBotRunDialog/index.jsx b/client/components/ManageBotRunDialog/index.jsx index 154a8db6b..8915ad55b 100644 --- a/client/components/ManageBotRunDialog/index.jsx +++ b/client/components/ManageBotRunDialog/index.jsx @@ -16,6 +16,7 @@ import MarkBotRunFinishedButton from './MarkBotRunFinishedButton'; import RetryCanceledCollectionsButton from './RetryCanceledCollectionsButton'; import StopRunningCollectionButton from './StopRunningCollectionButton'; import ViewLogsButton from './ViewLogsButton'; +import { TestPlanRunPropType, UserPropType } from '../common/proptypes'; const ManageBotRunDialog = ({ testPlanReportId, @@ -177,10 +178,10 @@ const ManageBotRunDialog = ({ }; ManageBotRunDialog.propTypes = { - testPlanRun: PropTypes.object.isRequired, + testPlanRun: TestPlanRunPropType.isRequired, show: PropTypes.bool.isRequired, setShow: PropTypes.func.isRequired, - testers: PropTypes.array.isRequired, + testers: PropTypes.arrayOf(UserPropType).isRequired, testPlanReportId: PropTypes.string.isRequired, runnableTestsLength: PropTypes.number.isRequired, onChange: PropTypes.func.isRequired diff --git a/client/components/ManageTestQueue/ManageAtVersions.jsx b/client/components/ManageTestQueue/ManageAtVersions.jsx index 0953d51e9..65beea962 100644 --- a/client/components/ManageTestQueue/ManageAtVersions.jsx +++ b/client/components/ManageTestQueue/ManageAtVersions.jsx @@ -15,6 +15,7 @@ import { import { useTriggerLoad } from '@components/common/LoadingStatus'; import { THEMES, useThemedModal } from '@client/hooks/useThemedModal'; import PropTypes from 'prop-types'; +import { AtPropType } from '../common/proptypes'; const ManageAtVersions = ({ ats = [], triggerUpdate = () => {} }) => { const { triggerLoad } = useTriggerLoad(); @@ -410,20 +411,7 @@ const ManageAtVersions = ({ ats = [], triggerUpdate = () => {} }) => { }; ManageAtVersions.propTypes = { - ats: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - key: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - browsers: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - key: PropTypes.string.isRequired, - name: PropTypes.string.isRequired - }) - ).isRequired - }) - ).isRequired, + ats: PropTypes.arrayOf(AtPropType).isRequired, triggerUpdate: PropTypes.func }; diff --git a/client/components/ManageTestQueue/index.jsx b/client/components/ManageTestQueue/index.jsx index d5aa795af..3bf82420d 100644 --- a/client/components/ManageTestQueue/index.jsx +++ b/client/components/ManageTestQueue/index.jsx @@ -5,6 +5,7 @@ import { LoadingStatus, useTriggerLoad } from '../common/LoadingStatus'; import DisclosureComponent from '../common/DisclosureComponent'; import ManageAtVersions from '@components/ManageTestQueue/ManageAtVersions'; import AddTestPlans from '@components/ManageTestQueue/AddTestPlans'; +import { AtPropType, TestPlanVersionPropType } from '../common/proptypes'; export const DisclosureContainer = styled.div` // Following directives are related to the ManageTestQueue component @@ -148,21 +149,8 @@ const ManageTestQueue = ({ }; ManageTestQueue.propTypes = { - ats: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - key: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - browsers: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - key: PropTypes.string.isRequired, - name: PropTypes.string.isRequired - }) - ).isRequired - }) - ).isRequired, - testPlanVersions: PropTypes.array, + ats: PropTypes.arrayOf(AtPropType).isRequired, + testPlanVersions: PropTypes.arrayOf(TestPlanVersionPropType), triggerUpdate: PropTypes.func }; diff --git a/client/components/Reports/SummarizeTestPlanReport.jsx b/client/components/Reports/SummarizeTestPlanReport.jsx index 6abd3d46c..ac9f2b138 100644 --- a/client/components/Reports/SummarizeTestPlanReport.jsx +++ b/client/components/Reports/SummarizeTestPlanReport.jsx @@ -18,6 +18,10 @@ import TestPlanResultsTable from '../common/TestPlanResultsTable'; import DisclosureComponent from '../common/DisclosureComponent'; import { Link, Navigate, useLocation, useParams } from 'react-router-dom'; import createIssueLink from '../../utils/createIssueLink'; +import { + TestPlanReportPropType, + TestPlanVersionPropType +} from '../common/proptypes'; const ResultsContainer = styled.div` padding: 1em 1.75em; @@ -378,60 +382,8 @@ const SummarizeTestPlanReport = ({ testPlanVersion, testPlanReports }) => { }; SummarizeTestPlanReport.propTypes = { - testPlanVersion: PropTypes.object.isRequired, - testPlanReports: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - runnableTests: PropTypes.arrayOf(PropTypes.object.isRequired).isRequired, - at: PropTypes.shape({ - id: PropTypes.string.isRequired, - name: PropTypes.string.isRequired - }).isRequired, - browser: PropTypes.shape({ - id: PropTypes.string.isRequired, - name: PropTypes.string.isRequired - }).isRequired, - finalizedTestResults: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - test: PropTypes.shape({ - title: PropTypes.string.isRequired, - renderedUrl: PropTypes.string.isRequired - }).isRequired, - scenarioResults: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - output: PropTypes.string.isRequired, - assertionResults: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - passed: PropTypes.bool.isRequired, - assertion: PropTypes.shape({ - text: PropTypes.string.isRequired - }).isRequired - }).isRequired - ).isRequired, - unexpectedBehaviors: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - text: PropTypes.string.isRequired, - impact: PropTypes.string.isRequired, - details: PropTypes.string.isRequired - }).isRequired - ).isRequired - }).isRequired - ).isRequired - }).isRequired - ).isRequired, - draftTestPlanRuns: PropTypes.arrayOf( - PropTypes.shape({ - tester: PropTypes.shape({ - username: PropTypes.string.isRequired - }) - }) - ) - }).isRequired - ) + testPlanVersion: TestPlanVersionPropType.isRequired, + testPlanReports: PropTypes.arrayOf(TestPlanReportPropType).isRequired }; export default SummarizeTestPlanReport; diff --git a/client/components/Reports/SummarizeTestPlanReports.jsx b/client/components/Reports/SummarizeTestPlanReports.jsx index 26867cd5a..ee3e4bbf7 100644 --- a/client/components/Reports/SummarizeTestPlanReports.jsx +++ b/client/components/Reports/SummarizeTestPlanReports.jsx @@ -9,6 +9,7 @@ import { derivePhaseName } from '../../utils/aria'; import { none } from './None'; import { getTestPlanTargetTitle, getTestPlanVersionTitle } from './getTitles'; import ClippedProgressBar from '@components/common/ClippedProgressBar'; +import { TestPlanVersionPropType } from '../common/proptypes'; const FullHeightContainer = styled(Container)` min-height: calc(100vh - 64px); @@ -151,26 +152,7 @@ const SummarizeTestPlanReports = ({ testPlanVersions }) => { }; SummarizeTestPlanReports.propTypes = { - testPlanVersions: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - title: PropTypes.string.isRequired, - phase: PropTypes.string.isRequired, - gitSha: PropTypes.string, - testPlan: PropTypes.shape({ - directory: PropTypes.string - }), - metadata: PropTypes.object, - testPlanReports: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - metrics: PropTypes.object.isRequired, - at: PropTypes.object.isRequired, - browser: PropTypes.object.isRequired - }) - ) - }) - ).isRequired + testPlanVersions: PropTypes.arrayOf(TestPlanVersionPropType).isRequired }; export default SummarizeTestPlanReports; diff --git a/client/components/Reports/SummarizeTestPlanVersion.jsx b/client/components/Reports/SummarizeTestPlanVersion.jsx index be579b5ba..74005bda1 100644 --- a/client/components/Reports/SummarizeTestPlanVersion.jsx +++ b/client/components/Reports/SummarizeTestPlanVersion.jsx @@ -11,6 +11,10 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faHome } from '@fortawesome/free-solid-svg-icons'; import styled from '@emotion/styled'; import DisclaimerInfo from '../DisclaimerInfo'; +import { + TestPlanReportPropType, + TestPlanVersionPropType +} from '../common/proptypes'; const FullHeightContainer = styled(Container)` min-height: calc(100vh - 64px); @@ -183,26 +187,8 @@ const SummarizeTestPlanVersion = ({ testPlanVersion, testPlanReports }) => { }; SummarizeTestPlanVersion.propTypes = { - testPlanVersion: PropTypes.shape({ - gitSha: PropTypes.string, - testPlan: PropTypes.object, - directory: PropTypes.string, - versionString: PropTypes.string, - id: PropTypes.string.isRequired, - title: PropTypes.string, - phase: PropTypes.string, - metadata: PropTypes.shape({ - exampleUrl: PropTypes.string.isRequired, - designPatternUrl: PropTypes.string - }).isRequired - }).isRequired, - testPlanReports: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - runnableTests: PropTypes.arrayOf(PropTypes.object).isRequired, - finalizedTestResults: PropTypes.arrayOf(PropTypes.object) - }).isRequired - ).isRequired + testPlanVersion: TestPlanVersionPropType.isRequired, + testPlanReports: PropTypes.arrayOf(TestPlanReportPropType).isRequired }; export default SummarizeTestPlanVersion; diff --git a/client/components/ReviewConflicts/ReviewConflicts.jsx b/client/components/ReviewConflicts/ReviewConflicts.jsx index c97740dc2..f272c5663 100644 --- a/client/components/ReviewConflicts/ReviewConflicts.jsx +++ b/client/components/ReviewConflicts/ReviewConflicts.jsx @@ -2,6 +2,7 @@ import React, { useEffect, useRef } from 'react'; import PropTypes from 'prop-types'; import styled from '@emotion/styled'; import TurndownService from 'turndown'; +import { TestPlanReportPropType, TestPropType } from '../common/proptypes'; const Wrapper = styled.div` & h2 { @@ -119,58 +120,8 @@ const ReviewConflicts = ({ }; ReviewConflicts.propTypes = { - testPlanReport: PropTypes.shape({ - id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - conflicts: PropTypes.arrayOf( - PropTypes.shape({ - source: PropTypes.shape({ - test: PropTypes.shape({ - id: PropTypes.string.isRequired - }).isRequired, - scenario: PropTypes.shape({ - id: PropTypes.string.isRequired, - commands: PropTypes.arrayOf( - PropTypes.shape({ - text: PropTypes.string.isRequired - }) - ).isRequired - }).isRequired, - assertion: PropTypes.shape({ - id: PropTypes.string.isRequired, - text: PropTypes.string.isRequired - }) - }).isRequired, - conflictingResults: PropTypes.arrayOf( - PropTypes.shape({ - testPlanRun: PropTypes.shape({ - id: PropTypes.string.isRequired, - tester: PropTypes.shape({ - username: PropTypes.string.isRequired - }).isRequired - }).isRequired, - scenarioResult: PropTypes.shape({ - output: PropTypes.string.isRequired, - unexpectedBehaviors: PropTypes.arrayOf( - PropTypes.shape({ - text: PropTypes.string.isRequired, - impact: PropTypes.string.isRequired, - details: PropTypes.string.isRequired - }) - ).isRequired - }), - assertionResult: PropTypes.shape({ - passed: PropTypes.bool.isRequired - }) - }) - ).isRequired - }) - ).isRequired - }), - test: PropTypes.shape({ - id: PropTypes.string.isRequired, - title: PropTypes.string.isRequired, - rowNumber: PropTypes.number.isRequired - }), + testPlanReport: TestPlanReportPropType.isRequired, + test: TestPropType.isRequired, hideHeadline: PropTypes.bool, conflictMarkdownRef: PropTypes.shape({ current: PropTypes.string diff --git a/client/components/TestPlanReportStatusDialog/index.jsx b/client/components/TestPlanReportStatusDialog/index.jsx index 37d109f0a..7bd981b0b 100644 --- a/client/components/TestPlanReportStatusDialog/index.jsx +++ b/client/components/TestPlanReportStatusDialog/index.jsx @@ -9,6 +9,7 @@ import BasicModal from '../common/BasicModal'; import './TestPlanReportStatusDialog.css'; import ReportStatusSummary from '../common/ReportStatusSummary'; import { AtVersion } from '../common/AtBrowserVersion'; +import { TestPlanVersionPropType } from '../common/proptypes'; const TestPlanReportStatusDialog = ({ testPlanVersion, @@ -147,37 +148,7 @@ const TestPlanReportStatusDialog = ({ }; TestPlanReportStatusDialog.propTypes = { - testPlanVersion: PropTypes.shape({ - id: PropTypes.string.isRequired, - title: PropTypes.string.isRequired, - phase: PropTypes.string.isRequired, - testPlanReportStatuses: PropTypes.arrayOf( - PropTypes.shape({ - at: PropTypes.shape({ - id: PropTypes.string.isRequired, - name: PropTypes.string.isRequired - }).isRequired, - browser: PropTypes.shape({ - id: PropTypes.string.isRequired, - name: PropTypes.string.isRequired - }).isRequired, - minimumAtVersion: PropTypes.shape({ - id: PropTypes.string.isRequired, - name: PropTypes.string.isRequired - }), - exactAtVersion: PropTypes.shape({ - id: PropTypes.string.isRequired, - name: PropTypes.string.isRequired - }), - testPlanReport: PropTypes.shape({ - id: PropTypes.string.isRequired, - status: PropTypes.string, - runnableTests: PropTypes.arrayOf(PropTypes.object), - finalizedTestResults: PropTypes.arrayOf(PropTypes.object) - }) - }).isRequired - ).isRequired - }).isRequired, + testPlanVersion: TestPlanVersionPropType.isRequired, handleHide: PropTypes.func.isRequired, triggerUpdate: PropTypes.func, show: PropTypes.bool.isRequired diff --git a/client/components/TestQueue/Actions.jsx b/client/components/TestQueue/Actions.jsx index c9ba177cc..444e244a6 100644 --- a/client/components/TestQueue/Actions.jsx +++ b/client/components/TestQueue/Actions.jsx @@ -22,6 +22,11 @@ import BasicThemedModal from '../common/BasicThemedModal'; import { evaluateAuth } from '../../utils/evaluateAuth'; import { TEST_PLAN_REPORT_STATUS_DIALOG_QUERY } from '../TestPlanReportStatusDialog/queries'; import ManageBotRunDialogWithButton from '@components/ManageBotRunDialog/WithButton'; +import { + TestPlanPropType, + TestPlanReportPropType, + UserPropType +} from '../common/proptypes'; const ActionContainer = styled.div` display: flex; @@ -296,42 +301,10 @@ const Actions = ({ }; Actions.propTypes = { - me: PropTypes.shape({ - id: PropTypes.string.isRequired, - username: PropTypes.string.isRequired - }), - testPlan: PropTypes.shape({ - directory: PropTypes.string.isRequired - }).isRequired, - testPlanReport: PropTypes.shape({ - id: PropTypes.string.isRequired, - runnableTestsLength: PropTypes.number.isRequired, - conflictsLength: PropTypes.number.isRequired, - draftTestPlanRuns: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - testResultsLength: PropTypes.number.isRequired, - tester: PropTypes.shape({ - id: PropTypes.string.isRequired, - username: PropTypes.string.isRequired, - isBot: PropTypes.bool.isRequired - }) - }) - ).isRequired - }).isRequired, - testers: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - username: PropTypes.string.isRequired, - isBot: PropTypes.bool.isRequired, - ats: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - key: PropTypes.string.isRequired - }) - ) - }) - ).isRequired, + me: UserPropType, + testPlan: TestPlanPropType.isRequired, + testPlanReport: TestPlanReportPropType.isRequired, + testers: PropTypes.arrayOf(UserPropType).isRequired, triggerUpdate: PropTypes.func.isRequired }; diff --git a/client/components/TestQueue/AssignTesters.jsx b/client/components/TestQueue/AssignTesters.jsx index 38f50c076..7e2c64c1a 100644 --- a/client/components/TestQueue/AssignTesters.jsx +++ b/client/components/TestQueue/AssignTesters.jsx @@ -19,6 +19,7 @@ import { } from './queries'; import { SCHEDULE_COLLECTION_JOB_MUTATION } from '../AddTestToQueueWithConfirmation/queries'; import { TEST_PLAN_REPORT_STATUS_DIALOG_QUERY } from '../TestPlanReportStatusDialog/queries'; +import { TestPlanReportPropType, UserPropType } from '../common/proptypes'; const AssignTestersContainer = styled.div` display: flex; @@ -328,56 +329,9 @@ const AssignTesters = ({ me, testers, testPlanReport }) => { }; AssignTesters.propTypes = { - me: PropTypes.shape({ - id: PropTypes.string.isRequired - }), - testers: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - username: PropTypes.string.isRequired, - isBot: PropTypes.bool.isRequired, - ats: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - key: PropTypes.string.isRequired - }) - ) - }) - ).isRequired, - testPlanReport: PropTypes.shape({ - id: PropTypes.string.isRequired, - runnableTestsLength: PropTypes.number.isRequired, - draftTestPlanRuns: PropTypes.arrayOf( - PropTypes.shape({ - tester: PropTypes.shape({ id: PropTypes.string.isRequired }).isRequired - }) - ).isRequired, - at: PropTypes.shape({ - id: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - key: PropTypes.string.isRequired, - atVersions: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - supportedByAutomation: PropTypes.bool.isRequired - }) - ) - }).isRequired, - browser: PropTypes.shape({ - id: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - key: PropTypes.string.isRequired - }).isRequired, - minimumAtVersion: PropTypes.shape({ - id: PropTypes.string.isRequired, - name: PropTypes.string.isRequired - }), - exactAtVersion: PropTypes.shape({ - id: PropTypes.string.isRequired, - name: PropTypes.string.isRequired - }) - }).isRequired + me: UserPropType, + testers: PropTypes.arrayOf(UserPropType).isRequired, + testPlanReport: TestPlanReportPropType.isRequired }; export default AssignTesters; diff --git a/client/components/TestQueue/CompletionStatusListItem/index.jsx b/client/components/TestQueue/CompletionStatusListItem/index.jsx index 98ed53eaa..2ba2c1818 100644 --- a/client/components/TestQueue/CompletionStatusListItem/index.jsx +++ b/client/components/TestQueue/CompletionStatusListItem/index.jsx @@ -4,6 +4,11 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faRobot } from '@fortawesome/free-solid-svg-icons'; import BotTestCompletionStatus from '@components/TestQueueCompletionStatusListItem/BotTestCompletionStatus'; import PreviouslyAutomatedTestCompletionStatus from '@components/TestQueueCompletionStatusListItem/PreviouslyAutomatedTestCompletionStatus'; +import { + TestPlanReportPropType, + TestPlanRunPropType, + UserPropType +} from '../../common/proptypes'; const CompletionStatusListItem = ({ rowId, @@ -67,20 +72,11 @@ const CompletionStatusListItem = ({ ); }; -// TODO: Update shape for testPlanReport and tester CompletionStatusListItem.propTypes = { rowId: PropTypes.string.isRequired, - testPlanReport: PropTypes.object.isRequired, - testPlanRun: PropTypes.shape({ - id: PropTypes.string.isRequired, - testResultsLength: PropTypes.number.isRequired, - initiatedByAutomation: PropTypes.bool.isRequired, - tester: PropTypes.shape({ - username: PropTypes.string.isRequired, - isBot: PropTypes.bool.isRequired - }).isRequired - }).isRequired, - tester: PropTypes.object.isRequired + testPlanReport: TestPlanReportPropType.isRequired, + testPlanRun: TestPlanRunPropType.isRequired, + tester: UserPropType.isRequired }; export default CompletionStatusListItem; diff --git a/client/components/TestQueueCompletionStatusListItem/BotTestCompletionStatus/index.js b/client/components/TestQueueCompletionStatusListItem/BotTestCompletionStatus/index.js index 0368b1165..e7e6f7b2e 100644 --- a/client/components/TestQueueCompletionStatusListItem/BotTestCompletionStatus/index.js +++ b/client/components/TestQueueCompletionStatusListItem/BotTestCompletionStatus/index.js @@ -1,6 +1,7 @@ import React, { useEffect } from 'react'; import PropTypes from 'prop-types'; import { useTestPlanRunValidatedAssertionCounts } from '../../../hooks/useTestPlanRunValidatedAssertionCounts'; +import { TestPlanRunPropType } from '../../common/proptypes'; const BotTestCompletionStatus = ({ testPlanRun, id, runnableTestsLength }) => { const { @@ -31,22 +32,7 @@ const BotTestCompletionStatus = ({ testPlanRun, id, runnableTestsLength }) => { }; BotTestCompletionStatus.propTypes = { - testPlanRun: PropTypes.shape({ - id: PropTypes.string.isRequired, - testResults: PropTypes.arrayOf( - PropTypes.shape({ - scenarioResults: PropTypes.arrayOf( - PropTypes.shape({ - assertionResults: PropTypes.arrayOf( - PropTypes.shape({ - passed: PropTypes.bool - }) - ) - }) - ) - }) - ) - }).isRequired, + testPlanRun: TestPlanRunPropType.isRequired, id: PropTypes.string.isRequired, runnableTestsLength: PropTypes.number.isRequired }; diff --git a/client/components/TestQueueCompletionStatusListItem/index.js b/client/components/TestQueueCompletionStatusListItem/index.js index 165ad5a47..1da90dfba 100644 --- a/client/components/TestQueueCompletionStatusListItem/index.js +++ b/client/components/TestQueueCompletionStatusListItem/index.js @@ -4,6 +4,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faRobot } from '@fortawesome/free-solid-svg-icons'; import BotTestCompletionStatus from './BotTestCompletionStatus'; import PreviouslyAutomatedTestCompletionStatus from './PreviouslyAutomatedTestCompletionStatus'; +import { TestPlanRunPropType } from '../common/proptypes'; const TestQueueCompletionStatusListItem = ({ runnableTestsLength, @@ -77,15 +78,7 @@ const TestQueueCompletionStatusListItem = ({ TestQueueCompletionStatusListItem.propTypes = { runnableTestsLength: PropTypes.number.isRequired, - testPlanRun: PropTypes.shape({ - id: PropTypes.string.isRequired, - testResultsLength: PropTypes.number.isRequired, - initiatedByAutomation: PropTypes.bool.isRequired, - tester: PropTypes.shape({ - username: PropTypes.string.isRequired, - isBot: PropTypes.bool.isRequired - }).isRequired - }).isRequired, + testPlanRun: TestPlanRunPropType.isRequired, id: PropTypes.string.isRequired }; diff --git a/client/components/TestRenderer/OutputTextArea/index.jsx b/client/components/TestRenderer/OutputTextArea/index.jsx index 62b173ab3..79dea9570 100644 --- a/client/components/TestRenderer/OutputTextArea/index.jsx +++ b/client/components/TestRenderer/OutputTextArea/index.jsx @@ -4,6 +4,7 @@ import styled from '@emotion/styled'; import { Feedback } from '..'; import { Form } from 'react-bootstrap'; import { NO_OUTPUT_STRING } from './constants'; +import { AtOutputPropType } from '../../common/proptypes'; const OutputTextAreaWrapper = styled.div` > textarea { @@ -85,21 +86,7 @@ const OutputTextArea = ({ OutputTextArea.propTypes = { commandIndex: PropTypes.number.isRequired, - atOutput: PropTypes.shape({ - description: PropTypes.arrayOf( - PropTypes.oneOfType([ - PropTypes.string, - PropTypes.shape({ - required: PropTypes.bool.isRequired, - highlightRequired: PropTypes.bool.isRequired, - description: PropTypes.string.isRequired - }) - ]) - ).isRequired, - value: PropTypes.string.isRequired, - change: PropTypes.func.isRequired, - focus: PropTypes.bool.isRequired - }).isRequired, + atOutput: AtOutputPropType.isRequired, readOnly: PropTypes.bool, isSubmitted: PropTypes.bool.isRequired }; diff --git a/client/components/TestRenderer/index.jsx b/client/components/TestRenderer/index.jsx index aac75c423..1780eac67 100644 --- a/client/components/TestRenderer/index.jsx +++ b/client/components/TestRenderer/index.jsx @@ -26,6 +26,7 @@ import AssertionsFieldset from './AssertionsFieldset'; import UnexpectedBehaviorsFieldset from './UnexpectedBehaviorsFieldset'; import supportJson from '../../resources/support.json'; import commandsJson from '../../resources/commands.json'; +import { AtPropType, TestResultPropType } from '../common/proptypes/index.js'; const Container = styled.div` width: 100%; @@ -580,8 +581,8 @@ ErrorComponent.propTypes = { }; TestRenderer.propTypes = { - at: PropTypes.object, - testResult: PropTypes.object, + at: AtPropType, + testResult: TestResultPropType, support: PropTypes.object, testPageUrl: PropTypes.string, testFormatVersion: PropTypes.number, diff --git a/client/components/TestRun/CollectionJobContext.js b/client/components/TestRun/CollectionJobContext.js index af16f4f83..2b5b69f9b 100644 --- a/client/components/TestRun/CollectionJobContext.js +++ b/client/components/TestRun/CollectionJobContext.js @@ -3,6 +3,7 @@ import React, { createContext, useState, useEffect } from 'react'; import { useLazyQuery } from '@apollo/client'; import { COLLECTION_JOB_UPDATES_QUERY } from './queries'; import { isJobStatusFinal } from '../../utils/collectionJobStatus'; +import { TestPlanRunPropType } from '../common/proptypes'; const pollInterval = 5000; export const Context = createContext({ @@ -60,12 +61,5 @@ export const Provider = ({ children, testPlanRun }) => { Provider.propTypes = { children: PropTypes.node, - testPlanRun: PropTypes.shape({ - id: PropTypes.string, - collectionJob: PropTypes.shape({ - id: PropTypes.string.isRequired, - status: PropTypes.string.isRequired, - testStatus: PropTypes.arrayOf(PropTypes.object).isRequired - }) - }) + testPlanRun: TestPlanRunPropType }; diff --git a/client/components/TestRun/ReviewConflictsModal/index.jsx b/client/components/TestRun/ReviewConflictsModal/index.jsx index 94dcf5b03..40e0ffd59 100644 --- a/client/components/TestRun/ReviewConflictsModal/index.jsx +++ b/client/components/TestRun/ReviewConflictsModal/index.jsx @@ -3,6 +3,11 @@ import PropTypes from 'prop-types'; import { Button, Modal } from 'react-bootstrap'; import styled from '@emotion/styled'; import ReviewConflicts from '../../ReviewConflicts'; +import { + TestPlanReportPropType, + TestPlanVersionPropType, + TestPropType +} from '../../common/proptypes'; const H2 = styled.h2` margin-top: 0; @@ -57,9 +62,9 @@ const ReviewConflictsModal = ({ ReviewConflictsModal.propTypes = { show: PropTypes.bool, - testPlanVersion: PropTypes.object.isRequired, - testPlanReport: PropTypes.object.isRequired, - test: PropTypes.object.isRequired, + testPlanVersion: TestPlanVersionPropType.isRequired, + testPlanReport: TestPlanReportPropType.isRequired, + test: TestPropType.isRequired, handleClose: PropTypes.func, conflictMarkdown: PropTypes.string, issueLink: PropTypes.string.isRequired diff --git a/client/components/common/AssignTesterDropdown/index.jsx b/client/components/common/AssignTesterDropdown/index.jsx index f576549fd..5d4cd9ceb 100644 --- a/client/components/common/AssignTesterDropdown/index.jsx +++ b/client/components/common/AssignTesterDropdown/index.jsx @@ -19,6 +19,7 @@ import { SCHEDULE_COLLECTION_JOB_MUTATION } from '../../AddTestToQueueWithConfir import { isSupportedByResponseCollector } from '../../../utils/automation'; import './AssignTesterDropdown.css'; +import { TestPlanRunPropType, UserPropType } from '../proptypes'; const AssignTesterDropdown = ({ testPlanReportId, @@ -209,23 +210,11 @@ const AssignTesterDropdown = ({ AssignTesterDropdown.propTypes = { testPlanReportId: PropTypes.string.isRequired, - possibleTesters: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - username: PropTypes.string.isRequired, - isBot: PropTypes.bool.isRequired, - ats: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string.isRequired, - key: PropTypes.string.isRequired - }) - ) - }) - ).isRequired, + possibleTesters: PropTypes.arrayOf(UserPropType).isRequired, onChange: PropTypes.func.isRequired, - testPlanRun: PropTypes.object, + testPlanRun: TestPlanRunPropType, label: PropTypes.string, - draftTestPlanRuns: PropTypes.array, + draftTestPlanRuns: PropTypes.arrayOf(TestPlanRunPropType), setAlertMessage: PropTypes.func, dropdownAssignTesterButtonRef: PropTypes.object }; diff --git a/client/components/common/AtAndBrowserDetailsModal/index.jsx b/client/components/common/AtAndBrowserDetailsModal/index.jsx index 1d8894153..e26475e18 100644 --- a/client/components/common/AtAndBrowserDetailsModal/index.jsx +++ b/client/components/common/AtAndBrowserDetailsModal/index.jsx @@ -10,6 +10,7 @@ import { } from '@fortawesome/free-solid-svg-icons'; import { useDetectUa } from '../../../hooks/useDetectUa'; import BasicModal from '../BasicModal'; +import { AtVersionPropType } from '../proptypes'; const ModalInnerSectionContainer = styled.div` display: flex; @@ -596,10 +597,7 @@ AtAndBrowserDetailsModal.propTypes = { browserVersions: PropTypes.arrayOf(PropTypes.string), patternName: PropTypes.string, testerName: PropTypes.string, - exactAtVersion: PropTypes.shape({ - id: PropTypes.string.isRequired, - name: PropTypes.string.isRequired - }), + exactAtVersion: AtVersionPropType, handleClose: PropTypes.func, handleAction: PropTypes.func }; diff --git a/client/components/common/BasicModal/index.jsx b/client/components/common/BasicModal/index.jsx index fdb015742..1ed363537 100644 --- a/client/components/common/BasicModal/index.jsx +++ b/client/components/common/BasicModal/index.jsx @@ -6,6 +6,7 @@ import FocusTrapper from '../FocusTrapper'; import { uniqueId } from 'lodash'; import './BasicModal.css'; +import { ModalActionPropType } from '../proptypes'; const ModalTitleStyle = styled.h1` border: 0; @@ -133,17 +134,7 @@ BasicModal.propTypes = { handleHide: PropTypes.func, staticBackdrop: PropTypes.bool, useOnHide: PropTypes.bool, - actions: PropTypes.arrayOf( - PropTypes.shape({ - label: PropTypes.string, - onClick: PropTypes.func, - variant: PropTypes.string, - className: PropTypes.string, - testId: PropTypes.string, - component: PropTypes.elementType, - props: PropTypes.object - }) - ), + actions: PropTypes.arrayOf(ModalActionPropType), initialFocusRef: PropTypes.shape({ current: PropTypes.any }) diff --git a/client/components/common/BasicThemedModal/index.jsx b/client/components/common/BasicThemedModal/index.jsx index d2dafffb2..5c53c5edb 100644 --- a/client/components/common/BasicThemedModal/index.jsx +++ b/client/components/common/BasicThemedModal/index.jsx @@ -5,6 +5,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; import styled from '@emotion/styled'; import { uniqueId } from 'lodash'; +import { ActionButtonPropType } from '../proptypes'; const ModalTitleStyle = styled.h1` border: 0; @@ -122,12 +123,7 @@ BasicThemedModal.propTypes = { dialogClassName: PropTypes.string, title: PropTypes.node.isRequired, content: PropTypes.node.isRequired, - actionButtons: PropTypes.arrayOf( - PropTypes.shape({ - text: PropTypes.string, - action: PropTypes.func - }) - ), + actionButtons: PropTypes.arrayOf(ActionButtonPropType), closeLabel: PropTypes.string, handleClose: PropTypes.func, showCloseAction: PropTypes.bool diff --git a/client/components/common/ReportStatusSummary/index.jsx b/client/components/common/ReportStatusSummary/index.jsx index df59b4689..aaae6acb8 100644 --- a/client/components/common/ReportStatusSummary/index.jsx +++ b/client/components/common/ReportStatusSummary/index.jsx @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import styled from '@emotion/styled'; import { dates } from 'shared'; import { calculatePercentComplete } from '../../../utils/calculatePercentComplete'; +import { TestPlanVersionPropType, TestPlanRunPropType } from '../proptypes'; const IncompleteStatusReport = styled.span` min-width: 5rem; @@ -74,20 +75,12 @@ const ReportStatusSummary = ({ }; ReportStatusSummary.propTypes = { - testPlanVersion: PropTypes.shape({ - id: PropTypes.string.isRequired - }).isRequired, + testPlanVersion: TestPlanVersionPropType.isRequired, testPlanReport: PropTypes.shape({ id: PropTypes.string.isRequired, markedFinalAt: PropTypes.string, metrics: PropTypes.object, - draftTestPlanRuns: PropTypes.arrayOf( - PropTypes.shape({ - tester: PropTypes.shape({ - username: PropTypes.string.isRequired - }).isRequired - }) - ).isRequired + draftTestPlanRuns: PropTypes.arrayOf(TestPlanRunPropType).isRequired }), fromTestQueue: PropTypes.bool }; diff --git a/client/components/common/TestPlanResultsTable/index.jsx b/client/components/common/TestPlanResultsTable/index.jsx index c29bcb688..1cd97a814 100644 --- a/client/components/common/TestPlanResultsTable/index.jsx +++ b/client/components/common/TestPlanResultsTable/index.jsx @@ -4,6 +4,7 @@ import { Table } from 'react-bootstrap'; import nextId from 'react-id-generator'; import { getMetrics } from 'shared'; import './TestPlanResultsTable.css'; +import { TestPropType, TestResultPropType } from '../proptypes'; const getAssertionResultText = (passed, priority) => { if (priority === 'MAY') { @@ -191,15 +192,8 @@ const TestPlanResultsTable = ({ }; TestPlanResultsTable.propTypes = { - test: PropTypes.shape({ - title: PropTypes.string.isRequired, - at: PropTypes.shape({ - name: PropTypes.string.isRequired - }).isRequired - }), - testResult: PropTypes.shape({ - scenarioResults: PropTypes.array.isRequired - }), + test: TestPropType.isRequired, + testResult: TestResultPropType.isRequired, tableClassName: PropTypes.string, optionalHeader: PropTypes.node, commandHeadingLevel: PropTypes.number diff --git a/client/components/common/proptypes/index.js b/client/components/common/proptypes/index.js new file mode 100644 index 000000000..7d98d1d78 --- /dev/null +++ b/client/components/common/proptypes/index.js @@ -0,0 +1,322 @@ +import PropTypes from 'prop-types'; + +export const AtPropType = PropTypes.shape({ + __typename: PropTypes.string, + id: PropTypes.string.isRequired, + key: PropTypes.string.isRequired, + name: PropTypes.string.isRequired +}); + +export const AtVersionPropType = PropTypes.shape({ + __typename: PropTypes.string, + id: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + releasedAt: PropTypes.string, + supportedByAutomation: PropTypes.bool +}); + +export const AssertionResultPropType = PropTypes.shape({ + __typename: PropTypes.string, + id: PropTypes.string.isRequired, + passed: PropTypes.bool.isRequired, + assertion: PropTypes.shape({ + id: PropTypes.string.isRequired, + text: PropTypes.string.isRequired, + phrase: PropTypes.string, + priority: PropTypes.string + }).isRequired +}); + +export const BrowserPropType = PropTypes.shape({ + __typename: PropTypes.string, + id: PropTypes.string.isRequired, + key: PropTypes.string.isRequired, + name: PropTypes.string.isRequired +}); + +export const BrowserVersionPropType = PropTypes.shape({ + __typename: PropTypes.string, + id: PropTypes.string.isRequired, + name: PropTypes.string.isRequired +}); + +export const CollectionJobPropType = PropTypes.shape({ + __typename: PropTypes.string, + id: PropTypes.string.isRequired, + status: PropTypes.oneOf([ + 'QUEUED', + 'RUNNING', + 'CANCELLED', + 'COMPLETED', + 'ERROR' + ]), + externalLogsUrl: PropTypes.string, + testStatus: PropTypes.arrayOf( + PropTypes.shape({ + test: PropTypes.shape({ + id: PropTypes.string.isRequired + }).isRequired, + status: PropTypes.string.isRequired + }) + ) +}); + +export const IssuePropType = PropTypes.shape({ + __typename: PropTypes.string, + link: PropTypes.string.isRequired, + isOpen: PropTypes.bool.isRequired, + feedbackType: PropTypes.string, + isCandidateReview: PropTypes.bool, + title: PropTypes.string, + author: PropTypes.string, + testNumberFilteredByAt: PropTypes.number, + createdAt: PropTypes.string, + closedAt: PropTypes.string +}); + +export const MePropType = PropTypes.shape({ + __typename: PropTypes.string, + id: PropTypes.string.isRequired, + username: PropTypes.string.isRequired, + roles: PropTypes.arrayOf(PropTypes.string) +}); + +export const ScenarioResultPropType = PropTypes.shape({ + __typename: PropTypes.string, + id: PropTypes.string.isRequired, + output: PropTypes.string, + scenario: PropTypes.shape({ + commands: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string.isRequired, + text: PropTypes.string.isRequired, + atOperatingMode: PropTypes.string + }) + ).isRequired + }).isRequired, + assertionResults: PropTypes.arrayOf(AssertionResultPropType), + mustAssertionResults: PropTypes.arrayOf(AssertionResultPropType), + shouldAssertionResults: PropTypes.arrayOf(AssertionResultPropType), + mayAssertionResults: PropTypes.arrayOf(AssertionResultPropType), + unexpectedBehaviors: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string.isRequired, + text: PropTypes.string.isRequired, + impact: PropTypes.string, + details: PropTypes.string + }) + ) +}); + +export const TestPropType = PropTypes.shape({ + __typename: PropTypes.string, + id: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, + rowNumber: PropTypes.number, + renderedUrl: PropTypes.string, + testFormatVersion: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), + ats: PropTypes.arrayOf(AtPropType), + scenarios: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string.isRequired, + at: AtPropType, + commands: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string.isRequired, + text: PropTypes.string.isRequired, + atOperatingMode: PropTypes.string + }) + ) + }) + ), + assertions: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string.isRequired, + text: PropTypes.string.isRequired, + phrase: PropTypes.string, + priority: PropTypes.string + }) + ) +}); + +export const TestPlanPropType = PropTypes.shape({ + __typename: PropTypes.string, + id: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, + directory: PropTypes.string +}); + +export const TestPlanReportPropType = PropTypes.shape({ + __typename: PropTypes.string, + id: PropTypes.string.isRequired, + metrics: PropTypes.object, + isFinal: PropTypes.bool, + createdAt: PropTypes.string, + markedFinalAt: PropTypes.string, + conflictsLength: PropTypes.number, + runnableTestsLength: PropTypes.number +}); + +export const TestPlanReportConflictPropType = PropTypes.shape({ + __typename: PropTypes.string, + source: PropTypes.shape({ + test: PropTypes.shape({ + id: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, + rowNumber: PropTypes.number + }).isRequired, + scenario: PropTypes.shape({ + id: PropTypes.string.isRequired, + commands: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string.isRequired, + text: PropTypes.string.isRequired, + atOperatingMode: PropTypes.string + }) + ) + }).isRequired, + assertion: PropTypes.shape({ + id: PropTypes.string.isRequired, + text: PropTypes.string.isRequired, + phrase: PropTypes.string, + priority: PropTypes.string + }).isRequired + }).isRequired, + conflictingResults: PropTypes.arrayOf( + PropTypes.shape({ + testPlanRun: PropTypes.shape({ + id: PropTypes.string.isRequired, + tester: PropTypes.shape({ + username: PropTypes.string.isRequired + }).isRequired + }).isRequired, + scenarioResult: PropTypes.shape({ + output: PropTypes.string, + unexpectedBehaviors: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string.isRequired, + text: PropTypes.string.isRequired, + impact: PropTypes.string, + details: PropTypes.string + }) + ) + }), + assertionResult: PropTypes.shape({ + passed: PropTypes.bool.isRequired + }).isRequired + }) + ).isRequired +}); + +export const TestPlanReportStatusPropType = PropTypes.shape({ + __typename: PropTypes.string, + isRequired: PropTypes.bool, + at: AtPropType, + browser: BrowserPropType, + minimumAtVersion: AtVersionPropType, + exactAtVersion: AtVersionPropType, + testPlanReport: PropTypes.shape({ + id: PropTypes.string.isRequired, + metrics: PropTypes.object, + isFinal: PropTypes.bool, + markedFinalAt: PropTypes.string, + issues: PropTypes.arrayOf(IssuePropType), + draftTestPlanRuns: PropTypes.arrayOf( + PropTypes.shape({ + tester: PropTypes.shape({ + username: PropTypes.string.isRequired + }).isRequired, + testPlanReport: PropTypes.shape({ + id: PropTypes.string.isRequired + }).isRequired, + testResults: PropTypes.arrayOf( + PropTypes.shape({ + test: PropTypes.shape({ + id: PropTypes.string.isRequired + }).isRequired, + atVersion: AtVersionPropType, + browserVersion: BrowserVersionPropType, + completedAt: PropTypes.string + }) + ) + }) + ) + }).isRequired +}); + +export const TestPlanRunPropType = PropTypes.shape({ + __typename: PropTypes.string, + id: PropTypes.string, + initiatedByAutomation: PropTypes.bool, + tester: PropTypes.shape({ + id: PropTypes.string, + username: PropTypes.string.isRequired, + isBot: PropTypes.bool + }).isRequired +}); + +export const TestPlanVersionPropType = PropTypes.shape({ + __typename: PropTypes.string, + id: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, + phase: PropTypes.string, + gitSha: PropTypes.string, + gitMessage: PropTypes.string, + versionString: PropTypes.string, + updatedAt: PropTypes.string, + draftPhaseReachedAt: PropTypes.string, + candidatePhaseReachedAt: PropTypes.string, + recommendedPhaseReachedAt: PropTypes.string, + recommendedPhaseTargetDate: PropTypes.string, + deprecatedAt: PropTypes.string, + testPageUrl: PropTypes.string, + metadata: PropTypes.object, + testPlan: PropTypes.shape({ + directory: PropTypes.string + }).isRequired +}); + +export const TestResultPropType = PropTypes.shape({ + __typename: PropTypes.string, + id: PropTypes.string, + startedAt: PropTypes.string, + completedAt: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]) +}); + +export const UserPropType = PropTypes.shape({ + __typename: PropTypes.string, + id: PropTypes.string.isRequired, + username: PropTypes.string.isRequired, + isBot: PropTypes.bool +}); + +export const ModalActionPropType = PropTypes.shape({ + label: PropTypes.string, + onClick: PropTypes.func, + variant: PropTypes.string, + className: PropTypes.string, + testId: PropTypes.string, + component: PropTypes.elementType, + props: PropTypes.object +}); + +export const ActionButtonPropType = PropTypes.shape({ + label: PropTypes.string, + action: PropTypes.func +}); + +export const AtOutputPropType = PropTypes.shape({ + description: PropTypes.arrayOf( + PropTypes.oneOfType([ + PropTypes.string, + PropTypes.shape({ + required: PropTypes.bool.isRequired, + highlightRequired: PropTypes.bool.isRequired, + description: PropTypes.string.isRequired + }) + ]) + ).isRequired, + value: PropTypes.string.isRequired, + change: PropTypes.func.isRequired, + focus: PropTypes.bool.isRequired +}); diff --git a/client/static/index.html b/client/static/index.html index 057213870..5db6d0959 100644 --- a/client/static/index.html +++ b/client/static/index.html @@ -5,6 +5,7 @@ +