From b82ae74c6b07a5a099de14d4cb8213abd3ff6029 Mon Sep 17 00:00:00 2001 From: alflennik Date: Tue, 19 Mar 2024 13:18:01 -0400 Subject: [PATCH 01/15] Try out tab width of 2 --- .prettierrc | 2 +- client/.storybook/main.js | 10 +- .../AddTestToQueueWithConfirmation.css | 2 +- .../AddTestToQueueWithConfirmation/index.jsx | 438 +- .../AddTestToQueueWithConfirmation/queries.js | 44 +- client/components/App/App.css | 522 +- client/components/App/App.jsx | 276 +- client/components/App/queries.js | 12 +- .../components/BotRunTestStatusList/index.js | 216 +- .../BotRunTestStatusList/queries.js | 40 +- .../ProvideFeedbackModal.css | 62 +- .../ProvideFeedbackModal/index.jsx | 218 +- .../ThankYouModal/ThankYouModal.css | 40 +- .../CandidateModals/ThankYouModal/index.jsx | 80 +- .../CandidateModals/common.css | 6 +- .../CandidateTestPlanRun.css | 130 +- .../InstructionsRenderer.jsx | 595 +- .../CandidateTestPlanRun/index.jsx | 1249 ++- .../CandidateTestPlanRun/queries.js | 296 +- .../FeedbackListItem/FeedbackListItem.css | 76 +- .../FeedbackListItem/index.jsx | 120 +- .../CandidateReview/TestPlans/TestPlans.css | 22 +- .../CandidateReview/TestPlans/index.jsx | 1486 ++- client/components/CandidateReview/index.jsx | 48 +- client/components/CandidateReview/queries.js | 94 +- client/components/ConfirmAuth/index.jsx | 32 +- .../DataManagement/DataManagement.css | 34 +- .../DataManagementRow/index.jsx | 2039 ++--- .../DataManagement/filterSortHooks.js | 408 +- client/components/DataManagement/index.jsx | 396 +- client/components/DataManagement/queries.js | 330 +- client/components/DataManagement/utils.js | 38 +- .../components/DeleteResultsModal/index.jsx | 125 +- .../DeleteTestPlanReportModal/index.jsx | 86 +- client/components/DisclaimerInfo/index.jsx | 180 +- .../GraphQLProvider/GraphQLProvider.jsx | 46 +- client/components/Home/Home.jsx | 386 +- client/components/InvalidRequest/index.jsx | 24 +- .../LoadingSpinner/LoadingSpinner.css | 68 +- .../LoadingSpinner/LoadingSpinner.jsx | 56 +- .../ManageBotRunDialog/ManageBotRunDialog.css | 6 +- .../MarkBotRunFinishedButton/index.jsx | 132 +- .../MarkBotRunFinishedButton/queries.js | 36 +- .../RetryCanceledCollectionsButton/index.jsx | 64 +- .../StopRunningCollectionButton/index.jsx | 84 +- .../ManageBotRunDialog/WithButton.jsx | 80 +- .../components/ManageBotRunDialog/index.jsx | 292 +- .../components/ManageBotRunDialog/queries.js | 68 +- client/components/ManageTestQueue/index.jsx | 1329 ++- client/components/NotFound/index.jsx | 24 +- client/components/Reports/None.js | 4 +- client/components/Reports/Report.jsx | 94 +- client/components/Reports/Reports.css | 154 +- client/components/Reports/Reports.jsx | 58 +- .../Reports/SummarizeTestPlanReport.jsx | 539 +- .../Reports/SummarizeTestPlanReports.jsx | 312 +- .../Reports/SummarizeTestPlanVersion.jsx | 341 +- client/components/Reports/getTitles.js | 4 +- client/components/Reports/queries.js | 256 +- .../ReviewConflicts/ReviewConflicts.jsx | 302 +- .../components/SignupInstructions/index.jsx | 24 +- client/components/SkipLink/SkipLink.jsx | 52 +- .../TestPlanReportStatusDialog.css | 4 +- .../TestPlanReportStatusDialog/WithButton.jsx | 302 +- ...ulateTestPlanReportCompletionPercentage.js | 24 +- .../TestPlanReportStatusDialog/index.jsx | 457 +- .../TestPlanReportStatusDialog/isRequired.js | 110 +- .../TestPlanReportStatusDialog/queries.js | 106 +- .../components/TestPlanVersionsPage/index.jsx | 1342 ++- .../TestPlanVersionsPage/queries.js | 82 +- .../AssignTesterDropdown.css | 28 +- .../TestQueue/AssignTesterDropdown/index.jsx | 331 +- client/components/TestQueue/TestQueue.css | 68 +- client/components/TestQueue/index.jsx | 503 +- client/components/TestQueue/queries.js | 514 +- .../BotTestCompletionStatus/index.js | 76 +- .../index.js | 76 +- .../index.js | 148 +- .../queries.js | 26 +- .../components/TestQueueRow/TestQueueRow.css | 58 +- client/components/TestQueueRow/index.jsx | 1114 ++- .../TestRenderer/AssertionsFieldset/index.jsx | 72 +- .../TestRenderer/OutputTextArea/index.jsx | 169 +- .../UnexpectedBehaviorsFieldset/index.jsx | 381 +- client/components/TestRenderer/index.jsx | 1030 +-- client/components/TestRenderer/utils.js | 152 +- client/components/TestReview/index.jsx | 582 +- client/components/TestReview/queries.js | 78 +- client/components/TestRun/OptionButton.js | 48 +- .../TestRun/ReviewConflictsModal/index.jsx | 102 +- client/components/TestRun/StatusBar/index.jsx | 89 +- .../components/TestRun/TestIframe/index.jsx | 308 +- client/components/TestRun/TestNavigator.jsx | 287 +- client/components/TestRun/TestRun.css | 468 +- client/components/TestRun/index.jsx | 2526 +++--- client/components/TestRun/queries.js | 2178 +++-- .../components/UserSettings/UserSettings.jsx | 256 +- client/components/UserSettings/queries.js | 36 +- .../common/AtAndBrowserDetailsModal/index.jsx | 1113 ++- .../common/BasicModal/BasicModal.css | 12 +- client/components/common/BasicModal/index.jsx | 252 +- .../common/BasicThemedModal/index.jsx | 212 +- .../ClippedProgressBar/ClippedProgressBar.css | 48 +- .../common/ClippedProgressBar/index.jsx | 62 +- .../components/common/DeleteButton/index.jsx | 32 +- .../common/DisclosureComponent/index.jsx | 326 +- .../components/common/FilterButtons/index.jsx | 96 +- .../components/common/FocusTrapper/index.jsx | 141 +- .../common/LoadingStatus/LoadingStatus.js | 76 +- .../common/LoadingStatus/useTriggerLoad.js | 30 +- .../common/PageStatus/PageStatus.css | 12 +- client/components/common/PageStatus/index.jsx | 50 +- client/components/common/PhasePill/index.jsx | 88 +- .../common/ReportStatusDot/index.jsx | 50 +- .../common/SortableTableHeader/index.js | 218 +- .../TestPlanResultsTable.css | 20 +- .../common/TestPlanResultsTable/index.jsx | 351 +- client/components/common/ThemeTable/index.jsx | 46 +- .../common/UpdateTargetDateModal/index.jsx | 230 +- .../common/UpdateVersionModal/index.jsx | 324 +- .../components/common/VersionString/index.js | 134 +- .../providers/AriaLiveRegionProvider/index.js | 50 +- client/hooks/useDetectUa.js | 34 +- client/hooks/useRouterQuery.js | 2 +- client/hooks/useTestPlanRunIsFinished.js | 52 +- .../useTestPlanRunValidatedAssertionCounts.js | 149 +- client/hooks/useThemedModal.js | 101 +- client/index.js | 44 +- client/routes/index.js | 128 +- client/static/index.css | 6 +- .../stories/ProvideFeedbackModal.stories.jsx | 54 +- client/stories/ThankYouModal.stories.jsx | 6 +- .../AddTestToQueueWithConfirmation.test.jsx | 180 +- client/tests/App.test.jsx | 16 +- client/tests/AssignTesterDropdown.test.jsx | 418 +- client/tests/BasicModal.test.jsx | 224 +- client/tests/BotRunTestStatusList.test.jsx | 292 +- client/tests/DataManagement.test.jsx | 466 +- client/tests/FilterButtons.test.jsx | 88 +- client/tests/FocusTrapper.test.jsx | 194 +- client/tests/SortableTableHeader.test.jsx | 102 +- .../tests/TestPlanReportStatusDialog.test.jsx | 90 +- client/tests/TestQueue.test.jsx | 572 +- .../TestRenderer/OutputTextArea.test.jsx | 228 +- client/tests/TestRun.test.jsx | 60 +- client/tests/UserSettings.test.jsx | 76 +- .../DataManagementPagePopulatedMock.js | 7988 ++++++++--------- .../TestPlanReportStatusDialogMock.js | 798 +- .../TestQueuePageAdminNotPopulatedMock.js | 70 +- .../TestQueuePageAdminPopulatedMock.js | 646 +- .../GraphQLMocks/TestQueuePageBaseMock.js | 186 +- .../TestQueuePageTesterNotPopulatedMock.js | 76 +- .../TestQueuePageTesterPopulatedMock.js | 678 +- client/tests/__mocks__/GraphQLMocks/index.js | 32 +- ...TestPlanReportCompletionPercentage.test.js | 96 +- client/tests/smokeTest.test.js | 132 +- client/tests/util/getPage.js | 170 +- client/tests/util/index.js | 2 +- client/utils/DisplayNone.jsx | 4 +- client/utils/ScrollFixer.jsx | 86 +- client/utils/alphabetizeObjectBy.js | 12 +- client/utils/alphabetizeObjectBy.test.js | 34 +- client/utils/aria.js | 34 +- client/utils/automation.js | 14 +- client/utils/constants.js | 8 +- client/utils/createIssueLink.js | 270 +- client/utils/evaluateAuth.js | 24 +- client/utils/formSerialization.js | 120 +- client/utils/formatter.js | 36 +- client/utils/gitUtils.js | 18 +- client/utils/gitUtils.test.js | 42 +- client/utils/navigateTests.js | 51 +- client/webpack.config.js | 166 +- client/webpack.prod.js | 128 +- server/app.js | 36 +- server/apps/embed.js | 416 +- server/controllers/AuthController.js | 122 +- server/controllers/AutomationController.js | 473 +- server/controllers/FakeUserController.js | 44 +- server/controllers/TestController.js | 24 +- server/graphql-context.js | 19 +- server/graphql-schema.js | 2770 +++--- server/graphql-server.js | 12 +- server/handlebars/embed/helpers/index.js | 107 +- server/handlebars/embed/public/script.js | 48 +- server/handlebars/embed/public/style.css | 230 +- server/jest.config.js | 2 +- server/middleware/handleError.js | 6 +- server/middleware/session.js | 20 +- server/middleware/transactionMiddleware.js | 68 +- .../middleware/transactionMiddleware.test.js | 120 +- .../middleware/verifyAutomationScheduler.js | 18 +- .../20200518185559-initial-migration.js | 30 +- ...20200521003201-create_table_test_issues.js | 64 +- ...-serialized-form-column-to-test-results.js | 16 +- .../20200528143617-add-run-status.js | 34 +- .../20200528143624-add-run-status-to-run.js | 26 +- ...8172804-add-run-status-to-run-data-view.js | 28 +- ...te-browser-version-to-at-and-at-version.js | 100 +- .../20200915184800-AddActiveFlags.js | 94 +- .../20200915203422-AddColumnsToTestRun.js | 132 +- ...te-create-browser-version-to-at-version.js | 276 +- .../20200929194042-AddActiveToTestVersions.js | 50 +- .../20201016203157-RemoveTestCycleModel.js | 206 +- ...01232332-add-links-columns-apg-examples.js | 60 +- .../20210512004505-BuildNewDatabaseSchema.js | 184 +- .../20210524210332-TestQueueChanges.js | 426 +- ...0601152335-supportNewTestQueueMutations.js | 190 +- .../20210601152340-emptyObsoleteTables.js | 38 +- ...-removeTestPlanTargetVersionConstraints.js | 122 +- .../migrations/20210809220722-UserSettings.js | 18 +- .../20210920195544-reportingBackend.js | 64 +- .../20211116172219-commandSequences.js | 110 +- .../20211118143508-testRowNumber.js | 108 +- .../20220427145338-alterAtVersionTable.js | 70 +- ...220427192638-changeConstraintsAtVersion.js | 36 +- ...20220427194229-addIdConstraintAtVersion.js | 36 +- .../20220427204420-changeAtVersionColumn.js | 34 +- ...20220503193406-alterBrowserVersionTable.js | 102 +- .../20220509140537-removeTestPlanTarget.js | 209 +- ...20220712044433-changeJsonbArraysToJsonb.js | 154 +- ...220801210224-updateJawsTestInstructions.js | 32 +- ...0825125643-addStatusChangeUpdateColumns.js | 114 +- ...20919142951-addVendorReviewStatusColumn.js | 54 +- .../20220928162616-addViewersToTests.js | 32 +- .../20220929155024-addMetricsColumn.js | 42 +- .../20220929155029-addMetricsValues.js | 150 +- ...1116154332-updateTestPlanReportStatuses.js | 40 +- ...-removeInReviewStatusFromTestPlanReport.js | 10 +- .../migrations/20230424152008-addAtBrowser.js | 46 +- .../20230424152008-createTestPlanTable.js | 60 +- .../20230425152008-createTestPlanColumns.js | 100 +- ...30425215656-updateTestPlanVersionTitles.js | 44 +- ...30501220810-deduplicateTestPlanVersions.js | 1135 ++- .../20230523163855-addColumnsToAtBrowsers.js | 64 +- ...3856-remove-OtherUnexpectedBehaviorText.js | 316 +- ...8170853-addDateColumnsToTestPlanVersion.js | 208 +- ...veTestPlanReportValuesToTestPlanVersion.js | 1081 ++- ...ameCandidateStatusReachedAtToApprovedAt.js | 108 +- ...PhaseReachedAtColumnsForTestPlanVersion.js | 122 +- ...230719174358-removeTestPlanReportStatus.js | 42 +- .../20230823212533-addCollectionJobs.js | 64 +- ...gDeprecatedAtAndReorderPhaseChangeDates.js | 274 +- .../20230927172432-addVersionStrings.js | 124 +- ...dd-initiatedByAutomation-to-testPlanRun.js | 23 +- .../20231031162340-verifyNoSkippedTests.js | 82 +- ...15-addScreenTextAndInstructionsToAtMode.js | 52 +- ...sultsUnexpectedBehaviorImpactAndDetails.js | 108 +- .../20231219212344-recalculateV2TestHashes.js | 18 +- ...deAdditionalTestFormatVersionAttributes.js | 117 +- ...25130-includeMissingAssertionExceptions.js | 73 +- ...teMetricsForCountingUnexpectedBehaviors.js | 89 +- ...3914-includeAssertionIdInTestAssertions.js | 77 +- ...6-updateMetricsForUsingTotalCalculation.js | 89 +- server/migrations/utils/index.js | 346 +- server/models/At.js | 80 +- server/models/AtBrowsers.js | 64 +- server/models/AtMode.js | 92 +- server/models/AtVersion.js | 82 +- server/models/Browser.js | 80 +- server/models/BrowserVersion.js | 70 +- server/models/CollectionJob.js | 92 +- server/models/Role.js | 54 +- server/models/TestPlan.js | 64 +- server/models/TestPlanReport.js | 142 +- server/models/TestPlanRun.js | 78 +- server/models/TestPlanVersion.js | 180 +- server/models/User.js | 92 +- server/models/UserAts.js | 48 +- server/models/UserRoles.js | 48 +- server/models/index.js | 58 +- server/models/loaders/AtLoader.js | 90 +- server/models/loaders/BrowserLoader.js | 76 +- server/models/loaders/utils.js | 12 +- .../models/services.deprecated/AtService.js | 620 +- .../services.deprecated/BrowserService.js | 408 +- .../CollectionJobService.js | 525 +- .../services.deprecated/ModelService.js | 502 +- .../models/services.deprecated/RoleService.js | 130 +- .../TestPlanReportService.js | 420 +- .../services.deprecated/TestPlanRunService.js | 432 +- .../services.deprecated/TestPlanService.js | 98 +- .../TestPlanVersionService.js | 559 +- .../TestResultReadService.js | 130 +- .../TestResultWriteService.js | 132 +- .../services.deprecated/TestsService.js | 95 +- .../models/services.deprecated/UserService.js | 513 +- server/models/services.deprecated/helpers.js | 62 +- server/models/services/AtService.js | 632 +- server/models/services/BrowserService.js | 426 +- .../models/services/CollectionJobService.js | 753 +- server/models/services/ModelService.js | 577 +- server/models/services/RoleService.js | 136 +- .../models/services/TestPlanReportService.js | 440 +- server/models/services/TestPlanRunService.js | 467 +- server/models/services/TestPlanService.js | 330 +- .../models/services/TestPlanVersionService.js | 396 +- .../models/services/TestResultReadService.js | 134 +- .../models/services/TestResultWriteService.js | 163 +- server/models/services/TestsService.js | 95 +- server/models/services/UserService.js | 450 +- server/models/services/helpers.js | 62 +- .../findOrCreateAtVersionResolver.js | 22 +- .../deleteAtVersionResolver.js | 92 +- .../updateAtVersionResolver.js | 16 +- .../findOrCreateBrowserVersionResolver.js | 32 +- .../cancelCollectionJobResolver.js | 64 +- .../retryCanceledCollectionsResolver.js | 62 +- .../assertionResultsResolver.js | 50 +- server/resolvers/ScenarioResult/index.js | 2 +- server/resolvers/Test/assertionsResolver.js | 10 +- server/resolvers/Test/index.js | 12 +- .../Test/renderableContentResolver.js | 36 +- .../Test/renderableContentsResolver.js | 42 +- server/resolvers/Test/renderedUrlResolver.js | 28 +- server/resolvers/Test/renderedUrlsResolver.js | 40 +- server/resolvers/Test/scenariosResolver.js | 10 +- server/resolvers/TestPlan/index.js | 2 +- server/resolvers/TestPlan/issuesResolver.js | 4 +- server/resolvers/TestPlanReport/atResolver.js | 8 +- .../TestPlanReport/atVersionsResolver.js | 20 +- .../TestPlanReport/browserResolver.js | 8 +- .../TestPlanReport/conflictsLengthResolver.js | 16 +- .../TestPlanReport/conflictsResolver.js | 188 +- .../draftTestPlanRunsResolver.js | 20 +- .../finalizedTestResultsResolver.js | 30 +- server/resolvers/TestPlanReport/index.js | 24 +- .../TestPlanReport/isFinalResolver.js | 8 +- .../TestPlanReport/issuesResolver.js | 140 +- .../latestAtVersionReleasedAtResolver.js | 42 +- .../runnableTestsLengthResolver.js | 16 +- .../TestPlanReport/runnableTestsResolver.js | 4 +- .../assignTesterResolver.js | 60 +- .../deleteTestPlanReportResolver.js | 30 +- .../deleteTestPlanRunResolver.js | 70 +- .../TestPlanReportOperations/index.js | 14 +- .../markAsFinalResolver.js | 70 +- .../promoteVendorReviewStatusResolver.js | 46 +- .../unmarkAsFinalResolver.js | 28 +- ...teTestPlanReportTestPlanVersionResolver.js | 587 +- server/resolvers/TestPlanRun/index.js | 4 +- .../TestPlanRun/testResultsLengthResolver.js | 8 +- .../TestPlanRun/testResultsResolver.js | 6 +- .../convertTestResultToInput.js | 34 +- .../createTestResultSkeleton.js | 107 +- .../deleteTestResultsResolver.js | 54 +- .../findOrCreateTestResultResolver.js | 76 +- .../resolvers/TestPlanRunOperations/index.js | 4 +- .../TestPlanVersion/gitMessageResolver.js | 8 +- server/resolvers/TestPlanVersion/index.js | 10 +- .../recommendedPhaseTargetDateResolver.js | 20 +- .../testPlanReportsResolver.js | 26 +- .../TestPlanVersion/testPlanResolver.js | 40 +- .../TestPlanVersion/testsResolver.js | 6 +- .../TestPlanVersionOperations/index.js | 4 +- .../updatePhaseResolver.js | 529 +- ...pdateRecommendedPhaseTargetDateResolver.js | 28 +- .../deleteTestResultResolver.js | 59 +- .../resolvers/TestResultOperations/index.js | 6 +- .../saveTestResultCommon.js | 242 +- .../saveTestResultResolver.js | 45 +- .../submitTestResultResolver.js | 91 +- server/resolvers/User/atsResolver.js | 6 +- server/resolvers/User/index.js | 4 +- server/resolvers/User/rolesResolver.js | 12 +- server/resolvers/addViewerResolver.js | 54 +- server/resolvers/atsResolver.js | 6 +- server/resolvers/browsersResolver.js | 6 +- .../collectionJobByTestPlanRunIdResolver.js | 34 +- server/resolvers/collectionJobResolver.js | 8 +- server/resolvers/collectionJobsResolver.js | 8 +- .../resolvers/deleteCollectionJobResolver.js | 12 +- .../findOrCreateCollectionJobResolver.js | 26 +- .../findOrCreateTestPlanReportResolver.js | 40 +- .../deriveAttributesFromCustomField.js | 104 +- .../helpers/persistConflictsCount.js | 42 +- .../resolvers/helpers/processCopiedReports.js | 681 +- .../resolvers/helpers/retrieveAttributes.js | 90 +- server/resolvers/helpers/retrieveCommands.js | 195 +- server/resolvers/index.js | 102 +- server/resolvers/meResolver.js | 2 +- server/resolvers/mutateAtResolver.js | 8 +- server/resolvers/mutateAtVersionResolver.js | 8 +- server/resolvers/mutateBrowserResolver.js | 8 +- .../resolvers/mutateCollectionJobResolver.js | 8 +- .../resolvers/mutateTestPlanReportResolver.js | 8 +- server/resolvers/mutateTestPlanRunResolver.js | 8 +- .../mutateTestPlanVersionResolver.js | 8 +- server/resolvers/mutateTestResultResolver.js | 8 +- server/resolvers/populateDataResolver.js | 4 +- .../resolvers/restartCollectionJobResolver.js | 12 +- .../scheduleCollectionJobResolver.js | 18 +- server/resolvers/testPlanReportResolver.js | 6 +- server/resolvers/testPlanReportsResolver.js | 136 +- server/resolvers/testPlanResolver.js | 14 +- server/resolvers/testPlanRunResolver.js | 4 +- server/resolvers/testPlanRunsResolver.js | 8 +- server/resolvers/testPlanVersionResolver.js | 6 +- server/resolvers/testPlanVersionsResolver.js | 54 +- server/resolvers/testPlansResolver.js | 92 +- .../resolvers/updateCollectionJobResolver.js | 36 +- server/resolvers/updateMe.js | 20 +- server/resolvers/usersResolver.js | 20 +- server/routes/auth.js | 6 +- server/routes/automation.js | 6 +- server/scripts/import-tests/index.js | 1090 ++- server/scripts/populate-test-data/index.js | 456 +- .../populateFakeTestResults.js | 480 +- server/seeders/20210824151240-at.js | 34 +- server/seeders/20210824151240-browser.js | 30 +- server/seeders/20210824151240-role.js | 22 +- .../20220510211045-at_browser_version.js | 125 +- ...6200024-test_results_at_browser_version.js | 109 +- server/seeders/20220727141440-vendor-role.js | 20 +- .../20230426165718-populateTestPlans.js | 102 +- ...-populateTestPlanIdsForTestPlanVersions.js | 92 +- ...9-populateTestPlanIdsForTestPlanReports.js | 74 +- server/seeders/20230622202911-addAtBrowser.js | 34 +- server/seeders/20231218191524-addNVDABot.js | 50 +- server/server.js | 4 +- server/services/GithubService.js | 162 +- server/services/GithubWorkflowService.js | 170 +- .../PopulatedData/locationOfDataId.js | 131 +- .../PopulatedData/locationOfDataId.test.js | 75 +- server/services/PopulatedData/populateData.js | 462 +- server/services/TestService.js | 66 +- .../tests/integration/authentication.test.js | 328 +- .../integration/automation-scheduler.test.js | 871 +- .../tests/integration/dataManagement.test.js | 1075 ++- server/tests/integration/embed.test.js | 143 +- server/tests/integration/graphql.test.js | 950 +- server/tests/integration/testPlanRun.test.js | 335 +- server/tests/integration/testQueue.test.js | 566 +- server/tests/models/At.spec.js | 76 +- server/tests/models/AtMode.spec.js | 54 +- server/tests/models/AtVersion.spec.js | 54 +- server/tests/models/Browser.spec.js | 64 +- server/tests/models/BrowserVersion.spec.js | 54 +- server/tests/models/CollectionJob.spec.js | 56 +- server/tests/models/Role.spec.js | 26 +- server/tests/models/TestPlan.spec.js | 68 +- server/tests/models/TestPlanReport.spec.js | 113 +- server/tests/models/TestPlanRun.spec.js | 76 +- server/tests/models/TestPlanVersion.spec.js | 72 +- server/tests/models/User.spec.js | 74 +- server/tests/models/UserRoles.spec.js | 26 +- .../tests/models/services/AtService.test.js | 1605 ++-- .../models/services/BrowserService.test.js | 1012 ++- .../services/CollectionJobService.test.js | 515 +- .../models/services/ModelService.test.js | 427 +- .../tests/models/services/RoleService.test.js | 442 +- .../services/TestPlanReportService.test.js | 360 +- .../services/TestPlanRunService.test.js | 472 +- .../models/services/TestPlanService.test.js | 302 +- .../services/TestPlanVersionService.test.js | 445 +- .../tests/models/services/UserService.test.js | 573 +- server/tests/unit/controllers.test.js | 26 +- server/tests/util/api-server.js | 98 +- server/tests/util/array-containing-exactly.js | 50 +- server/tests/util/db-cleaner.deprecated.js | 20 +- server/tests/util/db-cleaner.js | 16 +- server/tests/util/global-teardown.js | 2 +- server/tests/util/graphql-test-utilities.js | 82 +- .../util/mock-automation-scheduler-server.js | 384 +- server/tests/util/mock-github-server.js | 136 +- server/tests/util/post.js | 12 +- .../tests/util/random-character-generator.js | 18 +- server/util/allEqual.js | 8 +- server/util/allEqual.test.js | 48 +- server/util/aria.js | 80 +- server/util/aria.test.js | 312 +- server/util/constants.js | 2 +- server/util/convertDateToString.js | 4 +- server/util/db-config.js | 14 +- server/util/deepCustomMerge.js | 114 +- server/util/deepCustomMerge.test.js | 182 +- server/util/deepFlatFilter.js | 24 +- server/util/deepFlatFilter.test.js | 92 +- server/util/deepPickEqual.js | 44 +- server/util/deepPickEqual.test.js | 228 +- server/util/enums.js | 12 +- server/util/getUsersFromFile.js | 22 +- server/util/responseCollectionUser.js | 4 +- server/util/sortArrayLikeArray.js | 38 +- server/util/sortArrayLikeArray.test.js | 68 +- server/util/staleWhileRevalidate.js | 117 +- server/util/staleWhileRevalidate.test.js | 232 +- shared/convertAssertionPriority.js | 16 +- shared/getMetrics.js | 468 +- shared/tests/convertAssertionPriority.test.js | 76 +- 490 files changed, 46894 insertions(+), 48746 deletions(-) diff --git a/.prettierrc b/.prettierrc index e0fe2cf91..f05cc577a 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,6 +1,6 @@ { "singleQuote": true, - "tabWidth": 4, + "tabWidth": 2, "arrowParens": "avoid", "trailingComma": "none" } \ No newline at end of file diff --git a/client/.storybook/main.js b/client/.storybook/main.js index 47b716e96..7e913453b 100644 --- a/client/.storybook/main.js +++ b/client/.storybook/main.js @@ -1,7 +1,7 @@ module.exports = { - core: { - builder: 'webpack5' - }, - stories: ['../stories/*.stories.jsx'], - addons: ['@storybook/addon-a11y', '@storybook/addon-controls'] + core: { + builder: 'webpack5' + }, + stories: ['../stories/*.stories.jsx'], + addons: ['@storybook/addon-a11y', '@storybook/addon-controls'] }; diff --git a/client/components/AddTestToQueueWithConfirmation/AddTestToQueueWithConfirmation.css b/client/components/AddTestToQueueWithConfirmation/AddTestToQueueWithConfirmation.css index 47313b99a..8afcbafcb 100644 --- a/client/components/AddTestToQueueWithConfirmation/AddTestToQueueWithConfirmation.css +++ b/client/components/AddTestToQueueWithConfirmation/AddTestToQueueWithConfirmation.css @@ -1,3 +1,3 @@ .add-test-to-queue-confirmation { - max-width: clamp(40vw, 300px, 800px); + max-width: clamp(40vw, 300px, 800px); } diff --git a/client/components/AddTestToQueueWithConfirmation/index.jsx b/client/components/AddTestToQueueWithConfirmation/index.jsx index 637a7d2ee..daadf5713 100644 --- a/client/components/AddTestToQueueWithConfirmation/index.jsx +++ b/client/components/AddTestToQueueWithConfirmation/index.jsx @@ -6,243 +6,243 @@ import { useMutation, useQuery } from '@apollo/client'; import { ADD_TEST_QUEUE_MUTATION } from '../TestQueue/queries'; import { LoadingStatus, useTriggerLoad } from '../common/LoadingStatus'; import { - getBotUsernameFromAtBrowser, - isSupportedByResponseCollector + getBotUsernameFromAtBrowser, + isSupportedByResponseCollector } from '../../utils/automation'; import './AddTestToQueueWithConfirmation.css'; import { - SCHEDULE_COLLECTION_JOB_MUTATION, - EXISTING_TEST_PLAN_REPORTS + SCHEDULE_COLLECTION_JOB_MUTATION, + EXISTING_TEST_PLAN_REPORTS } from './queries'; function AddTestToQueueWithConfirmation({ - testPlanVersion, - browser, - at, - disabled = false, - buttonText = 'Add to Test Queue', - triggerUpdate = () => {} + testPlanVersion, + browser, + at, + disabled = false, + buttonText = 'Add to Test Queue', + triggerUpdate = () => {} }) { - const [errorMessage, setErrorMessage] = useState(false); - const [showConfirmation, setShowConfirmation] = useState(false); - const [addTestPlanReport] = useMutation(ADD_TEST_QUEUE_MUTATION); - const [scheduleCollection] = useMutation(SCHEDULE_COLLECTION_JOB_MUTATION); - const { data: existingTestPlanReportsData } = useQuery( - EXISTING_TEST_PLAN_REPORTS, - { - variables: { - testPlanVersionId: testPlanVersion?.id - }, - fetchPolicy: 'cache-and-network', - skip: !testPlanVersion?.id - } + const [errorMessage, setErrorMessage] = useState(false); + const [showConfirmation, setShowConfirmation] = useState(false); + const [addTestPlanReport] = useMutation(ADD_TEST_QUEUE_MUTATION); + const [scheduleCollection] = useMutation(SCHEDULE_COLLECTION_JOB_MUTATION); + const { data: existingTestPlanReportsData } = useQuery( + EXISTING_TEST_PLAN_REPORTS, + { + variables: { + testPlanVersionId: testPlanVersion?.id + }, + fetchPolicy: 'cache-and-network', + skip: !testPlanVersion?.id + } + ); + + const existingTestPlanReports = + existingTestPlanReportsData?.testPlanVersion.testPlanReports; + + const conflictingReportExists = existingTestPlanReports?.some(report => { + return ( + report.at.id === at?.id && + report.browser.id === browser?.id && + report.isFinal ); + }); - const existingTestPlanReports = - existingTestPlanReportsData?.testPlanVersion.testPlanReports; - - const conflictingReportExists = existingTestPlanReports?.some(report => { - return ( - report.at.id === at?.id && - report.browser.id === browser?.id && - report.isFinal - ); - }); - - const { triggerLoad, loadingMessage } = useTriggerLoad(); - const buttonRef = useRef(); - - const hasAutomationSupport = isSupportedByResponseCollector({ - at, - browser - }); - - const alreadyHasBotInTestPlanReport = useMemo( - () => - existingTestPlanReports?.some( - tpr => - tpr.markedFinalAt === null && - tpr.draftTestPlanRuns.some(run => run.initiatedByAutomation) - ), - [existingTestPlanReports] - ); + const { triggerLoad, loadingMessage } = useTriggerLoad(); + const buttonRef = useRef(); - const feedbackModalTitle = - hasAutomationSupport && testPlanVersion - ? `Adding ${testPlanVersion.title} Test Plan to the Test Queue` - : 'Successfully Added Test Plan'; - - const feedbackModalContent = hasAutomationSupport ? ( - <> - Choose how the report for {at?.name} and {browser?.name} will be - generated. Add it to the queue so it can be assigned to a tester at - a later time or start running automated response collection with{' '} - {getBotUsernameFromAtBrowser(at, browser)}. - - ) : ( - <> - Successfully added {testPlanVersion?.title} for{' '} - - {at?.name} and {browser?.name} - {' '} - to the Test Queue. - + const hasAutomationSupport = isSupportedByResponseCollector({ + at, + browser + }); + + const alreadyHasBotInTestPlanReport = useMemo( + () => + existingTestPlanReports?.some( + tpr => + tpr.markedFinalAt === null && + tpr.draftTestPlanRuns.some(run => run.initiatedByAutomation) + ), + [existingTestPlanReports] + ); + + const feedbackModalTitle = + hasAutomationSupport && testPlanVersion + ? `Adding ${testPlanVersion.title} Test Plan to the Test Queue` + : 'Successfully Added Test Plan'; + + const feedbackModalContent = hasAutomationSupport ? ( + <> + Choose how the report for {at?.name} and {browser?.name} will be + generated. Add it to the queue so it can be assigned to a tester at a + later time or start running automated response collection with{' '} + {getBotUsernameFromAtBrowser(at, browser)}. + + ) : ( + <> + Successfully added {testPlanVersion?.title} for{' '} + + {at?.name} and {browser?.name} + {' '} + to the Test Queue. + + ); + + const closeWithUpdate = async () => { + setShowConfirmation(false); + await triggerUpdate(); + await new Promise(resolve => setTimeout(resolve, 0)); + if (buttonRef?.current) { + buttonRef.current.focus(); + } + }; + + const renderConfirmation = () => { + const actions = []; + if (hasAutomationSupport) { + actions.push({ + label: 'Add and run later', + onClick: async () => { + await addTestToQueue(); + await closeWithUpdate(); + } + }); + + if (!alreadyHasBotInTestPlanReport) { + actions.push({ + label: 'Add and run with bot', + onClick: async () => { + const testPlanReport = await addTestToQueue(); + await scheduleCollectionJob(testPlanReport); + await closeWithUpdate(); + } + }); + } + } + return ( + { + if (hasAutomationSupport) { + setShowConfirmation(false); + } else { + await closeWithUpdate(); + } + }} + /> ); + }; - const closeWithUpdate = async () => { - setShowConfirmation(false); - await triggerUpdate(); - await new Promise(resolve => setTimeout(resolve, 0)); - if (buttonRef?.current) { - buttonRef.current.focus(); + const renderErrorDialog = () => { + return ( + { - const actions = []; - if (hasAutomationSupport) { - actions.push({ - label: 'Add and run later', - onClick: async () => { - await addTestToQueue(); - await closeWithUpdate(); - } - }); - - if (!alreadyHasBotInTestPlanReport) { - actions.push({ - label: 'Add and run with bot', - onClick: async () => { - const testPlanReport = await addTestToQueue(); - await scheduleCollectionJob(testPlanReport); - await closeWithUpdate(); - } - }); + closeLabel="Cancel" + staticBackdrop={true} + actions={[ + { + label: 'Proceed', + onClick: async () => { + setErrorMessage(false); + if (hasAutomationSupport) { + setShowConfirmation(true); + } else { + await addTestToQueue(); + } } - } - return ( - { - if (hasAutomationSupport) { - setShowConfirmation(false); - } else { - await closeWithUpdate(); - } - }} - /> - ); - }; - - const renderErrorDialog = () => { - return ( - { - setErrorMessage(false); - if (hasAutomationSupport) { - setShowConfirmation(true); - } else { - await addTestToQueue(); - } - } - } - ]} - useOnHide - handleClose={async () => { - setErrorMessage(false); - }} - /> - ); - }; - - const addTestToQueue = async () => { - let tpr; - await triggerLoad(async () => { - const res = await addTestPlanReport({ - variables: { - testPlanVersionId: testPlanVersion.id, - atId: at.id, - browserId: browser.id - } - }); - const testPlanReport = - res?.data?.findOrCreateTestPlanReport?.populatedData - ?.testPlanReport ?? null; - tpr = testPlanReport; - }, 'Adding Test Plan to Test Queue'); - setShowConfirmation(true); - return tpr; - }; - - const scheduleCollectionJob = async testPlanReport => { - await triggerLoad(async () => { - await scheduleCollection({ - variables: { - testPlanReportId: testPlanReport.id - } - }); - }, 'Scheduling Collection Job'); - setShowConfirmation(true); - }; - - return ( - - - {renderErrorDialog()} - {renderConfirmation()} - + } + ]} + useOnHide + handleClose={async () => { + setErrorMessage(false); + }} + /> ); + }; + + const addTestToQueue = async () => { + let tpr; + await triggerLoad(async () => { + const res = await addTestPlanReport({ + variables: { + testPlanVersionId: testPlanVersion.id, + atId: at.id, + browserId: browser.id + } + }); + const testPlanReport = + res?.data?.findOrCreateTestPlanReport?.populatedData?.testPlanReport ?? + null; + tpr = testPlanReport; + }, 'Adding Test Plan to Test Queue'); + setShowConfirmation(true); + return tpr; + }; + + const scheduleCollectionJob = async testPlanReport => { + await triggerLoad(async () => { + await scheduleCollection({ + variables: { + testPlanReportId: testPlanReport.id + } + }); + }, 'Scheduling Collection Job'); + setShowConfirmation(true); + }; + + return ( + + + {renderErrorDialog()} + {renderConfirmation()} + + ); } AddTestToQueueWithConfirmation.propTypes = { - testPlanVersion: PropTypes.object, - browser: PropTypes.object, - at: PropTypes.object, - buttonRef: PropTypes.object, - onFocus: PropTypes.func, - onBlur: PropTypes.func, - disabled: PropTypes.bool, - buttonText: PropTypes.string, - triggerUpdate: PropTypes.func + testPlanVersion: PropTypes.object, + browser: PropTypes.object, + at: PropTypes.object, + buttonRef: PropTypes.object, + onFocus: PropTypes.func, + onBlur: PropTypes.func, + disabled: PropTypes.bool, + buttonText: PropTypes.string, + triggerUpdate: PropTypes.func }; export default AddTestToQueueWithConfirmation; diff --git a/client/components/AddTestToQueueWithConfirmation/queries.js b/client/components/AddTestToQueueWithConfirmation/queries.js index 796098849..114a7ab2a 100644 --- a/client/components/AddTestToQueueWithConfirmation/queries.js +++ b/client/components/AddTestToQueueWithConfirmation/queries.js @@ -1,32 +1,32 @@ import { gql } from '@apollo/client'; export const SCHEDULE_COLLECTION_JOB_MUTATION = gql` - mutation ScheduleCollectionJob($testPlanReportId: ID!) { - scheduleCollectionJob(testPlanReportId: $testPlanReportId) { - id - status - } + mutation ScheduleCollectionJob($testPlanReportId: ID!) { + scheduleCollectionJob(testPlanReportId: $testPlanReportId) { + id + status } + } `; export const EXISTING_TEST_PLAN_REPORTS = gql` - query ExistingTestPlanReports($testPlanVersionId: ID!) { - testPlanVersion(id: $testPlanVersionId) { - id - testPlanReports { - id - markedFinalAt - isFinal - draftTestPlanRuns { - initiatedByAutomation - } - at { - id - } - browser { - id - } - } + query ExistingTestPlanReports($testPlanVersionId: ID!) { + testPlanVersion(id: $testPlanVersionId) { + id + testPlanReports { + id + markedFinalAt + isFinal + draftTestPlanRuns { + initiatedByAutomation + } + at { + id + } + browser { + id } + } } + } `; diff --git a/client/components/App/App.css b/client/components/App/App.css index 920654a10..862482592 100644 --- a/client/components/App/App.css +++ b/client/components/App/App.css @@ -1,24 +1,24 @@ #root { - width: 100%; - height: 100vh; - background: #eaeaea; + width: 100%; + height: 100vh; + background: #eaeaea; } #root > div, main { - overflow: visible; + overflow: visible; } main { - background: white; - height: 100%; + background: white; + height: 100%; } nav.navbar, main.container, .test-run-container { - max-width: 1400px; - margin: auto; + max-width: 1400px; + margin: auto; } .container-fluid, @@ -26,216 +26,216 @@ main.container, .container-md, .container-lg, .container-xl { - padding: 0rem; + padding: 0rem; } .container { - background-color: white; + background-color: white; } nav.navbar { - padding: 0.5rem 1rem; + padding: 0.5rem 1rem; } .nav-link { - position: relative; + position: relative; } .nav-link:hover { - color: #000; - text-decoration: none; + color: #000; + text-decoration: none; } a.nav-link { - color: #0b60ab; + color: #0b60ab; } .nav-link[aria-current='true'] { - color: #000; + color: #000; } .nav-link:hover:after { - background: #cfcece; + background: #cfcece; } .nav-link[aria-current='true']:after { - background: #0b60ab; + background: #0b60ab; } @media all and (min-width: 1200px) { - .navbar-expand-lg .navbar-collapse ul { - display: flex; - flex-basis: auto; - margin-bottom: 0; - } - .nav-link[aria-current='true']:after, - .nav-link:hover:after { - position: absolute; - content: ''; - width: 90%; - height: 2px; - left: 0; - bottom: -12px; - right: 0; - margin: auto; - } + .navbar-expand-lg .navbar-collapse ul { + display: flex; + flex-basis: auto; + margin-bottom: 0; + } + .nav-link[aria-current='true']:after, + .nav-link:hover:after { + position: absolute; + content: ''; + width: 90%; + height: 2px; + left: 0; + bottom: -12px; + right: 0; + margin: auto; + } } @media all and (max-width: 1199px) { - .nav-link[aria-current='true']:after, - .nav-link:hover:after { - position: absolute; - content: ''; - width: 100%; - height: 2px; - left: 0; - bottom: 6px; - } + .nav-link[aria-current='true']:after, + .nav-link:hover:after { + position: absolute; + content: ''; + width: 100%; + height: 2px; + left: 0; + bottom: 6px; + } } main.container-fluid .row { - padding: 0.5rem 1rem; + padding: 0.5rem 1rem; } .row { - margin: 0; + margin: 0; } nav .logo.navbar-brand { - font-weight: 700; - font-size: 1.6em; - /* The logo is focused on every page navigation, making this particular + font-weight: 700; + font-size: 1.6em; + /* The logo is focused on every page navigation, making this particular outline quite distracting. It looks like part of the logo design. Furthermore, the top left of the page is where focus is implicitly expected to be, so the outline is not really adding anything. And Browsers are not consistently showing the outline anyway. */ - outline: none; + outline: none; } a { - color: #0b60ab; - text-decoration: none; + color: #0b60ab; + text-decoration: none; } a:hover { - color: #214e86; - text-decoration: underline; + color: #214e86; + text-decoration: underline; } h1 { - margin-bottom: 0.5em; - border-bottom: 1px solid gainsboro; - padding-bottom: 0.25em; - font-size: 2em; + margin-bottom: 0.5em; + border-bottom: 1px solid gainsboro; + padding-bottom: 0.25em; + font-size: 2em; } h2 { - margin: 1.5em 0 0.5em; - font-size: 1.5em; + margin: 1.5em 0 0.5em; + font-size: 1.5em; } h3 { - margin: 1em 0 0.5em; - font-size: 1.25em; + margin: 1em 0 0.5em; + font-size: 1.25em; } h4 { - margin: 1em 0 0.5em; - font-size: 1em; - font-weight: 600; + margin: 1em 0 0.5em; + font-size: 1em; + font-weight: 600; } h5 { - margin: 1em 0 0.5em; - font-size: 1em; - font-weight: 600; + margin: 1em 0 0.5em; + font-size: 1em; + font-weight: 600; } button { - margin: 0.25em 0; + margin: 0.25em 0; } .table thead th { - border-bottom: 0; - background: #e9ebee; + border-bottom: 0; + background: #e9ebee; } table tbody th { - font-weight: 400; + font-weight: 400; } table tbody tr { - background-color: #fafbfc; + background-color: #fafbfc; } table tbody tr:nth-of-type(odd), .table-striped tbody tr:nth-of-type(odd) { - background-color: #fff; + background-color: #fff; } .table-bordered th, .table-bordered td { - border: 1px solid #d2d5d9; + border: 1px solid #d2d5d9; } .table td { - padding: 0.75rem; + padding: 0.75rem; } table.table-hover tbody tr:hover, table tbody tr:hover { - background-color: #f6f8fa; + background-color: #f6f8fa; } table .form-control { - width: auto; - border: 1px solid #d2d5d9; + width: auto; + border: 1px solid #d2d5d9; } table label { - margin-bottom: 0; + margin-bottom: 0; } table label input { - margin-right: 0.5em; + margin-right: 0.5em; } table tbody tr.assign-testers { - background-color: #f6f8fa; + background-color: #f6f8fa; } .table ul { - margin-bottom: 0; + margin-bottom: 0; } ol { - padding-left: 1.75em; + padding-left: 1.75em; } ul { - padding-left: 0; + padding-left: 0; } ul li { - list-style: none; + list-style: none; } .col-md-9 li { - padding-right: 0.5em; + padding-right: 0.5em; } /* BUTTONS */ /* Button Primary */ .btn { - font-size: 0.9rem; - font-weight: 500; + font-size: 0.9rem; + font-weight: 500; } .btn-primary { - background: #0b60ab; - border: 1px solid #095190; + background: #0b60ab; + border: 1px solid #095190; } .btn-primary:hover { - background: #09589e; + background: #09589e; } .btn-primary:focus, @@ -243,23 +243,23 @@ ul li { .btn-primary:active, .btn-primary.active, .btn-primary:not(:disabled):not(.disabled):active { - background: #0b60ab; - border-color: #095190; - box-shadow: 0 0 0 0.2rem rgba(103, 171, 197, 0.5); + background: #0b60ab; + border-color: #095190; + box-shadow: 0 0 0 0.2rem rgba(103, 171, 197, 0.5); } /* Button Secondary */ .btn-secondary, .btn-danger { - background: white; - color: black; - border: 1px solid #d7d7d7; + background: white; + color: black; + border: 1px solid #d7d7d7; } .btn-secondary:hover { - background: #e8e8e8; - color: black; - border-color: #c2c2c2; + background: #e8e8e8; + color: black; + border-color: #c2c2c2; } .btn-secondary:focus, @@ -268,9 +268,9 @@ ul li { .btn-secondary.active, .btn-secondary:not(:disabled):not(.disabled):active, .show > .btn-secondary.dropdown-toggle { - background: #f4f4f4; - color: black; - box-shadow: 0 0 0 0.2rem rgba(103, 171, 197, 0.5); + background: #f4f4f4; + color: black; + box-shadow: 0 0 0 0.2rem rgba(103, 171, 197, 0.5); } .btn-primary.disabled, @@ -279,17 +279,17 @@ ul li { .btn-secondary:disabled, .btn-danger.disabled, .btn-danger:disabled { - background: #f4f4f4; - color: #999999; - border: 1px solid #d7d7d7; - border: 1px solid #d7d7d7; + background: #f4f4f4; + color: #999999; + border: 1px solid #d7d7d7; + border: 1px solid #d7d7d7; } /* Button Tertiary */ .btn-tertiary { - background: white; - color: #0b60ab; - border: 1px solid #d7d7d7; + background: white; + color: #0b60ab; + border: 1px solid #d7d7d7; } .btn-primary:focus, @@ -297,294 +297,294 @@ ul li { .btn-primary:active, .btn-primary.active, .btn-primary:not(:disabled):not(.disabled):active { - background: white; - color: #0b60ab; + background: white; + color: #0b60ab; } /* Button Danger */ .btn-danger { - color: #d52a49; + color: #d52a49; } .form-group { - margin-bottom: 1rem; + margin-bottom: 1rem; } /* STATUS LABELS */ .status-wrapper { - display: flex; - align-items: center; + display: flex; + align-items: center; } .status-label { - font-size: 0.9rem; - padding: 0.15em 0.65em 0.15em; - border-radius: 22px; - font-weight: 500; - display: inline-block; - white-space: nowrap; - width: 100%; - text-align: center; + font-size: 0.9rem; + padding: 0.15em 0.65em 0.15em; + border-radius: 22px; + font-weight: 500; + display: inline-block; + white-space: nowrap; + width: 100%; + text-align: center; } .status-label.conflicts { - background: #f9aeae; - color: #640303; + background: #f9aeae; + color: #640303; } .status-label.in-progress { - background: #d9f6de; - color: #2c6c37; + background: #d9f6de; + color: #2c6c37; } .status-label.not-started { - background: #e7ecef; - color: #63697e; + background: #e7ecef; + color: #63697e; } .status-label.complete { - background: #bcddfa; - color: #10548f; + background: #bcddfa; + color: #10548f; } .dropdown-toggle { - position: relative; + position: relative; } .dropdown-toggle::after { - position: absolute; - right: 0.5em; - top: 50%; + position: absolute; + right: 0.5em; + top: 50%; } /* Home Page */ main.home-page.container { - padding: 0; + padding: 0; } main.home-page.container h1 { - border: none; - padding-bottom: 0; + border: none; + padding-bottom: 0; } .hero-section { - padding: 1em; + padding: 1em; } .hero-section p { - font-weight: 400; - font-size: 1.2em; - color: #5c728e; + font-weight: 400; + font-size: 1.2em; + color: #5c728e; } .hero-copy { - margin-bottom: 2em; + margin-bottom: 2em; } .hero-video { - display: flex; - justify-content: center; + display: flex; + justify-content: center; } .hero-video iframe { - max-width: 100%; - max-height: calc(calc(100vw - 2em) / 1.75); + max-width: 100%; + max-height: calc(calc(100vw - 2em) / 1.75); } .hero-link { - color: #0072ed; - text-decoration: underline; + color: #0072ed; + text-decoration: underline; } .hero-link:hover, .hero-link:active, .hero-link:focus { - color: #0058b6; + color: #0058b6; } .w3c-authorization-message { - background-color: #fff9ea; - display: flex; - padding: 1em; + background-color: #fff9ea; + display: flex; + padding: 1em; } .w3c-authorization-message i { - padding-right: 0.5em; - font-size: 25px; - font-style: normal; + padding-right: 0.5em; + font-size: 25px; + font-style: normal; } .w3c-authorization-message em { - display: block; - font-style: normal; - font-size: 0.875rem; - color: #654e29; - line-height: 1.3; + display: block; + font-style: normal; + font-size: 0.875rem; + color: #654e29; + line-height: 1.3; } .w3c-authorization-message strong { - font-style: italic; + font-style: italic; } .w3c-authorization-message a { - font-weight: bold; - color: #654e29; + font-weight: bold; + color: #654e29; } .w3c-authorization-message a:hover { - text-decoration: underline; + text-decoration: underline; } .right { - float: right; + float: right; } img { - max-width: 100%; + max-width: 100%; } .improvements { - background-color: #f6fbfe; - padding: 1em; + background-color: #f6fbfe; + padding: 1em; } .improvements-container { - background: none; + background: none; } .improvements-container h2 { - margin: 0 0 1em 0; - text-align: center; - font-weight: bold; + margin: 0 0 1em 0; + text-align: center; + font-weight: bold; } .improvement-list li { - background: white; - padding: 2em 1em; - margin-bottom: 1em; - box-shadow: 0px 6px 11px 0px rgba(0, 0, 0, 0.15); - border-radius: 5px; - padding: 40px; + background: white; + padding: 2em 1em; + margin-bottom: 1em; + box-shadow: 0px 6px 11px 0px rgba(0, 0, 0, 0.15); + border-radius: 5px; + padding: 40px; } .improvement-list img { - width: 100px; - height: 100px; - display: block; - margin: 0 auto 40px auto; + width: 100px; + height: 100px; + display: block; + margin: 0 auto 40px auto; } .get-involved { - padding: 1em; - min-height: 40vh; + padding: 1em; + min-height: 40vh; } .get-involved h2 { - text-align: center; - font-weight: bold; - margin: 1em 0 1.5em; + text-align: center; + font-weight: bold; + margin: 1em 0 1.5em; } .get-involved .container { - max-width: 660px; - padding-bottom: 2em; + max-width: 660px; + padding-bottom: 2em; } ol.breadcrumb { - padding: 0.75rem 1rem; + padding: 0.75rem 1rem; } @media (min-width: 700px) { - nav.navbar { - padding: 0.5rem 3rem; - } - - main.container, - .test-run-container, - .hero-section, - .get-involved, - .improvements { - padding: 3rem; - } - - .get-involved h2 { - margin: 1em 0 1.5em; - } + nav.navbar { + padding: 0.5rem 3rem; + } + + main.container, + .test-run-container, + .hero-section, + .get-involved, + .improvements { + padding: 3rem; + } + + .get-involved h2 { + margin: 1em 0 1.5em; + } } @media (min-width: 800px) { - .hero-section { - padding: 5rem; - } + .hero-section { + padding: 5rem; + } } @media (min-width: 1000px) { - nav.navbar { - padding: 0.5rem 5rem; - } + nav.navbar { + padding: 0.5rem 5rem; + } - main.container, - .test-run-container, - .get-involved, - .improvements { - padding: 5rem; - } + main.container, + .test-run-container, + .get-involved, + .improvements { + padding: 5rem; + } - .improvements-container h2 { - font-size: 1.75em; - } + .improvements-container h2 { + font-size: 1.75em; + } } @media (min-width: 768px) { - .improvement-list { - display: grid; - grid-template-columns: 48.5% 48.5%; - column-gap: 3%; - } + .improvement-list { + display: grid; + grid-template-columns: 48.5% 48.5%; + column-gap: 3%; + } } @media (min-width: 1100px) { - .hero-section { - padding: 5rem; - } + .hero-section { + padding: 5rem; + } - .hero-section h1 { - width: 45%; - } + .hero-section h1 { + width: 45%; + } - .hero-copy { - margin-bottom: 0; - } + .hero-copy { + margin-bottom: 0; + } - .hero-copy-and-video { - display: grid; - grid-template-columns: repeat(2, calc(50% - 20px)); - column-gap: 40px; - } + .hero-copy-and-video { + display: grid; + grid-template-columns: repeat(2, calc(50% - 20px)); + column-gap: 40px; + } - .hero-video iframe { - /* sorry for the magic number */ - max-height: calc(calc(44vw - 2em) / 1.75); - } + .hero-video iframe { + /* sorry for the magic number */ + max-height: calc(calc(44vw - 2em) / 1.75); + } } @media (min-width: 1250px) { - .improvement-list { - grid-template-columns: repeat(4, 1fr); - column-gap: 1.25%; - } + .improvement-list { + grid-template-columns: repeat(4, 1fr); + column-gap: 1.25%; + } } .signed-in-wrapper { - display: flex; - align-items: center; + display: flex; + align-items: center; } .signed-in { - padding-left: 0.75em; - margin: 0.5rem 1rem 0.5rem 0; - border-left: 2px solid #d2d5d9; + padding-left: 0.75em; + margin: 0.5rem 1rem 0.5rem 0; + border-left: 2px solid #d2d5d9; } @media (max-width: 991px) { - .signed-in-wrapper { - align-items: stretch; - flex-direction: column; - } - .signed-in { - border-left: none; - } + .signed-in-wrapper { + align-items: stretch; + flex-direction: column; + } + .signed-in { + border-left: none; + } } diff --git a/client/components/App/App.jsx b/client/components/App/App.jsx index d1282ccf5..143a245a3 100644 --- a/client/components/App/App.jsx +++ b/client/components/App/App.jsx @@ -14,163 +14,141 @@ import SkipLink from '../SkipLink'; import './App.css'; const App = () => { - const location = useLocation(); - const { client, loading, data } = useQuery(ME_QUERY); - const [isNavbarExpanded, setIsNavbarExpanded] = useState(false); + const location = useLocation(); + const { client, loading, data } = useQuery(ME_QUERY); + const [isNavbarExpanded, setIsNavbarExpanded] = useState(false); - const auth = evaluateAuth(data && data.me ? data.me : {}); - const { username, isSignedIn, isAdmin, isVendor } = auth; + const auth = evaluateAuth(data && data.me ? data.me : {}); + const { username, isSignedIn, isAdmin, isVendor } = auth; - const signOut = async () => { - await fetch('/api/auth/signout', { method: 'POST' }); - await client.resetStore(); - }; + const signOut = async () => { + await fetch('/api/auth/signout', { method: 'POST' }); + await client.resetStore(); + }; - useEffect(() => { - setIsNavbarExpanded(false); - }, [location]); + useEffect(() => { + setIsNavbarExpanded(false); + }, [location]); - if (loading) return null; + if (loading) return null; - return ( - - - setIsNavbarExpanded(previous => !previous)} + return ( + + + setIsNavbarExpanded(previous => !previous)} + > + + ARIA-AT + + + + + + + + + {routes()} + + ); }; export default App; diff --git a/client/components/App/queries.js b/client/components/App/queries.js index ad105d709..793c404f5 100644 --- a/client/components/App/queries.js +++ b/client/components/App/queries.js @@ -1,11 +1,11 @@ import { gql } from '@apollo/client'; export const ME_QUERY = gql` - query Me { - me { - id - username - roles - } + query Me { + me { + id + username + roles } + } `; diff --git a/client/components/BotRunTestStatusList/index.js b/client/components/BotRunTestStatusList/index.js index 4fb00a729..ce23c6d25 100644 --- a/client/components/BotRunTestStatusList/index.js +++ b/client/components/BotRunTestStatusList/index.js @@ -1,8 +1,8 @@ import React, { useEffect, useMemo, useRef, useState } from 'react'; import PropTypes from 'prop-types'; import { - COLLECTION_JOB_STATUS_BY_TEST_PLAN_RUN_ID_QUERY, - TEST_PLAN_RUNS_TEST_RESULTS_QUERY + COLLECTION_JOB_STATUS_BY_TEST_PLAN_RUN_ID_QUERY, + TEST_PLAN_RUNS_TEST_RESULTS_QUERY } from './queries'; import { useLazyQuery, useQuery } from '@apollo/client'; import styled from '@emotion/styled'; @@ -10,12 +10,12 @@ import ReportStatusDot from '../common/ReportStatusDot'; import { isBot } from '../../utils/automation'; const BotRunTestStatusUnorderedList = styled.ul` - list-style-type: none; - background-color: #f6f8fa; - font-size: 0.9rem !important; - padding: 0.5rem 0; - margin: 0.5rem 0; - white-space: nowrap; + list-style-type: none; + background-color: #f6f8fa; + font-size: 0.9rem !important; + padding: 0.5rem 0; + margin: 0.5rem 0; + white-space: nowrap; `; /** @@ -33,123 +33,117 @@ const BotRunTestStatusUnorderedList = styled.ul` * @returns {string} the pluralized text */ const testCountString = (count, status) => - `${count} Test${count === 1 ? '' : 's'} ${status}`; + `${count} Test${count === 1 ? '' : 's'} ${status}`; const BotRunTestStatusList = ({ testPlanReportId, runnableTestsLength }) => { - const { - data: testPlanRunsQueryResult, - startPolling, - stopPolling - } = useQuery(TEST_PLAN_RUNS_TEST_RESULTS_QUERY, { - variables: { testPlanReportId }, - fetchPolicy: 'cache-and-network', - pollInterval: 2000 - }); - - const [getCollectionJobStatus, { data: collectionJobStatusQueryResult }] = - useLazyQuery(COLLECTION_JOB_STATUS_BY_TEST_PLAN_RUN_ID_QUERY, { - fetchPolicy: 'cache-and-network' - }); + const { + data: testPlanRunsQueryResult, + startPolling, + stopPolling + } = useQuery(TEST_PLAN_RUNS_TEST_RESULTS_QUERY, { + variables: { testPlanReportId }, + fetchPolicy: 'cache-and-network', + pollInterval: 2000 + }); - const [collectedData, setCollectedData] = useState([]); - const requestedTestRunIds = useRef(new Set()); + const [getCollectionJobStatus, { data: collectionJobStatusQueryResult }] = + useLazyQuery(COLLECTION_JOB_STATUS_BY_TEST_PLAN_RUN_ID_QUERY, { + fetchPolicy: 'cache-and-network' + }); - const botTestPlanRuns = useMemo(() => { - if (!testPlanRunsQueryResult?.testPlanRuns) { - return []; - } - return testPlanRunsQueryResult.testPlanRuns.filter(testPlanRun => - isBot(testPlanRun.tester) - ); - }, [testPlanRunsQueryResult?.testPlanRuns]); + const [collectedData, setCollectedData] = useState([]); + const requestedTestRunIds = useRef(new Set()); - useEffect(() => { - const ids = botTestPlanRuns.map(run => run.id); - for (const id of ids) { - if (!requestedTestRunIds.current.has(id)) { - requestedTestRunIds.current.add(id); - getCollectionJobStatus({ - variables: { testPlanRunId: id } - }); - } - } - }, [botTestPlanRuns]); + const botTestPlanRuns = useMemo(() => { + if (!testPlanRunsQueryResult?.testPlanRuns) { + return []; + } + return testPlanRunsQueryResult.testPlanRuns.filter(testPlanRun => + isBot(testPlanRun.tester) + ); + }, [testPlanRunsQueryResult?.testPlanRuns]); - useEffect(() => { - if (collectionJobStatusQueryResult?.collectionJobByTestPlanRunId) { - const { status } = - collectionJobStatusQueryResult.collectionJobByTestPlanRunId; - setCollectedData(prev => [...prev, status]); - } - }, [collectionJobStatusQueryResult?.collectionJobByTestPlanRunId]); + useEffect(() => { + const ids = botTestPlanRuns.map(run => run.id); + for (const id of ids) { + if (!requestedTestRunIds.current.has(id)) { + requestedTestRunIds.current.add(id); + getCollectionJobStatus({ + variables: { testPlanRunId: id } + }); + } + } + }, [botTestPlanRuns]); - const [numTestsCompleted, numTestsQueued, numTestsCancelled] = - useMemo(() => { - const res = [0, 0, 0]; - if ( - botTestPlanRuns && - botTestPlanRuns.length && - collectedData.length === botTestPlanRuns.length - ) { - for (let i = 0; i < botTestPlanRuns.length; i++) { - const status = collectedData[i]; - res[0] += botTestPlanRuns[i].testResults.length; - switch (status) { - case 'COMPLETED': - case 'RUNNING': - case 'QUEUED': - res[1] += - runnableTestsLength - - botTestPlanRuns[i].testResults.length; - break; - case 'CANCELLED': - res[2] += - runnableTestsLength - - botTestPlanRuns[i].testResults.length; - break; - default: - break; - } - } - if ( - res[0] + res[2] === - runnableTestsLength * botTestPlanRuns.length - ) { - stopPolling(); - } - } - return res; - }, [testPlanRunsQueryResult, collectedData, stopPolling, startPolling]); + useEffect(() => { + if (collectionJobStatusQueryResult?.collectionJobByTestPlanRunId) { + const { status } = + collectionJobStatusQueryResult.collectionJobByTestPlanRunId; + setCollectedData(prev => [...prev, status]); + } + }, [collectionJobStatusQueryResult?.collectionJobByTestPlanRunId]); + const [numTestsCompleted, numTestsQueued, numTestsCancelled] = useMemo(() => { + const res = [0, 0, 0]; if ( - !botTestPlanRuns || - botTestPlanRuns.length === 0 || - !collectedData || - !(collectedData.length === botTestPlanRuns.length) + botTestPlanRuns && + botTestPlanRuns.length && + collectedData.length === botTestPlanRuns.length ) { - return null; + for (let i = 0; i < botTestPlanRuns.length; i++) { + const status = collectedData[i]; + res[0] += botTestPlanRuns[i].testResults.length; + switch (status) { + case 'COMPLETED': + case 'RUNNING': + case 'QUEUED': + res[1] += + runnableTestsLength - botTestPlanRuns[i].testResults.length; + break; + case 'CANCELLED': + res[2] += + runnableTestsLength - botTestPlanRuns[i].testResults.length; + break; + default: + break; + } + } + if (res[0] + res[2] === runnableTestsLength * botTestPlanRuns.length) { + stopPolling(); + } } - return ( - -
  • - - {testCountString(numTestsCompleted, 'Completed')} -
  • -
  • - - {testCountString(numTestsQueued, 'Queued')} -
  • -
  • - - {testCountString(numTestsCancelled, 'Cancelled')} -
  • -
    - ); + return res; + }, [testPlanRunsQueryResult, collectedData, stopPolling, startPolling]); + + if ( + !botTestPlanRuns || + botTestPlanRuns.length === 0 || + !collectedData || + !(collectedData.length === botTestPlanRuns.length) + ) { + return null; + } + return ( + +
  • + + {testCountString(numTestsCompleted, 'Completed')} +
  • +
  • + + {testCountString(numTestsQueued, 'Queued')} +
  • +
  • + + {testCountString(numTestsCancelled, 'Cancelled')} +
  • +
    + ); }; BotRunTestStatusList.propTypes = { - testPlanReportId: PropTypes.string.isRequired, - runnableTestsLength: PropTypes.number.isRequired + testPlanReportId: PropTypes.string.isRequired, + runnableTestsLength: PropTypes.number.isRequired }; export default BotRunTestStatusList; diff --git a/client/components/BotRunTestStatusList/queries.js b/client/components/BotRunTestStatusList/queries.js index 048acc1aa..3dcedca38 100644 --- a/client/components/BotRunTestStatusList/queries.js +++ b/client/components/BotRunTestStatusList/queries.js @@ -1,30 +1,30 @@ import { gql } from '@apollo/client'; export const TEST_PLAN_RUNS_TEST_RESULTS_QUERY = gql` - query TestPlanRunsTestResults($testPlanReportId: ID!) { - testPlanRuns(testPlanReportId: $testPlanReportId) { - id - tester { - username - } - testResults { - id - scenarioResults { - assertionResults { - passed - failedReason - } - } - } + query TestPlanRunsTestResults($testPlanReportId: ID!) { + testPlanRuns(testPlanReportId: $testPlanReportId) { + id + tester { + username + } + testResults { + id + scenarioResults { + assertionResults { + passed + failedReason + } } + } } + } `; export const COLLECTION_JOB_STATUS_BY_TEST_PLAN_RUN_ID_QUERY = gql` - query CollectionJobStatusByTestPlanRunId($testPlanRunId: ID!) { - collectionJobByTestPlanRunId(testPlanRunId: $testPlanRunId) { - id - status - } + query CollectionJobStatusByTestPlanRunId($testPlanRunId: ID!) { + collectionJobByTestPlanRunId(testPlanRunId: $testPlanRunId) { + id + status } + } `; diff --git a/client/components/CandidateReview/CandidateModals/ProvideFeedbackModal/ProvideFeedbackModal.css b/client/components/CandidateReview/CandidateModals/ProvideFeedbackModal/ProvideFeedbackModal.css index 17cadc7e9..f9257bfee 100644 --- a/client/components/CandidateReview/CandidateModals/ProvideFeedbackModal/ProvideFeedbackModal.css +++ b/client/components/CandidateReview/CandidateModals/ProvideFeedbackModal/ProvideFeedbackModal.css @@ -1,72 +1,72 @@ .submit-button { - padding: 5px 25px; - width: auto; + padding: 5px 25px; + width: auto; } .close { - position: relative; - bottom: 15px; - left: 10px; + position: relative; + bottom: 15px; + left: 10px; } .feedback { - min-width: 60%; + min-width: 60%; } .feedback .modal-content { - padding-left: 1em; - padding-bottom: 1em; + padding-left: 1em; + padding-bottom: 1em; } .feedback .modal-header { - padding: 30px 30px 10px 40px; - text-align: left; + padding: 30px 30px 10px 40px; + text-align: left; } .feedback .modal-body { - padding: 0px 30px 0px 40px; + padding: 0px 30px 0px 40px; } .feedback .modal-footer { - padding-right: 30px; + padding-right: 30px; } .feedback-bold { - font-weight: 600; + font-weight: 600; } .feedback-title { - font-size: 24px; - font-weight: normal; - border-bottom: solid #e5e5e5 1px; - margin-bottom: 3px; + font-size: 24px; + font-weight: normal; + border-bottom: solid #e5e5e5 1px; + margin-bottom: 3px; } .feedback-content h2 { - font-size: 16px; - padding-bottom: 5px; + font-size: 16px; + padding-bottom: 5px; } .feedback-content p { - padding: 10px 0px; + padding: 10px 0px; } .feedback-text { - height: 150px; - background-color: #f7f7f7; + height: 150px; + background-color: #f7f7f7; } .radio-text { - padding-bottom: 10px; - color: #656565; - display: block; + padding-bottom: 10px; + color: #656565; + display: block; } .sr-only { - position: absolute; - height: 1px; - width: 1px; - overflow: hidden; - clip: rect(1px, 1px, 1px, 1px); - white-space: nowrap; + position: absolute; + height: 1px; + width: 1px; + overflow: hidden; + clip: rect(1px, 1px, 1px, 1px); + white-space: nowrap; } diff --git a/client/components/CandidateReview/CandidateModals/ProvideFeedbackModal/index.jsx b/client/components/CandidateReview/CandidateModals/ProvideFeedbackModal/index.jsx index 94db801d4..e62e2f4b5 100644 --- a/client/components/CandidateReview/CandidateModals/ProvideFeedbackModal/index.jsx +++ b/client/components/CandidateReview/CandidateModals/ProvideFeedbackModal/index.jsx @@ -8,125 +8,117 @@ import './ProvideFeedbackModal.css'; import FeedbackListItem from '../../FeedbackListItem'; const ProvideFeedbackModal = ({ - at = '', - handleAction = () => {}, - handleHide = () => {}, - feedbackIssues = [], - feedbackGithubUrl = '', - changesRequestedIssues = [], - changesRequestedGithubUrl = '', - testPlan = '', - username = '' + at = '', + handleAction = () => {}, + handleHide = () => {}, + feedbackIssues = [], + feedbackGithubUrl = '', + changesRequestedIssues = [], + changesRequestedGithubUrl = '', + testPlan = '', + username = '' }) => { - const [selectedRadio, setSelectedRadio] = useState('not-approved-input'); + const [selectedRadio, setSelectedRadio] = useState('not-approved-input'); - return ( - - {changesRequestedIssues.length > 0 && ( - - )} - {feedbackIssues.length > 0 && ( - - )} + return ( + + {changesRequestedIssues.length > 0 && ( + + )} + {feedbackIssues.length > 0 && ( + + )} -

    Finish Your Review

    -
    - setSelectedRadio(e.target.id)} - > - - - - Not Approved Yet - - - Submit your Review without explicit approval - - - - - - Approve - - - {' '} - Submit feedback and approve this Test Plan - - - -
    - - } - dialogClassName="feedback" - actions={[ - { - label: 'Submit Review', - className: 'submit-button', - onClick: () => { - handleAction( - selectedRadio === 'approve-input' ? 'APPROVED' : '' - ); - } - } - ]} - title={ - <> -

    - Great {username}! You have reviewed every test in the{' '} - {testPlan} with {at} -

    - - - } - /> - ); +

    Finish Your Review

    +
    + setSelectedRadio(e.target.id)}> + + + + Not Approved Yet + + + Submit your Review without explicit approval + + + + + + Approve + + + {' '} + Submit feedback and approve this Test Plan + + + +
    + + } + dialogClassName="feedback" + actions={[ + { + label: 'Submit Review', + className: 'submit-button', + onClick: () => { + handleAction(selectedRadio === 'approve-input' ? 'APPROVED' : ''); + } + } + ]} + title={ + <> +

    + Great {username}! You have reviewed every test in the {testPlan}{' '} + with {at} +

    + + + } + /> + ); }; ProvideFeedbackModal.propTypes = { - at: PropTypes.string, - handleAction: PropTypes.func, - handleHide: PropTypes.func, - changesRequestedIssues: PropTypes.array, - changesRequestedGithubUrl: PropTypes.string, - feedbackIssues: PropTypes.array, - feedbackGithubUrl: PropTypes.string, - show: PropTypes.bool, - testPlan: PropTypes.string, - username: PropTypes.string + at: PropTypes.string, + handleAction: PropTypes.func, + handleHide: PropTypes.func, + changesRequestedIssues: PropTypes.array, + changesRequestedGithubUrl: PropTypes.string, + feedbackIssues: PropTypes.array, + feedbackGithubUrl: PropTypes.string, + show: PropTypes.bool, + testPlan: PropTypes.string, + username: PropTypes.string }; export default ProvideFeedbackModal; diff --git a/client/components/CandidateReview/CandidateModals/ThankYouModal/ThankYouModal.css b/client/components/CandidateReview/CandidateModals/ThankYouModal/ThankYouModal.css index 88acd7796..5f2cdd0fe 100644 --- a/client/components/CandidateReview/CandidateModals/ThankYouModal/ThankYouModal.css +++ b/client/components/CandidateReview/CandidateModals/ThankYouModal/ThankYouModal.css @@ -1,52 +1,52 @@ .thank-you { - justify-content: center; + justify-content: center; } .thank-you .modal-content { - align-items: center; - width: 360px; - padding-top: 2em; - padding-bottom: 2em; + align-items: center; + width: 360px; + padding-top: 2em; + padding-bottom: 2em; } .thank-you-check { - font-size: 100px; - margin-right: 0 !important; - margin-bottom: 20px; + font-size: 100px; + margin-right: 0 !important; + margin-bottom: 20px; } .thank-you-title { - text-align: center; + text-align: center; } .thank-you-title h1 { - border-bottom: none; - font-size: 1.5em; + border-bottom: none; + font-size: 1.5em; } .thank-you-content { - font-weight: bold; - text-align: center; + font-weight: bold; + text-align: center; } .thank-you-share { - margin-bottom: 0; + margin-bottom: 0; } .thank-you-issue { - text-align: center; - font-size: 12px; - margin-bottom: 0; + text-align: center; + font-size: 12px; + margin-bottom: 0; } .thank-you .modal-header { - padding-bottom: 0; + padding-bottom: 0; } .thank-you .modal-footer { - padding-bottom: 30px; + padding-bottom: 30px; } .thank-you .modal-footer .btn { - width: 100px; + width: 100px; } diff --git a/client/components/CandidateReview/CandidateModals/ThankYouModal/index.jsx b/client/components/CandidateReview/CandidateModals/ThankYouModal/index.jsx index 4a676e638..cbe48499f 100644 --- a/client/components/CandidateReview/CandidateModals/ThankYouModal/index.jsx +++ b/client/components/CandidateReview/CandidateModals/ThankYouModal/index.jsx @@ -7,51 +7,47 @@ import '../common.css'; import './ThankYouModal.css'; const ThankYouModal = ({ handleAction = () => {}, githubUrl = '#' }) => { - return ( - -

    - Your Review has been submitted! -

    -

    - Do you have anything else to share? -

    -

    - - Open a GitHub issue - {' '} - to leave more feedback{' '} -

    - - } - dialogClassName="thank-you" - actions={[ - { - label: 'Close', - onClick: handleAction - } - ]} - title={ -
    - -

    Thank you!

    -
    - } - /> - ); + return ( + +

    Your Review has been submitted!

    +

    Do you have anything else to share?

    +

    + + Open a GitHub issue + {' '} + to leave more feedback{' '} +

    + + } + dialogClassName="thank-you" + actions={[ + { + label: 'Close', + onClick: handleAction + } + ]} + title={ +
    + +

    Thank you!

    +
    + } + /> + ); }; ThankYouModal.propTypes = { - handleAction: PropTypes.func, - githubUrl: PropTypes.string + handleAction: PropTypes.func, + githubUrl: PropTypes.string }; export default ThankYouModal; diff --git a/client/components/CandidateReview/CandidateModals/common.css b/client/components/CandidateReview/CandidateModals/common.css index ba6b281c4..3a92a1be8 100644 --- a/client/components/CandidateReview/CandidateModals/common.css +++ b/client/components/CandidateReview/CandidateModals/common.css @@ -1,11 +1,11 @@ .btn-primary { - background: #0b60ab; + background: #0b60ab; } .modal-footer { - border-top: none; + border-top: none; } .modal-header { - border-bottom: none; + border-bottom: none; } diff --git a/client/components/CandidateReview/CandidateTestPlanRun/CandidateTestPlanRun.css b/client/components/CandidateReview/CandidateTestPlanRun/CandidateTestPlanRun.css index 0f2b4b068..82cb873aa 100644 --- a/client/components/CandidateReview/CandidateTestPlanRun/CandidateTestPlanRun.css +++ b/client/components/CandidateReview/CandidateTestPlanRun/CandidateTestPlanRun.css @@ -1,154 +1,154 @@ .card-body { - padding: 0; + padding: 0; } .card-body > div { - border: none; + border: none; } .current-test-title { - border: none; + border: none; } .current-test-options .options-wrapper { - text-align: center; + text-align: center; } .current-test-options .options-wrapper li { - margin-bottom: 0.5em; + margin-bottom: 0.5em; } .current-test-options .options-wrapper li:last-child { - margin-bottom: 0; + margin-bottom: 0; } .feedback-accordion { - width: 100%; + width: 100%; } .feedback-accordion-header { - display: grid; - grid-template-columns: 50% 50%; + display: grid; + grid-template-columns: 50% 50%; } .feedback-accordion-header span { - text-align: right; + text-align: right; } .feedback-from-text { - font-weight: 400; + font-weight: 400; } .feedback-list-item { - padding: 1em 0 1em 0.5em; - position: relative; - margin: 1em 0 1em 0em; - list-style: none; - font-size: 14px; - border: solid 1px #e5e5e5; - width: 100%; + padding: 1em 0 1em 0.5em; + position: relative; + margin: 1em 0 1em 0em; + list-style: none; + font-size: 14px; + border: solid 1px #e5e5e5; + width: 100%; } .feedback-indicator { - position: absolute; - left: -2em; - top: 1.3em; - width: 16px; - height: 16px; - border-radius: 50px; - border: 2px solid #9a9a9a; + position: absolute; + left: -2em; + top: 1.3em; + width: 16px; + height: 16px; + border-radius: 50px; + border: 2px solid #9a9a9a; } .feedback-list-item:before { - content: ''; - position: absolute; - height: 2.3em; - width: 2px; - top: -1.1em; - left: -1.5em; - background: #d2d5d9; + content: ''; + position: absolute; + height: 2.3em; + width: 2px; + top: -1.1em; + left: -1.5em; + background: #d2d5d9; } .feedback-list-item:after { - content: ''; - position: absolute; - height: calc(100% - 1.3em); - width: 2px; - bottom: -1.2em; - left: -1.5em; - background: #d2d5d9; + content: ''; + position: absolute; + height: calc(100% - 1.3em); + width: 2px; + bottom: -1.2em; + left: -1.5em; + background: #d2d5d9; } .feedback-list-item .feedback-indicator { - background: white; + background: white; } .issues-container { - max-width: 800px; - margin-bottom: -14px; + max-width: 800px; + margin-bottom: -14px; } .issues-container > h2 { - margin: 0 0 0.5em; - font-size: 18px; - padding-bottom: 5px; - border-bottom: solid 1px #e5e5e5; + margin: 0 0 0.5em; + font-size: 18px; + padding-bottom: 5px; + border-bottom: solid 1px #e5e5e5; } .task-label { - font-size: 18px !important; + font-size: 18px !important; } .test-results-header, .test-instructions-header { - border-bottom: none; + border-bottom: none; } .review-status, .target-date, .apg-example-name { - width: 32% !important; + width: 32% !important; } .results-container { - padding: 0px; + padding: 0px; } .results-container-col { - padding: 0; + padding: 0; } .results-container-row { - border: solid 1px #e5e5e5; - padding: 1em; + border: solid 1px #e5e5e5; + padding: 1em; } .results-container { - padding: 0; + padding: 0; } .options-feedback { - top: 35px; + top: 35px; } .test-results-header { - margin: 0 0 1rem; + margin: 0 0 1rem; } .test-results-table { - margin-bottom: 0; - border-left: none; + margin-bottom: 0; + border-left: none; } .using { - font-weight: 300; + font-weight: 300; } .viewed-badge { - background-color: #e5e5e5 !important; - color: black; - font-size: 15px; - font-weight: 400; - position: relative; - top: -5px; + background-color: #e5e5e5 !important; + color: black; + font-size: 15px; + font-weight: 400; + position: relative; + top: -5px; } diff --git a/client/components/CandidateReview/CandidateTestPlanRun/InstructionsRenderer.jsx b/client/components/CandidateReview/CandidateTestPlanRun/InstructionsRenderer.jsx index f55b6f2e8..8eb202170 100644 --- a/client/components/CandidateReview/CandidateTestPlanRun/InstructionsRenderer.jsx +++ b/client/components/CandidateReview/CandidateTestPlanRun/InstructionsRenderer.jsx @@ -4,16 +4,16 @@ import styled from '@emotion/styled'; import { Button, Table } from 'react-bootstrap'; import { unescape } from 'lodash'; import { - parseListContent, - parseSettingsContent + parseListContent, + parseSettingsContent } from '../../TestRenderer/utils'; import { - userCloseWindow, - userOpenWindow + userCloseWindow, + userOpenWindow } from '../../../resources/aria-at-test-run.mjs'; import { - TestRunExport, - TestRunInputOutput + TestRunExport, + TestRunInputOutput } from '../../../resources/aria-at-test-io-format.mjs'; import { TestWindow } from '../../../resources/aria-at-test-window.mjs'; import { evaluateAtNameKey } from '../../../utils/aria.js'; @@ -22,326 +22,301 @@ import supportJson from '../../../resources/support.json'; import { convertAssertionPriority } from 'shared'; const NumberedList = styled.ol` - counter-reset: numbered-list; - list-style: none; - > li { - counter-increment: numbered-list; - position: relative; - margin-bottom: 10px; - } - - > li::before { - content: counter(numbered-list); - position: absolute; - color: #78869c; - font-size: 1em; - --size: 25px; - left: calc(-1 * var(--size) - 10px); - line-height: var(--size); - width: var(--size); - height: var(--size); - top: 2px; - background: #edf6ff; - border-radius: 50%; - border: 1px solid #d5deec; - text-align: center; - } + counter-reset: numbered-list; + list-style: none; + > li { + counter-increment: numbered-list; + position: relative; + margin-bottom: 10px; + } + + > li::before { + content: counter(numbered-list); + position: absolute; + color: #78869c; + font-size: 1em; + --size: 25px; + left: calc(-1 * var(--size) - 10px); + line-height: var(--size); + width: var(--size); + height: var(--size); + top: 2px; + background: #edf6ff; + border-radius: 50%; + border: 1px solid #d5deec; + text-align: center; + } `; const InstructionsRenderer = ({ - test, - testPageUrl, - at, - headingLevel = 2, - testFormatVersion + test, + testPageUrl, + at, + headingLevel = 2, + testFormatVersion }) => { - const { renderableContent } = test; - const [testRunExport, setTestRunExport] = useState(); - const [pageContent, setPageContent] = useState({ - instructions: { - assertions: { assertions: [] }, - instructions: { - instructions: [], - strongInstructions: [], - commands: { commands: [], description: '' } - }, - openTestPage: { enabled: false } + const { renderableContent } = test; + const [testRunExport, setTestRunExport] = useState(); + const [pageContent, setPageContent] = useState({ + instructions: { + assertions: { assertions: [] }, + instructions: { + instructions: [], + strongInstructions: [], + commands: { commands: [], description: '' } + }, + openTestPage: { enabled: false } + } + }); + const setup = async () => { + const testRunIO = new TestRunInputOutput(); + const configQueryParams = [['at', evaluateAtNameKey(at.name)]]; + + testRunIO.setAllCommandsInputFromJSON(commandsJson); + await testRunIO.setInputsFromCollectedTestAsync(renderableContent); + testRunIO.setConfigInputFromQueryParamsAndSupport(configQueryParams); + + if (renderableContent.target?.referencePage) { + const replaceIndex = testPageUrl.indexOf('reference/'); + // sync with proxy url expected for aria-at-app to work properly + const constructedTestPageUrl = + testPageUrl.substring(0, replaceIndex) + + renderableContent.target?.referencePage; + testRunIO.setPageUriInputFromPageUri(constructedTestPageUrl); + } else testRunIO.setPageUriInputFromPageUri(testPageUrl); + + const testWindow = new TestWindow({ + ...testRunIO.testWindowOptions(), + hooks: { + windowOpened() { + testRunExport.dispatch(userOpenWindow()); + }, + windowClosed() { + testRunExport.dispatch(userCloseWindow()); } + } }); - const setup = async () => { - const testRunIO = new TestRunInputOutput(); - const configQueryParams = [['at', evaluateAtNameKey(at.name)]]; - - testRunIO.setAllCommandsInputFromJSON(commandsJson); - await testRunIO.setInputsFromCollectedTestAsync(renderableContent); - testRunIO.setConfigInputFromQueryParamsAndSupport(configQueryParams); - - if (renderableContent.target?.referencePage) { - const replaceIndex = testPageUrl.indexOf('reference/'); - // sync with proxy url expected for aria-at-app to work properly - const constructedTestPageUrl = - testPageUrl.substring(0, replaceIndex) + - renderableContent.target?.referencePage; - testRunIO.setPageUriInputFromPageUri(constructedTestPageUrl); - } else testRunIO.setPageUriInputFromPageUri(testPageUrl); - - const testWindow = new TestWindow({ - ...testRunIO.testWindowOptions(), - hooks: { - windowOpened() { - testRunExport.dispatch(userOpenWindow()); - }, - windowClosed() { - testRunExport.dispatch(userCloseWindow()); - } - } - }); - - const testRunExport = new TestRunExport({ - hooks: { - openTestPage() { - testWindow.open(); - }, - closeTestPage() { - testWindow.close(); - } - }, - resultsJSON: state => testRunIO.submitResultsJSON(state), - state: testRunIO.testRunState() - }); - setTestRunExport(testRunExport); - }; - - useEffect(() => { - setup(); - }, []); - - useEffect(() => { - if (testRunExport) { - setPageContent(testRunExport.instructions()); + + const testRunExport = new TestRunExport({ + hooks: { + openTestPage() { + testWindow.open(); + }, + closeTestPage() { + testWindow.close(); } - }, [testRunExport]); - - let allInstructions; - const isV2 = testFormatVersion === 2; - let settingsContent = []; - - if (isV2) { - // There is at least one defined 'setting' for the list of AT commands - const commandSettingSpecified = renderableContent.commands.some( - ({ settings }) => settings && settings !== 'defaultMode' - ); - - const defaultInstructions = - renderableContent.target.at.raw - .defaultConfigurationInstructionsHTML; - const setupScriptDescription = `${supportJson.testPlanStrings.openExampleInstruction} ${renderableContent.target.setupScript.scriptDescription}`; - const testInstructions = renderableContent.instructions.instructions; - const settingsInstructions = `${ - supportJson.testPlanStrings.commandListPreface - }${ - commandSettingSpecified - ? ` ${supportJson.testPlanStrings.commandListSettingsPreface}` - : '' - }`; - - allInstructions = [ - defaultInstructions, - setupScriptDescription + '.', - testInstructions + ' ' + settingsInstructions - ].map(e => unescape(e)); - settingsContent = parseSettingsContent( - renderableContent.instructions.mode, - renderableContent.target.at.raw.settings - ); - } else { - allInstructions = [ - ...pageContent.instructions.instructions.instructions, - ...pageContent.instructions.instructions.strongInstructions, - pageContent.instructions.instructions.commands.description - ]; + }, + resultsJSON: state => testRunIO.submitResultsJSON(state), + state: testRunIO.testRunState() + }); + setTestRunExport(testRunExport); + }; + + useEffect(() => { + setup(); + }, []); + + useEffect(() => { + if (testRunExport) { + setPageContent(testRunExport.instructions()); } + }, [testRunExport]); - const commands = pageContent.instructions.instructions.commands.commands; - const commandsContent = parseListContent(commands); + let allInstructions; + const isV2 = testFormatVersion === 2; + let settingsContent = []; - const allInstructionsContent = parseListContent( - allInstructions, - commandsContent + if (isV2) { + // There is at least one defined 'setting' for the list of AT commands + const commandSettingSpecified = renderableContent.commands.some( + ({ settings }) => settings && settings !== 'defaultMode' ); - const Heading = `h${headingLevel}`; - - return ( - <> - {allInstructionsContent} - {settingsContent.length ? settingsContent : null} - - {renderableContent.commands.map( - ({ id, settings, assertionExceptions = [] }, i) => { - const settingsScreenText = isV2 - ? renderableContent.target.at.raw.settings[settings] - ?.screenText ?? '' - : null; - - let mustCount = 0; - let shouldCount = 0; - let mayCount = 0; - - let assertions = [...renderableContent.assertions]; - - assertionExceptions.forEach(exception => { - const assertionIndex = assertions.findIndex( - assertion => { - return ( - assertion.assertionId === - exception.assertionId - ); - } - ); - - if (assertionIndex < 0) return; - - if (exception.priority === 0) { - assertions.splice(assertionIndex, 1); - } else { - assertions[assertionIndex] = { - ...assertions[assertionIndex], - priority: exception.priority - }; - } - }); - - // Filter out assertions that were originally set to 0 when declared through - // tests.csv instead of *-commands.csv - assertions = assertions.filter( - ({ priority }) => priority !== 0 - ); - - assertions.forEach(({ priority }) => { - const priorityString = - convertAssertionPriority(priority); - if (priorityString === 'MUST') mustCount += 1; - if (priorityString === 'SHOULD') shouldCount += 1; - if (priorityString === 'MAY') mayCount += 1; - }); - - const settingsScreenTextFormatted = settingsScreenText - ? ` (${settingsScreenText})` - : ''; - - const scenarioTitle = - `${renderableContent.commands[i].keystroke}` + - `${settingsScreenTextFormatted}: ${mustCount} MUST, ` + - `${shouldCount} SHOULD, ${mayCount} MAY Assertions`; - - const scenarioId = - `${at.name}-test${test.rowNumber}-${id}-cmd${i}`.replaceAll( - /[,+\s]+/g, - '_' - ); - - if (isV2) { - return ( - - - {scenarioTitle} - - - - - - - - - - - {assertions.map( - ({ - assertionPhrase, - assertionStatement, - priority, - assertionId - }) => ( - - - - - - ) - )} - -
    PriorityAssertion PhraseAssertion Statement
    - {convertAssertionPriority( - priority - )} - {assertionPhrase} - {assertionStatement} -
    -
    - ); - } else { - return ( - - - {scenarioTitle} - - - - - - - - - - {assertions.map( - ({ expectation, priority }) => ( - - - - - ) - )} - -
    PriorityAssertion Statement
    - {convertAssertionPriority( - priority - )} - {expectation}
    -
    - ); - } - } - )} - - - + const defaultInstructions = + renderableContent.target.at.raw.defaultConfigurationInstructionsHTML; + const setupScriptDescription = `${supportJson.testPlanStrings.openExampleInstruction} ${renderableContent.target.setupScript.scriptDescription}`; + const testInstructions = renderableContent.instructions.instructions; + const settingsInstructions = `${ + supportJson.testPlanStrings.commandListPreface + }${ + commandSettingSpecified + ? ` ${supportJson.testPlanStrings.commandListSettingsPreface}` + : '' + }`; + + allInstructions = [ + defaultInstructions, + setupScriptDescription + '.', + testInstructions + ' ' + settingsInstructions + ].map(e => unescape(e)); + settingsContent = parseSettingsContent( + renderableContent.instructions.mode, + renderableContent.target.at.raw.settings ); + } else { + allInstructions = [ + ...pageContent.instructions.instructions.instructions, + ...pageContent.instructions.instructions.strongInstructions, + pageContent.instructions.instructions.commands.description + ]; + } + + const commands = pageContent.instructions.instructions.commands.commands; + const commandsContent = parseListContent(commands); + + const allInstructionsContent = parseListContent( + allInstructions, + commandsContent + ); + + const Heading = `h${headingLevel}`; + + return ( + <> + {allInstructionsContent} + {settingsContent.length ? settingsContent : null} + + {renderableContent.commands.map( + ({ id, settings, assertionExceptions = [] }, i) => { + const settingsScreenText = isV2 + ? renderableContent.target.at.raw.settings[settings]?.screenText ?? + '' + : null; + + let mustCount = 0; + let shouldCount = 0; + let mayCount = 0; + + let assertions = [...renderableContent.assertions]; + + assertionExceptions.forEach(exception => { + const assertionIndex = assertions.findIndex(assertion => { + return assertion.assertionId === exception.assertionId; + }); + + if (assertionIndex < 0) return; + + if (exception.priority === 0) { + assertions.splice(assertionIndex, 1); + } else { + assertions[assertionIndex] = { + ...assertions[assertionIndex], + priority: exception.priority + }; + } + }); + + // Filter out assertions that were originally set to 0 when declared through + // tests.csv instead of *-commands.csv + assertions = assertions.filter(({ priority }) => priority !== 0); + + assertions.forEach(({ priority }) => { + const priorityString = convertAssertionPriority(priority); + if (priorityString === 'MUST') mustCount += 1; + if (priorityString === 'SHOULD') shouldCount += 1; + if (priorityString === 'MAY') mayCount += 1; + }); + + const settingsScreenTextFormatted = settingsScreenText + ? ` (${settingsScreenText})` + : ''; + + const scenarioTitle = + `${renderableContent.commands[i].keystroke}` + + `${settingsScreenTextFormatted}: ${mustCount} MUST, ` + + `${shouldCount} SHOULD, ${mayCount} MAY Assertions`; + + const scenarioId = + `${at.name}-test${test.rowNumber}-${id}-cmd${i}`.replaceAll( + /[,+\s]+/g, + '_' + ); + + if (isV2) { + return ( + + {scenarioTitle} + + + + + + + + + + {assertions.map( + ({ + assertionPhrase, + assertionStatement, + priority, + assertionId + }) => ( + + + + + + ) + )} + +
    PriorityAssertion PhraseAssertion Statement
    {convertAssertionPriority(priority)}{assertionPhrase}{assertionStatement}
    +
    + ); + } else { + return ( + + {scenarioTitle} + + + + + + + + + {assertions.map(({ expectation, priority }) => ( + + + + + ))} + +
    PriorityAssertion Statement
    {convertAssertionPriority(priority)}{expectation}
    +
    + ); + } + } + )} + + + + ); }; InstructionsRenderer.propTypes = { - test: PropTypes.object.isRequired, - testPageUrl: PropTypes.string, - at: PropTypes.shape({ - name: PropTypes.string.isRequired - }), - testFormatVersion: PropTypes.number, - headingLevel: PropTypes.number + test: PropTypes.object.isRequired, + testPageUrl: PropTypes.string, + at: PropTypes.shape({ + name: PropTypes.string.isRequired + }), + testFormatVersion: PropTypes.number, + headingLevel: PropTypes.number }; export default InstructionsRenderer; diff --git a/client/components/CandidateReview/CandidateTestPlanRun/index.jsx b/client/components/CandidateReview/CandidateTestPlanRun/index.jsx index 85a1ae709..c3df2df10 100644 --- a/client/components/CandidateReview/CandidateTestPlanRun/index.jsx +++ b/client/components/CandidateReview/CandidateTestPlanRun/index.jsx @@ -6,9 +6,9 @@ import OptionButton from '../../TestRun/OptionButton'; import PageStatus from '../../common/PageStatus'; import { navigateTests } from '../../../utils/navigateTests'; import { - ADD_VIEWER_MUTATION, - CANDIDATE_REPORTS_QUERY, - PROMOTE_VENDOR_REVIEW_STATUS_REPORT_MUTATION + ADD_VIEWER_MUTATION, + CANDIDATE_REPORTS_QUERY, + PROMOTE_VENDOR_REVIEW_STATUS_REPORT_MUTATION } from './queries'; import Badge from 'react-bootstrap/Badge'; import Container from 'react-bootstrap/Container'; @@ -29,677 +29,634 @@ import ThankYouModal from '../CandidateModals/ThankYouModal'; import FeedbackListItem from '../FeedbackListItem'; import DisclosureComponent from '../../common/DisclosureComponent'; import createIssueLink, { - getIssueSearchLink + getIssueSearchLink } from '../../../utils/createIssueLink'; const CandidateTestPlanRun = () => { - const { atId, testPlanVersionId } = useParams(); - const navigate = useNavigate(); - - let testPlanVersionIds = []; - if (testPlanVersionId.includes(',')) - testPlanVersionIds = testPlanVersionId.split(','); - - const { loading, data, error, refetch } = useQuery( - CANDIDATE_REPORTS_QUERY, - { - variables: testPlanVersionIds.length - ? { testPlanVersionIds, atId } - : { testPlanVersionId, atId } - } + const { atId, testPlanVersionId } = useParams(); + const navigate = useNavigate(); + + let testPlanVersionIds = []; + if (testPlanVersionId.includes(',')) + testPlanVersionIds = testPlanVersionId.split(','); + + const { loading, data, error, refetch } = useQuery(CANDIDATE_REPORTS_QUERY, { + variables: testPlanVersionIds.length + ? { testPlanVersionIds, atId } + : { testPlanVersionId, atId } + }); + const [addViewer] = useMutation(ADD_VIEWER_MUTATION); + const [promoteVendorReviewStatus] = useMutation( + PROMOTE_VENDOR_REVIEW_STATUS_REPORT_MUTATION + ); + + const nextButtonRef = useRef(); + const finishButtonRef = useRef(); + + const [reviewStatus, setReviewStatus] = useState(''); + const [firstTimeViewing, setFirstTimeViewing] = useState(false); + const [viewedTests, setViewedTests] = useState([]); + const [currentTestIndex, setCurrentTestIndex] = useState(0); + const [showTestNavigator, setShowTestNavigator] = useState(true); + const [isFirstTest, setIsFirstTest] = useState(true); + const [isLastTest, setIsLastTest] = useState(false); + const [feedbackModalShowing, setFeedbackModalShowing] = useState(false); + const [thankYouModalShowing, setThankYouModalShowing] = useState(false); + const [showInstructions, setShowInstructions] = useState(false); + const [showBrowserBools, setShowBrowserBools] = useState([]); + const [showBrowserClicks, setShowBrowserClicks] = useState([]); + + const isLaptopOrLarger = useMediaQuery({ + query: '(min-width: 792px)' + }); + + const toggleTestNavigator = () => setShowTestNavigator(!showTestNavigator); + + const handleTestClick = async index => { + setCurrentTestIndex(index); + if (index === 0) { + setIsFirstTest(true); + setIsLastTest(false); + } else if (index === tests.length - 1) { + setIsFirstTest(false); + setIsLastTest(true); + } else { + setIsFirstTest(false); + setIsLastTest(false); + } + }; + const handleNextTestClick = async () => { + navigateTests( + false, + currentTest, + tests, + setCurrentTestIndex, + setIsFirstTest, + setIsLastTest ); - const [addViewer] = useMutation(ADD_VIEWER_MUTATION); - const [promoteVendorReviewStatus] = useMutation( - PROMOTE_VENDOR_REVIEW_STATUS_REPORT_MUTATION + }; + const handlePreviousTestClick = async () => { + const { isFirstTest } = navigateTests( + true, + currentTest, + tests, + setCurrentTestIndex, + setIsFirstTest, + setIsLastTest ); - - const nextButtonRef = useRef(); - const finishButtonRef = useRef(); - - const [reviewStatus, setReviewStatus] = useState(''); - const [firstTimeViewing, setFirstTimeViewing] = useState(false); - const [viewedTests, setViewedTests] = useState([]); - const [currentTestIndex, setCurrentTestIndex] = useState(0); - const [showTestNavigator, setShowTestNavigator] = useState(true); - const [isFirstTest, setIsFirstTest] = useState(true); - const [isLastTest, setIsLastTest] = useState(false); - const [feedbackModalShowing, setFeedbackModalShowing] = useState(false); - const [thankYouModalShowing, setThankYouModalShowing] = useState(false); - const [showInstructions, setShowInstructions] = useState(false); - const [showBrowserBools, setShowBrowserBools] = useState([]); - const [showBrowserClicks, setShowBrowserClicks] = useState([]); - - const isLaptopOrLarger = useMediaQuery({ - query: '(min-width: 792px)' - }); - - const toggleTestNavigator = () => setShowTestNavigator(!showTestNavigator); - - const handleTestClick = async index => { - setCurrentTestIndex(index); - if (index === 0) { - setIsFirstTest(true); - setIsLastTest(false); - } else if (index === tests.length - 1) { - setIsFirstTest(false); - setIsLastTest(true); - } else { - setIsFirstTest(false); - setIsLastTest(false); - } - }; - const handleNextTestClick = async () => { - navigateTests( - false, - currentTest, - tests, - setCurrentTestIndex, - setIsFirstTest, - setIsLastTest - ); - }; - const handlePreviousTestClick = async () => { - const { isFirstTest } = navigateTests( - true, - currentTest, - tests, - setCurrentTestIndex, - setIsFirstTest, - setIsLastTest - ); - if (isFirstTest) nextButtonRef.current.focus(); - }; - - const addViewerToTest = async testId => { - await addViewer({ variables: { testPlanVersionId, testId } }); - }; - - const updateTestViewed = async () => { - const userPreviouslyViewedTest = viewedTests.includes(currentTest.id); - if (!userPreviouslyViewedTest) { - setFirstTimeViewing(true); - setViewedTests(tests => [...tests, currentTest.id]); - await addViewerToTest(currentTest.id); - refetch(); - } else { - setFirstTimeViewing(false); - } - }; - - const updateVendorStatus = async (reportApproved = false) => { - if (reviewStatus === 'READY') { - await Promise.all( - testPlanReports?.map(report => - promoteVendorReviewStatus({ - variables: { testReportId: report.id, reviewStatus } - }) - ) - ); - setReviewStatus('IN_PROGRESS'); - } else if (reviewStatus === 'IN_PROGRESS' && reportApproved) { - await Promise.all( - testPlanReports?.map(report => - promoteVendorReviewStatus({ - variables: { testReportId: report.id, reviewStatus } - }) - ) - ); - setReviewStatus('APPROVED'); - } - }; - - const submitApproval = async (status = '') => { - if (status === 'APPROVED') { - updateVendorStatus(true); - } - setFeedbackModalShowing(false); - setThankYouModalShowing(true); - }; - - useEffect(() => { - if (data) { - if ( - !tests[0].viewers?.find( - viewer => viewer.username === data.me.username - ) - ) { - addViewerToTest(tests[0].id); - setFirstTimeViewing(true); - } - const viewedTests = [ - tests[0].id, - ...tests - .filter(test => - test.viewers?.find( - viewer => viewer.username === data.me.username - ) - ) - .map(test => test.id) - ]; - setViewedTests(viewedTests); - setReviewStatus(vendorReviewStatus); - - const bools = testPlanReports.map(() => false); - setShowBrowserBools(bools); - - const browserClicks = testPlanReports.map((report, index) => () => { - setShowBrowserBools(browserBools => { - let bools = [...browserBools]; - bools[index] = !bools[index]; - return bools; - }); - }); - - setShowBrowserClicks(browserClicks); - } - }, [data]); - - useEffect(() => { - if (data) { - updateVendorStatus(); - } - }, [reviewStatus]); - - useEffect(() => { - if (data) { - updateTestViewed(); - } - }, [currentTestIndex]); - - useEffect(() => { - if (data) { - setIsLastTest(tests?.length === 1); - } - }, [data, tests]); - - useEffect(() => { - if (isLastTest) finishButtonRef.current.focus(); - }, [isLastTest]); - - if (error) - return ( - - ); - - if (loading) { - return ( - - ); + if (isFirstTest) nextButtonRef.current.focus(); + }; + + const addViewerToTest = async testId => { + await addViewer({ variables: { testPlanVersionId, testId } }); + }; + + const updateTestViewed = async () => { + const userPreviouslyViewedTest = viewedTests.includes(currentTest.id); + if (!userPreviouslyViewedTest) { + setFirstTimeViewing(true); + setViewedTests(tests => [...tests, currentTest.id]); + await addViewerToTest(currentTest.id); + refetch(); + } else { + setFirstTimeViewing(false); } + }; + + const updateVendorStatus = async (reportApproved = false) => { + if (reviewStatus === 'READY') { + await Promise.all( + testPlanReports?.map(report => + promoteVendorReviewStatus({ + variables: { testReportId: report.id, reviewStatus } + }) + ) + ); + setReviewStatus('IN_PROGRESS'); + } else if (reviewStatus === 'IN_PROGRESS' && reportApproved) { + await Promise.all( + testPlanReports?.map(report => + promoteVendorReviewStatus({ + variables: { testReportId: report.id, reviewStatus } + }) + ) + ); + setReviewStatus('APPROVED'); + } + }; - if (!data) return null; - - const atMap = { - 1: 'JAWS', - 2: 'NVDA', - 3: 'VoiceOver for macOS' - }; - const at = atMap[atId]; - - const testPlanReports = []; - const _testPlanReports = data.testPlanReports; - if (_testPlanReports.length === 0) return ; - - const getLatestReleasedAtVersionReport = arr => { - return arr.reduce((o1, o2) => { - return new Date(o1.latestAtVersionReleasedAt.releasedAt) > - new Date(o2.latestAtVersionReleasedAt.releasedAt) - ? o1 - : o2; + const submitApproval = async (status = '') => { + if (status === 'APPROVED') { + updateVendorStatus(true); + } + setFeedbackModalShowing(false); + setThankYouModalShowing(true); + }; + + useEffect(() => { + if (data) { + if ( + !tests[0].viewers?.find(viewer => viewer.username === data.me.username) + ) { + addViewerToTest(tests[0].id); + setFirstTimeViewing(true); + } + const viewedTests = [ + tests[0].id, + ...tests + .filter(test => + test.viewers?.find(viewer => viewer.username === data.me.username) + ) + .map(test => test.id) + ]; + setViewedTests(viewedTests); + setReviewStatus(vendorReviewStatus); + + const bools = testPlanReports.map(() => false); + setShowBrowserBools(bools); + + const browserClicks = testPlanReports.map((report, index) => () => { + setShowBrowserBools(browserBools => { + let bools = [...browserBools]; + bools[index] = !bools[index]; + return bools; }); - }; - - Object.keys(atMap).forEach(k => { - const group = _testPlanReports.filter(t => t.browser.id == k); - if (group.length) { - const latestReport = getLatestReleasedAtVersionReport(group); - testPlanReports.push(latestReport); - } - }); + }); - const testPlanReport = testPlanReports.find( - each => - each.testPlanVersion.id === testPlanVersionId || - testPlanVersionIds.includes(each.testPlanVersion.id) - ); - - const tests = testPlanReport.runnableTests.map((test, index) => ({ - ...test, - index, - seq: index + 1 - })); + setShowBrowserClicks(browserClicks); + } + }, [data]); - const currentTest = tests[currentTestIndex]; - const { testPlanVersion, vendorReviewStatus } = testPlanReport; - const { recommendedPhaseTargetDate } = testPlanVersion; + useEffect(() => { + if (data) { + updateVendorStatus(); + } + }, [reviewStatus]); - const vendorReviewStatusMap = { - READY: 'Ready', - IN_PROGRESS: 'In Progress', - APPROVED: 'Approved' - }; + useEffect(() => { + if (data) { + updateTestViewed(); + } + }, [currentTestIndex]); - const reviewStatusText = vendorReviewStatusMap[reviewStatus]; + useEffect(() => { + if (data) { + setIsLastTest(tests?.length === 1); + } + }, [data, tests]); - const targetCompletionDate = convertDateToString( - new Date(recommendedPhaseTargetDate), - 'MMMM D, YYYY' - ); + useEffect(() => { + if (isLastTest) finishButtonRef.current.focus(); + }, [isLastTest]); - // Assumes that the issues are across the entire AT/Browser combination - const changesRequestedIssues = testPlanReport.issues?.filter( - issue => - issue.isCandidateReview && - issue.feedbackType === 'CHANGES_REQUESTED' && - issue.testNumberFilteredByAt === currentTest.seq + if (error) + return ( + ); - const feedbackIssues = testPlanReport.issues?.filter( - issue => - issue.isCandidateReview && - issue.feedbackType === 'FEEDBACK' && - issue.testNumberFilteredByAt === currentTest.seq + if (loading) { + return ( + ); - - const issue = { - isCandidateReview: true, - isCandidateReviewChangesRequested: true, - testPlanTitle: testPlanVersion.title, - testPlanDirectory: testPlanVersion.testPlan.directory, - versionString: testPlanVersion.versionString, - testTitle: currentTest.title, - testRowNumber: currentTest.rowNumber, - testRenderedUrl: currentTest.renderedUrl, - atName: testPlanReport.at.name - }; - - const requestChangesUrl = createIssueLink(issue); - - const feedbackUrl = createIssueLink({ - ...issue, - isCandidateReviewChangesRequested: false - }); - - const generalFeedbackUrl = createIssueLink({ - ...issue, - isCandidateReviewChangesRequested: false, - testTitle: undefined, - testRowNumber: undefined, - testRenderedUrl: undefined - }); - - const issueQuery = { - isCandidateReview: true, - isCandidateReviewChangesRequested: false, - testPlanTitle: testPlanVersion.title, - versionString: testPlanVersion.versionString, - testRowNumber: currentTest.rowNumber, - username: data.me.username, - atName: testPlanReport.at.name - }; - - const feedbackGithubUrl = getIssueSearchLink(issueQuery); - - const changesRequestedGithubUrl = getIssueSearchLink({ - ...issueQuery, - isCandidateReviewChangesRequested: true + } + + if (!data) return null; + + const atMap = { + 1: 'JAWS', + 2: 'NVDA', + 3: 'VoiceOver for macOS' + }; + const at = atMap[atId]; + + const testPlanReports = []; + const _testPlanReports = data.testPlanReports; + if (_testPlanReports.length === 0) return ; + + const getLatestReleasedAtVersionReport = arr => { + return arr.reduce((o1, o2) => { + return new Date(o1.latestAtVersionReleasedAt.releasedAt) > + new Date(o2.latestAtVersionReleasedAt.releasedAt) + ? o1 + : o2; }); + }; - let fileBugUrl; - - const githubAtLabelMap = { - 'VoiceOver for macOS': 'vo', - JAWS: 'jaws', - NVDA: 'nvda' - }; - - if (githubAtLabelMap[at] == 'vo') { - fileBugUrl = - 'https://bugs.webkit.org/buglist.cgi?quicksearch=voiceover'; - } else if (githubAtLabelMap[at] == 'nvda') { - fileBugUrl = 'https://github.com/nvaccess/nvda/issues'; - } else { - fileBugUrl = - 'https://github.com/FreedomScientific/VFO-standards-support/issues'; + Object.keys(atMap).forEach(k => { + const group = _testPlanReports.filter(t => t.browser.id == k); + if (group.length) { + const latestReport = getLatestReleasedAtVersionReport(group); + testPlanReports.push(latestReport); } - - const heading = ( -
    -
    - Viewing Test {currentTest.title}, Test {currentTest.seq} of{' '} - {tests.length} - {currentTest.seq === tests.length - ? 'You are on the last test.' - : ''} -
    - - Reviewing Test {currentTest.seq} of {tests.length}: - -

    - {`${currentTest.seq}. ${currentTest.title}`}{' '} - using {`${at}`} - {viewedTests.includes(currentTest.id) && - !firstTimeViewing && - ' '} - {viewedTests.includes(currentTest.id) && !firstTimeViewing && ( - - Previously Viewed - - )} -

    + }); + + const testPlanReport = testPlanReports.find( + each => + each.testPlanVersion.id === testPlanVersionId || + testPlanVersionIds.includes(each.testPlanVersion.id) + ); + + const tests = testPlanReport.runnableTests.map((test, index) => ({ + ...test, + index, + seq: index + 1 + })); + + const currentTest = tests[currentTestIndex]; + const { testPlanVersion, vendorReviewStatus } = testPlanReport; + const { recommendedPhaseTargetDate } = testPlanVersion; + + const vendorReviewStatusMap = { + READY: 'Ready', + IN_PROGRESS: 'In Progress', + APPROVED: 'Approved' + }; + + const reviewStatusText = vendorReviewStatusMap[reviewStatus]; + + const targetCompletionDate = convertDateToString( + new Date(recommendedPhaseTargetDate), + 'MMMM D, YYYY' + ); + + // Assumes that the issues are across the entire AT/Browser combination + const changesRequestedIssues = testPlanReport.issues?.filter( + issue => + issue.isCandidateReview && + issue.feedbackType === 'CHANGES_REQUESTED' && + issue.testNumberFilteredByAt === currentTest.seq + ); + + const feedbackIssues = testPlanReport.issues?.filter( + issue => + issue.isCandidateReview && + issue.feedbackType === 'FEEDBACK' && + issue.testNumberFilteredByAt === currentTest.seq + ); + + const issue = { + isCandidateReview: true, + isCandidateReviewChangesRequested: true, + testPlanTitle: testPlanVersion.title, + testPlanDirectory: testPlanVersion.testPlan.directory, + versionString: testPlanVersion.versionString, + testTitle: currentTest.title, + testRowNumber: currentTest.rowNumber, + testRenderedUrl: currentTest.renderedUrl, + atName: testPlanReport.at.name + }; + + const requestChangesUrl = createIssueLink(issue); + + const feedbackUrl = createIssueLink({ + ...issue, + isCandidateReviewChangesRequested: false + }); + + const generalFeedbackUrl = createIssueLink({ + ...issue, + isCandidateReviewChangesRequested: false, + testTitle: undefined, + testRowNumber: undefined, + testRenderedUrl: undefined + }); + + const issueQuery = { + isCandidateReview: true, + isCandidateReviewChangesRequested: false, + testPlanTitle: testPlanVersion.title, + versionString: testPlanVersion.versionString, + testRowNumber: currentTest.rowNumber, + username: data.me.username, + atName: testPlanReport.at.name + }; + + const feedbackGithubUrl = getIssueSearchLink(issueQuery); + + const changesRequestedGithubUrl = getIssueSearchLink({ + ...issueQuery, + isCandidateReviewChangesRequested: true + }); + + let fileBugUrl; + + const githubAtLabelMap = { + 'VoiceOver for macOS': 'vo', + JAWS: 'jaws', + NVDA: 'nvda' + }; + + if (githubAtLabelMap[at] == 'vo') { + fileBugUrl = 'https://bugs.webkit.org/buglist.cgi?quicksearch=voiceover'; + } else if (githubAtLabelMap[at] == 'nvda') { + fileBugUrl = 'https://github.com/nvaccess/nvda/issues'; + } else { + fileBugUrl = + 'https://github.com/FreedomScientific/VFO-standards-support/issues'; + } + + const heading = ( +
    +
    + Viewing Test {currentTest.title}, Test {currentTest.seq} of{' '} + {tests.length} + {currentTest.seq === tests.length ? 'You are on the last test.' : ''} +
    + + Reviewing Test {currentTest.seq} of {tests.length}: + +

    + {`${currentTest.seq}. ${currentTest.title}`}{' '} + using {`${at}`} + {viewedTests.includes(currentTest.id) && !firstTimeViewing && ' '} + {viewedTests.includes(currentTest.id) && !firstTimeViewing && ( + + Previously Viewed + + )} +

    +
    + ); + + const testInfo = ( +
    +
    +
    + Candidate Test Plan:{' '} + {`${ + testPlanVersion.title || testPlanVersion.testPlan?.directory || '' + }`}
    - ); - - const testInfo = ( -
    -
    -
    - Candidate Test Plan:{' '} - {`${ - testPlanVersion.title || - testPlanVersion.testPlan?.directory || - '' - }`} -
    -
    -
    -
    - Review status by {at} Representative:{' '} - {`${reviewStatusText} `} -
    -
    -
    -
    - Target Completion Date: - {targetCompletionDate} -
    -
    +
    +
    +
    + Review status by {at} Representative: {`${reviewStatusText} `}
    - ); - - const feedback = testPlanReport.issues.filter( - issue => - issue.isCandidateReview && - issue.testNumberFilteredByAt == currentTest.seq - ).length > 0 && ( -
    -

    - Feedback from{' '} - {at} Representative -

    -
      - {[changesRequestedIssues, feedbackIssues].map((list, index) => { - if (list.length > 0) { - const uniqueAuthors = [ - ...new Set(list.map(issue => issue.author)) - ]; - const differentAuthors = !( - uniqueAuthors.length === 1 && - uniqueAuthors[0] === data.me.username - ); - return ( - - ); - } - })} -
    -
    - ); - - const results = ( -
    -

    {currentTest.title}

    - - `Test Results for ${testPlanReport.browser.name}` - ) - ]} - onClick={[ - () => setShowInstructions(!showInstructions), - ...showBrowserClicks - ]} - expanded={[showInstructions, ...showBrowserBools]} - disclosureContainerView={[ - , - ...testPlanReports.map(testPlanReport => { - const testResult = - testPlanReport.finalizedTestResults[ - currentTestIndex - ]; - - const { assertionsPassedCount, assertionsFailedCount } = - getMetrics({ testResult }); - - return ( - <> -

    - Test Results ( - {assertionsPassedCount} passed,  - {assertionsFailedCount} failed) -

    - - - ); - }) - ]} - stacked - >
    +
    +
    +
    + Target Completion Date: + {targetCompletionDate}
    - ); +
    +
    + ); + + const feedback = testPlanReport.issues.filter( + issue => + issue.isCandidateReview && issue.testNumberFilteredByAt == currentTest.seq + ).length > 0 && ( +
    +

    + Feedback from{' '} + {at} Representative +

    +
      + {[changesRequestedIssues, feedbackIssues].map((list, index) => { + if (list.length > 0) { + const uniqueAuthors = [...new Set(list.map(issue => issue.author))]; + const differentAuthors = !( + uniqueAuthors.length === 1 && + uniqueAuthors[0] === data.me.username + ); + return ( + + ); + } + })} +
    +
    + ); + + const results = ( +
    +

    {currentTest.title}

    + `Test Results for ${testPlanReport.browser.name}` + ) + ]} + onClick={[ + () => setShowInstructions(!showInstructions), + ...showBrowserClicks + ]} + expanded={[showInstructions, ...showBrowserBools]} + disclosureContainerView={[ + , + ...testPlanReports.map(testPlanReport => { + const testResult = + testPlanReport.finalizedTestResults[currentTestIndex]; + + const { assertionsPassedCount, assertionsFailedCount } = getMetrics( + { testResult } + ); - return ( - - - Candidate Test Run Page | ARIA-AT - - - +

    + Test Results ( + {assertionsPassedCount} passed,  + {assertionsFailedCount} failed) +

    + + + ); + }) + ]} + stacked + >
    +
    + ); + + return ( + + + Candidate Test Run Page | ARIA-AT + + + + + + {heading} + {testInfo} + + - - {heading} - {testInfo} - - - - {feedback} - - {results} - - -
      -
    • - -
    • -
    • - -
    • -
    • - -
    • -
    -
    - - -
    -

    - Test Review Options -

    - -
    - -
    - -
    + {feedback} + {results} + +
      +
    • + +
    • +
    • + +
    • +
    • + +
    • +
    +
    -
    - {feedbackModalShowing ? ( - - issue.isCandidateReview && - issue.feedbackType === 'FEEDBACK' && - issue.author == data.me.username - )} - feedbackGithubUrl={feedbackGithubUrl} - changesRequestedIssues={testPlanReport.issues?.filter( - issue => - issue.isCandidateReview && - issue.feedbackType === 'CHANGES_REQUESTED' && - issue.author == data.me.username - )} - changesRequestedGithubUrl={changesRequestedGithubUrl} - handleAction={submitApproval} - handleHide={() => setFeedbackModalShowing(false)} - /> - ) : ( - <> - )} - {thankYouModalShowing ? ( - { - setThankYouModalShowing(false); - navigate('/candidate-review'); - }} - githubUrl={generalFeedbackUrl} - /> - ) : ( - <> - )} -
    - ); + +
    +

    Test Review Options

    + +
    + + + + + + + {feedbackModalShowing ? ( + + issue.isCandidateReview && + issue.feedbackType === 'FEEDBACK' && + issue.author == data.me.username + )} + feedbackGithubUrl={feedbackGithubUrl} + changesRequestedIssues={testPlanReport.issues?.filter( + issue => + issue.isCandidateReview && + issue.feedbackType === 'CHANGES_REQUESTED' && + issue.author == data.me.username + )} + changesRequestedGithubUrl={changesRequestedGithubUrl} + handleAction={submitApproval} + handleHide={() => setFeedbackModalShowing(false)} + /> + ) : ( + <> + )} + {thankYouModalShowing ? ( + { + setThankYouModalShowing(false); + navigate('/candidate-review'); + }} + githubUrl={generalFeedbackUrl} + /> + ) : ( + <> + )} + + ); }; export default CandidateTestPlanRun; diff --git a/client/components/CandidateReview/CandidateTestPlanRun/queries.js b/client/components/CandidateReview/CandidateTestPlanRun/queries.js index 94cd04a52..fac63aa0a 100644 --- a/client/components/CandidateReview/CandidateTestPlanRun/queries.js +++ b/client/components/CandidateReview/CandidateTestPlanRun/queries.js @@ -1,172 +1,168 @@ import { gql } from '@apollo/client'; export const ADD_VIEWER_MUTATION = gql` - mutation AddViewerMutation($testPlanVersionId: ID!, $testId: ID!) { - addViewer(testPlanVersionId: $testPlanVersionId, testId: $testId) { - username - } + mutation AddViewerMutation($testPlanVersionId: ID!, $testId: ID!) { + addViewer(testPlanVersionId: $testPlanVersionId, testId: $testId) { + username } + } `; export const PROMOTE_VENDOR_REVIEW_STATUS_REPORT_MUTATION = gql` - mutation UpdateVendorReviewStatusReport( - $testReportId: ID! - $reviewStatus: String! - ) { - testPlanReport(id: $testReportId) { - promoteVendorReviewStatus(vendorReviewStatus: $reviewStatus) { - testPlanReport { - id - vendorReviewStatus - } - } + mutation UpdateVendorReviewStatusReport( + $testReportId: ID! + $reviewStatus: String! + ) { + testPlanReport(id: $testReportId) { + promoteVendorReviewStatus(vendorReviewStatus: $reviewStatus) { + testPlanReport { + id + vendorReviewStatus } + } } + } `; export const CANDIDATE_REPORTS_QUERY = gql` - query CandidateReportsQuery( - $atId: ID! - $testPlanVersionId: ID - $testPlanVersionIds: [ID] + query CandidateReportsQuery( + $atId: ID! + $testPlanVersionId: ID + $testPlanVersionIds: [ID] + ) { + me { + id + roles + username + } + testPlanReports( + atId: $atId + testPlanVersionPhases: [CANDIDATE] + testPlanVersionId: $testPlanVersionId + testPlanVersionIds: $testPlanVersionIds + isFinal: true ) { - me { - id - roles - username + id + vendorReviewStatus + issues { + author + isCandidateReview + feedbackType + testNumberFilteredByAt + link + } + at { + id + name + } + latestAtVersionReleasedAt { + id + name + releasedAt + } + browser { + id + name + } + testPlanVersion { + id + title + phase + gitSha + testPlan { + directory } - testPlanReports( - atId: $atId - testPlanVersionPhases: [CANDIDATE] - testPlanVersionId: $testPlanVersionId - testPlanVersionIds: $testPlanVersionIds - isFinal: true - ) { - id - vendorReviewStatus - issues { - author - isCandidateReview - feedbackType - testNumberFilteredByAt - link - } - at { - id - name - } - latestAtVersionReleasedAt { - id - name - releasedAt - } - browser { - id - name + metadata + testPageUrl + updatedAt + versionString + candidatePhaseReachedAt + recommendedPhaseTargetDate + } + runnableTests { + id + title + rowNumber + renderedUrl + renderableContent + viewers { + username + } + } + finalizedTestResults { + id + completedAt + test { + id + rowNumber + title + renderedUrl + renderableContent + } + scenarioResults { + id + scenario { + commands { + id + text } - testPlanVersion { - id - title - phase - gitSha - testPlan { - directory - } - metadata - testPageUrl - updatedAt - versionString - candidatePhaseReachedAt - recommendedPhaseTargetDate + } + output + assertionResults { + id + assertion { + text } - runnableTests { - id - title - rowNumber - renderedUrl - renderableContent - viewers { - username - } + passed + } + requiredAssertionResults: assertionResults(priority: REQUIRED) { + assertion { + text } - finalizedTestResults { - id - completedAt - test { - id - rowNumber - title - renderedUrl - renderableContent - } - scenarioResults { - id - scenario { - commands { - id - text - } - } - output - assertionResults { - id - assertion { - text - } - passed - } - requiredAssertionResults: assertionResults( - priority: REQUIRED - ) { - assertion { - text - } - passed - } - optionalAssertionResults: assertionResults( - priority: OPTIONAL - ) { - assertion { - text - } - passed - } - mayAssertionResults: assertionResults(priority: MAY) { - assertion { - text - } - passed - } - unexpectedBehaviors { - id - text - impact - details - } - } + passed + } + optionalAssertionResults: assertionResults(priority: OPTIONAL) { + assertion { + text } - draftTestPlanRuns { - tester { - username - } - testPlanReport { - id - } - testResults { - test { - id - } - atVersion { - id - name - } - browserVersion { - id - name - } - completedAt - } + passed + } + mayAssertionResults: assertionResults(priority: MAY) { + assertion { + text } + passed + } + unexpectedBehaviors { + id + text + impact + details + } + } + } + draftTestPlanRuns { + tester { + username + } + testPlanReport { + id + } + testResults { + test { + id + } + atVersion { + id + name + } + browserVersion { + id + name + } + completedAt } + } } + } `; diff --git a/client/components/CandidateReview/FeedbackListItem/FeedbackListItem.css b/client/components/CandidateReview/FeedbackListItem/FeedbackListItem.css index 7a641bb0e..82dfba9a6 100644 --- a/client/components/CandidateReview/FeedbackListItem/FeedbackListItem.css +++ b/client/components/CandidateReview/FeedbackListItem/FeedbackListItem.css @@ -1,53 +1,53 @@ .feedback-list-item { - padding: 0.5em 0 0.5em 0.5em; - position: relative; - margin: 1em 0 1em 0em; - left: 2em; - bottom: 0.5em; - list-style: none; - font-size: 14px; - border: solid 1px #e5e5e5; - width: calc(100% - 2em); + padding: 0.5em 0 0.5em 0.5em; + position: relative; + margin: 1em 0 1em 0em; + left: 2em; + bottom: 0.5em; + list-style: none; + font-size: 14px; + border: solid 1px #e5e5e5; + width: calc(100% - 2em); } .feedback-list-item:before { - content: ''; - position: absolute; - height: 90%; - width: 2px; - margin-top: 7px; - bottom: 1.7em; - left: -1.5em; - background: #d2d5d9; + content: ''; + position: absolute; + height: 90%; + width: 2px; + margin-top: 7px; + bottom: 1.7em; + left: -1.5em; + background: #d2d5d9; } .feedback-list-item:after { - content: ''; - position: absolute; - height: 60%; - width: 2px; - top: 1.8em; - left: -1.5em; - background: #d2d5d9; + content: ''; + position: absolute; + height: 60%; + width: 2px; + top: 1.8em; + left: -1.5em; + background: #d2d5d9; } @media (max-width: 425px) { - .feedback-list-item:before { - height: 55%; - bottom: 3.3em; - } + .feedback-list-item:before { + height: 55%; + bottom: 3.3em; + } - .feedback-list-item:after { - height: 55%; - } + .feedback-list-item:after { + height: 55%; + } } .feedback-indicator { - position: absolute; - left: -1.9em; - top: 0.9em; - width: 13px; - height: 13px; - border-radius: 50px; - border: 2px solid #9a9a9a; + position: absolute; + left: -1.9em; + top: 0.9em; + width: 13px; + height: 13px; + border-radius: 50px; + border: 2px solid #9a9a9a; } diff --git a/client/components/CandidateReview/FeedbackListItem/index.jsx b/client/components/CandidateReview/FeedbackListItem/index.jsx index 773548e60..e60a8045d 100644 --- a/client/components/CandidateReview/FeedbackListItem/index.jsx +++ b/client/components/CandidateReview/FeedbackListItem/index.jsx @@ -6,76 +6,70 @@ import { faFlag, faCommentAlt } from '@fortawesome/free-solid-svg-icons'; import './FeedbackListItem.css'; const FeedbackListItem = ({ - differentAuthors = false, - type = 'feedback', - issues = [], - individualTest = false, - githubUrl = '#' + differentAuthors = false, + type = 'feedback', + issues = [], + individualTest = false, + githubUrl = '#' }) => { - let content; + let content; - if (!differentAuthors && !individualTest) { - content = ( - - {`You ${ - type === 'feedback' - ? 'left feedback for' - : 'requested changes for' - } + if (!differentAuthors && !individualTest) { + content = ( + + {`You ${ + type === 'feedback' ? 'left feedback for' : 'requested changes for' + } `} - - {issues.length} {issues.length === 1 ? 'test' : 'tests'} - {' '} - in this Test Plan - - ); - } else if (!differentAuthors && individualTest) { - githubUrl = issues[0].link; - content = ( - <> - You{' '} - - {type === 'feedback' - ? 'left feedback' - : 'requested changes'} - {' '} - for this test. - - ); - } else { - content = ( - <> - - {issues.length} {issues.length === 1 ? 'person' : 'people'}{' '} - {type === 'feedback' - ? 'left feedback' - : 'requested changes'} - - {' for this test'} - - ); - } - - return ( -
  • - {type === 'feedback' ? ( - - ) : ( - - )} - {' '} - {content} - -
  • + + {issues.length} {issues.length === 1 ? 'test' : 'tests'} + {' '} + in this Test Plan +
    + ); + } else if (!differentAuthors && individualTest) { + githubUrl = issues[0].link; + content = ( + <> + You{' '} + + {type === 'feedback' ? 'left feedback' : 'requested changes'} + {' '} + for this test. + ); + } else { + content = ( + <> + + {issues.length} {issues.length === 1 ? 'person' : 'people'}{' '} + {type === 'feedback' ? 'left feedback' : 'requested changes'} + + {' for this test'} + + ); + } + + return ( +
  • + {type === 'feedback' ? ( + + ) : ( + + )} + {' '} + {content} + +
  • + ); }; FeedbackListItem.propTypes = { - differentAuthors: PropTypes.bool, - issues: PropTypes.array, - type: PropTypes.string, - individualTest: PropTypes.bool, - githubUrl: PropTypes.string + differentAuthors: PropTypes.bool, + issues: PropTypes.array, + type: PropTypes.string, + individualTest: PropTypes.bool, + githubUrl: PropTypes.string }; export default FeedbackListItem; diff --git a/client/components/CandidateReview/TestPlans/TestPlans.css b/client/components/CandidateReview/TestPlans/TestPlans.css index d76219ffb..fdef0dc1b 100644 --- a/client/components/CandidateReview/TestPlans/TestPlans.css +++ b/client/components/CandidateReview/TestPlans/TestPlans.css @@ -1,18 +1,18 @@ .dropdown-btn-mark-as .btn { - display: flex; - align-items: center; - width: fit-content; - height: 30px; + display: flex; + align-items: center; + width: fit-content; + height: 30px; - padding-right: 1.5em; - font-size: 0.875rem; + padding-right: 1.5em; + font-size: 0.875rem; } .dropdown-btn-mark-as.btn { - display: flex; - align-items: center; - width: fit-content; - height: 30px; + display: flex; + align-items: center; + width: fit-content; + height: 30px; - font-size: 0.875rem; + font-size: 0.875rem; } diff --git a/client/components/CandidateReview/TestPlans/index.jsx b/client/components/CandidateReview/TestPlans/index.jsx index 81a77084b..057b72512 100644 --- a/client/components/CandidateReview/TestPlans/index.jsx +++ b/client/components/CandidateReview/TestPlans/index.jsx @@ -6,868 +6,776 @@ import { Container, Table } from 'react-bootstrap'; import { Link } from 'react-router-dom'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { - faFlag, - faCheck, - faChevronUp, - faChevronDown, - faCommentAlt + faFlag, + faCheck, + faChevronUp, + faChevronDown, + faCommentAlt } from '@fortawesome/free-solid-svg-icons'; import alphabetizeObjectBy from '@client/utils/alphabetizeObjectBy'; import { - getTestPlanTargetTitle, - getTestPlanVersionTitle + getTestPlanTargetTitle, + getTestPlanVersionTitle } from '@components/Reports/getTitles'; import ClippedProgressBar from '@components/common/ClippedProgressBar'; import { convertDateToString } from '@client/utils/formatter'; import './TestPlans.css'; const FullHeightContainer = styled(Container)` - min-height: calc(100vh - 64px); + min-height: calc(100vh - 64px); `; const StatusText = styled.span` - height: 1.625em; - font-size: 0.875em; - padding: 4px 10px; - border-radius: 1.625rem; - - overflow: hidden; - white-space: nowrap; - - &.feedback { - border: 2px solid #b253f8; - svg { - color: #b253f8; - } - } + height: 1.625em; + font-size: 0.875em; + padding: 4px 10px; + border-radius: 1.625rem; - &.changes-requested { - border: 2px solid #f87f1b; - svg { - color: #f87f1b; - } - } + overflow: hidden; + white-space: nowrap; - &.ready-for-review { - border: 2px solid #edbb1d; - - span.dot { - height: 10px; - width: 10px; - padding: 0; - margin-right: 8px; - border-radius: 50%; - background: #edbb1d; - } + &.feedback { + border: 2px solid #b253f8; + svg { + color: #b253f8; } + } - &.in-progress { - border: 2px solid #2560ab; - - span.dot { - height: 10px; - width: 10px; - padding: 0; - margin-right: 8px; - border-radius: 50%; - background: #2560ab; - } + &.changes-requested { + border: 2px solid #f87f1b; + svg { + color: #f87f1b; } + } + + &.ready-for-review { + border: 2px solid #edbb1d; + + span.dot { + height: 10px; + width: 10px; + padding: 0; + margin-right: 8px; + border-radius: 50%; + background: #edbb1d; + } + } + + &.in-progress { + border: 2px solid #2560ab; + + span.dot { + height: 10px; + width: 10px; + padding: 0; + margin-right: 8px; + border-radius: 50%; + background: #2560ab; + } + } - &.approved { - border: 2px solid #309d08; - svg { - color: #309d08; - } + &.approved { + border: 2px solid #309d08; + svg { + color: #309d08; } + } `; const DisclosureParent = styled.div` - border: 1px solid #d3d5da; - border-radius: 3px; - margin-bottom: 3rem; + border: 1px solid #d3d5da; + border-radius: 3px; + margin-bottom: 3rem; - h3 { - margin: 0; - padding: 0; - } + h3 { + margin: 0; + padding: 0; + } `; const DisclosureButton = styled.button` - position: relative; - width: 100%; - margin: 0; + position: relative; + width: 100%; + margin: 0; + padding: 0.75rem; + text-align: left; + font-size: 1.5rem; + font-weight: 500; + border: none; + border-radius: 3px; + background-color: transparent; + + &:hover, + &:focus { padding: 0.75rem; - text-align: left; - font-size: 1.5rem; - font-weight: 500; - border: none; - border-radius: 3px; - background-color: transparent; - - &:hover, - &:focus { - padding: 0.75rem; - border: 0 solid #005a9c; - background-color: #def; - cursor: pointer; - } + border: 0 solid #005a9c; + background-color: #def; + cursor: pointer; + } - svg { - position: absolute; - margin: 0; - top: 50%; - right: 1.25rem; + svg { + position: absolute; + margin: 0; + top: 50%; + right: 1.25rem; - color: #969696; - transform: translateY(-50%); - } + color: #969696; + transform: translateY(-50%); + } `; const DisclosureContainer = styled.div` - display: ${({ show }) => (show ? 'flex' : 'none')}; - flex-direction: column; - gap: 1.25rem; + display: ${({ show }) => (show ? 'flex' : 'none')}; + flex-direction: column; + gap: 1.25rem; - background-color: #f8f9fa; + background-color: #f8f9fa; - table { - margin-bottom: 0; - } + table { + margin-bottom: 0; + } `; const CellSubRow = styled.span` - display: flex; - flex-direction: row; - gap: 0.5rem; - margin-top: 0.5rem; - font-size: 0.875rem; - - svg { - align-self: center; - margin: 0; - } + display: flex; + flex-direction: row; + gap: 0.5rem; + margin-top: 0.5rem; + font-size: 0.875rem; + + svg { + align-self: center; + margin: 0; + } `; const CenteredTh = styled.th` - text-align: center; + text-align: center; `; const CenteredTd = styled.td` - text-align: center; - vertical-align: middle !important; + text-align: center; + vertical-align: middle !important; `; const StyledH3 = styled.h3` - padding: 0; - margin: 0 0 0.75rem; - text-align: left; - font-size: 1.5rem; - font-weight: 500; + padding: 0; + margin: 0 0 0.75rem; + text-align: left; + font-size: 1.5rem; + font-weight: 500; `; const None = styled.span` - font-style: italic; - color: #727272; - padding: 12px; + font-style: italic; + color: #727272; + padding: 12px; - &.bordered { - border-top: 1px solid #d2d5d9; - } + &.bordered { + border-top: 1px solid #d2d5d9; + } `; const TestPlans = ({ testPlanVersions }) => { - const [atExpandTableItems, setAtExpandTableItems] = useState({ - 1: true, - 2: true, - 3: true - }); - - const none = None; - const borderedNone = None; - - const onClickExpandAtTable = atId => { - // { jaws/nvda/vo: boolean } ] - if (!atExpandTableItems[atId]) - setAtExpandTableItems({ ...atExpandTableItems, [atId]: true }); - else - setAtExpandTableItems({ - ...atExpandTableItems, - [atId]: !atExpandTableItems[atId] - }); - }; - - const testPlanReportsExist = testPlanVersions.some( - testPlanVersion => testPlanVersion.testPlanReports.length + const [atExpandTableItems, setAtExpandTableItems] = useState({ + 1: true, + 2: true, + 3: true + }); + + const none = None; + const borderedNone = None; + + const onClickExpandAtTable = atId => { + // { jaws/nvda/vo: boolean } ] + if (!atExpandTableItems[atId]) + setAtExpandTableItems({ ...atExpandTableItems, [atId]: true }); + else + setAtExpandTableItems({ + ...atExpandTableItems, + [atId]: !atExpandTableItems[atId] + }); + }; + + const testPlanReportsExist = testPlanVersions.some( + testPlanVersion => testPlanVersion.testPlanReports.length + ); + + if (!testPlanReportsExist) { + return ( + + + Candidate Review | ARIA-AT + +

    Candidate Review

    +

    There are no results to show just yet. Please check back soon!

    +
    ); - - if (!testPlanReportsExist) { - return ( - - - Candidate Review | ARIA-AT - -

    Candidate Review

    -

    - There are no results to show just yet. Please check back - soon! -

    -
    - ); + } + + const getRowStatus = ({ + issues = [], + isInProgressStatusExists, + isApprovedStatusExists + }) => { + let issueChangesRequestedTypeCount = 0; + let issueFeedbackTypeCount = 0; + + for (let i = 0; i < issues.length; i++) { + if (issues[i].feedbackType === 'CHANGES_REQUESTED') + issueChangesRequestedTypeCount++; + else issueFeedbackTypeCount++; } - const getRowStatus = ({ - issues = [], - isInProgressStatusExists, - isApprovedStatusExists - }) => { - let issueChangesRequestedTypeCount = 0; - let issueFeedbackTypeCount = 0; - - for (let i = 0; i < issues.length; i++) { - if (issues[i].feedbackType === 'CHANGES_REQUESTED') - issueChangesRequestedTypeCount++; - else issueFeedbackTypeCount++; - } - - const changesRequestedContent = ( - <> - - - Changes requested for {issueChangesRequestedTypeCount} test - {issueChangesRequestedTypeCount !== 1 ? 's' : ''} - - - ); + const changesRequestedContent = ( + <> + + + Changes requested for {issueChangesRequestedTypeCount} test + {issueChangesRequestedTypeCount !== 1 ? 's' : ''} + + + ); - const issueFeedbackContent = ( - <> - - - Feedback left for {issueFeedbackTypeCount} test - {issueFeedbackTypeCount !== 1 ? 's' : ''} - - - ); + const issueFeedbackContent = ( + <> + + + Feedback left for {issueFeedbackTypeCount} test + {issueFeedbackTypeCount !== 1 ? 's' : ''} + + + ); - const approvedContent = ( - <> - - - Approved - - - ); + const approvedContent = ( + <> + + + Approved + + + ); - const inProgressContent = ( - <> - - - Review in Progress - - - ); + const inProgressContent = ( + <> + + + Review in Progress + + + ); - const readyForReviewContent = ( - <> - - - Ready for Review - - - ); + const readyForReviewContent = ( + <> + + + Ready for Review + + + ); - let result = null; - if (issueChangesRequestedTypeCount) result = changesRequestedContent; - else if (issueFeedbackTypeCount) { - result = issueFeedbackContent; - if (isApprovedStatusExists) - result = ( - <> - {result && ( - <> - {result} -
    -
    - - )} - {approvedContent} - - ); - } else if (isInProgressStatusExists) result = inProgressContent; - else if (isApprovedStatusExists) result = approvedContent; - else result = readyForReviewContent; - - return result; - }; - - const evaluateTestsAssertionsMessage = ({ - totalSupportPercent, - browsersLength, - totalTestsFailedCount, - totalAssertionsFailedCount - }) => { - if (totalSupportPercent === 100) { - return ( - <> - No assertions failed - - ); - } else { - return ( - <> - - {totalAssertionsFailedCount} assertion - {totalAssertionsFailedCount !== 1 ? 's' : ''} - {' '} - failed across{' '} - - {totalTestsFailedCount} test - {totalTestsFailedCount !== 1 ? 's' : ''} - {' '} - run with{' '} - - {browsersLength} browser - {browsersLength !== 1 ? 's' : ''} - - - ); - } - }; - - const uniqueFilter = (element, unique, key) => { - const isDuplicate = unique.includes(element[key]); - if (!isDuplicate) { - unique.push(element[key]); - return true; - } - return false; - }; - - const constructTableForAtById = (atId, atName) => { - const testPlanReportsForAtExists = testPlanVersions.some( - testPlanVersion => - testPlanVersion.testPlanReports.some( - testPlanReport => testPlanReport.at.id == atId - ) + let result = null; + if (issueChangesRequestedTypeCount) result = changesRequestedContent; + else if (issueFeedbackTypeCount) { + result = issueFeedbackContent; + if (isApprovedStatusExists) + result = ( + <> + {result && ( + <> + {result} +
    +
    + + )} + {approvedContent} + ); + } else if (isInProgressStatusExists) result = inProgressContent; + else if (isApprovedStatusExists) result = approvedContent; + else result = readyForReviewContent; + + return result; + }; + + const evaluateTestsAssertionsMessage = ({ + totalSupportPercent, + browsersLength, + totalTestsFailedCount, + totalAssertionsFailedCount + }) => { + if (totalSupportPercent === 100) { + return ( + <> + No assertions failed + + ); + } else { + return ( + <> + + {totalAssertionsFailedCount} assertion + {totalAssertionsFailedCount !== 1 ? 's' : ''} + {' '} + failed across{' '} + + {totalTestsFailedCount} test + {totalTestsFailedCount !== 1 ? 's' : ''} + {' '} + run with{' '} + + {browsersLength} browser + {browsersLength !== 1 ? 's' : ''} + + + ); + } + }; - // return 'None' element if no reports exists for AT - if (!testPlanReportsForAtExists) { - return ( - -

    - onClickExpandAtTable(atId)} - > - {atName} - - -

    - - {borderedNone} - -
    - ); - } - - let testPlanTargetsById = {}; - testPlanVersions.forEach(testPlanVersion => { - const { testPlanReports } = testPlanVersion; - - testPlanReports.forEach(testPlanReport => { - const { at, browser } = testPlanReport; - // Construct testPlanTarget - const testPlanTarget = { - id: `${at.id}${browser.id}`, - at, - browser - }; - testPlanTargetsById[testPlanTarget.id] = testPlanTarget; - }); - }); - testPlanTargetsById = alphabetizeObjectBy( - testPlanTargetsById, - keyValue => getTestPlanTargetTitle(keyValue[1]) - ); + const uniqueFilter = (element, unique, key) => { + const isDuplicate = unique.includes(element[key]); + if (!isDuplicate) { + unique.push(element[key]); + return true; + } + return false; + }; + + const constructTableForAtById = (atId, atName) => { + const testPlanReportsForAtExists = testPlanVersions.some(testPlanVersion => + testPlanVersion.testPlanReports.some( + testPlanReport => testPlanReport.at.id == atId + ) + ); - return ( - -

    - onClickExpandAtTable(atId)} - > - {atName} - - -

    - - - - - - - Candidate Phase Start Date - - Target Completion Date - Review Status - Results Summary - - - - {Object.values(testPlanVersions) - .sort((a, b) => (a.title < b.title ? -1 : 1)) - .map(testPlanVersion => { - const testPlanReports = - testPlanVersion.testPlanReports.filter( - ({ at }) => at.id === atId - ); - const candidatePhaseReachedAt = - testPlanVersion.candidatePhaseReachedAt; - const recommendedPhaseTargetDate = - testPlanVersion.recommendedPhaseTargetDate; - - const allMetrics = []; - - let testsCount = 0; - let dataExists = false; - - Object.values(testPlanTargetsById).map( - testPlanTarget => { - const testPlanReport = - testPlanReports.find( - testPlanReport => - testPlanReport.at.id === - testPlanTarget.at - .id && - testPlanReport.at.id === - atId && - testPlanReport.browser - .id === - testPlanTarget - .browser.id - ); - - if (testPlanReport) { - const metrics = - testPlanReport.metrics; - allMetrics.push(metrics); - - if ( - !dataExists && - testPlanReport.at.id === - atId - ) { - dataExists = true; - } - - testsCount = - metrics.testsCount > - testsCount - ? metrics.testsCount - : testsCount; - } - } - ); - - const metrics = { - testsCount, - browsersLength: allMetrics.length, - totalTestsFailedCount: - allMetrics.reduce( - (acc, obj) => - acc + obj.testsFailedCount, - 0 - ), - totalAssertionsFailedCount: - allMetrics.reduce( - (acc, obj) => - acc + - obj.optionalAssertionsFailedCount + - obj.requiredAssertionsFailedCount, - 0 - ), - totalSupportPercent: - Math.round( - allMetrics.reduce( - (acc, obj) => - acc + - obj.supportPercent, - 0 - ) / allMetrics.length - ) || 0 - }; - - // Make sure issues are unique - const uniqueLinks = []; - const allIssues = testPlanReports - .map(testPlanReport => [ - ...testPlanReport.issues - ]) - .flat() - .filter( - t => t.isCandidateReview === true - ) - .filter(t => - uniqueFilter(t, uniqueLinks, 'link') - ); - - return ( - dataExists && ( - - - - - {convertDateToString( - candidatePhaseReachedAt, - 'MMM D, YYYY' - )} - - - - - {convertDateToString( - recommendedPhaseTargetDate, - 'MMM D, YYYY' - )} - - - - {getRowStatus({ - issues: allIssues, - isInProgressStatusExists: - testPlanReports.some( - testPlanReport => - testPlanReport.vendorReviewStatus === - 'IN_PROGRESS' - ), - isApprovedStatusExists: - testPlanReports.some( - testPlanReport => - testPlanReport.vendorReviewStatus === - 'APPROVED' - ) - })} - - - - - - - - {evaluateTestsAssertionsMessage( - metrics - )} - - - - - ) - ); - })} - -
    Candidate Test Plans
    - - {getTestPlanVersionTitle( - testPlanVersion - )}{' '} - { - testPlanVersion.versionString - }{' '} - ({testsCount} Test - {testsCount === 0 || - testsCount > 1 - ? `s` - : ''} - ) - -
    -
    -
    - ); - }; - - const constructTableForResultsSummary = () => { - if (!testPlanReportsExist) return borderedNone; - - let testPlanTargetsById = {}; - testPlanVersions.forEach(testPlanVersion => { - const { testPlanReports } = testPlanVersion; - - testPlanReports.forEach(testPlanReport => { - const { at, browser } = testPlanReport; - // Construct testPlanTarget - const testPlanTarget = { - id: `${at.id}${browser.id}`, - at, - browser - }; - testPlanTargetsById[testPlanTarget.id] = testPlanTarget; - }); - }); - testPlanTargetsById = alphabetizeObjectBy( - testPlanTargetsById, - keyValue => getTestPlanTargetTitle(keyValue[1]) - ); + // return 'None' element if no reports exists for AT + if (!testPlanReportsForAtExists) { + return ( + +

    + onClickExpandAtTable(atId)} + > + {atName} + + +

    + + {borderedNone} + +
    + ); + } - return ( - <> - Review Status Summary - - - - - JAWS - NVDA - VoiceOver for macOS - - - - {Object.values(testPlanVersions) - .sort((a, b) => (a.title < b.title ? -1 : 1)) - .map(testPlanVersion => { - const testPlanReports = - testPlanVersion.testPlanReports; - - let jawsDataExists = false; - let nvdaDataExists = false; - let voDataExists = false; - - Object.values(testPlanTargetsById).map( - testPlanTarget => { - const testPlanReport = - testPlanReports.find( - testPlanReport => - testPlanReport.at.id === - testPlanTarget.at.id && - testPlanReport.browser - .id === - testPlanTarget.browser - .id - ); - - if (testPlanReport) { - if ( - !jawsDataExists && - testPlanReport.at.id === '1' - ) { - jawsDataExists = true; - } - if ( - !nvdaDataExists && - testPlanReport.at.id === '2' - ) { - nvdaDataExists = true; - } - if ( - !voDataExists && - testPlanReport.at.id === '3' - ) { - voDataExists = true; - } - } - } - ); - - const allJawsIssues = []; - const allNvdaIssues = []; - const allVoIssues = []; - - const jawsTestPlanReports = - testPlanReports.filter(t => { - if (t.at.id === '1') { - allJawsIssues.push(...t.issues); - return true; - } else return false; - }); - const nvdaTestPlanReports = - testPlanReports.filter(t => { - if (t.at.id === '2') { - allNvdaIssues.push(...t.issues); - return true; - } else return false; - }); - const voTestPlanReports = - testPlanReports.filter(t => { - if (t.at.id === '3') { - allVoIssues.push(...t.issues); - return true; - } else return false; - }); - - const uniqueLinks = []; - const jawsIssues = allJawsIssues.filter(t => - uniqueFilter(t, uniqueLinks, 'link') - ); - const nvdaIssues = allNvdaIssues.filter(t => - uniqueFilter(t, uniqueLinks, 'link') - ); - const voIssues = allVoIssues.filter(t => - uniqueFilter(t, uniqueLinks, 'link') - ); - - return ( - - - - {jawsDataExists - ? getRowStatus({ - issues: jawsIssues, - isInProgressStatusExists: - jawsTestPlanReports.some( - testPlanReport => - testPlanReport.vendorReviewStatus === - 'IN_PROGRESS' - ), - isApprovedStatusExists: - jawsTestPlanReports.some( - testPlanReport => - testPlanReport.vendorReviewStatus === - 'APPROVED' - ) - }) - : none} - - - {nvdaDataExists - ? getRowStatus({ - issues: nvdaIssues, - isInProgressStatusExists: - nvdaTestPlanReports.some( - testPlanReport => - testPlanReport.vendorReviewStatus === - 'IN_PROGRESS' - ), - isApprovedStatusExists: - nvdaTestPlanReports.some( - testPlanReport => - testPlanReport.vendorReviewStatus === - 'APPROVED' - ) - }) - : none} - - - {voDataExists - ? getRowStatus({ - issues: voIssues, - isInProgressStatusExists: - voTestPlanReports.some( - testPlanReport => - testPlanReport.vendorReviewStatus === - 'IN_PROGRESS' - ), - isApprovedStatusExists: - voTestPlanReports.some( - testPlanReport => - testPlanReport.vendorReviewStatus === - 'APPROVED' - ) - }) - : none} - - - ); - })} - -
    Test Plan
    - {getTestPlanVersionTitle( - testPlanVersion - )}{' '} - {testPlanVersion.versionString} -
    - - ); - }; + let testPlanTargetsById = {}; + testPlanVersions.forEach(testPlanVersion => { + const { testPlanReports } = testPlanVersion; + + testPlanReports.forEach(testPlanReport => { + const { at, browser } = testPlanReport; + // Construct testPlanTarget + const testPlanTarget = { + id: `${at.id}${browser.id}`, + at, + browser + }; + testPlanTargetsById[testPlanTarget.id] = testPlanTarget; + }); + }); + testPlanTargetsById = alphabetizeObjectBy(testPlanTargetsById, keyValue => + getTestPlanTargetTitle(keyValue[1]) + ); return ( - - - Candidate Review | ARIA-AT - -

    Candidate Review

    -

    Introduction

    -

    - This page summarizes the test results for each AT and Browser - which executed the Test Plan. -

    - {constructTableForAtById('1', 'JAWS')} - {constructTableForAtById('2', 'NVDA')} - {constructTableForAtById('3', 'VoiceOver for macOS')} - {constructTableForResultsSummary()} -
    + +

    + onClickExpandAtTable(atId)} + > + {atName} + + +

    + + + + + + Candidate Phase Start Date + Target Completion Date + Review Status + Results Summary + + + + {Object.values(testPlanVersions) + .sort((a, b) => (a.title < b.title ? -1 : 1)) + .map(testPlanVersion => { + const testPlanReports = + testPlanVersion.testPlanReports.filter( + ({ at }) => at.id === atId + ); + const candidatePhaseReachedAt = + testPlanVersion.candidatePhaseReachedAt; + const recommendedPhaseTargetDate = + testPlanVersion.recommendedPhaseTargetDate; + + const allMetrics = []; + + let testsCount = 0; + let dataExists = false; + + Object.values(testPlanTargetsById).map(testPlanTarget => { + const testPlanReport = testPlanReports.find( + testPlanReport => + testPlanReport.at.id === testPlanTarget.at.id && + testPlanReport.at.id === atId && + testPlanReport.browser.id === testPlanTarget.browser.id + ); + + if (testPlanReport) { + const metrics = testPlanReport.metrics; + allMetrics.push(metrics); + + if (!dataExists && testPlanReport.at.id === atId) { + dataExists = true; + } + + testsCount = + metrics.testsCount > testsCount + ? metrics.testsCount + : testsCount; + } + }); + + const metrics = { + testsCount, + browsersLength: allMetrics.length, + totalTestsFailedCount: allMetrics.reduce( + (acc, obj) => acc + obj.testsFailedCount, + 0 + ), + totalAssertionsFailedCount: allMetrics.reduce( + (acc, obj) => + acc + + obj.optionalAssertionsFailedCount + + obj.requiredAssertionsFailedCount, + 0 + ), + totalSupportPercent: + Math.round( + allMetrics.reduce( + (acc, obj) => acc + obj.supportPercent, + 0 + ) / allMetrics.length + ) || 0 + }; + + // Make sure issues are unique + const uniqueLinks = []; + const allIssues = testPlanReports + .map(testPlanReport => [...testPlanReport.issues]) + .flat() + .filter(t => t.isCandidateReview === true) + .filter(t => uniqueFilter(t, uniqueLinks, 'link')); + + return ( + dataExists && ( + + + + + {convertDateToString( + candidatePhaseReachedAt, + 'MMM D, YYYY' + )} + + + + + {convertDateToString( + recommendedPhaseTargetDate, + 'MMM D, YYYY' + )} + + + + {getRowStatus({ + issues: allIssues, + isInProgressStatusExists: testPlanReports.some( + testPlanReport => + testPlanReport.vendorReviewStatus === + 'IN_PROGRESS' + ), + isApprovedStatusExists: testPlanReports.some( + testPlanReport => + testPlanReport.vendorReviewStatus === 'APPROVED' + ) + })} + + + + + + + {evaluateTestsAssertionsMessage(metrics)} + + + + ) + ); + })} + +
    Candidate Test Plans
    + + {getTestPlanVersionTitle(testPlanVersion)}{' '} + {testPlanVersion.versionString} ({testsCount} Test + {testsCount === 0 || testsCount > 1 ? `s` : ''}) + +
    +
    +
    + ); + }; + + const constructTableForResultsSummary = () => { + if (!testPlanReportsExist) return borderedNone; + + let testPlanTargetsById = {}; + testPlanVersions.forEach(testPlanVersion => { + const { testPlanReports } = testPlanVersion; + + testPlanReports.forEach(testPlanReport => { + const { at, browser } = testPlanReport; + // Construct testPlanTarget + const testPlanTarget = { + id: `${at.id}${browser.id}`, + at, + browser + }; + testPlanTargetsById[testPlanTarget.id] = testPlanTarget; + }); + }); + testPlanTargetsById = alphabetizeObjectBy(testPlanTargetsById, keyValue => + getTestPlanTargetTitle(keyValue[1]) + ); + + return ( + <> + Review Status Summary + + + + + JAWS + NVDA + VoiceOver for macOS + + + + {Object.values(testPlanVersions) + .sort((a, b) => (a.title < b.title ? -1 : 1)) + .map(testPlanVersion => { + const testPlanReports = testPlanVersion.testPlanReports; + + let jawsDataExists = false; + let nvdaDataExists = false; + let voDataExists = false; + + Object.values(testPlanTargetsById).map(testPlanTarget => { + const testPlanReport = testPlanReports.find( + testPlanReport => + testPlanReport.at.id === testPlanTarget.at.id && + testPlanReport.browser.id === testPlanTarget.browser.id + ); + + if (testPlanReport) { + if (!jawsDataExists && testPlanReport.at.id === '1') { + jawsDataExists = true; + } + if (!nvdaDataExists && testPlanReport.at.id === '2') { + nvdaDataExists = true; + } + if (!voDataExists && testPlanReport.at.id === '3') { + voDataExists = true; + } + } + }); + + const allJawsIssues = []; + const allNvdaIssues = []; + const allVoIssues = []; + + const jawsTestPlanReports = testPlanReports.filter(t => { + if (t.at.id === '1') { + allJawsIssues.push(...t.issues); + return true; + } else return false; + }); + const nvdaTestPlanReports = testPlanReports.filter(t => { + if (t.at.id === '2') { + allNvdaIssues.push(...t.issues); + return true; + } else return false; + }); + const voTestPlanReports = testPlanReports.filter(t => { + if (t.at.id === '3') { + allVoIssues.push(...t.issues); + return true; + } else return false; + }); + + const uniqueLinks = []; + const jawsIssues = allJawsIssues.filter(t => + uniqueFilter(t, uniqueLinks, 'link') + ); + const nvdaIssues = allNvdaIssues.filter(t => + uniqueFilter(t, uniqueLinks, 'link') + ); + const voIssues = allVoIssues.filter(t => + uniqueFilter(t, uniqueLinks, 'link') + ); + + return ( + + + + {jawsDataExists + ? getRowStatus({ + issues: jawsIssues, + isInProgressStatusExists: jawsTestPlanReports.some( + testPlanReport => + testPlanReport.vendorReviewStatus === + 'IN_PROGRESS' + ), + isApprovedStatusExists: jawsTestPlanReports.some( + testPlanReport => + testPlanReport.vendorReviewStatus === 'APPROVED' + ) + }) + : none} + + + {nvdaDataExists + ? getRowStatus({ + issues: nvdaIssues, + isInProgressStatusExists: nvdaTestPlanReports.some( + testPlanReport => + testPlanReport.vendorReviewStatus === + 'IN_PROGRESS' + ), + isApprovedStatusExists: nvdaTestPlanReports.some( + testPlanReport => + testPlanReport.vendorReviewStatus === 'APPROVED' + ) + }) + : none} + + + {voDataExists + ? getRowStatus({ + issues: voIssues, + isInProgressStatusExists: voTestPlanReports.some( + testPlanReport => + testPlanReport.vendorReviewStatus === + 'IN_PROGRESS' + ), + isApprovedStatusExists: voTestPlanReports.some( + testPlanReport => + testPlanReport.vendorReviewStatus === 'APPROVED' + ) + }) + : none} + + + ); + })} + +
    Test Plan
    + {getTestPlanVersionTitle(testPlanVersion)}{' '} + {testPlanVersion.versionString} +
    + ); + }; + + return ( + + + Candidate Review | ARIA-AT + +

    Candidate Review

    +

    Introduction

    +

    + This page summarizes the test results for each AT and Browser which + executed the Test Plan. +

    + {constructTableForAtById('1', 'JAWS')} + {constructTableForAtById('2', 'NVDA')} + {constructTableForAtById('3', 'VoiceOver for macOS')} + {constructTableForResultsSummary()} +
    + ); }; TestPlans.propTypes = { - testPlanVersions: PropTypes.arrayOf( + 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, - 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 - }) - ) + id: PropTypes.string.isRequired, + metrics: PropTypes.object.isRequired, + at: PropTypes.object.isRequired, + browser: PropTypes.object.isRequired }) - ).isRequired, - triggerPageUpdate: PropTypes.func + ) + }) + ).isRequired, + triggerPageUpdate: PropTypes.func }; export default TestPlans; diff --git a/client/components/CandidateReview/index.jsx b/client/components/CandidateReview/index.jsx index 0a8373c25..ba0ded88f 100644 --- a/client/components/CandidateReview/index.jsx +++ b/client/components/CandidateReview/index.jsx @@ -5,35 +5,35 @@ import TestPlans from './TestPlans'; import { CANDIDATE_REVIEW_PAGE_QUERY } from './queries'; const CandidateReview = () => { - const { loading, data, error } = useQuery(CANDIDATE_REVIEW_PAGE_QUERY, { - fetchPolicy: 'cache-and-network' - }); + const { loading, data, error } = useQuery(CANDIDATE_REVIEW_PAGE_QUERY, { + fetchPolicy: 'cache-and-network' + }); - if (error) { - return ( - - ); - } + if (error) { + return ( + + ); + } - if (loading) { - return ( - - ); - } + if (loading) { + return ( + + ); + } - if (!data) return null; + if (!data) return null; - const testPlanVersions = data.testPlanVersions; + const testPlanVersions = data.testPlanVersions; - return ; + return ; }; export default CandidateReview; diff --git a/client/components/CandidateReview/queries.js b/client/components/CandidateReview/queries.js index 193bc82f3..4fd8ab8e2 100644 --- a/client/components/CandidateReview/queries.js +++ b/client/components/CandidateReview/queries.js @@ -1,53 +1,53 @@ import { gql } from '@apollo/client'; export const CANDIDATE_REVIEW_PAGE_QUERY = gql` - query { - testPlanVersions(phases: [CANDIDATE]) { - id - phase - title - gitSha - testPlan { - directory - } - metadata - versionString - candidatePhaseReachedAt - recommendedPhaseTargetDate - testPlanReports(isFinal: true) { - id - metrics - at { - id - name - } - latestAtVersionReleasedAt { - id - name - releasedAt - } - browser { - id - name - } - testPlanVersion { - id - title - gitSha - testPlan { - directory - } - metadata - updatedAt - } - vendorReviewStatus - issues { - link - isOpen - isCandidateReview - feedbackType - } - } + query { + testPlanVersions(phases: [CANDIDATE]) { + id + phase + title + gitSha + testPlan { + directory + } + metadata + versionString + candidatePhaseReachedAt + recommendedPhaseTargetDate + testPlanReports(isFinal: true) { + id + metrics + at { + id + name } + latestAtVersionReleasedAt { + id + name + releasedAt + } + browser { + id + name + } + testPlanVersion { + id + title + gitSha + testPlan { + directory + } + metadata + updatedAt + } + vendorReviewStatus + issues { + link + isOpen + isCandidateReview + feedbackType + } + } } + } `; diff --git a/client/components/ConfirmAuth/index.jsx b/client/components/ConfirmAuth/index.jsx index 6bc96ef9e..c39bd0104 100644 --- a/client/components/ConfirmAuth/index.jsx +++ b/client/components/ConfirmAuth/index.jsx @@ -6,30 +6,30 @@ import { ME_QUERY } from '../App/queries'; import { evaluateAuth } from '../../utils/evaluateAuth'; const ConfirmAuth = ({ children, requiredPermission }) => { - const { data } = useQuery(ME_QUERY); + const { data } = useQuery(ME_QUERY); - const auth = evaluateAuth(data && data.me ? data.me : {}); - const { roles, username, isAdmin, isSignedIn } = auth; + const auth = evaluateAuth(data && data.me ? data.me : {}); + const { roles, username, isAdmin, isSignedIn } = auth; - if (!username) return ; + if (!username) return ; - // If you are an admin, you can access all other role actions by default - const authConfirmed = - isSignedIn && (roles.includes(requiredPermission) || isAdmin); + // If you are an admin, you can access all other role actions by default + const authConfirmed = + isSignedIn && (roles.includes(requiredPermission) || isAdmin); - if (!authConfirmed) { - return ; - } + if (!authConfirmed) { + return ; + } - return children; + return children; }; ConfirmAuth.propTypes = { - children: PropTypes.oneOfType([ - PropTypes.arrayOf(PropTypes.node), - PropTypes.node - ]).isRequired, - requiredPermission: PropTypes.string + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node + ]).isRequired, + requiredPermission: PropTypes.string }; export default ConfirmAuth; diff --git a/client/components/DataManagement/DataManagement.css b/client/components/DataManagement/DataManagement.css index 5513e08cf..b26fd6e51 100644 --- a/client/components/DataManagement/DataManagement.css +++ b/client/components/DataManagement/DataManagement.css @@ -1,52 +1,52 @@ .data-management.table { - padding: 0; - margin: 0; - height: 100%; + padding: 0; + margin: 0; + height: 100%; } .data-management.table thead tr th { - padding-left: 0.75rem; - padding-right: 0.75rem; + padding-left: 0.75rem; + padding-right: 0.75rem; } .data-management.table tbody tr th { - padding: 0.75rem; + padding: 0.75rem; } /* Test Plan column & Covered ATs column */ .data-management.table thead tr th:nth-of-type(-n + 2), .data-management.table tbody tr th:nth-of-type(1), .data-management.table tbody tr td:nth-of-type(1) { - max-width: 200px; + max-width: 200px; } /* RD, DRAFT, CANDIDATE & RECOMMENDED columns */ .data-management.table thead tr th:nth-last-of-type(-n + 4), .data-management.table tbody tr td:nth-last-of-type(-n + 4) { - max-width: 150px; + max-width: 150px; } .data-management.table tbody tr td { - position: relative; - padding: 0; - height: 100%; + position: relative; + padding: 0; + height: 100%; } .data-management.table tbody tr td > * { - padding: 0.75rem; + padding: 0.75rem; } .data-management.table tbody tr:nth-of-type(even), .table-striped tbody tr:nth-of-type(even) { - background-color: #fff; + background-color: #fff; } .change-phase { - margin-left: 12px; - margin-right: 12px; + margin-left: 12px; + margin-right: 12px; } .change-phase .btn { - display: flex; - align-items: center; + display: flex; + align-items: center; } diff --git a/client/components/DataManagement/DataManagementRow/index.jsx b/client/components/DataManagement/DataManagementRow/index.jsx index ad1853be9..656692b97 100644 --- a/client/components/DataManagement/DataManagementRow/index.jsx +++ b/client/components/DataManagement/DataManagementRow/index.jsx @@ -4,14 +4,14 @@ import PropTypes from 'prop-types'; import styled from '@emotion/styled'; import { Button } from 'react-bootstrap'; import { - UPDATE_TEST_PLAN_VERSION_PHASE, - UPDATE_TEST_PLAN_VERSION_RECOMMENDED_TARGET_DATE + UPDATE_TEST_PLAN_VERSION_PHASE, + UPDATE_TEST_PLAN_VERSION_RECOMMENDED_TARGET_DATE } from '../queries'; import { LoadingStatus, useTriggerLoad } from '../../common/LoadingStatus'; import { - checkDaysBetweenDates, - convertDateToString, - convertStringFormatToAnotherFormat + checkDaysBetweenDates, + convertDateToString, + convertStringFormatToAnotherFormat } from '../../../utils/formatter'; import { derivePhaseName } from '@client/utils/aria'; import { THEMES, useThemedModal } from '@client/hooks/useThemedModal'; @@ -25,1148 +25,1061 @@ import { differenceBy, uniq as unique, uniqBy as uniqueBy } from 'lodash'; import { getVersionData } from '../utils'; const StatusCell = styled.div` - display: flex; - flex-direction: column; - height: 100%; + display: flex; + flex-direction: column; + height: 100%; - .review-text { - margin-top: 1rem; - font-size: 14px; - text-align: center; + .review-text { + margin-top: 1rem; + font-size: 14px; + text-align: center; - margin-bottom: 88px; - } + margin-bottom: 88px; + } - .versions-in-progress { - display: flex; - justify-content: center; - padding: 12px; - font-size: 14px; + .versions-in-progress { + display: flex; + justify-content: center; + padding: 12px; + font-size: 14px; - position: absolute; - bottom: 0; - left: 0; - right: 0; + position: absolute; + bottom: 0; + left: 0; + right: 0; - color: #6a7989; - background: #f6f8fa; + color: #6a7989; + background: #f6f8fa; - > span.pill { - display: flex; - width: fit-content; - height: 20px; + > span.pill { + display: flex; + width: fit-content; + height: 20px; - justify-content: center; - align-items: center; - align-self: center; + justify-content: center; + align-items: center; + align-self: center; - margin-right: 6px; - min-width: 40px; - border-radius: 14px; + margin-right: 6px; + min-width: 40px; + border-radius: 14px; - background: #6a7989; - color: white; - } + background: #6a7989; + color: white; } + } `; const PhaseCell = styled.div` - padding: 0 !important; /* override padding for td and add margins into specific children */ + padding: 0 !important; /* override padding for td and add margins into specific children */ + + display: flex; + flex-direction: column; + height: 100%; + > span.review-complete { + display: block; + font-size: 14px; + text-align: center; + margin: 12px 0.75rem; + color: #333f4d; + } + + > span.more { display: flex; flex-direction: column; - height: 100%; - - > span.review-complete { - display: block; - font-size: 14px; - text-align: center; - margin: 12px 0.75rem; - color: #333f4d; - } - - > span.more { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; + justify-content: center; + align-items: center; - padding: 0.5rem; - font-size: 14px; + padding: 0.5rem; + font-size: 14px; - margin-top: 6px; + margin-top: 6px; - color: #6a7989; - background: #f6f8fa; + color: #6a7989; + background: #f6f8fa; - > span.more-issues-container { - width: 100%; - text-align: center; + > span.more-issues-container { + width: 100%; + text-align: center; - .issues { - margin-right: 4px; - } + .issues { + margin-right: 4px; + } - align-items: center; - } + align-items: center; + } - > span.target-days-container { - text-align: center; + > span.target-days-container { + text-align: center; - button { - appearance: none; - border: none; - background: none; - color: inherit; + button { + appearance: none; + border: none; + background: none; + color: inherit; - margin: 0; - padding: 0; - } - } + margin: 0; + padding: 0; + } } + } - > .advance-button { - margin: 12px 0.75rem; - width: calc(100% - 1.5rem); - } + > .advance-button { + margin: 12px 0.75rem; + width: calc(100% - 1.5rem); + } `; const NoneText = styled.span` - display: flex; - justify-content: center; - align-items: center; - - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - - font-style: italic; - color: #6a7989; + display: flex; + justify-content: center; + align-items: center; + + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + + font-style: italic; + color: #6a7989; `; const DataManagementRow = ({ - isAdmin, - ats, - testPlan, - testPlanVersions, - setTestPlanVersions, - tableRowIndex + isAdmin, + ats, + testPlan, + testPlanVersions, + setTestPlanVersions, + tableRowIndex }) => { - const { triggerLoad, loadingMessage } = useTriggerLoad(); - const { - themedModal, - showThemedModal, - setShowThemedModal, - setThemedModalTitle, - setThemedModalContent, - setFocusRef - } = useThemedModal({ - type: THEMES.WARNING, - title: 'Error Updating Test Plan Status' - }); - const [updateTestPlanVersionPhaseMutation] = useMutation( - UPDATE_TEST_PLAN_VERSION_PHASE + const { triggerLoad, loadingMessage } = useTriggerLoad(); + const { + themedModal, + showThemedModal, + setShowThemedModal, + setThemedModalTitle, + setThemedModalContent, + setFocusRef + } = useThemedModal({ + type: THEMES.WARNING, + title: 'Error Updating Test Plan Status' + }); + const [updateTestPlanVersionPhaseMutation] = useMutation( + UPDATE_TEST_PLAN_VERSION_PHASE + ); + const [updateTestPlanVersionRecommendedTargetDate] = useMutation( + UPDATE_TEST_PLAN_VERSION_RECOMMENDED_TARGET_DATE + ); + + // State + const [activePhases, setActivePhases] = useState({}); + const [rdTestPlanVersions, setRdTestPlanVersions] = useState([]); + const [draftTestPlanVersions, setDraftTestPlanVersions] = useState([]); + const [candidateTestPlanVersions, setCandidateTestPlanVersions] = useState( + [] + ); + const [recommendedTestPlanVersions, setRecommendedTestPlanVersions] = + useState([]); + + const [showAdvanceModal, setShowAdvanceModal] = useState(false); + const [advanceModalData, setAdvanceModalData] = useState({}); + + const [showUpdateTargetModal, setShowUpdateTargetModal] = useState(false); + const [updateTargetModalData, setUpdateTargetModalData] = useState({}); + + const draftVersionStringRef = useRef(); + const candidateVersionStringRef = useRef(); + const recommendedVersionStringRef = useRef(); + const updateTargetRef = useRef(); + + useEffect(() => { + // TestPlanVersions separated by current TestPlan's phase + setActivePhases({}); + setRdTestPlanVersions( + testPlanVersions.filter(({ phase }) => phase === 'RD') ); - const [updateTestPlanVersionRecommendedTargetDate] = useMutation( - UPDATE_TEST_PLAN_VERSION_RECOMMENDED_TARGET_DATE + setDraftTestPlanVersions( + testPlanVersions.filter(({ phase }) => phase === 'DRAFT') ); + setCandidateTestPlanVersions( + testPlanVersions.filter(({ phase }) => phase === 'CANDIDATE') + ); + setRecommendedTestPlanVersions( + testPlanVersions.filter(({ phase }) => phase === 'RECOMMENDED') + ); + }, [testPlanVersions]); + + const completedRequiredReports = testPlanVersion => { + const reportAtBrowsers = testPlanVersion.testPlanReports + .filter(testPlanReport => testPlanReport.isFinal) + .map(report => { + return [report.at.id, report.browser.id]; + }); + + let browsersKey; + if (testPlanVersion.phase === 'DRAFT') { + browsersKey = 'candidateBrowsers'; + } else if (testPlanVersion.phase === 'CANDIDATE') { + browsersKey = 'recommendedBrowsers'; + } else { + throw new Error('Unexpected case'); + } + + let requiredAtBrowsers = []; + ats.forEach(at => { + const browsers = at[browsersKey]; + browsers.forEach(browser => { + requiredAtBrowsers.push([at.id, browser.id]); + }); + }); - // State - const [activePhases, setActivePhases] = useState({}); - const [rdTestPlanVersions, setRdTestPlanVersions] = useState([]); - const [draftTestPlanVersions, setDraftTestPlanVersions] = useState([]); - const [candidateTestPlanVersions, setCandidateTestPlanVersions] = useState( - [] + const missingReports = differenceBy( + requiredAtBrowsers, + reportAtBrowsers, + (atId, browserId) => `${atId},${browserId}` ); - const [recommendedTestPlanVersions, setRecommendedTestPlanVersions] = - useState([]); - const [showAdvanceModal, setShowAdvanceModal] = useState(false); - const [advanceModalData, setAdvanceModalData] = useState({}); + return missingReports.length === 0; + }; + + const handleClickUpdateTestPlanVersionPhase = async ( + testPlanVersionId, + phase, + testPlanVersionDataToInclude + ) => { + try { + await triggerLoad(async () => { + const result = await updateTestPlanVersionPhaseMutation({ + variables: { + testPlanVersionId, + phase, + testPlanVersionDataToIncludeId: testPlanVersionDataToInclude?.id + } + }); - const [showUpdateTargetModal, setShowUpdateTargetModal] = useState(false); - const [updateTargetModalData, setUpdateTargetModalData] = useState({}); + const updatedTestPlanVersion = + result.data.testPlanVersion.updatePhase.testPlanVersion; + setTestPlanVersions(prevTestPlanVersions => { + let testPlanVersions = [...prevTestPlanVersions]; - const draftVersionStringRef = useRef(); - const candidateVersionStringRef = useRef(); - const recommendedVersionStringRef = useRef(); - const updateTargetRef = useRef(); + const index = testPlanVersions.findIndex( + testPlanVersion => testPlanVersion.id === updatedTestPlanVersion.id + ); + if (index !== -1) testPlanVersions[index] = updatedTestPlanVersion; - useEffect(() => { - // TestPlanVersions separated by current TestPlan's phase - setActivePhases({}); - setRdTestPlanVersions( - testPlanVersions.filter(({ phase }) => phase === 'RD') - ); - setDraftTestPlanVersions( - testPlanVersions.filter(({ phase }) => phase === 'DRAFT') - ); - setCandidateTestPlanVersions( - testPlanVersions.filter(({ phase }) => phase === 'CANDIDATE') - ); - setRecommendedTestPlanVersions( - testPlanVersions.filter(({ phase }) => phase === 'RECOMMENDED') - ); - }, [testPlanVersions]); - - const completedRequiredReports = testPlanVersion => { - const reportAtBrowsers = testPlanVersion.testPlanReports - .filter(testPlanReport => testPlanReport.isFinal) - .map(report => { - return [report.at.id, report.browser.id]; - }); - - let browsersKey; - if (testPlanVersion.phase === 'DRAFT') { - browsersKey = 'candidateBrowsers'; - } else if (testPlanVersion.phase === 'CANDIDATE') { - browsersKey = 'recommendedBrowsers'; - } else { - throw new Error('Unexpected case'); - } + return testPlanVersions; + }); - let requiredAtBrowsers = []; - ats.forEach(at => { - const browsers = at[browsersKey]; - browsers.forEach(browser => { - requiredAtBrowsers.push([at.id, browser.id]); - }); + setTimeout(() => { + if (phase === 'DRAFT' && draftVersionStringRef.current) + draftVersionStringRef.current.focus(); + + if (phase === 'CANDIDATE' && candidateVersionStringRef.current) + candidateVersionStringRef.current.focus(); + + if (phase === 'RECOMMENDED' && recommendedVersionStringRef.current) + recommendedVersionStringRef.current.focus(); + }, 250); + }, 'Updating Test Plan Version Phase'); + } catch (e) { + console.error(e.message); + setShowThemedModal(true); + setThemedModalTitle('Error Updating Test Plan Version Phase'); + setThemedModalContent(<>{e.message}); + } + }; + + const handleClickUpdateTestPlanVersionRecommendedPhaseTargetDate = async ({ + updatedDateText + }) => { + setShowUpdateTargetModal(false); + try { + await triggerLoad(async () => { + const result = await updateTestPlanVersionRecommendedTargetDate({ + variables: { + testPlanVersionId: updateTargetModalData.testPlanVersionId, + recommendedPhaseTargetDate: + convertStringFormatToAnotherFormat(updatedDateText) + } + }); + const updatedTestPlanVersion = + result.data.testPlanVersion.updateRecommendedPhaseTargetDate + .testPlanVersion; + setTestPlanVersions(prevTestPlanVersions => { + let testPlanVersions = [...prevTestPlanVersions]; + + const index = testPlanVersions.findIndex( + testPlanVersion => testPlanVersion.id === updatedTestPlanVersion.id + ); + if (index !== -1) testPlanVersions[index] = updatedTestPlanVersion; + + return testPlanVersions; }); - const missingReports = differenceBy( - requiredAtBrowsers, - reportAtBrowsers, - (atId, browserId) => `${atId},${browserId}` - ); + setTimeout(() => { + if (updateTargetRef.current) updateTargetRef.current.focus(); + }, 250); + }, 'Updating Test Plan Version Recommended Phase Target Date'); + } catch (e) { + console.error(e.message); + setShowThemedModal(true); + setThemedModalTitle( + 'Error Updating Test Plan Version Recommended Phase Target Date' + ); + setThemedModalContent(<>{e.message}); + } + }; + + const renderCellForCoveredAts = () => { + const atNames = ats.map(({ name }) => name); + + if (atNames.length > 1) { + return ( +
    + {atNames.map((item, index) => ( + + {item} + {index !== atNames.length - 1 ? ( + index === atNames.length - 2 ? ( + and + ) : ( + , + ) + ) : null} + + ))} +
    + ); + } else if (atNames.length === 1) return {atNames[0]}; + else return N/A; + }; + + const renderCellForOverallStatus = () => { + const phaseView = (phase, versionDate) => { + let phaseText = ''; + + switch (phase) { + case 'RD': + phaseText = 'Complete '; + break; + case 'DRAFT': + case 'CANDIDATE': + phaseText = 'Review Started '; + break; + case 'RECOMMENDED': + phaseText = 'Since '; + break; + } + + const dateString = convertDateToString(versionDate, 'MMM D, YYYY'); + + return ( + <> + {phase} +

    + {phaseText} + {dateString} +

    + + ); + }; - return missingReports.length === 0; + const versionsInProgressView = versionsCount => { + return versionsCount ? ( + + <> + +{versionsCount} New Version + {versionsCount === 1 ? '' : 's'} in Progress + + + ) : null; }; - const handleClickUpdateTestPlanVersionPhase = async ( - testPlanVersionId, - phase, - testPlanVersionDataToInclude + const otherVersionsInProgressCount = ( + currentPhase, // To exclude in check + excludedPhases = [] ) => { - try { - await triggerLoad(async () => { - const result = await updateTestPlanVersionPhaseMutation({ - variables: { - testPlanVersionId, - phase, - testPlanVersionDataToIncludeId: - testPlanVersionDataToInclude?.id - } - }); - - const updatedTestPlanVersion = - result.data.testPlanVersion.updatePhase.testPlanVersion; - setTestPlanVersions(prevTestPlanVersions => { - let testPlanVersions = [...prevTestPlanVersions]; - - const index = testPlanVersions.findIndex( - testPlanVersion => - testPlanVersion.id === updatedTestPlanVersion.id - ); - if (index !== -1) - testPlanVersions[index] = updatedTestPlanVersion; - - return testPlanVersions; - }); - - setTimeout(() => { - if (phase === 'DRAFT' && draftVersionStringRef.current) - draftVersionStringRef.current.focus(); - - if ( - phase === 'CANDIDATE' && - candidateVersionStringRef.current - ) - candidateVersionStringRef.current.focus(); - - if ( - phase === 'RECOMMENDED' && - recommendedVersionStringRef.current - ) - recommendedVersionStringRef.current.focus(); - }, 250); - }, 'Updating Test Plan Version Phase'); - } catch (e) { - console.error(e.message); - setShowThemedModal(true); - setThemedModalTitle('Error Updating Test Plan Version Phase'); - setThemedModalContent(<>{e.message}); - } + const otherVersionsInProgress = Object.keys(activePhases).filter( + e => ![currentPhase, ...excludedPhases].includes(e) + ); + return otherVersionsInProgress.length; }; - const handleClickUpdateTestPlanVersionRecommendedPhaseTargetDate = async ({ - updatedDateText - }) => { - setShowUpdateTargetModal(false); - try { - await triggerLoad(async () => { - const result = await updateTestPlanVersionRecommendedTargetDate( - { - variables: { - testPlanVersionId: - updateTargetModalData.testPlanVersionId, - recommendedPhaseTargetDate: - convertStringFormatToAnotherFormat( - updatedDateText - ) - } - } - ); - const updatedTestPlanVersion = - result.data.testPlanVersion.updateRecommendedPhaseTargetDate - .testPlanVersion; - setTestPlanVersions(prevTestPlanVersions => { - let testPlanVersions = [...prevTestPlanVersions]; - - const index = testPlanVersions.findIndex( - testPlanVersion => - testPlanVersion.id === updatedTestPlanVersion.id - ); - if (index !== -1) - testPlanVersions[index] = updatedTestPlanVersion; - - return testPlanVersions; - }); - - setTimeout(() => { - if (updateTargetRef.current) - updateTargetRef.current.focus(); - }, 250); - }, 'Updating Test Plan Version Recommended Phase Target Date'); - } catch (e) { - console.error(e.message); - setShowThemedModal(true); - setThemedModalTitle( - 'Error Updating Test Plan Version Recommended Phase Target Date' - ); - setThemedModalContent(<>{e.message}); - } - }; + if (recommendedTestPlanVersions.length) { + const { earliestVersion, earliestVersionDate } = getVersionData( + recommendedTestPlanVersions, + 'recommendedPhaseReachedAt' + ); + const { phase } = earliestVersion; + const versionsInProgressCount = otherVersionsInProgressCount(phase); + + return ( + + {phaseView(phase, earliestVersionDate)} + {versionsInProgressView(versionsInProgressCount)} + + ); + } - const renderCellForCoveredAts = () => { - const atNames = ats.map(({ name }) => name); - - if (atNames.length > 1) { - return ( -
    - {atNames.map((item, index) => ( - - {item} - {index !== atNames.length - 1 ? ( - index === atNames.length - 2 ? ( - and - ) : ( - , - ) - ) : null} - - ))} -
    - ); - } else if (atNames.length === 1) return {atNames[0]}; - else return N/A; - }; + if (candidateTestPlanVersions.length) { + const { earliestVersion, earliestVersionDate } = getVersionData( + candidateTestPlanVersions, + 'candidatePhaseReachedAt' + ); + const { phase } = earliestVersion; + + const versionsInProgressCount = otherVersionsInProgressCount(phase, [ + 'RECOMMENDED' + ]); + + return ( + + {phaseView(phase, earliestVersionDate)} + {versionsInProgressView(versionsInProgressCount)} + + ); + } - const renderCellForOverallStatus = () => { - const phaseView = (phase, versionDate) => { - let phaseText = ''; - - switch (phase) { - case 'RD': - phaseText = 'Complete '; - break; - case 'DRAFT': - case 'CANDIDATE': - phaseText = 'Review Started '; - break; - case 'RECOMMENDED': - phaseText = 'Since '; - break; - } + if (draftTestPlanVersions.length) { + const { earliestVersion, earliestVersionDate } = getVersionData( + draftTestPlanVersions, + 'draftPhaseReachedAt' + ); + const { phase } = earliestVersion; + + const versionsInProgressCount = otherVersionsInProgressCount(phase, [ + 'RECOMMENDED', + 'CANDIDATE' + ]); + + return ( + + {phaseView(phase, earliestVersionDate)} + {versionsInProgressView(versionsInProgressCount)} + + ); + } - const dateString = convertDateToString(versionDate, 'MMM D, YYYY'); + if (rdTestPlanVersions.length) { + const { latestVersion, latestVersionDate } = + getVersionData(rdTestPlanVersions); + const { phase } = latestVersion; + return {phaseView(phase, latestVersionDate)}; + } - return ( - <> - {phase} -

    - {phaseText} - {dateString} -

    - - ); - }; + // Should never be called but just in case + return null; + }; - const versionsInProgressView = versionsCount => { - return versionsCount ? ( - - <> - +{versionsCount} New - Version - {versionsCount === 1 ? '' : 's'} in Progress - - - ) : null; - }; + const renderCellForPhase = (phase, testPlanVersions = []) => { + const defaultView = N/A; - const otherVersionsInProgressCount = ( - currentPhase, // To exclude in check - excludedPhases = [] - ) => { - const otherVersionsInProgress = Object.keys(activePhases).filter( - e => ![currentPhase, ...excludedPhases].includes(e) - ); - return otherVersionsInProgress.length; + const insertActivePhaseForTestPlan = testPlanVersion => { + if (!activePhases[phase]) { + const result = { + ...activePhases, + [phase]: testPlanVersion }; + setActivePhases(result); + } + }; - if (recommendedTestPlanVersions.length) { - const { earliestVersion, earliestVersionDate } = getVersionData( - recommendedTestPlanVersions, - 'recommendedPhaseReachedAt' - ); - const { phase } = earliestVersion; - const versionsInProgressCount = otherVersionsInProgressCount(phase); - - return ( - - {phaseView(phase, earliestVersionDate)} - {versionsInProgressView(versionsInProgressCount)} - - ); - } - - if (candidateTestPlanVersions.length) { - const { earliestVersion, earliestVersionDate } = getVersionData( - candidateTestPlanVersions, - 'candidatePhaseReachedAt' - ); - const { phase } = earliestVersion; - - const versionsInProgressCount = otherVersionsInProgressCount( - phase, - ['RECOMMENDED'] - ); - - return ( - - {phaseView(phase, earliestVersionDate)} - {versionsInProgressView(versionsInProgressCount)} - - ); + switch (phase) { + case 'RD': { + // If the latest version of the plan is in the draft, candidate, or recommended + // phase, show string "N/A". This should also apply if there is no R&D phase + // TestPlanVersions + if (!testPlanVersions.length) return defaultView; + + const { latestVersion, latestVersionDate } = + getVersionData(testPlanVersions); + + const otherTestPlanVersions = [ + ...draftTestPlanVersions, + ...candidateTestPlanVersions, + ...recommendedTestPlanVersions + ]; + + if (otherTestPlanVersions.length) { + const { latestVersionDate: otherLatestVersionDate } = getVersionData( + otherTestPlanVersions + ); + if (otherLatestVersionDate > latestVersionDate) { + return defaultView; + } } + // If there is an earlier version that is draft and that version has some test plan + // runs in the test queue, this button will run the process for updating existing + // reports and preserving data for tests that have not changed. + let testPlanVersionDataToInclude; if (draftTestPlanVersions.length) { - const { earliestVersion, earliestVersionDate } = getVersionData( - draftTestPlanVersions, - 'draftPhaseReachedAt' - ); - const { phase } = earliestVersion; + const { + latestVersion: draftLatestVersion, + latestVersionDate: draftLatestVersionDate + } = getVersionData(draftTestPlanVersions); - const versionsInProgressCount = otherVersionsInProgressCount( - phase, - ['RECOMMENDED', 'CANDIDATE'] - ); - - return ( - - {phaseView(phase, earliestVersionDate)} - {versionsInProgressView(versionsInProgressCount)} - - ); + if (draftLatestVersionDate < latestVersionDate) + testPlanVersionDataToInclude = draftLatestVersion; } - if (rdTestPlanVersions.length) { - const { latestVersion, latestVersionDate } = - getVersionData(rdTestPlanVersions); - const { phase } = latestVersion; - return ( - {phaseView(phase, latestVersionDate)} + // Otherwise, show VERSION_STRING link with a draft transition button. Phase is + // "active" + insertActivePhaseForTestPlan(latestVersion); + + return ( + + + {latestVersion.versionString} + + {isAdmin && ( + + )} + + ); + } + case 'DRAFT': { + let latestVersion, latestVersionDate; + + let otherTestPlanVersions = [ + ...candidateTestPlanVersions, + ...recommendedTestPlanVersions + ]; + + if (testPlanVersions.length) { + const { + latestVersion: _latestVersion, + latestVersionDate: _latestVersionDate + } = getVersionData(testPlanVersions); + + latestVersion = _latestVersion; + latestVersionDate = _latestVersionDate; + + if (otherTestPlanVersions.length) + otherTestPlanVersions = otherTestPlanVersions.filter( + other => new Date(other.updatedAt) > latestVersionDate ); } - // Should never be called but just in case - return null; - }; - - const renderCellForPhase = (phase, testPlanVersions = []) => { - const defaultView = N/A; - - const insertActivePhaseForTestPlan = testPlanVersion => { - if (!activePhases[phase]) { - const result = { - ...activePhases, - [phase]: testPlanVersion - }; - setActivePhases(result); - } - }; + // If a version of the plan is not in the draft phase and there are no versions in + // later phases, show string "Not Started" + if (![...testPlanVersions, ...otherTestPlanVersions].length) + return Not Started; + + // If a version of the plan is not in the draft phase and there is a version in at + // least one of candidate or recommended phases, show string "Review of + // VERSION_STRING completed DATE" + if (otherTestPlanVersions.length) { + const { latestVersion: otherLatestVersion } = getVersionData( + otherTestPlanVersions + ); + + const completionDate = otherLatestVersion.candidatePhaseReachedAt; + + return ( + + + {otherLatestVersion.versionString} + + + Review Completed  + {convertDateToString(completionDate, 'MMM D, YYYY')} + + + ); + } - switch (phase) { - case 'RD': { - // If the latest version of the plan is in the draft, candidate, or recommended - // phase, show string "N/A". This should also apply if there is no R&D phase - // TestPlanVersions - if (!testPlanVersions.length) return defaultView; - - const { latestVersion, latestVersionDate } = - getVersionData(testPlanVersions); - - const otherTestPlanVersions = [ - ...draftTestPlanVersions, - ...candidateTestPlanVersions, - ...recommendedTestPlanVersions - ]; - - if (otherTestPlanVersions.length) { - const { latestVersionDate: otherLatestVersionDate } = - getVersionData(otherTestPlanVersions); - if (otherLatestVersionDate > latestVersionDate) { - return defaultView; - } - } - - // If there is an earlier version that is draft and that version has some test plan - // runs in the test queue, this button will run the process for updating existing - // reports and preserving data for tests that have not changed. - let testPlanVersionDataToInclude; - if (draftTestPlanVersions.length) { - const { - latestVersion: draftLatestVersion, - latestVersionDate: draftLatestVersionDate - } = getVersionData(draftTestPlanVersions); - - if (draftLatestVersionDate < latestVersionDate) - testPlanVersionDataToInclude = draftLatestVersion; - } - - // Otherwise, show VERSION_STRING link with a draft transition button. Phase is - // "active" - insertActivePhaseForTestPlan(latestVersion); - - return ( - - - {latestVersion.versionString} - - {isAdmin && ( - - )} - - ); - } - case 'DRAFT': { - let latestVersion, latestVersionDate; - - let otherTestPlanVersions = [ - ...candidateTestPlanVersions, - ...recommendedTestPlanVersions - ]; - - if (testPlanVersions.length) { - const { - latestVersion: _latestVersion, - latestVersionDate: _latestVersionDate - } = getVersionData(testPlanVersions); - - latestVersion = _latestVersion; - latestVersionDate = _latestVersionDate; - - if (otherTestPlanVersions.length) - otherTestPlanVersions = otherTestPlanVersions.filter( - other => - new Date(other.updatedAt) > latestVersionDate + // Link with text "VERSION_STRING" that targets the single-page view of the plan. + // If required reports are complete and user is an admin, show "Advance to + // Candidate" button. + if (testPlanVersions.length) { + // If there is an earlier version that is candidate and that version has some + // test plan runs in the test queue, this button will run the process for + // updating existing reports and preserving data for tests that have not + // changed. + let testPlanVersionDataToInclude; + if (candidateTestPlanVersions.length) { + const { + latestVersion: candidateLatestVersion, + latestVersionDate: candidateLatestVersionDate + } = getVersionData(candidateTestPlanVersions); + + if (candidateLatestVersionDate < latestVersionDate) + testPlanVersionDataToInclude = candidateLatestVersion; + } + + let coveredReports = []; + latestVersion.testPlanReports.forEach(testPlanReport => { + const markedFinalAt = testPlanReport.markedFinalAt; + const atName = testPlanReport.at.name; + const browserName = testPlanReport.browser.name; + const value = `${atName}_${browserName}`; + + if (markedFinalAt && !coveredReports.includes(value)) + coveredReports.push(value); + }); + + // Phase is "active" + insertActivePhaseForTestPlan(latestVersion); + + return ( + + + {latestVersion.versionString} + + {isAdmin && completedRequiredReports(latestVersion) && ( + + )} + + + + + ); + } + return defaultView; + } + case 'CANDIDATE': { + let latestVersion, latestVersionDate; - // Phase is "active" - insertActivePhaseForTestPlan(latestVersion); - - return ( - - - {latestVersion.versionString} - - {isAdmin && - completedRequiredReports(latestVersion) && ( - - )} - - - - - ); - } - return defaultView; - } - case 'CANDIDATE': { - let latestVersion, latestVersionDate; + let otherTestPlanVersions = [...recommendedTestPlanVersions]; - let otherTestPlanVersions = [...recommendedTestPlanVersions]; + if (testPlanVersions.length) { + const { + latestVersion: _latestVersion, + latestVersionDate: _latestVersionDate + } = getVersionData(testPlanVersions); - if (testPlanVersions.length) { - const { - latestVersion: _latestVersion, - latestVersionDate: _latestVersionDate - } = getVersionData(testPlanVersions); + latestVersion = _latestVersion; + latestVersionDate = _latestVersionDate; - latestVersion = _latestVersion; - latestVersionDate = _latestVersionDate; + if (otherTestPlanVersions.length) + otherTestPlanVersions = otherTestPlanVersions.filter( + other => new Date(other.updatedAt) > latestVersionDate + ); + } - if (otherTestPlanVersions.length) - otherTestPlanVersions = otherTestPlanVersions.filter( - other => - new Date(other.updatedAt) > latestVersionDate - ); - } - - // If a version of the plan is not in the candidate phase and there has not yet been - // a recommended version, show string "Not Started" - if (![...testPlanVersions, ...otherTestPlanVersions].length) - return Not Started; - - // If a version of the plan is not in the candidate phase and there is a recommended - // version, show string "Review of VERSION_STRING completed DATE" - if (otherTestPlanVersions.length) { - const { latestVersion: otherLatestVersion } = - getVersionData(otherTestPlanVersions); - - const completionDate = - otherLatestVersion.recommendedPhaseReachedAt; - - return ( - - - {otherLatestVersion.versionString} - - - Review Completed  - - {convertDateToString( - completionDate, - 'MMM D, YYYY' - )} - - - - ); - } - - // Link with text "VERSION_STRING" that targets the single-page view of the plan. - // - // Show string "N Open Review Issues" and if N>=2, append " from N AT" Examples: "3 - // Open Review Issues from 2 AT" or "0 Open Review Issues" - // - // Show button "Advance to Recommended" when the following conditions are met: - // - If there has not yet been a recommended version and open issues = 0 and days - // in review > 120 and user is admin, show the button. - // - If there is already a recommended version and open review issues = 0 and user - // is admin, show the button. - // - If there is an earlier version that is recommended and that version has some - // test plan runs in the test queue, this button will run the process for - // updating existing reports and preserving data for tests that have not changed. - // - if there is an earlier version in the recommended phase, this button will - // sunset that version. This will also sunset any reports completed using that - // version. - if (testPlanVersions.length) { - const uniqueAtsCount = unique( - testPlanVersions - .flatMap( - testPlanVersion => - testPlanVersion.testPlanReports - ) - .filter( - testPlanReport => testPlanReport.issues.length - ) - .map(testPlanReport => testPlanReport.at.id) - ).length; - - const issuesCount = uniqueBy( - testPlanVersions.flatMap(testPlanVersion => - testPlanVersion.testPlanReports.flatMap( - testPlanReport => - testPlanReport.issues.filter( - issue => issue.isOpen - ) - ) - ), - item => item.link - ).length; - - // If there is an earlier version that is recommended and that version has some - // test plan runs in the test queue, this button will run the process for - // updating existing reports and preserving data for tests that have not - // changed. - let testPlanVersionDataToInclude; - if (recommendedTestPlanVersions.length) { - const { - latestVersion: recommendedLatestVersion, - latestVersionDate: recommendedLatestVersionDate - } = getVersionData(recommendedTestPlanVersions); - - if (recommendedLatestVersionDate < latestVersionDate) - testPlanVersionDataToInclude = - recommendedLatestVersion; - } - - const currentDate = new Date(); - const recommendedPhaseTargetDate = new Date( - latestVersion.recommendedPhaseTargetDate - ); - const candidatePhaseReachedDate = new Date( - latestVersion.candidatePhaseReachedAt - ); - const daysInReview = checkDaysBetweenDates( - currentDate, - candidatePhaseReachedDate - ); - const workingModeDaysToReview = 120; - - let timeToTargetDate = 0; - if (currentDate > recommendedPhaseTargetDate) { - // Indicates that this is in the past - timeToTargetDate = checkDaysBetweenDates( - currentDate, - recommendedPhaseTargetDate - ); - timeToTargetDate = -timeToTargetDate; - } else - timeToTargetDate = checkDaysBetweenDates( - recommendedPhaseTargetDate, - currentDate - ); + // If a version of the plan is not in the candidate phase and there has not yet been + // a recommended version, show string "Not Started" + if (![...testPlanVersions, ...otherTestPlanVersions].length) + return Not Started; + + // If a version of the plan is not in the candidate phase and there is a recommended + // version, show string "Review of VERSION_STRING completed DATE" + if (otherTestPlanVersions.length) { + const { latestVersion: otherLatestVersion } = getVersionData( + otherTestPlanVersions + ); + + const completionDate = otherLatestVersion.recommendedPhaseReachedAt; + + return ( + + + {otherLatestVersion.versionString} + + + Review Completed  + {convertDateToString(completionDate, 'MMM D, YYYY')} + + + ); + } - let coveredReports = []; - latestVersion.testPlanReports.forEach(testPlanReport => { - const markedFinalAt = testPlanReport.markedFinalAt; - const atName = testPlanReport.at.name; - const browserName = testPlanReport.browser.name; - const value = `${atName}_${browserName}`; + // Link with text "VERSION_STRING" that targets the single-page view of the plan. + // + // Show string "N Open Review Issues" and if N>=2, append " from N AT" Examples: "3 + // Open Review Issues from 2 AT" or "0 Open Review Issues" + // + // Show button "Advance to Recommended" when the following conditions are met: + // - If there has not yet been a recommended version and open issues = 0 and days + // in review > 120 and user is admin, show the button. + // - If there is already a recommended version and open review issues = 0 and user + // is admin, show the button. + // - If there is an earlier version that is recommended and that version has some + // test plan runs in the test queue, this button will run the process for + // updating existing reports and preserving data for tests that have not changed. + // - if there is an earlier version in the recommended phase, this button will + // sunset that version. This will also sunset any reports completed using that + // version. + if (testPlanVersions.length) { + const uniqueAtsCount = unique( + testPlanVersions + .flatMap(testPlanVersion => testPlanVersion.testPlanReports) + .filter(testPlanReport => testPlanReport.issues.length) + .map(testPlanReport => testPlanReport.at.id) + ).length; + + const issuesCount = uniqueBy( + testPlanVersions.flatMap(testPlanVersion => + testPlanVersion.testPlanReports.flatMap(testPlanReport => + testPlanReport.issues.filter(issue => issue.isOpen) + ) + ), + item => item.link + ).length; + + // If there is an earlier version that is recommended and that version has some + // test plan runs in the test queue, this button will run the process for + // updating existing reports and preserving data for tests that have not + // changed. + let testPlanVersionDataToInclude; + if (recommendedTestPlanVersions.length) { + const { + latestVersion: recommendedLatestVersion, + latestVersionDate: recommendedLatestVersionDate + } = getVersionData(recommendedTestPlanVersions); + + if (recommendedLatestVersionDate < latestVersionDate) + testPlanVersionDataToInclude = recommendedLatestVersion; + } + + const currentDate = new Date(); + const recommendedPhaseTargetDate = new Date( + latestVersion.recommendedPhaseTargetDate + ); + const candidatePhaseReachedDate = new Date( + latestVersion.candidatePhaseReachedAt + ); + const daysInReview = checkDaysBetweenDates( + currentDate, + candidatePhaseReachedDate + ); + const workingModeDaysToReview = 120; + + let timeToTargetDate = 0; + if (currentDate > recommendedPhaseTargetDate) { + // Indicates that this is in the past + timeToTargetDate = checkDaysBetweenDates( + currentDate, + recommendedPhaseTargetDate + ); + timeToTargetDate = -timeToTargetDate; + } else + timeToTargetDate = checkDaysBetweenDates( + recommendedPhaseTargetDate, + currentDate + ); - if (markedFinalAt && !coveredReports.includes(value)) - coveredReports.push(value); + let coveredReports = []; + latestVersion.testPlanReports.forEach(testPlanReport => { + const markedFinalAt = testPlanReport.markedFinalAt; + const atName = testPlanReport.at.name; + const browserName = testPlanReport.browser.name; + const value = `${atName}_${browserName}`; + + if (markedFinalAt && !coveredReports.includes(value)) + coveredReports.push(value); + }); + + // Phase is "active" + insertActivePhaseForTestPlan(latestVersion); + + return ( + + + {latestVersion.versionString} + + {isAdmin && ( + - )} - - - - - - - {issuesCount} Open Issue - {`${issuesCount === 1 ? '' : 's'}`} - {`${ - issuesCount >= 2 - ? ` from ${uniqueAtsCount} ATs` - : '' - }`} - - - {isAdmin ? ( - - ) : ( - <> - Target  - - {Math.abs(timeToTargetDate)}{' '} - Days - -   - {timeToTargetDate < 0 - ? 'Past' - : 'Away'} - - )} - - - - ); - } - return defaultView; - } - case 'RECOMMENDED': { - // If a version of the plan is not in the recommended phase, shows the string "None - // Yet" - if (!testPlanVersions.length) - return None Yet; - - // Link with text "VERSION_STRING" that targets the single-page view of the plan - const { latestVersion } = getVersionData(testPlanVersions); - - const completionDate = latestVersion.recommendedPhaseReachedAt; - - // Phase is "active" - insertActivePhaseForTestPlan(latestVersion); - - return ( - - - {latestVersion.versionString} - - - - - - Approved  - - {convertDateToString( - completionDate, - 'MMM D, YYYY' - )} - - - - ); - } - } - }; - - return ( - - - - - {testPlan.title} - - - {renderCellForCoveredAts()} - {renderCellForOverallStatus()} - {renderCellForPhase('RD', rdTestPlanVersions)} - {renderCellForPhase('DRAFT', draftTestPlanVersions)} - - {renderCellForPhase('CANDIDATE', candidateTestPlanVersions)} - - - {renderCellForPhase( - 'RECOMMENDED', - recommendedTestPlanVersions - )} - - - {showThemedModal && themedModal} - {showAdvanceModal && ( - - {advanceModalData.candidateWorkingModeDaysToReview - - advanceModalData.candidateDaysInReview > - 0 ? ( -

    - Warning! the {testPlan.title} test plan has - been in candidate review for{' '} - {advanceModalData.candidateDaysInReview}{' '} - days, which is{' '} - {advanceModalData.candidateWorkingModeDaysToReview - - advanceModalData.candidateDaysInReview}{' '} - fewer days than recommended by the ARIA-AT - working mode. Confirm this action only if - impacted stakeholders have had sufficient - opportunity to provide consensus. -

    - ) : null} - This version will be updated to  - {advanceModalData.phase}.  - {advanceModalData.coveredReports?.length ? ( - <> -
    -
    - The included reports cover: -
      - {advanceModalData.coveredReports.map( - e => { - const [atName, browserName] = - e.split('_'); - - return ( -
    • - - {atName} and  - {browserName} - -
    • - ); - } - )} -
    - Do you want to continue? - - ) : ( - <>Do you want to continue? - )} - - } - actions={[ - { - label: 'Continue', - onClick: async () => { - await advanceModalData.advanceFunc(); - } - } - ]} - closeLabel="Cancel" - handleClose={() => setShowAdvanceModal(false)} - staticBackdrop={true} - /> - )} - {showUpdateTargetModal && ( - setShowUpdateTargetModal(false)} + }} + > + Advance to Recommended + + )} + + - )} -
    - ); + + + + + {issuesCount} Open Issue + {`${issuesCount === 1 ? '' : 's'}`} + {`${issuesCount >= 2 ? ` from ${uniqueAtsCount} ATs` : ''}`} + + + {isAdmin ? ( + + ) : ( + <> + Target  + {Math.abs(timeToTargetDate)} Days +   + {timeToTargetDate < 0 ? 'Past' : 'Away'} + + )} + + + + ); + } + return defaultView; + } + case 'RECOMMENDED': { + // If a version of the plan is not in the recommended phase, shows the string "None + // Yet" + if (!testPlanVersions.length) return None Yet; + + // Link with text "VERSION_STRING" that targets the single-page view of the plan + const { latestVersion } = getVersionData(testPlanVersions); + + const completionDate = latestVersion.recommendedPhaseReachedAt; + + // Phase is "active" + insertActivePhaseForTestPlan(latestVersion); + + return ( + + + {latestVersion.versionString} + + + + + + Approved  + {convertDateToString(completionDate, 'MMM D, YYYY')} + + + ); + } + } + }; + + return ( + + + + + {testPlan.title} + + + {renderCellForCoveredAts()} + {renderCellForOverallStatus()} + {renderCellForPhase('RD', rdTestPlanVersions)} + {renderCellForPhase('DRAFT', draftTestPlanVersions)} + {renderCellForPhase('CANDIDATE', candidateTestPlanVersions)} + + {renderCellForPhase('RECOMMENDED', recommendedTestPlanVersions)} + + + {showThemedModal && themedModal} + {showAdvanceModal && ( + + {advanceModalData.candidateWorkingModeDaysToReview - + advanceModalData.candidateDaysInReview > + 0 ? ( +

    + Warning! the {testPlan.title} test plan has been in candidate + review for {advanceModalData.candidateDaysInReview} days, + which is{' '} + {advanceModalData.candidateWorkingModeDaysToReview - + advanceModalData.candidateDaysInReview}{' '} + fewer days than recommended by the ARIA-AT working mode. + Confirm this action only if impacted stakeholders have had + sufficient opportunity to provide consensus. +

    + ) : null} + This version will be updated to  + {advanceModalData.phase}.  + {advanceModalData.coveredReports?.length ? ( + <> +
    +
    + The included reports cover: +
      + {advanceModalData.coveredReports.map(e => { + const [atName, browserName] = e.split('_'); + + return ( +
    • + + {atName} and  + {browserName} + +
    • + ); + })} +
    + Do you want to continue? + + ) : ( + <>Do you want to continue? + )} + + } + actions={[ + { + label: 'Continue', + onClick: async () => { + await advanceModalData.advanceFunc(); + } + } + ]} + closeLabel="Cancel" + handleClose={() => setShowAdvanceModal(false)} + staticBackdrop={true} + /> + )} + {showUpdateTargetModal && ( + setShowUpdateTargetModal(false)} + /> + )} +
    + ); }; 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, + 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, + testPlanVersions: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string, + title: PropTypes.string, + phase: PropTypes.string, + gitSha: PropTypes.string, + testPlan: PropTypes.shape({ directory: PropTypes.string - }).isRequired, - testPlanVersions: PropTypes.arrayOf( - PropTypes.shape({ - id: PropTypes.string, - 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, - tableRowIndex: PropTypes.number.isRequired, - setTestPlanVersions: PropTypes.func + }), + updatedAt: PropTypes.string, + draftPhaseReachedAt: PropTypes.string, + candidatePhaseReachedAt: PropTypes.string, + recommendedPhaseReachedAt: PropTypes.string + }) + ).isRequired, + tableRowIndex: PropTypes.number.isRequired, + setTestPlanVersions: PropTypes.func }; export default DataManagementRow; diff --git a/client/components/DataManagement/filterSortHooks.js b/client/components/DataManagement/filterSortHooks.js index 4da8cdf18..b5a416c90 100644 --- a/client/components/DataManagement/filterSortHooks.js +++ b/client/components/DataManagement/filterSortHooks.js @@ -1,243 +1,235 @@ import { useMemo, useState } from 'react'; import { - DATA_MANAGEMENT_TABLE_FILTER_OPTIONS, - DATA_MANAGEMENT_TABLE_SORT_OPTIONS, - getVersionData + DATA_MANAGEMENT_TABLE_FILTER_OPTIONS, + DATA_MANAGEMENT_TABLE_SORT_OPTIONS, + getVersionData } from './utils'; import { TEST_PLAN_VERSION_PHASES } from '../../utils/constants'; import { TABLE_SORT_ORDERS } from '../common/SortableTableHeader'; export const useTestPlanVersionsByPhase = testPlanVersions => { - const testPlanVersionsByPhase = useMemo(() => { - const initialPhases = Object.keys(TEST_PLAN_VERSION_PHASES).reduce( - (acc, key) => { - acc[TEST_PLAN_VERSION_PHASES[key]] = []; - return acc; - }, - {} - ); + const testPlanVersionsByPhase = useMemo(() => { + const initialPhases = Object.keys(TEST_PLAN_VERSION_PHASES).reduce( + (acc, key) => { + acc[TEST_PLAN_VERSION_PHASES[key]] = []; + return acc; + }, + {} + ); - return testPlanVersions.reduce((acc, testPlanVersion) => { - acc[testPlanVersion.phase].push(testPlanVersion); - return acc; - }, initialPhases); - }, [testPlanVersions]); + return testPlanVersions.reduce((acc, testPlanVersion) => { + acc[testPlanVersion.phase].push(testPlanVersion); + return acc; + }, initialPhases); + }, [testPlanVersions]); - return { testPlanVersionsByPhase }; + return { testPlanVersionsByPhase }; }; export const useDerivedActivePhasesByTestPlanId = ( - testPlans, - testPlanVersions + testPlans, + testPlanVersions ) => { - const { testPlanVersionsByPhase } = - useTestPlanVersionsByPhase(testPlanVersions); - - const getVersionDataByDirectory = (directory, phaseKey, phaseTimeKey) => { - if ( - testPlanVersionsByPhase[phaseKey].some( - testPlanVersion => - testPlanVersion.testPlan.directory === directory - ) - ) { - const { earliestVersion, latestVersion } = getVersionData( - testPlanVersionsByPhase[phaseKey], - phaseTimeKey - ); - return phaseTimeKey ? earliestVersion?.phase : latestVersion?.phase; - } - return undefined; - }; - - const derivedActivePhasesByTestPlanId = useMemo(() => { - const activeTestPlanVersionsByPhase = {}; - const phases = [ - { - phase: TEST_PLAN_VERSION_PHASES.RECOMMENDED, - timeKey: 'recommendedPhaseReachedAt' - }, - { - phase: TEST_PLAN_VERSION_PHASES.CANDIDATE, - timeKey: 'candidatePhaseReachedAt' - }, - { - phase: TEST_PLAN_VERSION_PHASES.DRAFT, - timeKey: 'draftPhaseReachedAt' - }, - { phase: TEST_PLAN_VERSION_PHASES.RD } - ]; - for (const testPlan of testPlans) { - for (const { phase, timeKey } of phases) { - const derivedPhase = getVersionDataByDirectory( - testPlan.directory, - phase, - timeKey - ); - // Gather all of the phases for a test plan - // The first element in the array is the overall phase - // while the subsequent elements in the array are TestPlanVersions - // that are in other phases - if (derivedPhase) { - // Ensure the array exists or initialize it directly before pushing the new phase - activeTestPlanVersionsByPhase[testPlan.id] = - activeTestPlanVersionsByPhase[testPlan.id] ?? []; - activeTestPlanVersionsByPhase[testPlan.id].push( - derivedPhase - ); - } - } + const { testPlanVersionsByPhase } = + useTestPlanVersionsByPhase(testPlanVersions); + + const getVersionDataByDirectory = (directory, phaseKey, phaseTimeKey) => { + if ( + testPlanVersionsByPhase[phaseKey].some( + testPlanVersion => testPlanVersion.testPlan.directory === directory + ) + ) { + const { earliestVersion, latestVersion } = getVersionData( + testPlanVersionsByPhase[phaseKey], + phaseTimeKey + ); + return phaseTimeKey ? earliestVersion?.phase : latestVersion?.phase; + } + return undefined; + }; + + const derivedActivePhasesByTestPlanId = useMemo(() => { + const activeTestPlanVersionsByPhase = {}; + const phases = [ + { + phase: TEST_PLAN_VERSION_PHASES.RECOMMENDED, + timeKey: 'recommendedPhaseReachedAt' + }, + { + phase: TEST_PLAN_VERSION_PHASES.CANDIDATE, + timeKey: 'candidatePhaseReachedAt' + }, + { + phase: TEST_PLAN_VERSION_PHASES.DRAFT, + timeKey: 'draftPhaseReachedAt' + }, + { phase: TEST_PLAN_VERSION_PHASES.RD } + ]; + for (const testPlan of testPlans) { + for (const { phase, timeKey } of phases) { + const derivedPhase = getVersionDataByDirectory( + testPlan.directory, + phase, + timeKey + ); + // Gather all of the phases for a test plan + // The first element in the array is the overall phase + // while the subsequent elements in the array are TestPlanVersions + // that are in other phases + if (derivedPhase) { + // Ensure the array exists or initialize it directly before pushing the new phase + activeTestPlanVersionsByPhase[testPlan.id] = + activeTestPlanVersionsByPhase[testPlan.id] ?? []; + activeTestPlanVersionsByPhase[testPlan.id].push(derivedPhase); } - return activeTestPlanVersionsByPhase; - }, [testPlans, testPlanVersions]); + } + } + return activeTestPlanVersionsByPhase; + }, [testPlans, testPlanVersions]); - return { derivedActivePhasesByTestPlanId }; + return { derivedActivePhasesByTestPlanId }; }; export const useTestPlansByPhase = (testPlans, testPlanVersions) => { - const { derivedActivePhasesByTestPlanId } = - useDerivedActivePhasesByTestPlanId(testPlans, testPlanVersions); + const { derivedActivePhasesByTestPlanId } = + useDerivedActivePhasesByTestPlanId(testPlans, testPlanVersions); - const testPlansByPhase = useMemo(() => { - const testPlansByPhase = {}; - for (const key of Object.keys(TEST_PLAN_VERSION_PHASES)) { - testPlansByPhase[TEST_PLAN_VERSION_PHASES[key]] = []; - } - for (const testPlan of testPlans) { - for (let phase of derivedActivePhasesByTestPlanId[testPlan.id]) { - testPlansByPhase[phase].push(testPlan); - } - } - return testPlansByPhase; - }, [derivedActivePhasesByTestPlanId]); + const testPlansByPhase = useMemo(() => { + const testPlansByPhase = {}; + for (const key of Object.keys(TEST_PLAN_VERSION_PHASES)) { + testPlansByPhase[TEST_PLAN_VERSION_PHASES[key]] = []; + } + for (const testPlan of testPlans) { + for (let phase of derivedActivePhasesByTestPlanId[testPlan.id]) { + testPlansByPhase[phase].push(testPlan); + } + } + return testPlansByPhase; + }, [derivedActivePhasesByTestPlanId]); - return { testPlansByPhase }; + return { testPlansByPhase }; }; export const useDataManagementTableFiltering = ( - testPlans, - testPlanVersions, - filter + testPlans, + testPlanVersions, + filter ) => { - const { testPlansByPhase } = useTestPlansByPhase( - testPlans, - testPlanVersions - ); + const { testPlansByPhase } = useTestPlansByPhase(testPlans, testPlanVersions); - const filteredTestPlans = useMemo(() => { - if (!filter || filter === DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.ALL) { - return testPlans; - } else { - return testPlansByPhase[filter]; - } - }, [filter, testPlansByPhase, testPlans]); + const filteredTestPlans = useMemo(() => { + if (!filter || filter === DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.ALL) { + return testPlans; + } else { + return testPlansByPhase[filter]; + } + }, [filter, testPlansByPhase, testPlans]); + + const filterLabels = { + [DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.ALL]: `All Plans (${testPlans.length})` + }; + + if (testPlansByPhase[TEST_PLAN_VERSION_PHASES.RD].length > 0) { + filterLabels[DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.RD] = `R&D Complete (${ + testPlansByPhase[TEST_PLAN_VERSION_PHASES.RD].length + })`; + } + + if (testPlansByPhase[TEST_PLAN_VERSION_PHASES.DRAFT].length) { + filterLabels[ + DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.DRAFT + ] = `In Draft Review (${ + testPlansByPhase[TEST_PLAN_VERSION_PHASES.DRAFT].length + })`; + } + + if (testPlansByPhase[TEST_PLAN_VERSION_PHASES.CANDIDATE].length > 0) { + filterLabels[ + DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.CANDIDATE + ] = `In Candidate Review (${ + testPlansByPhase[TEST_PLAN_VERSION_PHASES.CANDIDATE].length + })`; + } + + if (testPlansByPhase[TEST_PLAN_VERSION_PHASES.RECOMMENDED].length > 0) { + filterLabels[ + DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.RECOMMENDED + ] = `Recommended Plans (${ + testPlansByPhase[TEST_PLAN_VERSION_PHASES.RECOMMENDED].length + })`; + } + + return { filteredTestPlans, filterLabels }; +}; - const filterLabels = { - [DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.ALL]: `All Plans (${testPlans.length})` +export const useDataManagementTableSorting = ( + testPlans, + testPlanVersions, + ats, + initialSortDirection = TABLE_SORT_ORDERS.ASC +) => { + const [activeSort, setActiveSort] = useState({ + key: DATA_MANAGEMENT_TABLE_SORT_OPTIONS.PHASE, + direction: initialSortDirection + }); + + const { derivedActivePhasesByTestPlanId } = + useDerivedActivePhasesByTestPlanId(testPlans, testPlanVersions); + + const sortedTestPlans = useMemo(() => { + // Ascending and descending interpreted differently for statuses + // (ascending = earlier phase first, descending = later phase first) + const phaseOrder = { + NOT_STARTED: 4, + RD: 3, + DRAFT: 2, + CANDIDATE: 1, + RECOMMENDED: 0 }; + const directionMod = + activeSort.direction === TABLE_SORT_ORDERS.ASC ? -1 : 1; - if (testPlansByPhase[TEST_PLAN_VERSION_PHASES.RD].length > 0) { - filterLabels[ - DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.RD - ] = `R&D Complete (${ - testPlansByPhase[TEST_PLAN_VERSION_PHASES.RD].length - })`; - } + const sortByName = (a, b, dir = directionMod) => + dir * (a.title < b.title ? 1 : -1); - if (testPlansByPhase[TEST_PLAN_VERSION_PHASES.DRAFT].length) { - filterLabels[ - DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.DRAFT - ] = `In Draft Review (${ - testPlansByPhase[TEST_PLAN_VERSION_PHASES.DRAFT].length - })`; - } + const sortByAts = (a, b) => { + const countA = ats.length; // Stubs based on current rendering in DataManagementRow + const countB = ats.length; + if (countA === countB) return sortByName(a, b, -1); + return directionMod * (countA - countB); + }; - if (testPlansByPhase[TEST_PLAN_VERSION_PHASES.CANDIDATE].length > 0) { - filterLabels[ - DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.CANDIDATE - ] = `In Candidate Review (${ - testPlansByPhase[TEST_PLAN_VERSION_PHASES.CANDIDATE].length - })`; - } + const sortByPhase = (a, b) => { + const testPlanVersionOverallA = + derivedActivePhasesByTestPlanId[a.id][0] ?? 'NOT_STARTED'; + const testPlanVersionOverallB = + derivedActivePhasesByTestPlanId[b.id][0] ?? 'NOT_STARTED'; + if (testPlanVersionOverallA === testPlanVersionOverallB) { + return sortByName(a, b, -1); + } + return ( + directionMod * + (phaseOrder[testPlanVersionOverallA] - + phaseOrder[testPlanVersionOverallB]) + ); + }; - if (testPlansByPhase[TEST_PLAN_VERSION_PHASES.RECOMMENDED].length > 0) { - filterLabels[ - DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.RECOMMENDED - ] = `Recommended Plans (${ - testPlansByPhase[TEST_PLAN_VERSION_PHASES.RECOMMENDED].length - })`; - } + const sortFunctions = { + NAME: sortByName, + ATS: sortByAts, + PHASE: sortByPhase + }; - return { filteredTestPlans, filterLabels }; -}; + return testPlans.slice().sort(sortFunctions[activeSort.key]); + }, [activeSort, testPlans]); -export const useDataManagementTableSorting = ( - testPlans, - testPlanVersions, - ats, - initialSortDirection = TABLE_SORT_ORDERS.ASC -) => { - const [activeSort, setActiveSort] = useState({ - key: DATA_MANAGEMENT_TABLE_SORT_OPTIONS.PHASE, - direction: initialSortDirection - }); - - const { derivedActivePhasesByTestPlanId } = - useDerivedActivePhasesByTestPlanId(testPlans, testPlanVersions); - - const sortedTestPlans = useMemo(() => { - // Ascending and descending interpreted differently for statuses - // (ascending = earlier phase first, descending = later phase first) - const phaseOrder = { - NOT_STARTED: 4, - RD: 3, - DRAFT: 2, - CANDIDATE: 1, - RECOMMENDED: 0 - }; - const directionMod = - activeSort.direction === TABLE_SORT_ORDERS.ASC ? -1 : 1; - - const sortByName = (a, b, dir = directionMod) => - dir * (a.title < b.title ? 1 : -1); - - const sortByAts = (a, b) => { - const countA = ats.length; // Stubs based on current rendering in DataManagementRow - const countB = ats.length; - if (countA === countB) return sortByName(a, b, -1); - return directionMod * (countA - countB); - }; - - const sortByPhase = (a, b) => { - const testPlanVersionOverallA = - derivedActivePhasesByTestPlanId[a.id][0] ?? 'NOT_STARTED'; - const testPlanVersionOverallB = - derivedActivePhasesByTestPlanId[b.id][0] ?? 'NOT_STARTED'; - if (testPlanVersionOverallA === testPlanVersionOverallB) { - return sortByName(a, b, -1); - } - return ( - directionMod * - (phaseOrder[testPlanVersionOverallA] - - phaseOrder[testPlanVersionOverallB]) - ); - }; - - const sortFunctions = { - NAME: sortByName, - ATS: sortByAts, - PHASE: sortByPhase - }; - - return testPlans.slice().sort(sortFunctions[activeSort.key]); - }, [activeSort, testPlans]); - - const updateSort = ({ key, direction }) => { - setActiveSort({ key, direction }); - }; + const updateSort = ({ key, direction }) => { + setActiveSort({ key, direction }); + }; - return { - sortedTestPlans, - updateSort, - activeSort - }; + return { + sortedTestPlans, + updateSort, + activeSort + }; }; diff --git a/client/components/DataManagement/index.jsx b/client/components/DataManagement/index.jsx index ae75f5dda..75bda18ad 100644 --- a/client/components/DataManagement/index.jsx +++ b/client/components/DataManagement/index.jsx @@ -9,223 +9,217 @@ import DataManagementRow from '@components/DataManagement/DataManagementRow'; import './DataManagement.css'; import { evaluateAuth } from '@client/utils/evaluateAuth'; import SortableTableHeader, { - TABLE_SORT_ORDERS + TABLE_SORT_ORDERS } from '../common/SortableTableHeader'; import FilterButtons from '../common/FilterButtons'; import { - useDataManagementTableFiltering, - useDataManagementTableSorting + useDataManagementTableFiltering, + useDataManagementTableSorting } from './filterSortHooks'; import { - DATA_MANAGEMENT_TABLE_FILTER_OPTIONS, - DATA_MANAGEMENT_TABLE_SORT_OPTIONS + DATA_MANAGEMENT_TABLE_FILTER_OPTIONS, + DATA_MANAGEMENT_TABLE_SORT_OPTIONS } from './utils'; const DataManagement = () => { - const { loading, data, error, refetch } = useQuery( - DATA_MANAGEMENT_PAGE_QUERY, - { fetchPolicy: 'cache-and-network' } + const { loading, data, error, refetch } = useQuery( + DATA_MANAGEMENT_PAGE_QUERY, + { fetchPolicy: 'cache-and-network' } + ); + + const [pageReady, setPageReady] = useState(false); + const [ats, setAts] = useState([]); + const [testPlans, setTestPlans] = useState([]); + const [testPlanVersions, setTestPlanVersions] = useState([]); + const [filter, setFilter] = useState( + DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.ALL + ); + + const auth = evaluateAuth(data && data.me ? data.me : {}); + const { isAdmin } = auth; + + useEffect(() => { + if (data) { + const { ats = [], testPlanVersions = [], testPlans = [] } = data; + setAts(ats); + setTestPlans(testPlans); + setTestPlanVersions(testPlanVersions); + setPageReady(true); + } + }, [data]); + + const { filteredTestPlans, filterLabels } = useDataManagementTableFiltering( + testPlans, + testPlanVersions, + filter + ); + + const { sortedTestPlans, updateSort, activeSort } = + useDataManagementTableSorting( + filteredTestPlans, + testPlanVersions, + ats, + TABLE_SORT_ORDERS.DESC ); - const [pageReady, setPageReady] = useState(false); - const [ats, setAts] = useState([]); - const [testPlans, setTestPlans] = useState([]); - const [testPlanVersions, setTestPlanVersions] = useState([]); - const [filter, setFilter] = useState( - DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.ALL + if (error) { + return ( + ); + } - const auth = evaluateAuth(data && data.me ? data.me : {}); - const { isAdmin } = auth; - - useEffect(() => { - if (data) { - const { ats = [], testPlanVersions = [], testPlans = [] } = data; - setAts(ats); - setTestPlans(testPlans); - setTestPlanVersions(testPlanVersions); - setPageReady(true); - } - }, [data]); - - const { filteredTestPlans, filterLabels } = useDataManagementTableFiltering( - testPlans, - testPlanVersions, - filter + if (loading || !pageReady) { + return ( + ); - - const { sortedTestPlans, updateSort, activeSort } = - useDataManagementTableSorting( - filteredTestPlans, - testPlanVersions, - ats, - TABLE_SORT_ORDERS.DESC - ); - - if (error) { - return ( - + + Data Management | ARIA-AT + +

    Data Management

    + + {emptyTestPlans && ( +

    + There are no Test Plans available +

    + )} + + {emptyTestPlans && isAdmin && ( + + Add a Test Plan to the Queue + + )} + + {isAdmin ? ( + <> +

    Introduction

    +

    + This page provides a view of the latest test plan version + information, and where they currently are in the{' '} + + ARIA-AT Community Group’s review process + + .
    + Use this page to manage Test Plans in the Test Queue and their + phases. +

    + + + + ) : ( + <> +

    Introduction

    +

    + This page provides a view of the latest test plan version + information, and where they currently are in the{' '} + + ARIA-AT Community Group’s review process + + . +

    + + )} + +

    Test Plans Status Summary

    + + + + + + updateSort({ + key: DATA_MANAGEMENT_TABLE_SORT_OPTIONS.NAME, + direction + }) + } /> - ); - } - - if (loading || !pageReady) { - return ( - + updateSort({ + key: DATA_MANAGEMENT_TABLE_SORT_OPTIONS.ATS, + direction + }) + } /> - ); - } - - const emptyTestPlans = !testPlans.length; - - return ( - - - Data Management | ARIA-AT - -

    Data Management

    - - {emptyTestPlans && ( -

    - There are no Test Plans available -

    - )} - - {emptyTestPlans && isAdmin && ( - - Add a Test Plan to the Queue - - )} - - {isAdmin ? ( - <> -

    Introduction

    -

    - This page provides a view of the latest test plan - version information, and where they currently are in the{' '} - - ARIA-AT Community Group’s review process - - .
    - Use this page to manage Test Plans in the Test Queue and - their phases. -

    - - - - ) : ( - <> -

    Introduction

    -

    - This page provides a view of the latest test plan - version information, and where they currently are in the{' '} - - ARIA-AT Community Group’s review process - - . -

    - - )} - -

    Test Plans Status Summary

    - + updateSort({ + key: DATA_MANAGEMENT_TABLE_SORT_OPTIONS.PHASE, + direction + }) + } + initialSortDirection={TABLE_SORT_ORDERS.DESC} /> -
    - - - - updateSort({ - key: DATA_MANAGEMENT_TABLE_SORT_OPTIONS.NAME, - direction - }) - } - /> - - updateSort({ - key: DATA_MANAGEMENT_TABLE_SORT_OPTIONS.ATS, - direction - }) - } - /> - - updateSort({ - key: DATA_MANAGEMENT_TABLE_SORT_OPTIONS.PHASE, - direction - }) - } - initialSortDirection={TABLE_SORT_ORDERS.DESC} - /> - - - - - - - - {sortedTestPlans.map((testPlan, index) => { - return ( - - testPlanVersion.testPlan.directory === - testPlan.directory - )} - tableRowIndex={index} - setTestPlanVersions={setTestPlanVersions} - /> - ); - })} - -
    R&D VersionDraft ReviewCandidate ReviewRecommended Version
    - - ); + R&D Version + Draft Review + Candidate Review + Recommended Version + + + + {sortedTestPlans.map((testPlan, index) => { + return ( + + testPlanVersion.testPlan.directory === testPlan.directory + )} + tableRowIndex={index} + setTestPlanVersions={setTestPlanVersions} + /> + ); + })} + + + + ); }; export default DataManagement; diff --git a/client/components/DataManagement/queries.js b/client/components/DataManagement/queries.js index 20ccdb328..8af20ec46 100644 --- a/client/components/DataManagement/queries.js +++ b/client/components/DataManagement/queries.js @@ -1,189 +1,189 @@ import { gql } from '@apollo/client'; export const DATA_MANAGEMENT_PAGE_QUERY = gql` - query DataManagementPage { - me { - id - username - roles + query DataManagementPage { + me { + id + username + roles + } + ats { + id + name + browsers { + id + name + } + atVersions { + id + name + releasedAt + } + candidateBrowsers { + id + } + recommendedBrowsers { + id + } + } + testPlans { + id + directory + title + } + testPlanVersions(phases: [RD, DRAFT, CANDIDATE, RECOMMENDED]) { + id + title + phase + gitSha + gitMessage + updatedAt + versionString + draftPhaseReachedAt + candidatePhaseReachedAt + recommendedPhaseTargetDate + recommendedPhaseReachedAt + testPlan { + directory + } + testPlanReports { + id + metrics + isFinal + markedFinalAt + at { + id + name } - ats { - id - name - browsers { - id - name - } - atVersions { - id - name - releasedAt - } - candidateBrowsers { - id - } - recommendedBrowsers { - id - } + browser { + id + name } - testPlans { - id - directory - title + issues { + link + isOpen + feedbackType } - testPlanVersions(phases: [RD, DRAFT, CANDIDATE, RECOMMENDED]) { + draftTestPlanRuns { + tester { + username + } + testPlanReport { id - title - phase - gitSha - gitMessage - updatedAt - versionString - draftPhaseReachedAt - candidatePhaseReachedAt - recommendedPhaseTargetDate - recommendedPhaseReachedAt - testPlan { - directory + } + testResults { + test { + id + } + atVersion { + id + name } - testPlanReports { - id - metrics - isFinal - markedFinalAt - at { - id - name - } - browser { - id - name - } - issues { - link - isOpen - feedbackType - } - draftTestPlanRuns { - tester { - username - } - testPlanReport { - id - } - testResults { - test { - id - } - atVersion { - id - name - } - browserVersion { - id - name - } - completedAt - } - } + browserVersion { + id + name } - metadata + completedAt + } } + } + metadata } + } `; export const UPDATE_TEST_PLAN_VERSION_PHASE = gql` - mutation UpdateTestPlanVersionPhase( - $testPlanVersionId: ID! - $phase: TestPlanVersionPhase! - $testPlanVersionDataToIncludeId: ID - ) { - testPlanVersion(id: $testPlanVersionId) { - updatePhase( - phase: $phase - testPlanVersionDataToIncludeId: $testPlanVersionDataToIncludeId - ) { - testPlanVersion { - id - title - phase - gitSha - gitMessage - versionString - updatedAt - draftPhaseReachedAt - candidatePhaseReachedAt - recommendedPhaseTargetDate - recommendedPhaseReachedAt - testPlan { - directory - } - testPlanReports { - id - at { - id - name - } - browser { - id - name - } - issues { - link - isOpen - feedbackType - } - } - metadata - } + mutation UpdateTestPlanVersionPhase( + $testPlanVersionId: ID! + $phase: TestPlanVersionPhase! + $testPlanVersionDataToIncludeId: ID + ) { + testPlanVersion(id: $testPlanVersionId) { + updatePhase( + phase: $phase + testPlanVersionDataToIncludeId: $testPlanVersionDataToIncludeId + ) { + testPlanVersion { + id + title + phase + gitSha + gitMessage + versionString + updatedAt + draftPhaseReachedAt + candidatePhaseReachedAt + recommendedPhaseTargetDate + recommendedPhaseReachedAt + testPlan { + directory + } + testPlanReports { + id + at { + id + name + } + browser { + id + name } + issues { + link + isOpen + feedbackType + } + } + metadata } + } } + } `; export const UPDATE_TEST_PLAN_VERSION_RECOMMENDED_TARGET_DATE = gql` - mutation UpdateTestPlanReportRecommendedTargetDate( - $testPlanVersionId: ID! - $recommendedPhaseTargetDate: Timestamp! - ) { - testPlanVersion(id: $testPlanVersionId) { - updateRecommendedPhaseTargetDate( - recommendedPhaseTargetDate: $recommendedPhaseTargetDate - ) { - testPlanVersion { - id - title - phase - gitSha - gitMessage - versionString - updatedAt - draftPhaseReachedAt - candidatePhaseReachedAt - recommendedPhaseTargetDate - recommendedPhaseReachedAt - testPlan { - directory - } - testPlanReports { - id - at { - id - name - } - browser { - id - name - } - issues { - link - isOpen - feedbackType - } - } - metadata - } + mutation UpdateTestPlanReportRecommendedTargetDate( + $testPlanVersionId: ID! + $recommendedPhaseTargetDate: Timestamp! + ) { + testPlanVersion(id: $testPlanVersionId) { + updateRecommendedPhaseTargetDate( + recommendedPhaseTargetDate: $recommendedPhaseTargetDate + ) { + testPlanVersion { + id + title + phase + gitSha + gitMessage + versionString + updatedAt + draftPhaseReachedAt + candidatePhaseReachedAt + recommendedPhaseTargetDate + recommendedPhaseReachedAt + testPlan { + directory + } + testPlanReports { + id + at { + id + name + } + browser { + id + name + } + issues { + link + isOpen + feedbackType } + } + metadata } + } } + } `; diff --git a/client/components/DataManagement/utils.js b/client/components/DataManagement/utils.js index 292d3a270..21c6763a1 100644 --- a/client/components/DataManagement/utils.js +++ b/client/components/DataManagement/utils.js @@ -4,31 +4,31 @@ import { TEST_PLAN_VERSION_PHASES } from '../../utils/constants'; // TestPlanVersions export const getVersionData = (testPlanVersions, dateKey = 'updatedAt') => { - const earliestVersion = testPlanVersions.reduce((a, b) => - new Date(a[dateKey]) < new Date(b[dateKey]) ? a : b - ); - const earliestVersionDate = new Date(earliestVersion[dateKey]); + const earliestVersion = testPlanVersions.reduce((a, b) => + new Date(a[dateKey]) < new Date(b[dateKey]) ? a : b + ); + const earliestVersionDate = new Date(earliestVersion[dateKey]); - const latestVersion = testPlanVersions.reduce((a, b) => - new Date(a[dateKey]) > new Date(b[dateKey]) ? a : b - ); - const latestVersionDate = new Date(latestVersion[dateKey]); + const latestVersion = testPlanVersions.reduce((a, b) => + new Date(a[dateKey]) > new Date(b[dateKey]) ? a : b + ); + const latestVersionDate = new Date(latestVersion[dateKey]); - return { - earliestVersion, - earliestVersionDate, - latestVersion, - latestVersionDate - }; + return { + earliestVersion, + earliestVersionDate, + latestVersion, + latestVersionDate + }; }; export const DATA_MANAGEMENT_TABLE_SORT_OPTIONS = { - NAME: 'NAME', - ATS: 'ATS', - PHASE: 'PHASE' + NAME: 'NAME', + ATS: 'ATS', + PHASE: 'PHASE' }; export const DATA_MANAGEMENT_TABLE_FILTER_OPTIONS = { - ALL: 'ALL', - ...TEST_PLAN_VERSION_PHASES + ALL: 'ALL', + ...TEST_PLAN_VERSION_PHASES }; diff --git a/client/components/DeleteResultsModal/index.jsx b/client/components/DeleteResultsModal/index.jsx index d834320e8..07d26e4d8 100644 --- a/client/components/DeleteResultsModal/index.jsx +++ b/client/components/DeleteResultsModal/index.jsx @@ -3,74 +3,73 @@ import { Button, Modal } from 'react-bootstrap'; import PropTypes from 'prop-types'; const DeleteResultsModal = ({ - show = false, - isAdmin = false, - details = { - title: 'Title N/A', - username: null - }, - handleClose = () => {}, - handleAction = () => {} + show = false, + isAdmin = false, + details = { + title: 'Title N/A', + username: null + }, + handleClose = () => {}, + handleAction = () => {} }) => { - const { title, username } = details; + const { title, username } = details; - return ( - - - - {isAdmin - ? `You are about to delete results for ${username}` - : 'You are about to delete your results'} - - - - {isAdmin ? ( - <> -

    - The following results for {username} will be - deleted: -

    -

    - {title} -

    -

    - Please press Delete to confirm this action. -

    - - ) : ( - <> -

    Your results will be deleted for:

    -

    - {title} -

    -

    - Please press Delete to confirm this action. -

    - - )} -
    - - - - -
    - ); + return ( + + + + {isAdmin + ? `You are about to delete results for ${username}` + : 'You are about to delete your results'} + + + + {isAdmin ? ( + <> +

    + The following results for {username} will be deleted: +

    +

    + {title} +

    +

    + Please press Delete to confirm this action. +

    + + ) : ( + <> +

    Your results will be deleted for:

    +

    + {title} +

    +

    + Please press Delete to confirm this action. +

    + + )} +
    + + + + +
    + ); }; DeleteResultsModal.propTypes = { - show: PropTypes.bool, - isAdmin: PropTypes.bool, - details: PropTypes.object, - handleClose: PropTypes.func, - handleAction: PropTypes.func + show: PropTypes.bool, + isAdmin: PropTypes.bool, + details: PropTypes.object, + handleClose: PropTypes.func, + handleAction: PropTypes.func }; export default DeleteResultsModal; diff --git a/client/components/DeleteTestPlanReportModal/index.jsx b/client/components/DeleteTestPlanReportModal/index.jsx index 0fdd61bf0..1b6add454 100644 --- a/client/components/DeleteTestPlanReportModal/index.jsx +++ b/client/components/DeleteTestPlanReportModal/index.jsx @@ -3,54 +3,54 @@ import { Button, Modal } from 'react-bootstrap'; import PropTypes from 'prop-types'; const DeleteTestPlanModal = ({ - show = false, - details = { - title: 'Title N/A' - }, - handleClose = () => {}, - handleAction = () => {} + show = false, + details = { + title: 'Title N/A' + }, + handleClose = () => {}, + handleAction = () => {} }) => { - const { title } = details; + const { title } = details; - return ( - - - - {`You are about the delete the Test Plan Report for ${title}`} - - - - <> -

    The following Test Plan Report will be deleted:

    -

    - {title} -

    -

    - Please press Delete to confirm this action. -

    - -
    - - - - -
    - ); + return ( + + + + {`You are about the delete the Test Plan Report for ${title}`} + + + + <> +

    The following Test Plan Report will be deleted:

    +

    + {title} +

    +

    + Please press Delete to confirm this action. +

    + +
    + + + + +
    + ); }; DeleteTestPlanModal.propTypes = { - show: PropTypes.bool, - details: PropTypes.object, - handleClose: PropTypes.func, - handleAction: PropTypes.func + show: PropTypes.bool, + details: PropTypes.object, + handleClose: PropTypes.func, + handleAction: PropTypes.func }; export default DeleteTestPlanModal; diff --git a/client/components/DisclaimerInfo/index.jsx b/client/components/DisclaimerInfo/index.jsx index 822dd8739..5730e5433 100644 --- a/client/components/DisclaimerInfo/index.jsx +++ b/client/components/DisclaimerInfo/index.jsx @@ -5,127 +5,127 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faExclamationCircle } from '@fortawesome/free-solid-svg-icons'; const Container = styled.div` - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; - font-size: 1rem; - padding: 0.5rem 1rem; - margin-top: 0.5rem; - margin-bottom: 0.5rem; - background: #f7f7f7; + font-size: 1rem; + padding: 0.5rem 1rem; + margin-top: 0.5rem; + margin-bottom: 0.5rem; + background: #f7f7f7; - border: 2px solid #d3d5d9; - border-radius: 0.5rem; + border: 2px solid #d3d5d9; + border-radius: 0.5rem; - details { - font-weight: normal; - font-size: 1rem; + details { + font-weight: normal; + font-size: 1rem; - span > ol { - margin-bottom: 0; - } + span > ol { + margin-bottom: 0; + } - summary { - width: fit-content; + summary { + width: fit-content; - list-style: none; + list-style: none; - font-weight: bold; - text-align: left; - border: thin solid transparent; - background-color: transparent; + font-weight: bold; + text-align: left; + border: thin solid transparent; + background-color: transparent; - :hover, - :focus { - background-color: #eee; - } + :hover, + :focus { + background-color: #eee; + } - ::-webkit-details-marker { - display: none; - } - } + ::-webkit-details-marker { + display: none; + } } + } `; const candidateTitle = 'Unapproved Report'; const candidateMessageContent = ( - <> - The information in this report is generated from candidate tests. - Candidate ARIA-AT tests are in review by assistive technology developers - and lack consensus regarding: -
      -
    1. applicability and validity of the tests, and
    2. -
    3. accuracy of test results.
    4. -
    - + <> + The information in this report is generated from candidate tests. Candidate + ARIA-AT tests are in review by assistive technology developers and lack + consensus regarding: +
      +
    1. applicability and validity of the tests, and
    2. +
    3. accuracy of test results.
    4. +
    + ); const recommendedTitle = 'Approved Report'; const recommendedMessageContent = ( - <> - The information in this report is generated from recommended tests. - Recommended ARIA-AT tests have been reviewed by assistive technology - developers and represent consensus regarding: applicability and validity - of the tests, and accuracy of test results. - + <> + The information in this report is generated from recommended tests. + Recommended ARIA-AT tests have been reviewed by assistive technology + developers and represent consensus regarding: applicability and validity of + the tests, and accuracy of test results. + ); const deprecatedTitle = 'Deprecated Report'; const deprecatedMessageContent = ( - <> - The information in this report is generated from previously set - candidate or recommended tests. - + <> + The information in this report is generated from previously set candidate or + recommended tests. + ); const content = { - CANDIDATE: { - title: candidateTitle, - messageContent: candidateMessageContent - }, - RECOMMENDED: { - title: recommendedTitle, - messageContent: recommendedMessageContent - }, - DEPRECATED: { - title: deprecatedTitle, - messageContent: deprecatedMessageContent - } + CANDIDATE: { + title: candidateTitle, + messageContent: candidateMessageContent + }, + RECOMMENDED: { + title: recommendedTitle, + messageContent: recommendedMessageContent + }, + DEPRECATED: { + title: deprecatedTitle, + messageContent: deprecatedMessageContent + } }; const DisclaimerInfo = ({ phase }) => { - const [expanded, setExpanded] = useState(false); - - const title = content[phase]?.title || content.CANDIDATE.title; - const messageContent = - content[phase]?.messageContent || content.CANDIDATE.messageContent; - - return ( - -
    - setExpanded(!expanded)} - aria-label={`Warning! ${title}`} - > - - {title} - - {messageContent} -
    -
    - ); + const [expanded, setExpanded] = useState(false); + + const title = content[phase]?.title || content.CANDIDATE.title; + const messageContent = + content[phase]?.messageContent || content.CANDIDATE.messageContent; + + return ( + +
    + setExpanded(!expanded)} + aria-label={`Warning! ${title}`} + > + + {title} + + {messageContent} +
    +
    + ); }; DisclaimerInfo.propTypes = { - phase: PropTypes.string + phase: PropTypes.string }; export default DisclaimerInfo; diff --git a/client/components/GraphQLProvider/GraphQLProvider.jsx b/client/components/GraphQLProvider/GraphQLProvider.jsx index fcc4e7f38..9e8c5907f 100644 --- a/client/components/GraphQLProvider/GraphQLProvider.jsx +++ b/client/components/GraphQLProvider/GraphQLProvider.jsx @@ -3,37 +3,37 @@ import PropTypes from 'prop-types'; import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client'; const client = new ApolloClient({ - uri: '/api/graphql', - cache: new InMemoryCache({ - addTypename: false, - typePolicies: { - Query: { - fields: { - testPlanReport: { merge: true }, - testPlanReports: { merge: false }, - collectionJobByTestPlanRunId: { - merge(existing, incoming) { - return { ...existing, ...incoming }; - } - } - } - }, - Mutation: { - fields: { - testPlanReport: { merge: false }, - testPlanRun: { merge: false } - } + uri: '/api/graphql', + cache: new InMemoryCache({ + addTypename: false, + typePolicies: { + Query: { + fields: { + testPlanReport: { merge: true }, + testPlanReports: { merge: false }, + collectionJobByTestPlanRunId: { + merge(existing, incoming) { + return { ...existing, ...incoming }; } + } } - }) + }, + Mutation: { + fields: { + testPlanReport: { merge: false }, + testPlanRun: { merge: false } + } + } + } + }) }); const GraphQLProvider = ({ children }) => { - return {children}; + return {children}; }; GraphQLProvider.propTypes = { - children: PropTypes.node.isRequired + children: PropTypes.node.isRequired }; export default GraphQLProvider; diff --git a/client/components/Home/Home.jsx b/client/components/Home/Home.jsx index 1bc4668c6..06baee601 100644 --- a/client/components/Home/Home.jsx +++ b/client/components/Home/Home.jsx @@ -10,207 +10,191 @@ import iconReviewAssertions from '../../assets/review-assertion.jpg'; // import iconFixIssue from '../../assets/fix-issue.jpg'; const Home = () => { - return ( - - - Home | ARIA-AT - -
    -

    - Enabling Interoperability for Assistive Technology Users -

    -
    -
    -

    - - - Note: The{' '} - - ARIA-AT Project - {' '} - is managed by the{' '} - - ARIA-AT Community Group - {' '} - in coordination with the{' '} - - Authoring Practices Task Force - {' '} - of the{' '} - - ARIA Working Group - - . The W3C staff contact is{' '} - - Daniel Montalvo - - . - -

    -

    - Today, different screen readers often yield - conflicting experiences when presenting a web page, - disadvantaging or even excluding some users. These - differences also create accessibility design and - test barriers for web developers. -

    -

    - On the other hand, browsers are interoperable for - people who do not use assistive technologies. That - is, different browsers provide equivalent - experiences. Browser interoperability facilitates an - inclusive web. -

    -

    - Assistive technology users deserve equal inclusion. - The ARIA-AT project aims to empower equal inclusion - by realizing interoperability for AT users. -

    -

    - - Read more about how the AT interoperability gap - hinders inclusion on the web for people with - disabilities. - -

    -
    -
    - - ); + } + + componentWillUnmount() { + // stop listening for results if we haven't already above + window.removeEventListener('message', this.handleResultsMessage); + } + + async componentDidUpdate(prevProps) { + // If the test we are looking at changes + if (prevProps.file !== this.props.file) { + // Before hydrating, save local copy of serialized state with no results + // This is a short cut to tell whether the form has been edited + await this.waitForTestHarnessReload(); + this.emptyForm = JSON.stringify(this.serializeForm()); + + // Load partial results + const { serializedForm } = this.props; + if (serializedForm) { + this.reloadAndHydrate(serializedForm); + } } + } + + render() { + const { git_hash, file, at_key } = this.props; + + return ( + + ); + } } export default TestIframe; TestIframe.propTypes = { - saveTestResultOrProgress: PropTypes.func, - git_hash: PropTypes.string, - file: PropTypes.string, - at_key: PropTypes.string, - serializedForm: PropTypes.array + saveTestResultOrProgress: PropTypes.func, + git_hash: PropTypes.string, + file: PropTypes.string, + at_key: PropTypes.string, + serializedForm: PropTypes.array }; diff --git a/client/components/TestRun/TestNavigator.jsx b/client/components/TestRun/TestNavigator.jsx index 68e99ba36..e7477f92c 100644 --- a/client/components/TestRun/TestNavigator.jsx +++ b/client/components/TestRun/TestNavigator.jsx @@ -1,9 +1,9 @@ import PropTypes from 'prop-types'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { - faAlignLeft, - faArrowLeft, - faArrowRight + faAlignLeft, + faArrowLeft, + faArrowRight } from '@fortawesome/free-solid-svg-icons'; import { Col } from 'react-bootstrap'; import React, { useMemo } from 'react'; @@ -13,160 +13,151 @@ import { COLLECTION_JOB_STATUS_BY_TEST_PLAN_RUN_ID_QUERY } from './queries'; import { useQuery } from '@apollo/client'; const TestNavigator = ({ - show = true, - isSignedIn = false, - viewedTests = [], - isVendor = false, - testPlanReport = {}, - tests = [], - currentTestIndex = 0, - toggleShowClick = () => {}, - handleTestClick = () => {}, - testPlanRun = null + show = true, + isSignedIn = false, + viewedTests = [], + isVendor = false, + testPlanReport = {}, + tests = [], + currentTestIndex = 0, + toggleShowClick = () => {}, + handleTestClick = () => {}, + testPlanRun = null }) => { - const isBotCompletedTest = isBot(testPlanRun?.tester); + const isBotCompletedTest = isBot(testPlanRun?.tester); - const { data: collectionJobQuery } = useQuery( - COLLECTION_JOB_STATUS_BY_TEST_PLAN_RUN_ID_QUERY, - { - variables: { - testPlanRunId: testPlanRun?.id - } - } - ); + const { data: collectionJobQuery } = useQuery( + COLLECTION_JOB_STATUS_BY_TEST_PLAN_RUN_ID_QUERY, + { + variables: { + testPlanRunId: testPlanRun?.id + } + } + ); - const status = useMemo(() => { - return collectionJobQuery?.collectionJobByTestPlanRunId?.status; - }, [collectionJobQuery]); + const status = useMemo(() => { + return collectionJobQuery?.collectionJobByTestPlanRunId?.status; + }, [collectionJobQuery]); - return ( - -
    -

    - -

    -
    - + + ); }; TestNavigator.propTypes = { - show: PropTypes.bool, - isSignedIn: PropTypes.bool, - isVendor: PropTypes.bool, - testPlanReport: PropTypes.object, - tests: PropTypes.array, - testResult: PropTypes.object, - conflicts: PropTypes.object, - currentTestIndex: PropTypes.number, - viewedTests: PropTypes.array, - toggleShowClick: PropTypes.func, - handleTestClick: PropTypes.func, - testPlanRun: PropTypes.object + show: PropTypes.bool, + isSignedIn: PropTypes.bool, + isVendor: PropTypes.bool, + testPlanReport: PropTypes.object, + tests: PropTypes.array, + testResult: PropTypes.object, + conflicts: PropTypes.object, + currentTestIndex: PropTypes.number, + viewedTests: PropTypes.array, + toggleShowClick: PropTypes.func, + handleTestClick: PropTypes.func, + testPlanRun: PropTypes.object }; export default TestNavigator; diff --git a/client/components/TestRun/TestRun.css b/client/components/TestRun/TestRun.css index 25cc521fd..8a7a2452f 100644 --- a/client/components/TestRun/TestRun.css +++ b/client/components/TestRun/TestRun.css @@ -1,322 +1,322 @@ @import url('https://use.fontawesome.com/releases/v5.0.1/css/all.css'); .main-test-area { - position: relative; + position: relative; } /* Test Navigator */ .test-navigator h2 { - margin-top: 0; + margin-top: 0; } #test-navigator-heading { - font-size: 1em; - margin-top: 0.75em; + font-size: 1em; + margin-top: 0.75em; } button.test-navigator-toggle { - border: 0; - background-color: transparent; - color: #929292; + border: 0; + background-color: transparent; + color: #929292; } button.test-navigator-toggle:hover, button.test-navigator-toggle:focus { - color: #0b60ab; + color: #0b60ab; } .test-navigator-toggle-container { - display: flex; - flex-direction: row; + display: flex; + flex-direction: row; } .test-navigator-toggle-inner-container { - width: fit-content; + width: fit-content; } @media all and (max-width: 767px) { - .test-navigator-toggle-inner-container { - position: relative; - top: -0.15em; - } + .test-navigator-toggle-inner-container { + position: relative; + top: -0.15em; + } } @media all and (min-width: 768px) { - .test-navigator-toggle-inner-container { - position: absolute; - top: -0.15em; - left: -2.75em; - } + .test-navigator-toggle-inner-container { + position: absolute; + top: -0.15em; + left: -2.75em; + } } .test-navigator-list { - position: relative; - margin-top: 1em; - font-size: 0.9em; - padding-left: 3.25em; + position: relative; + margin-top: 1em; + font-size: 0.9em; + padding-left: 3.25em; } .test-name-wrapper { - position: relative; - margin: 0 0 1em 0.25em; - list-style: unset; + position: relative; + margin: 0 0 1em 0.25em; + list-style: unset; } .test-name-wrapper:before { - content: ''; - height: 100%; - left: -2.8em; - position: absolute; - top: 1.2em; - background: #d2d5d9; - width: 2px; + content: ''; + height: 100%; + left: -2.8em; + position: absolute; + top: 1.2em; + background: #d2d5d9; + width: 2px; } .test-name-wrapper:last-child:before { - height: 0%; + height: 0%; } .complete.test-name-wrapper:before, .changes-requested.test-name-wrapper:before { - background: #1d8f37; + background: #1d8f37; } .progress-indicator { - position: absolute; - left: -3.35em; - top: 0.2em; - width: 18px; - height: 18px; - border-radius: 50px; + position: absolute; + left: -3.35em; + top: 0.2em; + width: 18px; + height: 18px; + border-radius: 50px; } .test-name-wrapper .test-name { - display: block; - color: #2f2f2f; + display: block; + color: #2f2f2f; } .test-name-wrapper .test-name:hover { - color: #0b60ab; + color: #0b60ab; } .test-navigator a[aria-current='true'] ~ span { - box-shadow: 0px 0px 0px 2px #ffffff, 0px 0px 0px 4px #1d8f37; + box-shadow: 0px 0px 0px 2px #ffffff, 0px 0px 0px 4px #1d8f37; } /* Test States in Test Navigator */ .test-name-wrapper.not-started .progress-indicator { - background: #d2d5d9; + background: #d2d5d9; } .test-name-wrapper.in-progress .progress-indicator { - background: #1e8f37; - background: linear-gradient( - 135deg, - #1e8f37 0%, - #1e8f37 50%, - rgba(255, 255, 255, 1) 50%, - rgba(255, 255, 255, 1) 100% - ); - border: 2px solid #1e8f37; + background: #1e8f37; + background: linear-gradient( + 135deg, + #1e8f37 0%, + #1e8f37 50%, + rgba(255, 255, 255, 1) 50%, + rgba(255, 255, 255, 1) 100% + ); + border: 2px solid #1e8f37; } .test-name-wrapper.changes-requested .progress-indicator { - background: #f87f1c; + background: #f87f1c; } .test-name-wrapper.changes-requested .progress-indicator:before { - position: relative; - content: '\f024'; - font-family: 'Font Awesome 5 Free'; - font-weight: 900; - color: white; - font-size: 10px; - top: -3px; - left: 4px; + position: relative; + content: '\f024'; + font-family: 'Font Awesome 5 Free'; + font-weight: 900; + color: white; + font-size: 10px; + top: -3px; + left: 4px; } .test-name-wrapper.skipped .progress-indicator { - background: White; - border: 2px dashed black; + background: White; + border: 2px dashed black; } .test-name-wrapper.bot-complete .progress-indicator { - background: #1e8f37; + background: #1e8f37; } .test-name-wrapper.bot-complete .progress-indicator:before { - display: inline-block; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - font-family: 'Font Awesome 5 Free'; - font-weight: 900; - content: '\f00c'; - color: white; - font-size: 10px; - position: relative; - top: -3px; - left: 4px; + display: inline-block; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + font-family: 'Font Awesome 5 Free'; + font-weight: 900; + content: '\f00c'; + color: white; + font-size: 10px; + position: relative; + top: -3px; + left: 4px; } .test-name-wrapper.bot-queued .progress-indicator { - background: #295fa6; + background: #295fa6; } .test-name-wrapper.bot-queued .progress-indicator:before { - display: inline-block; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - font-family: 'Font Awesome 5 Free'; - font-weight: 900; - content: '\f061'; - color: white; - font-size: 10px; - position: relative; - top: -3px; - left: 4px; + display: inline-block; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + font-family: 'Font Awesome 5 Free'; + font-weight: 900; + content: '\f061'; + color: white; + font-size: 10px; + position: relative; + top: -3px; + left: 4px; } .test-name-wrapper.bot-cancelled .progress-indicator { - background: #a331fe; + background: #a331fe; } .test-name-wrapper.bot-cancelled .progress-indicator:before { - display: inline-block; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - font-family: 'Font Awesome 5 Free'; - font-weight: 900; - content: '\f05e'; - color: white; - font-size: 10px; - position: relative; - top: -3px; - left: 4px; + display: inline-block; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + font-family: 'Font Awesome 5 Free'; + font-weight: 900; + content: '\f05e'; + color: white; + font-size: 10px; + position: relative; + top: -3px; + left: 4px; } .test-name-wrapper.conflicts .progress-indicator { - background: #ffcd00; + background: #ffcd00; } .test-name-wrapper.conflicts .progress-indicator:before, .test-name-wrapper.conflicts .progress-indicator:after { - content: ''; - position: absolute; - background: #976005; - width: 2px; - left: 8px; + content: ''; + position: absolute; + background: #976005; + width: 2px; + left: 8px; } .test-name-wrapper.conflicts .progress-indicator:before { - top: 3px; - height: 7px; + top: 3px; + height: 7px; } .test-name-wrapper.conflicts .progress-indicator:after { - top: 12px; - height: 2px; + top: 12px; + height: 2px; } .test-name-wrapper.complete .progress-indicator { - background: #1e8f37; + background: #1e8f37; } .test-name-wrapper.complete .progress-indicator:before, .test-name-wrapper.complete .progress-indicator:after { - content: ''; - position: absolute; - background: white; - -ms-transform: rotate(45deg); /* IE 9 */ - -webkit-transform: rotate(45deg); /* Chrome, Safari, Opera */ - transform: rotate(45deg); + content: ''; + position: absolute; + background: white; + -ms-transform: rotate(45deg); /* IE 9 */ + -webkit-transform: rotate(45deg); /* Chrome, Safari, Opera */ + transform: rotate(45deg); } .test-name-wrapper.complete .progress-indicator:before { - width: 4px; - height: 3px; - top: 8px; - left: 4px; + width: 4px; + height: 3px; + top: 8px; + left: 4px; } .test-name-wrapper.complete .progress-indicator:after { - width: 3px; - height: 9px; - top: 5px; - left: 9px; + width: 3px; + height: 9px; + top: 5px; + left: 9px; } .test-iframe-container { - padding: 0; + padding: 0; } main.container-fluid .test-iframe-container > .row { - padding-top: 0; + padding-top: 0; } #test-iframe { - width: 80vw; - height: 65vh; - border: 1px solid #d2d5d9; - border-radius: 3px; - padding: 0 1em; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, - 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', - 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; + width: 80vw; + height: 65vh; + border: 1px solid #d2d5d9; + border-radius: 3px; + padding: 0 1em; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, + 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', + 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; } .test-run-toolbar { - display: flex; - width: 100%; + display: flex; + width: 100%; - padding-left: 0; - padding-right: 0; + padding-left: 0; + padding-right: 0; } .test-run-toolbar li:first-of-type { - flex-grow: 1; + flex-grow: 1; } .test-run-toolbar li:last-of-type { - padding-right: 0; + padding-right: 0; } .dot { - height: 10px; - width: 10px; - background-color: #6bda84; - border-radius: 50%; - display: inline-block; + height: 10px; + width: 10px; + background-color: #6bda84; + border-radius: 50%; + display: inline-block; } .test-navigator a[aria-current='true'] { - color: black; - font-weight: bold; + color: black; + font-weight: bold; } .test-navigator a[aria-current='true']:hover { - text-decoration: none; - color: black; + text-decoration: none; + color: black; } /* Test Headings and information */ .task-label { - display: block; - font-size: 0.6em; - font-weight: normal; - border-radius: 3px; + display: block; + font-size: 0.6em; + font-weight: normal; + border-radius: 3px; } .test-info-wrapper { - display: flex; - flex-direction: row; - justify-content: space-between; - flex-wrap: wrap; + display: flex; + flex-direction: row; + justify-content: space-between; + flex-wrap: wrap; - padding: 0; + padding: 0; } .test-info-entity { - padding: 0.5em 0.75em; - border-radius: 3px; - margin-bottom: 1em; - font-size: 0.9em; + padding: 0.5em 0.75em; + border-radius: 3px; + margin-bottom: 1em; + font-size: 0.9em; } .apg-example-name, @@ -324,156 +324,156 @@ main.container-fluid .test-iframe-container > .row { .test-version, .review-status, .target-date { - background: #f5f8fa; - border: 1px solid #d2d5d9; - width: 37%; - text-align: center; + background: #f5f8fa; + border: 1px solid #d2d5d9; + width: 37%; + text-align: center; } .at-browser { - display: flex; - flex-direction: row; - align-items: flex-start; + display: flex; + flex-direction: row; + align-items: flex-start; - background: #f5f8fa; - border: 1px solid #d2d5d9; - width: 37%; - /*text-align: center;*/ + background: #f5f8fa; + border: 1px solid #d2d5d9; + width: 37%; + /*text-align: center;*/ } .at-browser-row { - width: 100%; - display: flex; - flex-direction: column; - align-items: flex-start; - justify-content: space-between; + width: 100%; + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: space-between; } #edit-fa-button { - padding: 0; - margin: 0; - background: none; - color: #919191; - border: none; + padding: 0; + margin: 0; + background: none; + color: #919191; + border: none; } #edit-fa-button svg { - padding: 0; - margin: 0; + padding: 0; + margin: 0; } .tests-completed { - width: 23.5%; + width: 23.5%; } .reviewing-as { - background: #ecf6ff; - border: 1px solid #c4d1e2; - width: 100%; + background: #ecf6ff; + border: 1px solid #c4d1e2; + width: 100%; } .reviewing-as p { - margin: 0; - font-style: italic; - margin-left: 0.5em; - display: inline-block; + margin: 0; + font-style: italic; + margin-left: 0.5em; + display: inline-block; } .reviewing-as.bot { - background: #f0e1ff; - border: 1px solid #d29fff; + background: #f0e1ff; + border: 1px solid #d29fff; } /* Current Test Options */ .current-test-options { - padding-right: 0; + padding-right: 0; } .current-test-options > div { - background: #f5f8fa; - border: 1px solid #d2d5d9; - border-radius: 3px; + background: #f5f8fa; + border: 1px solid #d2d5d9; + border-radius: 3px; } .current-test-options h2 { - margin-top: 0; - padding: 0.9em; - background: #e9ebee; - font-size: 1em; - font-weight: 700; - border-bottom: 1px solid #d2d5d9; - text-align: center; + margin-top: 0; + padding: 0.9em; + background: #e9ebee; + font-size: 1em; + font-weight: 700; + border-bottom: 1px solid #d2d5d9; + text-align: center; } .current-test-options .options-wrapper { - padding: 0.05em 0.75em; + padding: 0.05em 0.75em; } .help-link { - font-size: 0.9em; - text-align: center; - padding-top: 0.7em; + font-size: 0.9em; + text-align: center; + padding-top: 0.7em; } .fa-exclamation-circle, .fa-redo, .fa-pen, .fa-external-link-alt { - color: #959595; + color: #959595; } .fa-check { - color: #1e8f37; + color: #1e8f37; } .status-bar { - display: flex; - align-items: center; + display: flex; + align-items: center; } .at-browser-details-modal-alert { - display: flex; + display: flex; - grid-column: 1 / -1; + grid-column: 1 / -1; } fieldset .at-browser-details-modal-alert { - margin-bottom: 0; + margin-bottom: 0; } .btn-options { - width: 100%; + width: 100%; } a.btn-options:hover { - text-decoration: none; + text-decoration: none; } .at-browser-details-modal-alert span { - font-size: 0.875rem; - line-height: 1.125rem; + font-size: 0.875rem; + line-height: 1.125rem; } .at-browser-details-full-column { - grid-column: 1 / -1; + grid-column: 1 / -1; } .modal-header, .modal-body, .modal-footer { - padding: 1.5rem 2.5rem; + padding: 1.5rem 2.5rem; } @media (min-width: 768px) { - .modal-50w { - min-width: 50%; - } + .modal-50w { + min-width: 50%; + } - .modal-60w { - min-width: 60%; - } + .modal-60w { + min-width: 60%; + } } .form-control.is-invalid { - background-image: none; + background-image: none; } diff --git a/client/components/TestRun/index.jsx b/client/components/TestRun/index.jsx index 531c71a46..7b6fd865a 100644 --- a/client/components/TestRun/index.jsx +++ b/client/components/TestRun/index.jsx @@ -5,13 +5,13 @@ import useRouterQuery from '../../hooks/useRouterQuery'; import { useMutation, useQuery } from '@apollo/client'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { - faPen, - faEdit, - faRedo, - faCheck, - faCheckCircle, - faExclamationCircle, - faRobot + faPen, + faEdit, + faRedo, + faCheck, + faCheckCircle, + faExclamationCircle, + faRobot } from '@fortawesome/free-solid-svg-icons'; import nextId from 'react-id-generator'; import { Alert, Button, Col, Container, Row } from 'react-bootstrap'; @@ -28,14 +28,14 @@ import { useDetectUa } from '../../hooks/useDetectUa'; import DisplayNone from '../../utils/DisplayNone'; import { navigateTests } from '../../utils/navigateTests'; import { - COLLECTION_JOB_STATUS_BY_TEST_PLAN_RUN_ID_QUERY, - DELETE_TEST_RESULT_MUTATION, - FIND_OR_CREATE_BROWSER_VERSION_MUTATION, - FIND_OR_CREATE_TEST_RESULT_MUTATION, - SAVE_TEST_RESULT_MUTATION, - SUBMIT_TEST_RESULT_MUTATION, - TEST_RUN_PAGE_ANON_QUERY, - TEST_RUN_PAGE_QUERY + COLLECTION_JOB_STATUS_BY_TEST_PLAN_RUN_ID_QUERY, + DELETE_TEST_RESULT_MUTATION, + FIND_OR_CREATE_BROWSER_VERSION_MUTATION, + FIND_OR_CREATE_TEST_RESULT_MUTATION, + SAVE_TEST_RESULT_MUTATION, + SUBMIT_TEST_RESULT_MUTATION, + TEST_RUN_PAGE_ANON_QUERY, + TEST_RUN_PAGE_QUERY } from './queries'; import { evaluateAuth } from '../../utils/evaluateAuth'; import './TestRun.css'; @@ -45,1358 +45,1290 @@ import { convertDateToString } from '../../utils/formatter'; import { isBot } from '../../utils/automation'; const TestRun = () => { - const params = useParams(); - const navigate = useNavigate(); - const routerQuery = useRouterQuery(); - - // Detect UA information - const { uaBrowser, uaMajor, uaMinor, uaPatch } = useDetectUa(); - - const titleRef = useRef(); - // To prevent default AT/Browser versions being set before initial - // AT & Browser Details Modal is saved - const testRunStateRef = useRef(); - // HACK: Temporary fix to allow for consistency of TestRenderer after - // testRunStateRef is nullified during unmount. - // See 'unmount' of 'pageContent' hook in the TestRenderer component - const recentTestRunStateRef = useRef(); - const testRunResultRef = useRef(); - const testRendererSubmitButtonRef = useRef(); - const conflictMarkdownRef = useRef(); - const adminReviewerCheckedRef = useRef(false); - const adminReviewerOriginalTestRef = useRef(); - const editAtBrowserDetailsButtonRef = useRef(); - - const { runId: testPlanRunId, testPlanReportId } = params; - - const { loading, data, error } = useQuery( - testPlanRunId ? TEST_RUN_PAGE_QUERY : TEST_RUN_PAGE_ANON_QUERY, - { - fetchPolicy: 'cache-and-network', - variables: { testPlanRunId, testPlanReportId } - } - ); - - const { data: collectionJobQuery } = useQuery( - COLLECTION_JOB_STATUS_BY_TEST_PLAN_RUN_ID_QUERY, - { - variables: { testPlanRunId }, - fetchPolicy: 'cache-and-network' - } - ); + const params = useParams(); + const navigate = useNavigate(); + const routerQuery = useRouterQuery(); + + // Detect UA information + const { uaBrowser, uaMajor, uaMinor, uaPatch } = useDetectUa(); + + const titleRef = useRef(); + // To prevent default AT/Browser versions being set before initial + // AT & Browser Details Modal is saved + const testRunStateRef = useRef(); + // HACK: Temporary fix to allow for consistency of TestRenderer after + // testRunStateRef is nullified during unmount. + // See 'unmount' of 'pageContent' hook in the TestRenderer component + const recentTestRunStateRef = useRef(); + const testRunResultRef = useRef(); + const testRendererSubmitButtonRef = useRef(); + const conflictMarkdownRef = useRef(); + const adminReviewerCheckedRef = useRef(false); + const adminReviewerOriginalTestRef = useRef(); + const editAtBrowserDetailsButtonRef = useRef(); + + const { runId: testPlanRunId, testPlanReportId } = params; + + const { loading, data, error } = useQuery( + testPlanRunId ? TEST_RUN_PAGE_QUERY : TEST_RUN_PAGE_ANON_QUERY, + { + fetchPolicy: 'cache-and-network', + variables: { testPlanRunId, testPlanReportId } + } + ); - const [createTestResult, { loading: createTestResultLoading }] = - useMutation(FIND_OR_CREATE_TEST_RESULT_MUTATION); - const [saveTestResult] = useMutation(SAVE_TEST_RESULT_MUTATION); - const [submitTestResult] = useMutation(SUBMIT_TEST_RESULT_MUTATION); - const [deleteTestResult] = useMutation(DELETE_TEST_RESULT_MUTATION); - const [createBrowserVersion] = useMutation( - FIND_OR_CREATE_BROWSER_VERSION_MUTATION - ); + const { data: collectionJobQuery } = useQuery( + COLLECTION_JOB_STATUS_BY_TEST_PLAN_RUN_ID_QUERY, + { + variables: { testPlanRunId }, + fetchPolicy: 'cache-and-network' + } + ); + + const [createTestResult, { loading: createTestResultLoading }] = useMutation( + FIND_OR_CREATE_TEST_RESULT_MUTATION + ); + const [saveTestResult] = useMutation(SAVE_TEST_RESULT_MUTATION); + const [submitTestResult] = useMutation(SUBMIT_TEST_RESULT_MUTATION); + const [deleteTestResult] = useMutation(DELETE_TEST_RESULT_MUTATION); + const [createBrowserVersion] = useMutation( + FIND_OR_CREATE_BROWSER_VERSION_MUTATION + ); + + const [isRendererReady, setIsRendererReady] = useState(false); + const [isSavingForm, setIsSavingForm] = useState(false); + const [isTestSubmitClicked, setIsTestSubmitClicked] = useState(false); + const [isTestEditClicked, setIsTestEditClicked] = useState(false); + const [showTestNavigator, setShowTestNavigator] = useState(true); + const [showStartOverModal, setShowStartOverModal] = useState(false); + const [showReviewConflictsModal, setShowReviewConflictsModal] = + useState(false); + const [showGetInvolvedModal, setShowGetInvolvedModal] = useState(false); + + // Modal State Values + const [isShowingAtBrowserModal, setIsShowingAtBrowserModal] = useState(true); + const [showThemedModal, setShowThemedModal] = useState(false); + const [themedModalTitle, setThemedModalTitle] = useState(''); + const [themedModalContent, setThemedModalContent] = useState(<>); + const [themedModalOtherButton, setThemedModalOtherButton] = useState(null); + const [isEditAtBrowserDetailsModalClick, setIsEditAtBrowserDetailsClicked] = + useState(false); + const [updateMessageComponent, setUpdateMessageComponent] = useState(null); + + // Queried State Values + const [testPlanRun, setTestPlanRun] = useState({}); + const [users, setUsers] = useState([]); + const [tester, setTester] = useState(); + const [tests, setTests] = useState([]); + const [testResults, setTestResults] = useState([]); + const [testPlanReport, setTestPlanReport] = useState({}); + const [testPlanVersion, setTestPlanVersion] = useState(); + const [currentTest, setCurrentTest] = useState({}); + const [currentTestIndex, setCurrentTestIndex] = useState(0); + const [currentTestAtVersionId, setCurrentTestAtVersionId] = useState(''); + const [currentTestBrowserVersionId, setCurrentTestBrowserVersionId] = + useState(''); + const [currentAtVersion, setCurrentAtVersion] = useState(''); + const [currentBrowserVersion, setCurrentBrowserVersion] = useState(''); + const [pageReady, setPageReady] = useState(false); + + const auth = evaluateAuth(data && data.me ? data.me : {}); + let { id: userId, isSignedIn, isAdmin } = auth; + + // if a signed in user navigates to this page, treat them as anon to prevent + // invalid save attempts + if (testPlanReportId) isSignedIn = false; + + // check to ensure an admin that manually went to a test run url doesn't + // run the test as themselves + const openAsUserId = + routerQuery.get('user') || (tester && tester.id !== userId) + ? tester?.id + : null; + const testerId = openAsUserId || userId; + const isAdminReviewer = !!(isAdmin && openAsUserId); + const openAsUser = users?.find(user => user.id === openAsUserId); + + useEffect(() => { + if (data) setup(data); + }, [data]); + + useEffect(() => { + reset(); + + // Set up for the current test + const currentTest = tests[currentTestIndex]; + if (currentTest) { + setPageReady(false); + if (isSignedIn) { + (async () => { + const { testPlanRun, testPlanReport } = + await createTestResultForRenderer( + currentTest.id, + currentTestAtVersionId, + currentTestBrowserVersionId + ); + updateLocalState(testPlanRun, testPlanReport); + setPageReady(true); + })(); + } else { + // To account for ANON viewing + setCurrentTest(tests[currentTestIndex]); + setPageReady(true); + } + } else if (data) setup(data); + }, [currentTestIndex]); - const [isRendererReady, setIsRendererReady] = useState(false); - const [isSavingForm, setIsSavingForm] = useState(false); - const [isTestSubmitClicked, setIsTestSubmitClicked] = useState(false); - const [isTestEditClicked, setIsTestEditClicked] = useState(false); - const [showTestNavigator, setShowTestNavigator] = useState(true); - const [showStartOverModal, setShowStartOverModal] = useState(false); - const [showReviewConflictsModal, setShowReviewConflictsModal] = - useState(false); - const [showGetInvolvedModal, setShowGetInvolvedModal] = useState(false); - - // Modal State Values - const [isShowingAtBrowserModal, setIsShowingAtBrowserModal] = - useState(true); - const [showThemedModal, setShowThemedModal] = useState(false); - const [themedModalTitle, setThemedModalTitle] = useState(''); - const [themedModalContent, setThemedModalContent] = useState(<>); - const [themedModalOtherButton, setThemedModalOtherButton] = useState(null); - const [isEditAtBrowserDetailsModalClick, setIsEditAtBrowserDetailsClicked] = - useState(false); - const [updateMessageComponent, setUpdateMessageComponent] = useState(null); - - // Queried State Values - const [testPlanRun, setTestPlanRun] = useState({}); - const [users, setUsers] = useState([]); - const [tester, setTester] = useState(); - const [tests, setTests] = useState([]); - const [testResults, setTestResults] = useState([]); - const [testPlanReport, setTestPlanReport] = useState({}); - const [testPlanVersion, setTestPlanVersion] = useState(); - const [currentTest, setCurrentTest] = useState({}); - const [currentTestIndex, setCurrentTestIndex] = useState(0); - const [currentTestAtVersionId, setCurrentTestAtVersionId] = useState(''); - const [currentTestBrowserVersionId, setCurrentTestBrowserVersionId] = - useState(''); - const [currentAtVersion, setCurrentAtVersion] = useState(''); - const [currentBrowserVersion, setCurrentBrowserVersion] = useState(''); - const [pageReady, setPageReady] = useState(false); - - const auth = evaluateAuth(data && data.me ? data.me : {}); - let { id: userId, isSignedIn, isAdmin } = auth; + const setup = data => { + const { testPlanRun, users } = data; + const { tester, testResults = [] } = testPlanRun || {}; + let { testPlanReport } = testPlanRun || {}; // if a signed in user navigates to this page, treat them as anon to prevent // invalid save attempts if (testPlanReportId) isSignedIn = false; + if (!isSignedIn) testPlanReport = data.testPlanReport; + + const { + testPlanVersion, + runnableTests = [], + conflicts = [] + } = testPlanReport || {}; + + const tests = runnableTests.map((test, index) => ({ + ...test, + index, + seq: index + 1, + testResult: testResults.find(t => t.test.id === test.id), + hasConflicts: !!conflicts.find(c => c.source.test.id === test.id) + })); + const currentTest = tests[currentTestIndex]; + + // Capture the AT & Browser Versions + const defaultAtVersionId = testPlanReport.at.atVersions[0].id; + const defaultBrowserVersionId = + testPlanReport.browser.browserVersions[0].id; + + const currentTestAtVersionId = + currentTest.testResult?.atVersion?.id || defaultAtVersionId; + + const currentTestBrowserVersionId = + currentTest.testResult?.browserVersion?.id || defaultBrowserVersionId; + + const currentAtVersion = + currentTest.testResult?.atVersion || + testPlanReport.at.atVersions.find( + item => item.id === currentTestAtVersionId + ) || + 'N/A'; + + const currentBrowserVersion = + currentTest.testResult?.browserVersion || + testPlanReport.browser.browserVersions.find( + item => item.id === currentTestBrowserVersionId + ) || + 'N/A'; + + // Auto batch the states + setUsers(users); + setTester(tester); + setTestPlanRun(testPlanRun); + setTestPlanReport(testPlanReport); + setTestPlanVersion(testPlanVersion); + setTests(tests); + setTestResults(testResults); + setCurrentTest(currentTest); + setCurrentTestAtVersionId(currentTestAtVersionId); + setCurrentTestBrowserVersionId(currentTestBrowserVersionId); + setCurrentAtVersion(currentAtVersion); + setCurrentBrowserVersion(currentBrowserVersion); + // Testers do not need to change AT/Browser versions + // while assigning verdicts for previously automated tests + if (testPlanRun?.initiatedByAutomation) { + setIsShowingAtBrowserModal(false); + } + setPageReady(true); + }; + + const reset = () => { + testRunStateRef.current = null; + recentTestRunStateRef.current = null; + testRunResultRef.current = null; + conflictMarkdownRef.current = null; + + setPageReady(false); + setIsRendererReady(false); + setIsTestSubmitClicked(false); + + if (titleRef.current) titleRef.current.focus(); + }; + + const updateLocalState = (updatedTestPlanRun, updatedTestPlanReport) => { + const { conflicts, runnableTests } = updatedTestPlanReport; + + const testResults = updatedTestPlanRun.testResults; + const tests = runnableTests.map((test, index) => ({ + ...test, + index, + seq: index + 1, + testResult: testResults.find(t => t.test.id === test.id), + hasConflicts: !!conflicts.find(c => c.source.test.id === test.id) + })); + + setTests(tests); + setTestResults(testResults); + setCurrentTest(tests[currentTestIndex]); + setTestPlanReport({ ...testPlanReport, conflicts }); + }; + + if (error) { + const { message } = error; + return ( + + ); + } - // check to ensure an admin that manually went to a test run url doesn't - // run the test as themselves - const openAsUserId = - routerQuery.get('user') || (tester && tester.id !== userId) - ? tester?.id - : null; - const testerId = openAsUserId || userId; - const isAdminReviewer = !!(isAdmin && openAsUserId); - const openAsUser = users?.find(user => user.id === openAsUserId); - - useEffect(() => { - if (data) setup(data); - }, [data]); - - useEffect(() => { - reset(); - - // Set up for the current test - const currentTest = tests[currentTestIndex]; - if (currentTest) { - setPageReady(false); - if (isSignedIn) { - (async () => { - const { testPlanRun, testPlanReport } = - await createTestResultForRenderer( - currentTest.id, - currentTestAtVersionId, - currentTestBrowserVersionId - ); - updateLocalState(testPlanRun, testPlanReport); - setPageReady(true); - })(); - } else { - // To account for ANON viewing - setCurrentTest(tests[currentTestIndex]); - setPageReady(true); - } - } else if (data) setup(data); - }, [currentTestIndex]); - - const setup = data => { - const { testPlanRun, users } = data; - const { tester, testResults = [] } = testPlanRun || {}; - let { testPlanReport } = testPlanRun || {}; - - // if a signed in user navigates to this page, treat them as anon to prevent - // invalid save attempts - if (testPlanReportId) isSignedIn = false; - if (!isSignedIn) testPlanReport = data.testPlanReport; - - const { - testPlanVersion, - runnableTests = [], - conflicts = [] - } = testPlanReport || {}; - - const tests = runnableTests.map((test, index) => ({ - ...test, - index, - seq: index + 1, - testResult: testResults.find(t => t.test.id === test.id), - hasConflicts: !!conflicts.find(c => c.source.test.id === test.id) - })); - const currentTest = tests[currentTestIndex]; - - // Capture the AT & Browser Versions - const defaultAtVersionId = testPlanReport.at.atVersions[0].id; - const defaultBrowserVersionId = - testPlanReport.browser.browserVersions[0].id; - - const currentTestAtVersionId = - currentTest.testResult?.atVersion?.id || defaultAtVersionId; - - const currentTestBrowserVersionId = - currentTest.testResult?.browserVersion?.id || - defaultBrowserVersionId; - - const currentAtVersion = - currentTest.testResult?.atVersion || - testPlanReport.at.atVersions.find( - item => item.id === currentTestAtVersionId - ) || - 'N/A'; - - const currentBrowserVersion = - currentTest.testResult?.browserVersion || - testPlanReport.browser.browserVersions.find( - item => item.id === currentTestBrowserVersionId - ) || - 'N/A'; - - // Auto batch the states - setUsers(users); - setTester(tester); - setTestPlanRun(testPlanRun); - setTestPlanReport(testPlanReport); - setTestPlanVersion(testPlanVersion); - setTests(tests); - setTestResults(testResults); - setCurrentTest(currentTest); - setCurrentTestAtVersionId(currentTestAtVersionId); - setCurrentTestBrowserVersionId(currentTestBrowserVersionId); - setCurrentAtVersion(currentAtVersion); - setCurrentBrowserVersion(currentBrowserVersion); - // Testers do not need to change AT/Browser versions - // while assigning verdicts for previously automated tests - if (testPlanRun?.initiatedByAutomation) { - setIsShowingAtBrowserModal(false); - } - setPageReady(true); - }; - - const reset = () => { - testRunStateRef.current = null; - recentTestRunStateRef.current = null; - testRunResultRef.current = null; - conflictMarkdownRef.current = null; - - setPageReady(false); - setIsRendererReady(false); - setIsTestSubmitClicked(false); - - if (titleRef.current) titleRef.current.focus(); - }; - - const updateLocalState = (updatedTestPlanRun, updatedTestPlanReport) => { - const { conflicts, runnableTests } = updatedTestPlanReport; - - const testResults = updatedTestPlanRun.testResults; - const tests = runnableTests.map((test, index) => ({ - ...test, - index, - seq: index + 1, - testResult: testResults.find(t => t.test.id === test.id), - hasConflicts: !!conflicts.find(c => c.source.test.id === test.id) - })); - - setTests(tests); - setTestResults(testResults); - setCurrentTest(tests[currentTestIndex]); - setTestPlanReport({ ...testPlanReport, conflicts }); - }; + if (!data || loading || createTestResultLoading || isSavingForm) { + return ( + + ); + } - if (error) { - const { message } = error; - return ( - - ); + if (isSignedIn && !testPlanRun) { + return ( + + ); + } + + const toggleTestNavigator = () => setShowTestNavigator(!showTestNavigator); + + const createTestResultForRenderer = async ( + testId, + atVersionId, + browserVersionId + ) => { + const result = await createTestResult({ + variables: { + testPlanRunId, + testId, + atVersionId, + browserVersionId + } + }); + return result.data.testPlanRun.findOrCreateTestResult; + }; + + // Check to see if there are tests to run + const hasTestsToRun = tests.length; + + // Check if this test is being run as an admin + if ( + adminReviewerOriginalTestRef.current && + adminReviewerOriginalTestRef.current !== currentTest.id + ) + adminReviewerCheckedRef.current = false; + + if ( + isAdminReviewer && + currentTest.testResult && + !adminReviewerCheckedRef.current + ) + adminReviewerOriginalTestRef.current = currentTest; + + adminReviewerCheckedRef.current = true; + + let issueLink; + const hasLoadingCompleted = Object.keys(currentTest).length; + if (hasLoadingCompleted) { + issueLink = createIssueLink({ + testPlanTitle: testPlanVersion.title, + testPlanDirectory: testPlanVersion.testPlan.directory, + versionString: `V${convertDateToString( + testPlanVersion.updatedAt, + 'YY.MM.DD' + )}`, + testTitle: currentTest.title, + testRowNumber: currentTest.rowNumber, + testRenderedUrl: currentTest.renderedUrl, + atName: testPlanReport.at.name, + browserName: testPlanReport.browser.name, + atVersionName: currentAtVersion?.name, + browserVersionName: currentBrowserVersion?.name, + conflictMarkdown: conflictMarkdownRef.current + }); + } + + const remapScenarioResults = ( + rendererState, + scenarioResults, + captureHighlightRequired = false + ) => { + let newScenarioResults = []; + if (!rendererState || !scenarioResults) { + throw new Error( + `Unable to merge invalid results:rendererState:${rendererState} | scenarioResults:${scenarioResults}` + ); } - if (!data || loading || createTestResultLoading || isSavingForm) { - return ( - - ); + const { commands } = rendererState; + if (!commands || commands.length !== scenarioResults.length) { + throw new Error( + `Unable to merge invalid results:commands:${commands} | commands.length !== scenarioResults.length:${ + commands.length !== scenarioResults.length + }` + ); } - if (isSignedIn && !testPlanRun) { - return ( - + const UnexpectedBehaviorsArray = [ + 'EXCESSIVELY_VERBOSE', + 'UNEXPECTED_CURSOR_POSITION', + 'SLUGGISH', + 'AT_CRASHED', + 'BROWSER_CRASHED', + 'OTHER' + ]; + + for (let i = 0; i < commands.length; i++) { + let scenarioResult = { ...scenarioResults[i] }; + let assertionResults = []; + let unexpectedBehaviors = null; + + // collect variables + const { atOutput, assertions, unexpected } = commands[i]; + + // process assertion results + for (let j = 0; j < assertions.length; j++) { + const { description, result, highlightRequired } = assertions[j]; + const assertionResult = { + ...scenarioResult.assertionResults.find( + ({ assertion: { text } }) => text === description + ), + passed: result === 'pass' + }; + assertionResults.push( + captureHighlightRequired + ? { ...assertionResult, highlightRequired } + : assertionResult ); + } + + // process unexpected behaviors + const { hasUnexpected, behaviors, highlightRequired } = unexpected; + if (hasUnexpected === 'hasUnexpected') { + unexpectedBehaviors = []; + /** + * 0 = EXCESSIVELY_VERBOSE + * 1 = UNEXPECTED_CURSOR_POSITION + * 2 = SLUGGISH + * 3 = AT_CRASHED + * 4 = BROWSER_CRASHED + * 5 = OTHER + */ + for (let i = 0; i < behaviors.length; i++) { + const behavior = behaviors[i]; + if (behavior.checked) { + unexpectedBehaviors.push({ + id: UnexpectedBehaviorsArray[i], + text: behavior.description, + details: behavior.more.value, + impact: behavior.impact.toUpperCase(), + highlightRequired: captureHighlightRequired + ? behavior.more.highlightRequired + : false + }); + } + } + } else if (hasUnexpected === 'doesNotHaveUnexpected') + unexpectedBehaviors = []; + + // re-assign scenario result due to read only values + scenarioResult.output = atOutput.value ? atOutput.value : null; + if (captureHighlightRequired) + scenarioResult.highlightRequired = atOutput.highlightRequired; + scenarioResult.assertionResults = [...assertionResults]; + scenarioResult.unexpectedBehaviors = unexpectedBehaviors + ? [...unexpectedBehaviors] + : null; + if (captureHighlightRequired) + scenarioResult.unexpectedBehaviorHighlightRequired = highlightRequired; + + newScenarioResults.push(scenarioResult); } - const toggleTestNavigator = () => setShowTestNavigator(!showTestNavigator); - - const createTestResultForRenderer = async ( - testId, - atVersionId, - browserVersionId - ) => { - const result = await createTestResult({ - variables: { - testPlanRunId, - testId, - atVersionId, - browserVersionId - } - }); - return result.data.testPlanRun.findOrCreateTestResult; - }; - - // Check to see if there are tests to run - const hasTestsToRun = tests.length; + return newScenarioResults; + }; - // Check if this test is being run as an admin + const remapState = (rendererState, testResult) => { if ( - adminReviewerOriginalTestRef.current && - adminReviewerOriginalTestRef.current !== currentTest.id + !rendererState || + !testResult.scenarioResults || + rendererState.commands.length !== testResult.scenarioResults.length ) - adminReviewerCheckedRef.current = false; - - if ( - isAdminReviewer && - currentTest.testResult && - !adminReviewerCheckedRef.current - ) - adminReviewerOriginalTestRef.current = currentTest; - - adminReviewerCheckedRef.current = true; - - let issueLink; - const hasLoadingCompleted = Object.keys(currentTest).length; - if (hasLoadingCompleted) { - issueLink = createIssueLink({ - testPlanTitle: testPlanVersion.title, - testPlanDirectory: testPlanVersion.testPlan.directory, - versionString: `V${convertDateToString( - testPlanVersion.updatedAt, - 'YY.MM.DD' - )}`, - testTitle: currentTest.title, - testRowNumber: currentTest.rowNumber, - testRenderedUrl: currentTest.renderedUrl, - atName: testPlanReport.at.name, - browserName: testPlanReport.browser.name, - atVersionName: currentAtVersion?.name, - browserVersionName: currentBrowserVersion?.name, - conflictMarkdown: conflictMarkdownRef.current - }); - } + return testResult; - const remapScenarioResults = ( - rendererState, - scenarioResults, - captureHighlightRequired = false + const scenarioResults = remapScenarioResults( + rendererState, + testResult.scenarioResults, + true + ); + return { ...testResult, scenarioResults }; + }; + + const performButtonAction = async (action, index) => { + // TODO: Revise function + const saveForm = async ( + withResult = false, + forceSave = false, + forceEdit = false ) => { - let newScenarioResults = []; - if (!rendererState || !scenarioResults) { - throw new Error( - `Unable to merge invalid results:rendererState:${rendererState} | scenarioResults:${scenarioResults}` - ); - } + try { + if (forceEdit) setIsTestEditClicked(true); + else setIsTestEditClicked(false); - const { commands } = rendererState; - if (!commands || commands.length !== scenarioResults.length) { - throw new Error( - `Unable to merge invalid results:commands:${commands} | commands.length !== scenarioResults.length:${ - commands.length !== scenarioResults.length - }` - ); - } - - const UnexpectedBehaviorsArray = [ - 'EXCESSIVELY_VERBOSE', - 'UNEXPECTED_CURSOR_POSITION', - 'SLUGGISH', - 'AT_CRASHED', - 'BROWSER_CRASHED', - 'OTHER' - ]; - - for (let i = 0; i < commands.length; i++) { - let scenarioResult = { ...scenarioResults[i] }; - let assertionResults = []; - let unexpectedBehaviors = null; - - // collect variables - const { atOutput, assertions, unexpected } = commands[i]; - - // process assertion results - for (let j = 0; j < assertions.length; j++) { - const { description, result, highlightRequired } = - assertions[j]; - const assertionResult = { - ...scenarioResult.assertionResults.find( - ({ assertion: { text } }) => text === description - ), - passed: result === 'pass' - }; - assertionResults.push( - captureHighlightRequired - ? { ...assertionResult, highlightRequired } - : assertionResult - ); - } - - // process unexpected behaviors - const { hasUnexpected, behaviors, highlightRequired } = unexpected; - if (hasUnexpected === 'hasUnexpected') { - unexpectedBehaviors = []; - /** - * 0 = EXCESSIVELY_VERBOSE - * 1 = UNEXPECTED_CURSOR_POSITION - * 2 = SLUGGISH - * 3 = AT_CRASHED - * 4 = BROWSER_CRASHED - * 5 = OTHER - */ - for (let i = 0; i < behaviors.length; i++) { - const behavior = behaviors[i]; - if (behavior.checked) { - unexpectedBehaviors.push({ - id: UnexpectedBehaviorsArray[i], - text: behavior.description, - details: behavior.more.value, - impact: behavior.impact.toUpperCase(), - highlightRequired: captureHighlightRequired - ? behavior.more.highlightRequired - : false - }); - } - } - } else if (hasUnexpected === 'doesNotHaveUnexpected') - unexpectedBehaviors = []; - - // re-assign scenario result due to read only values - scenarioResult.output = atOutput.value ? atOutput.value : null; - if (captureHighlightRequired) - scenarioResult.highlightRequired = atOutput.highlightRequired; - scenarioResult.assertionResults = [...assertionResults]; - scenarioResult.unexpectedBehaviors = unexpectedBehaviors - ? [...unexpectedBehaviors] - : null; - if (captureHighlightRequired) - scenarioResult.unexpectedBehaviorHighlightRequired = - highlightRequired; - - newScenarioResults.push(scenarioResult); - } - - return newScenarioResults; - }; - - const remapState = (rendererState, testResult) => { - if ( - !rendererState || - !testResult.scenarioResults || - rendererState.commands.length !== testResult.scenarioResults.length - ) - return testResult; + if (!isSignedIn) return true; + if (!forceEdit && currentTest.testResult?.completedAt) return true; + setIsSavingForm(true); const scenarioResults = remapScenarioResults( - rendererState, - testResult.scenarioResults, - true + testRunStateRef.current || recentTestRunStateRef.current, + currentTest.testResult?.scenarioResults, + false ); - return { ...testResult, scenarioResults }; - }; - const performButtonAction = async (action, index) => { - // TODO: Revise function - const saveForm = async ( - withResult = false, - forceSave = false, - forceEdit = false - ) => { - try { - if (forceEdit) setIsTestEditClicked(true); - else setIsTestEditClicked(false); - - if (!isSignedIn) return true; - if (!forceEdit && currentTest.testResult?.completedAt) - return true; - - setIsSavingForm(true); - const scenarioResults = remapScenarioResults( - testRunStateRef.current || recentTestRunStateRef.current, - currentTest.testResult?.scenarioResults, - false - ); - - await handleSaveOrSubmitTestResultAction( - { - atVersionId: currentTestAtVersionId, - browserVersionId: currentTestBrowserVersionId, - scenarioResults - }, - forceSave ? false : !!testRunResultRef.current - ); - - if (withResult && !forceSave) { - setIsSavingForm(false); - return !!testRunResultRef.current; - } - - setIsSavingForm(false); - return true; - } catch (e) { - console.error('save.error', e); - setIsSavingForm(false); - } - }; + await handleSaveOrSubmitTestResultAction( + { + atVersionId: currentTestAtVersionId, + browserVersionId: currentTestBrowserVersionId, + scenarioResults + }, + forceSave ? false : !!testRunResultRef.current + ); - switch (action) { - case 'goToTestAtIndex': { - // Save renderer's form state - await saveForm(false, true); - setCurrentTestIndex(index); - break; - } - case 'goToNextTest': { - // Save renderer's form state - await saveForm(false, true); - navigateTests(false, currentTest, tests, setCurrentTestIndex); - break; - } - case 'goToPreviousTest': { - // Save renderer's form state - await saveForm(false, true); - navigateTests(true, currentTest, tests, setCurrentTestIndex); - break; - } - case 'editTest': { - testRunResultRef.current = null; - await saveForm(false, true, true); - if (titleRef.current) titleRef.current.focus(); - break; - } - case 'saveTest': { - if (!isSignedIn) { - setShowGetInvolvedModal(true); - break; - } - if (testRendererSubmitButtonRef.current) { - testRendererSubmitButtonRef.current.click(); - setIsTestSubmitClicked(true); - - // check to see if form was successfully submitted, if so, return to top of summary document - const forceFocusOnSave = await saveForm(true); - if (forceFocusOnSave) - if (titleRef.current) titleRef.current.focus(); - } - break; - } - case 'closeTest': { - // Save renderer's form state - await saveForm(); - navigate('/test-queue'); - break; - } + if (withResult && !forceSave) { + setIsSavingForm(false); + return !!testRunResultRef.current; } + + setIsSavingForm(false); + return true; + } catch (e) { + console.error('save.error', e); + setIsSavingForm(false); + } }; - const handleTestClick = async index => - await performButtonAction('goToTestAtIndex', index); + switch (action) { + case 'goToTestAtIndex': { + // Save renderer's form state + await saveForm(false, true); + setCurrentTestIndex(index); + break; + } + case 'goToNextTest': { + // Save renderer's form state + await saveForm(false, true); + navigateTests(false, currentTest, tests, setCurrentTestIndex); + break; + } + case 'goToPreviousTest': { + // Save renderer's form state + await saveForm(false, true); + navigateTests(true, currentTest, tests, setCurrentTestIndex); + break; + } + case 'editTest': { + testRunResultRef.current = null; + await saveForm(false, true, true); + if (titleRef.current) titleRef.current.focus(); + break; + } + case 'saveTest': { + if (!isSignedIn) { + setShowGetInvolvedModal(true); + break; + } + if (testRendererSubmitButtonRef.current) { + testRendererSubmitButtonRef.current.click(); + setIsTestSubmitClicked(true); - const handleSaveClick = async () => performButtonAction('saveTest'); + // check to see if form was successfully submitted, if so, return to top of summary document + const forceFocusOnSave = await saveForm(true); + if (forceFocusOnSave) if (titleRef.current) titleRef.current.focus(); + } + break; + } + case 'closeTest': { + // Save renderer's form state + await saveForm(); + navigate('/test-queue'); + break; + } + } + }; - const handleNextTestClick = async () => performButtonAction('goToNextTest'); + const handleTestClick = async index => + await performButtonAction('goToTestAtIndex', index); - const handlePreviousTestClick = async () => - performButtonAction('goToPreviousTest'); + const handleSaveClick = async () => performButtonAction('saveTest'); - const handleCloseRunClick = async () => performButtonAction('closeTest'); + const handleNextTestClick = async () => performButtonAction('goToNextTest'); - const handleEditResultsClick = async () => performButtonAction('editTest'); + const handlePreviousTestClick = async () => + performButtonAction('goToPreviousTest'); - const handleStartOverButtonClick = async () => setShowStartOverModal(true); + const handleCloseRunClick = async () => performButtonAction('closeTest'); - const handleStartOverAction = async () => { - const { id } = currentTest.testResult; - let variables = { - id - }; - await deleteTestResult({ variables }); + const handleEditResultsClick = async () => performButtonAction('editTest'); - reset(); - setPageReady(false); - const { testPlanRun, testPlanReport } = - await createTestResultForRenderer( - currentTest.id, - currentTestAtVersionId, - currentTestBrowserVersionId - ); - updateLocalState(testPlanRun, testPlanReport); - setPageReady(true); + const handleStartOverButtonClick = async () => setShowStartOverModal(true); - // close modal after action - setShowStartOverModal(false); + const handleStartOverAction = async () => { + const { id } = currentTest.testResult; + let variables = { + id }; - - const handleSaveOrSubmitTestResultAction = async ( - { atVersionId, browserVersionId, scenarioResults = [] }, - isSubmit = false - ) => { - const { id } = currentTest.testResult; - - /* - * The shape of scenarioResults should be: - * - * { - * ..id, - * ..output, - * ..assertionResults: [ - * ....{ - * ......id - * ......passed - * ....}, - * ....other assertionResults, - * ..], - * ..unexpectedBehaviors: [ - * ....{ - * ......id - * ......impact - * ......details - * ....}, - * ....other unexpectedBehaviors, - * ..] - * } - * */ - const formattedScenarioResults = scenarioResults.map( - ({ assertionResults, id, output, unexpectedBehaviors }) => ({ - id, - output: output, - unexpectedBehaviors: unexpectedBehaviors?.map( - ({ id, impact, details }) => ({ - id, - impact, - details - }) - ), - assertionResults: assertionResults - // All assertions are always being passed from the TestRenderer results, but - // when there is a 0-priority assertion exception, an id won't be provided, - // so do not include that result. - // This is due to the TestRenderer still requiring the position of the - // excluded assertion, but it can be removed at this point before being passed - // to the server - .filter(el => !!el.id) - .map(({ id, passed }) => ({ - id, - passed - })) - }) - ); - - let variables = { + await deleteTestResult({ variables }); + + reset(); + setPageReady(false); + const { testPlanRun, testPlanReport } = await createTestResultForRenderer( + currentTest.id, + currentTestAtVersionId, + currentTestBrowserVersionId + ); + updateLocalState(testPlanRun, testPlanReport); + setPageReady(true); + + // close modal after action + setShowStartOverModal(false); + }; + + const handleSaveOrSubmitTestResultAction = async ( + { atVersionId, browserVersionId, scenarioResults = [] }, + isSubmit = false + ) => { + const { id } = currentTest.testResult; + + /* + * The shape of scenarioResults should be: + * + * { + * ..id, + * ..output, + * ..assertionResults: [ + * ....{ + * ......id + * ......passed + * ....}, + * ....other assertionResults, + * ..], + * ..unexpectedBehaviors: [ + * ....{ + * ......id + * ......impact + * ......details + * ....}, + * ....other unexpectedBehaviors, + * ..] + * } + * */ + const formattedScenarioResults = scenarioResults.map( + ({ assertionResults, id, output, unexpectedBehaviors }) => ({ + id, + output: output, + unexpectedBehaviors: unexpectedBehaviors?.map( + ({ id, impact, details }) => ({ id, - atVersionId, - browserVersionId, - scenarioResults: formattedScenarioResults - }; + impact, + details + }) + ), + assertionResults: assertionResults + // All assertions are always being passed from the TestRenderer results, but + // when there is a 0-priority assertion exception, an id won't be provided, + // so do not include that result. + // This is due to the TestRenderer still requiring the position of the + // excluded assertion, but it can be removed at this point before being passed + // to the server + .filter(el => !!el.id) + .map(({ id, passed }) => ({ + id, + passed + })) + }) + ); - if (isSubmit) { - const result = await submitTestResult({ variables }); - const { testPlanRun, testPlanReport } = - result.data.testResult.submitTestResult; - updateLocalState(testPlanRun, testPlanReport); - } else { - const result = await saveTestResult({ variables }); - const { testPlanRun, testPlanReport } = - result.data.testResult.saveTestResult; - updateLocalState(testPlanRun, testPlanReport); - } + let variables = { + id, + atVersionId, + browserVersionId, + scenarioResults: formattedScenarioResults }; - const handleReviewConflictsButtonClick = async () => - setShowReviewConflictsModal(true); - - const handleEditAtBrowserDetailsClick = async () => { - setIsEditAtBrowserDetailsClicked(true); - - if (isAdminReviewer && adminReviewerOriginalTestRef.current) { - if (testPlanReport.browser.name !== uaBrowser) { - setThemedModalTitle( - 'Your Browser is different than the one used to record this result' - ); - setThemedModalContent( - <> - You are currently using{' '} - - {uaBrowser} {uaMajor}.{uaMinor}.{uaPatch} - - , but are trying to edit a test result that was - submitted with{' '} - - {testPlanReport.browser.name}{' '} - { - adminReviewerOriginalTestRef.current.testResult - .browserVersion.name - } - - .
    -
    - You can't change the Browser type but can make - other changes. Please proceed with caution. - - ); - setThemedModalOtherButton(null); - setShowThemedModal(true); - return; - } + if (isSubmit) { + const result = await submitTestResult({ variables }); + const { testPlanRun, testPlanReport } = + result.data.testResult.submitTestResult; + updateLocalState(testPlanRun, testPlanReport); + } else { + const result = await saveTestResult({ variables }); + const { testPlanRun, testPlanReport } = + result.data.testResult.saveTestResult; + updateLocalState(testPlanRun, testPlanReport); + } + }; - if ( - currentTest.testResult?.atVersion?.name !== - adminReviewerOriginalTestRef.current.testResult?.atVersion?.name - ) { - setThemedModalTitle( - 'Your AT Version is different than the one used to record this result' - ); - setThemedModalContent( - <> - You are currently running{' '} - - {testPlanReport.at.name}{' '} - {currentTest.testResult?.atVersion?.name} - - , but are editing a test result that was submitted with{' '} - - {testPlanReport.at.name}{' '} - { - adminReviewerOriginalTestRef.current.testResult - ?.atVersion?.name - } - - .
    -
    - Do you want to update the AT version used to record this - test result? - - ); - setThemedModalOtherButton({ - text: 'Update AT Version', - action: () => { - setShowThemedModal(false); - setIsShowingAtBrowserModal(true); - } - }); - setShowThemedModal(true); - return; - } + const handleReviewConflictsButtonClick = async () => + setShowReviewConflictsModal(true); - if ( - !adminReviewerOriginalTestRef.current.testResult?.browserVersion?.name.includes( - `${uaMajor}.${uaMinor}.${uaPatch}` - ) - ) { - setThemedModalTitle( - 'Your Browser Version is different than the one used to record this result' - ); - setThemedModalContent( - <> - You are currently using{' '} - - {uaBrowser} {uaMajor}.{uaMinor}.{uaPatch} - - , but are trying to edit a test result that was - submitted with{' '} - - {testPlanReport.browser.name}{' '} - { - adminReviewerOriginalTestRef.current.testResult - ?.browserVersion?.name - } - - .
    -
    - Do you want to update the Browser version used to record - this test result? - - ); - setThemedModalOtherButton({ - text: 'Update Browser Version', - action: () => { - setShowThemedModal(false); - setIsShowingAtBrowserModal(true); - } - }); - setShowThemedModal(true); - return; - } - } - setIsShowingAtBrowserModal(true); - }; + const handleEditAtBrowserDetailsClick = async () => { + setIsEditAtBrowserDetailsClicked(true); - const handleAtAndBrowserDetailsModalAction = async ( - updatedAtVersionName, - updatedBrowserVersionName, - updateMessage - ) => { - // Get version id for selected atVersion and browserVersion from name - const atVersion = testPlanReport.at.atVersions.find( - item => item.name === updatedAtVersionName + if (isAdminReviewer && adminReviewerOriginalTestRef.current) { + if (testPlanReport.browser.name !== uaBrowser) { + setThemedModalTitle( + 'Your Browser is different than the one used to record this result' ); - - let browserVersion = testPlanReport.browser.browserVersions.find( - item => item.name === updatedBrowserVersionName + setThemedModalContent( + <> + You are currently using{' '} + + {uaBrowser} {uaMajor}.{uaMinor}.{uaPatch} + + , but are trying to edit a test result that was submitted with{' '} + + {testPlanReport.browser.name}{' '} + { + adminReviewerOriginalTestRef.current.testResult.browserVersion + .name + } + + .
    +
    + You can't change the Browser type but can make other changes. + Please proceed with caution. + ); - - // create version if not exists (accounting for admin providing new versions) - if (!browserVersion) { - const createBrowserVersionResult = await createBrowserVersion({ - variables: { - browserId: testPlanReport.browser.id, - browserVersionName: updatedBrowserVersionName - } - }); - browserVersion = - createBrowserVersionResult.data?.browser - ?.findOrCreateBrowserVersion; - } - - const updateMessageComponent = updateMessage ? ( - <> - - {updateMessage} - - ) : null; - - setCurrentTestAtVersionId(atVersion.id); - setCurrentTestBrowserVersionId(browserVersion.id); - setCurrentAtVersion(atVersion); - setCurrentBrowserVersion(browserVersion); - setUpdateMessageComponent(updateMessageComponent); - - const { testPlanRun: _testPlanRun, testPlanReport: _testPlanReport } = - await createTestResultForRenderer( - currentTest.id, - atVersion.id, - browserVersion.id - ); - updateLocalState(_testPlanRun, _testPlanReport); - handleAtAndBrowserDetailsModalCloseAction(); - }; - - const handleAtAndBrowserDetailsModalCloseAction = () => { - setIsShowingAtBrowserModal(false); - if (isEditAtBrowserDetailsModalClick) - editAtBrowserDetailsButtonRef.current.focus(); - }; - - const onThemedModalClose = () => { - setShowThemedModal(false); - editAtBrowserDetailsButtonRef.current.focus(); - }; - - const renderTestsCompletedInfoBox = () => { - let isReviewingBot = false; - if (openAsUserId) { - isReviewingBot = isBot(openAsUser); - } - - let content; - - if (isReviewingBot) { - content = ( - <> - {`${testResults.reduce( - (acc, { scenarioResults }) => - acc + - (scenarioResults && - scenarioResults.every(({ output }) => !!output) - ? 1 - : 0), - 0 - )} of ${tests.length}`}{' '} - responses collected. - - ); - } else if (!isSignedIn) { - content = {tests.length} tests to view; - } else if (hasTestsToRun) { - content = ( - <> - {' '} - {`${testResults.reduce( - (acc, { completedAt }) => acc + (completedAt ? 1 : 0), - 0 - )} of ${tests.length}`}{' '} - tests completed - - ); - } else { - content =
    No tests for this AT and Browser combination
    ; - } - return ( -
    -
    - - {content} -
    -
    + setThemedModalOtherButton(null); + setShowThemedModal(true); + return; + } + + if ( + currentTest.testResult?.atVersion?.name !== + adminReviewerOriginalTestRef.current.testResult?.atVersion?.name + ) { + setThemedModalTitle( + 'Your AT Version is different than the one used to record this result' ); - }; - - const renderTestContent = (testPlanReport, currentTest, heading) => { - const { index } = currentTest; - const isComplete = currentTest.testResult - ? !!currentTest.testResult.completedAt - : false; - const isFirstTest = index === 0; - const isLastTest = currentTest.seq === tests.length; - - let primaryButtons; // These are the list of buttons that will appear below the tests - let forwardButtons = []; // These are buttons that navigate to next tests and continue - - const nextButton = ( - + setThemedModalContent( + <> + You are currently running{' '} + + {testPlanReport.at.name} {currentTest.testResult?.atVersion?.name} + + , but are editing a test result that was submitted with{' '} + + {testPlanReport.at.name}{' '} + {adminReviewerOriginalTestRef.current.testResult?.atVersion?.name} + + .
    +
    + Do you want to update the AT version used to record this test + result? + ); + setThemedModalOtherButton({ + text: 'Update AT Version', + action: () => { + setShowThemedModal(false); + setIsShowingAtBrowserModal(true); + } + }); + setShowThemedModal(true); + return; + } - const previousButton = ( - + if ( + !adminReviewerOriginalTestRef.current.testResult?.browserVersion?.name.includes( + `${uaMajor}.${uaMinor}.${uaPatch}` + ) + ) { + setThemedModalTitle( + 'Your Browser Version is different than the one used to record this result' ); - - if (isComplete) { - const editButton = ( - - ); - - const continueButton = ( - - ); - - if (!isLastTest) forwardButtons = [nextButton]; - primaryButtons = [ - previousButton, - editButton, - ...forwardButtons, - continueButton - ]; - } else { - // same key to maintain focus - const saveResultsButton = ( - - ); - if (!isLastTest) forwardButtons = [nextButton]; - primaryButtons = [ - previousButton, - ...forwardButtons, - saveResultsButton - ]; - } - - const menuRightOfContent = ( -
    -

    Test Options

    -
      -
    • - - } - target="_blank" - href={issueLink} - /> -
    • - {isBot(openAsUser) && - collectionJobQuery?.collectionJobByTestPlanRunId - ?.externalLogsUrl ? ( -
    • - -
    • - ) : ( -
    • - - } - onClick={handleStartOverButtonClick} - disabled={!isSignedIn} - /> -
    • - )} - -
    • - -
    • -
    • - - Email us if you need help - -
    • -
    -
    + setThemedModalContent( + <> + You are currently using{' '} + + {uaBrowser} {uaMajor}.{uaMinor}.{uaPatch} + + , but are trying to edit a test result that was submitted with{' '} + + {testPlanReport.browser.name}{' '} + { + adminReviewerOriginalTestRef.current.testResult?.browserVersion + ?.name + } + + .
    +
    + Do you want to update the Browser version used to record this test + result? + ); + setThemedModalOtherButton({ + text: 'Update Browser Version', + action: () => { + setShowThemedModal(false); + setIsShowingAtBrowserModal(true); + } + }); + setShowThemedModal(true); + return; + } + } + setIsShowingAtBrowserModal(true); + }; + + const handleAtAndBrowserDetailsModalAction = async ( + updatedAtVersionName, + updatedBrowserVersionName, + updateMessage + ) => { + // Get version id for selected atVersion and browserVersion from name + const atVersion = testPlanReport.at.atVersions.find( + item => item.name === updatedAtVersionName + ); - return ( - <> -

    - Test {currentTest.seq}: - {currentTest.title} -

    - {heading} - - {pageReady && (isSignedIn ? currentTest.testResult : true) && ( - - - - - - {isRendererReady && ( - -

    - Test Controls -

    -
      - {primaryButtons.map(button => ( -
    • {button}
    • - ))} -
    -
    - )} - - - {menuRightOfContent} - -
    - )} - - - - - {/* Modals */} - {showStartOverModal && ( - setShowStartOverModal(false)} - /> - )} - {showGetInvolvedModal && ( - - Only members of the ARIA-AT test team can submit - data. If you fill in this form, your data will - not be saved! Check out the{' '} - home page to learn more about - how to get involved. - - } - closeLabel="Close" - handleClose={() => setShowGetInvolvedModal(false)} - /> - )} - {showReviewConflictsModal && ( - setShowReviewConflictsModal(false)} - /> - )} - - ); - }; + let browserVersion = testPlanReport.browser.browserVersions.find( + item => item.name === updatedBrowserVersionName + ); - let heading; - let content; - let openAsUserHeading = null; + // create version if not exists (accounting for admin providing new versions) + if (!browserVersion) { + const createBrowserVersionResult = await createBrowserVersion({ + variables: { + browserId: testPlanReport.browser.id, + browserVersionName: updatedBrowserVersionName + } + }); + browserVersion = + createBrowserVersionResult.data?.browser?.findOrCreateBrowserVersion; + } + const updateMessageComponent = updateMessage ? ( + <> + + {updateMessage} + + ) : null; + + setCurrentTestAtVersionId(atVersion.id); + setCurrentTestBrowserVersionId(browserVersion.id); + setCurrentAtVersion(atVersion); + setCurrentBrowserVersion(browserVersion); + setUpdateMessageComponent(updateMessageComponent); + + const { testPlanRun: _testPlanRun, testPlanReport: _testPlanReport } = + await createTestResultForRenderer( + currentTest.id, + atVersion.id, + browserVersion.id + ); + updateLocalState(_testPlanRun, _testPlanReport); + handleAtAndBrowserDetailsModalCloseAction(); + }; + + const handleAtAndBrowserDetailsModalCloseAction = () => { + setIsShowingAtBrowserModal(false); + if (isEditAtBrowserDetailsModalClick) + editAtBrowserDetailsButtonRef.current.focus(); + }; + + const onThemedModalClose = () => { + setShowThemedModal(false); + editAtBrowserDetailsButtonRef.current.focus(); + }; + + const renderTestsCompletedInfoBox = () => { + let isReviewingBot = false; if (openAsUserId) { - if (isBot(openAsUser)) { - openAsUserHeading = ( -
    - Reviewing tests of{' '} - {' '} - {`${openAsUser.username}`}. -
    - ); - } else { - openAsUserHeading = ( -
    - Reviewing tests of {`${openAsUser.username}`}. -

    {`All changes will be saved as performed by ${openAsUser.username}.`}

    -
    - ); - } + isReviewingBot = isBot(openAsUser); } - heading = pageReady && ( + let content; + + if (isReviewingBot) { + content = ( <> -
    -
    -
    - Test Plan:{' '} - {`${ - testPlanVersion.title || - testPlanVersion.testPlan?.directory || - '' - }`} -
    -
    -
    -
    -
    - AT:{' '} - {`${testPlanReport.at?.name}${ - isSignedIn ? ` ${currentAtVersion?.name}` : '' - }`} -
    -
    - Browser:{' '} - {`${testPlanReport.browser?.name}${ - isSignedIn - ? ` ${currentBrowserVersion?.name || ''}` - : '' - }`} -
    -
    - {isSignedIn && ( - - )} -
    - {renderTestsCompletedInfoBox()} -
    - {openAsUserHeading} + {`${testResults.reduce( + (acc, { scenarioResults }) => + acc + + (scenarioResults && + scenarioResults.every(({ output }) => !!output) + ? 1 + : 0), + 0 + )} of ${tests.length}`}{' '} + responses collected. + + ); + } else if (!isSignedIn) { + content = {tests.length} tests to view; + } else if (hasTestsToRun) { + content = ( + <> + {' '} + {`${testResults.reduce( + (acc, { completedAt }) => acc + (completedAt ? 1 : 0), + 0 + )} of ${tests.length}`}{' '} + tests completed + ); + } else { + content =
    No tests for this AT and Browser combination
    ; + } + return ( +
    +
    + + {content} +
    +
    + ); + }; + + const renderTestContent = (testPlanReport, currentTest, heading) => { + const { index } = currentTest; + const isComplete = currentTest.testResult + ? !!currentTest.testResult.completedAt + : false; + const isFirstTest = index === 0; + const isLastTest = currentTest.seq === tests.length; + + let primaryButtons; // These are the list of buttons that will appear below the tests + let forwardButtons = []; // These are buttons that navigate to next tests and continue + + const nextButton = ( + ); - if (!isSignedIn || !testPlanRun?.isComplete) { - content = hasTestsToRun ? ( - renderTestContent(testPlanReport, currentTest, heading) - ) : ( - // No tests loaded - <> - {heading} -
    No tests for this At and Browser combination
    - - ); + const previousButton = ( + + ); + + if (isComplete) { + const editButton = ( + + ); + + const continueButton = ( + + ); + + if (!isLastTest) forwardButtons = [nextButton]; + primaryButtons = [ + previousButton, + editButton, + ...forwardButtons, + continueButton + ]; } else { - content = ( -
    - {heading} - - - Thanks! Your results - have been submitted. Please return to the{' '} - Test Queue. - - -
    - ); + // same key to maintain focus + const saveResultsButton = ( + + ); + if (!isLastTest) forwardButtons = [nextButton]; + primaryButtons = [previousButton, ...forwardButtons, saveResultsButton]; } + const menuRightOfContent = ( +
    +

    Test Options

    +
      +
    • + + } + target="_blank" + href={issueLink} + /> +
    • + {isBot(openAsUser) && + collectionJobQuery?.collectionJobByTestPlanRunId?.externalLogsUrl ? ( +
    • + +
    • + ) : ( +
    • + } + onClick={handleStartOverButtonClick} + disabled={!isSignedIn} + /> +
    • + )} + +
    • + +
    • +
    • + Email us if you need help +
    • +
    +
    + ); + return ( - pageReady && ( - - - - {hasTestsToRun - ? `${currentTest.title} for ${testPlanReport.at?.name} ${currentAtVersion?.name} and ${testPlanReport.browser?.name} ${currentBrowserVersion?.name} ` + - `| ARIA-AT` - : 'No tests for this AT and Browser | ARIA-AT'} - - - {updateMessageComponent && ( - - {updateMessageComponent} - - )} + <> +

    + Test {currentTest.seq}: + {currentTest.title} +

    + {heading} + + {pageReady && (isSignedIn ? currentTest.testResult : true) && ( + + + + + + {isRendererReady && ( - - - - {content} - - +

    + Test Controls +

    +
      + {primaryButtons.map(button => ( +
    • {button}
    • + ))} +
    - {showThemedModal && ( - - )} - {isSignedIn && isShowingAtBrowserModal && ( - item.name - )} - browserName={testPlanReport.browser.name} - browserVersion={ - currentTest.testResult?.browserVersion?.name - } - browserVersions={testPlanReport.browser.browserVersions.map( - item => item.name - )} - patternName={testPlanVersion.title} - testerName={tester.username} - handleAction={handleAtAndBrowserDetailsModalAction} - handleClose={handleAtAndBrowserDetailsModalCloseAction} - /> - )} -
    - ) + )} + + + {menuRightOfContent} + + + )} + + + + + {/* Modals */} + {showStartOverModal && ( + setShowStartOverModal(false)} + /> + )} + {showGetInvolvedModal && ( + + Only members of the ARIA-AT test team can submit data. If you + fill in this form, your data will not be saved! Check out the{' '} + home page to learn more about how to get + involved. + + } + closeLabel="Close" + handleClose={() => setShowGetInvolvedModal(false)} + /> + )} + {showReviewConflictsModal && ( + setShowReviewConflictsModal(false)} + /> + )} + + ); + }; + + let heading; + let content; + let openAsUserHeading = null; + + if (openAsUserId) { + if (isBot(openAsUser)) { + openAsUserHeading = ( +
    + Reviewing tests of {' '} + {`${openAsUser.username}`}. +
    + ); + } else { + openAsUserHeading = ( +
    + Reviewing tests of {`${openAsUser.username}`}. +

    {`All changes will be saved as performed by ${openAsUser.username}.`}

    +
    + ); + } + } + + heading = pageReady && ( + <> +
    +
    +
    + Test Plan:{' '} + {`${ + testPlanVersion.title || testPlanVersion.testPlan?.directory || '' + }`} +
    +
    +
    +
    +
    + AT:{' '} + {`${testPlanReport.at?.name}${ + isSignedIn ? ` ${currentAtVersion?.name}` : '' + }`} +
    +
    + Browser:{' '} + {`${testPlanReport.browser?.name}${ + isSignedIn ? ` ${currentBrowserVersion?.name || ''}` : '' + }`} +
    +
    + {isSignedIn && ( + + )} +
    + {renderTestsCompletedInfoBox()} +
    + {openAsUserHeading} + + ); + + if (!isSignedIn || !testPlanRun?.isComplete) { + content = hasTestsToRun ? ( + renderTestContent(testPlanReport, currentTest, heading) + ) : ( + // No tests loaded + <> + {heading} +
    No tests for this At and Browser combination
    + + ); + } else { + content = ( +
    + {heading} + + + Thanks! Your results have been + submitted. Please return to the{' '} + Test Queue. + + +
    ); + } + + return ( + pageReady && ( + + + + {hasTestsToRun + ? `${currentTest.title} for ${testPlanReport.at?.name} ${currentAtVersion?.name} and ${testPlanReport.browser?.name} ${currentBrowserVersion?.name} ` + + `| ARIA-AT` + : 'No tests for this AT and Browser | ARIA-AT'} + + + {updateMessageComponent && ( + + {updateMessageComponent} + + )} + + + + + {content} + + + + {showThemedModal && ( + + )} + {isSignedIn && isShowingAtBrowserModal && ( + item.name)} + browserName={testPlanReport.browser.name} + browserVersion={currentTest.testResult?.browserVersion?.name} + browserVersions={testPlanReport.browser.browserVersions.map( + item => item.name + )} + patternName={testPlanVersion.title} + testerName={tester.username} + handleAction={handleAtAndBrowserDetailsModalAction} + handleClose={handleAtAndBrowserDetailsModalCloseAction} + /> + )} + + ) + ); }; export default TestRun; diff --git a/client/components/TestRun/queries.js b/client/components/TestRun/queries.js index 2e5b86739..70b5adcb8 100644 --- a/client/components/TestRun/queries.js +++ b/client/components/TestRun/queries.js @@ -1,1181 +1,1159 @@ import { gql } from '@apollo/client'; export const TEST_RUN_PAGE_QUERY = gql` - query TestPlanRunPage($testPlanRunId: ID!) { - testPlanRun(id: $testPlanRunId) { + query TestPlanRunPage($testPlanRunId: ID!) { + testPlanRun(id: $testPlanRunId) { + id + initiatedByAutomation + tester { + id + username + } + testResults { + id + startedAt + completedAt + test { + id + rowNumber + title + renderedUrl + renderableContent + } + scenarioResults { + id + scenario { + commands { + id + text + } + } + output + assertionResults { id - initiatedByAutomation - tester { - id + assertion { + text + } + passed + } + requiredAssertionResults: assertionResults(priority: REQUIRED) { + assertion { + text + } + passed + } + optionalAssertionResults: assertionResults(priority: OPTIONAL) { + assertion { + text + } + passed + } + mayAssertionResults: assertionResults(priority: MAY) { + assertion { + text + } + passed + } + unexpectedBehaviors { + id + text + impact + details + } + } + atVersion { + id + name + } + browserVersion { + id + name + } + } + testPlanReport { + id + conflicts { + source { + test { + id + title + rowNumber + } + scenario { + id + commands { + text + } + } + assertion { + id + text + } + } + conflictingResults { + testPlanRun { + id + tester { username + } + } + scenarioResult { + output + unexpectedBehaviors { + text + impact + details + } + } + assertionResult { + passed + } + } + } + at { + id + name + atVersions { + id + name + } + } + browser { + id + name + browserVersions { + id + name + } + } + testPlanVersion { + id + title + phase + updatedAt + gitSha + testPageUrl + testPlan { + directory + } + metadata + } + runnableTests { + id + rowNumber + title + ats { + id + name + } + atMode + renderedUrl + scenarios { + id + at { + id + name + } + commands { + id + text + } + } + assertions { + id + priority + text + } + } + } + } + me { + id + username + roles + } + users { + id + username + } + } +`; + +export const TEST_RUN_PAGE_ANON_QUERY = gql` + query TestPlanRunAnonPage($testPlanReportId: ID!) { + testPlanReport(id: $testPlanReportId) { + id + conflicts { + source { + test { + id + title + rowNumber + } + scenario { + id + commands { + text + } + } + assertion { + id + text + } + } + conflictingResults { + testPlanRun { + id + tester { + username + } + } + scenarioResult { + output + unexpectedBehaviors { + text + impact + details + } + } + assertionResult { + passed + } + } + } + at { + id + name + atVersions { + id + name + } + } + browser { + id + name + browserVersions { + id + name + } + } + testPlanVersion { + id + title + phase + updatedAt + gitSha + testPageUrl + testPlan { + directory + } + metadata + } + runnableTests { + id + rowNumber + title + ats { + id + name + } + atMode + renderedUrl + renderableContent + scenarios { + id + at { + id + name + } + commands { + id + text + } + } + assertions { + id + priority + text + } + } + } + } +`; + +export const FIND_OR_CREATE_TEST_RESULT_MUTATION = gql` + mutation FindOrCreateTestResult( + $testPlanRunId: ID! + $testId: ID! + $atVersionId: ID! + $browserVersionId: ID! + ) { + testPlanRun(id: $testPlanRunId) { + findOrCreateTestResult( + testId: $testId + atVersionId: $atVersionId + browserVersionId: $browserVersionId + ) { + locationOfData + testPlanRun { + id + tester { + id + username + } + testResults { + id + startedAt + completedAt + test { + id + rowNumber + title + renderedUrl + renderableContent } - testResults { + scenarioResults { + id + scenario { + commands { + id + text + } + } + output + assertionResults { + id + assertion { + text + } + passed + } + requiredAssertionResults: assertionResults(priority: REQUIRED) { + assertion { + text + } + passed + } + optionalAssertionResults: assertionResults(priority: OPTIONAL) { + assertion { + text + } + passed + } + mayAssertionResults: assertionResults(priority: MAY) { + assertion { + text + } + passed + } + unexpectedBehaviors { id - startedAt - completedAt + text + impact + details + } + } + atVersion { + id + name + } + browserVersion { + id + name + } + } + testPlanReport { + id + conflicts { + source { test { - id - rowNumber - title - renderedUrl - renderableContent + id + title + rowNumber + } + scenario { + id + commands { + text + } + } + assertion { + id + text } - scenarioResults { - id - scenario { - commands { - id - text - } - } - output - assertionResults { - id - assertion { - text - } - passed - } - requiredAssertionResults: assertionResults( - priority: REQUIRED - ) { - assertion { - text - } - passed - } - optionalAssertionResults: assertionResults( - priority: OPTIONAL - ) { - assertion { - text - } - passed - } - mayAssertionResults: assertionResults(priority: MAY) { - assertion { - text - } - passed - } - unexpectedBehaviors { - id - text - impact - details - } + } + conflictingResults { + testPlanRun { + id + tester { + username + } } - atVersion { - id - name + scenarioResult { + output + unexpectedBehaviors { + text + impact + details + } } - browserVersion { - id - name + assertionResult { + passed } + } } - testPlanReport { + at { + id + name + atVersions { + id + name + } + } + browser { + id + name + browserVersions { + id + name + } + } + testPlanVersion { + id + title + phase + updatedAt + gitSha + testPageUrl + testPlan { + directory + } + metadata + } + runnableTests { + id + rowNumber + title + ats { + id + name + } + atMode + renderedUrl + scenarios { id - conflicts { - source { - test { - id - title - rowNumber - } - scenario { - id - commands { - text - } - } - assertion { - id - text - } - } - conflictingResults { - testPlanRun { - id - tester { - username - } - } - scenarioResult { - output - unexpectedBehaviors { - text - impact - details - } - } - assertionResult { - passed - } - } - } at { - id - name - atVersions { - id - name - } + id + name } - browser { - id - name - browserVersions { - id - name - } + commands { + id + text + } + } + assertions { + id + priority + text + } + } + } + } + testPlanReport { + id + conflicts { + source { + test { + id + title + rowNumber + } + scenario { + id + commands { + text } - testPlanVersion { - id - title - phase - updatedAt - gitSha - testPageUrl - testPlan { - directory - } - metadata + } + assertion { + id + text + } + } + conflictingResults { + testPlanRun { + id + tester { + username } - runnableTests { - id - rowNumber - title - ats { - id - name - } - atMode - renderedUrl - scenarios { - id - at { - id - name - } - commands { - id - text - } - } - assertions { - id - priority - text - } + } + scenarioResult { + output + unexpectedBehaviors { + text + impact + details } + } + assertionResult { + passed + } } - } - me { + } + at { id - username - roles - } - users { + name + atVersions { + id + name + } + } + browser { id - username + name + browserVersions { + id + name + } + } + testPlanVersion { + id + title + phase + updatedAt + gitSha + testPageUrl + testPlan { + directory + } + metadata + } + runnableTests { + id + rowNumber + title + ats { + id + name + } + atMode + renderedUrl + scenarios { + id + at { + id + name + } + commands { + id + text + } + } + assertions { + id + priority + text + } + } } + } } + } `; -export const TEST_RUN_PAGE_ANON_QUERY = gql` - query TestPlanRunAnonPage($testPlanReportId: ID!) { - testPlanReport(id: $testPlanReportId) { +export const SAVE_TEST_RESULT_MUTATION = gql` + mutation SaveTestResult( + $id: ID! + $atVersionId: ID! + $browserVersionId: ID! + $scenarioResults: [ScenarioResultInput]! + ) { + testResult(id: $id) { + saveTestResult( + input: { + id: $id + atVersionId: $atVersionId + browserVersionId: $browserVersionId + scenarioResults: $scenarioResults + } + ) { + locationOfData + testPlanRun { + id + tester { + id + username + } + testResults { + id + startedAt + completedAt + test { + id + rowNumber + title + renderedUrl + renderableContent + } + scenarioResults { + id + scenario { + commands { + id + text + } + } + output + assertionResults { + id + assertion { + text + } + passed + } + requiredAssertionResults: assertionResults(priority: REQUIRED) { + assertion { + text + } + passed + } + optionalAssertionResults: assertionResults(priority: OPTIONAL) { + assertion { + text + } + passed + } + mayAssertionResults: assertionResults(priority: MAY) { + assertion { + text + } + passed + } + unexpectedBehaviors { + id + text + impact + details + } + } + atVersion { + id + name + } + browserVersion { + id + name + } + } + testPlanReport { id conflicts { - source { - test { - id - title - rowNumber - } - scenario { - id - commands { - text - } - } - assertion { - id - text - } + source { + test { + id + title + rowNumber } - conflictingResults { - testPlanRun { - id - tester { - username - } - } - scenarioResult { - output - unexpectedBehaviors { - text - impact - details - } - } - assertionResult { - passed - } + scenario { + id + commands { + text + } + } + assertion { + id + text + } + } + conflictingResults { + testPlanRun { + id + tester { + username + } } + scenarioResult { + output + unexpectedBehaviors { + text + impact + details + } + } + assertionResult { + passed + } + } } at { + id + name + atVersions { id name - atVersions { - id - name - } + } } browser { + id + name + browserVersions { id name - browserVersions { - id - name - } + } } testPlanVersion { + id + title + phase + updatedAt + gitSha + testPageUrl + testPlan { + directory + } + metadata + } + runnableTests { + id + rowNumber + title + ats { id - title - phase - updatedAt - gitSha - testPageUrl - testPlan { - directory + name + } + atMode + renderedUrl + scenarios { + id + at { + id + name + } + commands { + id + text } - metadata + } + assertions { + id + priority + text + } } - runnableTests { + } + } + testPlanReport { + id + conflicts { + source { + test { id - rowNumber title - ats { - id - name + rowNumber + } + scenario { + id + commands { + text } - atMode - renderedUrl - renderableContent - scenarios { - id - at { - id - name - } - commands { - id - text - } + } + assertion { + id + text + } + } + conflictingResults { + testPlanRun { + id + tester { + username } - assertions { - id - priority - text + } + scenarioResult { + output + unexpectedBehaviors { + text + impact + details } + } + assertionResult { + passed + } + } + } + at { + id + name + atVersions { + id + name + } + } + browser { + id + name + browserVersions { + id + name + } + } + testPlanVersion { + id + title + phase + updatedAt + gitSha + testPageUrl + testPlan { + directory } + metadata + } + runnableTests { + id + rowNumber + title + ats { + id + name + } + atMode + renderedUrl + scenarios { + id + at { + id + name + } + commands { + id + text + } + } + assertions { + id + priority + text + } + } } + } } + } `; -export const FIND_OR_CREATE_TEST_RESULT_MUTATION = gql` - mutation FindOrCreateTestResult( - $testPlanRunId: ID! - $testId: ID! - $atVersionId: ID! - $browserVersionId: ID! - ) { - testPlanRun(id: $testPlanRunId) { - findOrCreateTestResult( - testId: $testId - atVersionId: $atVersionId - browserVersionId: $browserVersionId - ) { - locationOfData - testPlanRun { - id - tester { - id - username - } - testResults { - id - startedAt - completedAt - test { - id - rowNumber - title - renderedUrl - renderableContent - } - scenarioResults { - id - scenario { - commands { - id - text - } - } - output - assertionResults { - id - assertion { - text - } - passed - } - requiredAssertionResults: assertionResults( - priority: REQUIRED - ) { - assertion { - text - } - passed - } - optionalAssertionResults: assertionResults( - priority: OPTIONAL - ) { - assertion { - text - } - passed - } - mayAssertionResults: assertionResults( - priority: MAY - ) { - assertion { - text - } - passed - } - unexpectedBehaviors { - id - text - impact - details - } - } - atVersion { - id - name - } - browserVersion { - id - name - } - } - testPlanReport { - id - conflicts { - source { - test { - id - title - rowNumber - } - scenario { - id - commands { - text - } - } - assertion { - id - text - } - } - conflictingResults { - testPlanRun { - id - tester { - username - } - } - scenarioResult { - output - unexpectedBehaviors { - text - impact - details - } - } - assertionResult { - passed - } - } - } - at { - id - name - atVersions { - id - name - } - } - browser { - id - name - browserVersions { - id - name - } - } - testPlanVersion { - id - title - phase - updatedAt - gitSha - testPageUrl - testPlan { - directory - } - metadata - } - runnableTests { - id - rowNumber - title - ats { - id - name - } - atMode - renderedUrl - scenarios { - id - at { - id - name - } - commands { - id - text - } - } - assertions { - id - priority - text - } - } - } +export const SUBMIT_TEST_RESULT_MUTATION = gql` + mutation SubmitTestResult( + $id: ID! + $atVersionId: ID! + $browserVersionId: ID! + $scenarioResults: [ScenarioResultInput]! + ) { + testResult(id: $id) { + submitTestResult( + input: { + id: $id + atVersionId: $atVersionId + browserVersionId: $browserVersionId + scenarioResults: $scenarioResults + } + ) { + locationOfData + testPlanRun { + id + tester { + id + username + } + testResults { + id + startedAt + completedAt + test { + id + rowNumber + title + renderedUrl + renderableContent + } + scenarioResults { + id + scenario { + commands { + id + text + } + } + output + assertionResults { + id + assertion { + text + } + passed + } + requiredAssertionResults: assertionResults(priority: REQUIRED) { + assertion { + text } - testPlanReport { - id - conflicts { - source { - test { - id - title - rowNumber - } - scenario { - id - commands { - text - } - } - assertion { - id - text - } - } - conflictingResults { - testPlanRun { - id - tester { - username - } - } - scenarioResult { - output - unexpectedBehaviors { - text - impact - details - } - } - assertionResult { - passed - } - } - } - at { - id - name - atVersions { - id - name - } - } - browser { - id - name - browserVersions { - id - name - } - } - testPlanVersion { - id - title - phase - updatedAt - gitSha - testPageUrl - testPlan { - directory - } - metadata - } - runnableTests { - id - rowNumber - title - ats { - id - name - } - atMode - renderedUrl - scenarios { - id - at { - id - name - } - commands { - id - text - } - } - assertions { - id - priority - text - } - } + passed + } + optionalAssertionResults: assertionResults(priority: OPTIONAL) { + assertion { + text } + passed + } + mayAssertionResults: assertionResults(priority: MAY) { + assertion { + text + } + passed + } + unexpectedBehaviors { + id + text + impact + details + } } - } - } -`; - -export const SAVE_TEST_RESULT_MUTATION = gql` - mutation SaveTestResult( - $id: ID! - $atVersionId: ID! - $browserVersionId: ID! - $scenarioResults: [ScenarioResultInput]! - ) { - testResult(id: $id) { - saveTestResult( - input: { - id: $id - atVersionId: $atVersionId - browserVersionId: $browserVersionId - scenarioResults: $scenarioResults + atVersion { + id + name + } + browserVersion { + id + name + } + } + testPlanReport { + id + conflicts { + source { + test { + id + title + rowNumber + } + scenario { + id + commands { + text + } } - ) { - locationOfData + assertion { + id + text + } + } + conflictingResults { testPlanRun { - id - tester { - id - username - } - testResults { - id - startedAt - completedAt - test { - id - rowNumber - title - renderedUrl - renderableContent - } - scenarioResults { - id - scenario { - commands { - id - text - } - } - output - assertionResults { - id - assertion { - text - } - passed - } - requiredAssertionResults: assertionResults( - priority: REQUIRED - ) { - assertion { - text - } - passed - } - optionalAssertionResults: assertionResults( - priority: OPTIONAL - ) { - assertion { - text - } - passed - } - mayAssertionResults: assertionResults( - priority: MAY - ) { - assertion { - text - } - passed - } - unexpectedBehaviors { - id - text - impact - details - } - } - atVersion { - id - name - } - browserVersion { - id - name - } - } - testPlanReport { - id - conflicts { - source { - test { - id - title - rowNumber - } - scenario { - id - commands { - text - } - } - assertion { - id - text - } - } - conflictingResults { - testPlanRun { - id - tester { - username - } - } - scenarioResult { - output - unexpectedBehaviors { - text - impact - details - } - } - assertionResult { - passed - } - } - } - at { - id - name - atVersions { - id - name - } - } - browser { - id - name - browserVersions { - id - name - } - } - testPlanVersion { - id - title - phase - updatedAt - gitSha - testPageUrl - testPlan { - directory - } - metadata - } - runnableTests { - id - rowNumber - title - ats { - id - name - } - atMode - renderedUrl - scenarios { - id - at { - id - name - } - commands { - id - text - } - } - assertions { - id - priority - text - } - } - } + id + tester { + username + } + } + scenarioResult { + output + unexpectedBehaviors { + text + impact + details + } + } + assertionResult { + passed + } + } + } + at { + id + name + atVersions { + id + name + } + } + browser { + id + name + browserVersions { + id + name + } + } + testPlanVersion { + id + title + phase + updatedAt + gitSha + testPageUrl + testPlan { + directory + } + metadata + } + runnableTests { + id + rowNumber + title + ats { + id + name + } + atMode + renderedUrl + scenarios { + id + at { + id + name } - testPlanReport { - id - conflicts { - source { - test { - id - title - rowNumber - } - scenario { - id - commands { - text - } - } - assertion { - id - text - } - } - conflictingResults { - testPlanRun { - id - tester { - username - } - } - scenarioResult { - output - unexpectedBehaviors { - text - impact - details - } - } - assertionResult { - passed - } - } - } - at { - id - name - atVersions { - id - name - } - } - browser { - id - name - browserVersions { - id - name - } - } - testPlanVersion { - id - title - phase - updatedAt - gitSha - testPageUrl - testPlan { - directory - } - metadata - } - runnableTests { - id - rowNumber - title - ats { - id - name - } - atMode - renderedUrl - scenarios { - id - at { - id - name - } - commands { - id - text - } - } - assertions { - id - priority - text - } - } + commands { + id + text } + } + assertions { + id + priority + text + } } + } } - } -`; - -export const SUBMIT_TEST_RESULT_MUTATION = gql` - mutation SubmitTestResult( - $id: ID! - $atVersionId: ID! - $browserVersionId: ID! - $scenarioResults: [ScenarioResultInput]! - ) { - testResult(id: $id) { - submitTestResult( - input: { - id: $id - atVersionId: $atVersionId - browserVersionId: $browserVersionId - scenarioResults: $scenarioResults + testPlanReport { + id + conflicts { + source { + test { + id + title + rowNumber + } + scenario { + id + commands { + text } - ) { - locationOfData - testPlanRun { - id - tester { - id - username - } - testResults { - id - startedAt - completedAt - test { - id - rowNumber - title - renderedUrl - renderableContent - } - scenarioResults { - id - scenario { - commands { - id - text - } - } - output - assertionResults { - id - assertion { - text - } - passed - } - requiredAssertionResults: assertionResults( - priority: REQUIRED - ) { - assertion { - text - } - passed - } - optionalAssertionResults: assertionResults( - priority: OPTIONAL - ) { - assertion { - text - } - passed - } - mayAssertionResults: assertionResults( - priority: MAY - ) { - assertion { - text - } - passed - } - unexpectedBehaviors { - id - text - impact - details - } - } - atVersion { - id - name - } - browserVersion { - id - name - } - } - testPlanReport { - id - conflicts { - source { - test { - id - title - rowNumber - } - scenario { - id - commands { - text - } - } - assertion { - id - text - } - } - conflictingResults { - testPlanRun { - id - tester { - username - } - } - scenarioResult { - output - unexpectedBehaviors { - text - impact - details - } - } - assertionResult { - passed - } - } - } - at { - id - name - atVersions { - id - name - } - } - browser { - id - name - browserVersions { - id - name - } - } - testPlanVersion { - id - title - phase - updatedAt - gitSha - testPageUrl - testPlan { - directory - } - metadata - } - runnableTests { - id - rowNumber - title - ats { - id - name - } - atMode - renderedUrl - scenarios { - id - at { - id - name - } - commands { - id - text - } - } - assertions { - id - priority - text - } - } - } + } + assertion { + id + text + } + } + conflictingResults { + testPlanRun { + id + tester { + username } - testPlanReport { - id - conflicts { - source { - test { - id - title - rowNumber - } - scenario { - id - commands { - text - } - } - assertion { - id - text - } - } - conflictingResults { - testPlanRun { - id - tester { - username - } - } - scenarioResult { - output - unexpectedBehaviors { - text - impact - details - } - } - assertionResult { - passed - } - } - } - at { - id - name - atVersions { - id - name - } - } - browser { - id - name - browserVersions { - id - name - } - } - testPlanVersion { - id - title - phase - updatedAt - gitSha - testPageUrl - testPlan { - directory - } - metadata - } - runnableTests { - id - rowNumber - title - ats { - id - name - } - atMode - renderedUrl - scenarios { - id - at { - id - name - } - commands { - id - text - } - } - assertions { - id - priority - text - } - } + } + scenarioResult { + output + unexpectedBehaviors { + text + impact + details } + } + assertionResult { + passed + } + } + } + at { + id + name + atVersions { + id + name + } + } + browser { + id + name + browserVersions { + id + name + } + } + testPlanVersion { + id + title + phase + updatedAt + gitSha + testPageUrl + testPlan { + directory } + metadata + } + runnableTests { + id + rowNumber + title + ats { + id + name + } + atMode + renderedUrl + scenarios { + id + at { + id + name + } + commands { + id + text + } + } + assertions { + id + priority + text + } + } } + } } + } `; export const DELETE_TEST_RESULT_MUTATION = gql` - mutation DeleteTestResult($id: ID!) { - testResult(id: $id) { - deleteTestResult { - locationOfData - } - } + mutation DeleteTestResult($id: ID!) { + testResult(id: $id) { + deleteTestResult { + locationOfData + } } + } `; export const FIND_OR_CREATE_BROWSER_VERSION_MUTATION = gql` - mutation FindOrCreateBrowserVersion( - $browserId: ID! - $browserVersionName: String! - ) { - browser(id: $browserId) { - findOrCreateBrowserVersion(input: { name: $browserVersionName }) { - id - name - } - } + mutation FindOrCreateBrowserVersion( + $browserId: ID! + $browserVersionName: String! + ) { + browser(id: $browserId) { + findOrCreateBrowserVersion(input: { name: $browserVersionName }) { + id + name + } } + } `; export const COLLECTION_JOB_STATUS_BY_TEST_PLAN_RUN_ID_QUERY = gql` - query CollectionJobIdByTestPlanRunId($testPlanRunId: ID!) { - collectionJobByTestPlanRunId(testPlanRunId: $testPlanRunId) { - id - status - externalLogsUrl - } + query CollectionJobIdByTestPlanRunId($testPlanRunId: ID!) { + collectionJobByTestPlanRunId(testPlanRunId: $testPlanRunId) { + id + status + externalLogsUrl } + } `; diff --git a/client/components/UserSettings/UserSettings.jsx b/client/components/UserSettings/UserSettings.jsx index f28e34a60..3a8f99d22 100644 --- a/client/components/UserSettings/UserSettings.jsx +++ b/client/components/UserSettings/UserSettings.jsx @@ -6,151 +6,137 @@ import PageStatus from '../common/PageStatus'; import { CURRENT_SETTINGS_QUERY, UPDATE_ME_MUTATION } from './queries'; const UserSettings = () => { - const { loading, data, error } = useQuery(CURRENT_SETTINGS_QUERY); + const { loading, data, error } = useQuery(CURRENT_SETTINGS_QUERY); - const [updateMe] = useMutation(UPDATE_ME_MUTATION, { - refetchQueries: [{ query: CURRENT_SETTINGS_QUERY }] - }); + const [updateMe] = useMutation(UPDATE_ME_MUTATION, { + refetchQueries: [{ query: CURRENT_SETTINGS_QUERY }] + }); - const [checkedAts, setCheckedAts] = useState(undefined); + const [checkedAts, setCheckedAts] = useState(undefined); - const handleCheckedAt = useCallback( - event => { - const atId = event.target.id; - const isChecked = checkedAts.includes(atId); - if (isChecked) { - setCheckedAts(checkedAts.filter(item => item !== atId)); - } else { - setCheckedAts([...checkedAts, atId]); - } - }, - [checkedAts] - ); + const handleCheckedAt = useCallback( + event => { + const atId = event.target.id; + const isChecked = checkedAts.includes(atId); + if (isChecked) { + setCheckedAts(checkedAts.filter(item => item !== atId)); + } else { + setCheckedAts([...checkedAts, atId]); + } + }, + [checkedAts] + ); - const handleSave = useCallback( - event => { - event.preventDefault(); - updateMe({ variables: { input: { atIds: checkedAts } } }); - }, - [checkedAts] - ); + const handleSave = useCallback( + event => { + event.preventDefault(); + updateMe({ variables: { input: { atIds: checkedAts } } }); + }, + [checkedAts] + ); - useEffect(() => { - if (!data) return; - setCheckedAts(data.me.ats.map(at => at.id)); - }, [data]); + useEffect(() => { + if (!data) return; + setCheckedAts(data.me.ats.map(at => at.id)); + }, [data]); - if (error) { - return ( - - ); - } + if (error) { + return ( + + ); + } - if (loading) { - return ( - - ); - } + if (loading) { + return ( + + ); + } - if (!data || !checkedAts) return null; + if (!data || !checkedAts) return null; - const { - ats, - me: { username, ats: userAtsData } - } = data; - const savedAts = userAtsData.map(at => at.id); + const { + ats, + me: { username, ats: userAtsData } + } = data; + const savedAts = userAtsData.map(at => at.id); - return ( - - - - Settings | ARIA-AT - -

    Settings

    -
    -

    User Details

    -

    - - {username} - -

    -

    Assistive Technology Settings

    -
    - {savedAts.length > 0 ? ( -
    -

    - You can currently test the following - assistive technologies: -

    -
      - {ats - .filter(({ id: atId }) => - savedAts.includes(atId) - ) - .map(at => ( -
    • {at.name}
    • - ))} -
    -
    - ) : ( -

    - You currently are not configured to run any - assistive technologies. -

    - )} -
    -

    - Submit the form below to update the assistive - technologies you can test: -

    -
    -

    ATs

    - - {ats && - ats.map(at => { - return ( - atId === at.id - ) - } - /> - ); - })} - - -
    -
    -
    -
    - ); + return ( + + + + Settings | ARIA-AT + +

    Settings

    +
    +

    User Details

    +

    + + {username} + +

    +

    Assistive Technology Settings

    +
    + {savedAts.length > 0 ? ( +
    +

    + You can currently test the following assistive technologies: +

    +
      + {ats + .filter(({ id: atId }) => savedAts.includes(atId)) + .map(at => ( +
    • {at.name}
    • + ))} +
    +
    + ) : ( +

    + You currently are not configured to run any assistive + technologies. +

    + )} +
    +

    + Submit the form below to update the assistive technologies you can + test: +

    +
    +

    ATs

    + + {ats && + ats.map(at => { + return ( + atId === at.id)} + /> + ); + })} + + +
    +
    +
    +
    + ); }; export default UserSettings; diff --git a/client/components/UserSettings/queries.js b/client/components/UserSettings/queries.js index a04a00da9..552a47c2d 100644 --- a/client/components/UserSettings/queries.js +++ b/client/components/UserSettings/queries.js @@ -1,27 +1,27 @@ import { gql } from '@apollo/client'; export const CURRENT_SETTINGS_QUERY = gql` - query CurrentSettings { - me { - id - username - ats { - id - } - } - ats { - id - name - } + query CurrentSettings { + me { + id + username + ats { + id + } } + ats { + id + name + } + } `; export const UPDATE_ME_MUTATION = gql` - mutation UpdateMe($input: UserInput) { - updateMe(input: $input) { - ats { - id - } - } + mutation UpdateMe($input: UserInput) { + updateMe(input: $input) { + ats { + id + } } + } `; diff --git a/client/components/common/AtAndBrowserDetailsModal/index.jsx b/client/components/common/AtAndBrowserDetailsModal/index.jsx index 6010586c7..7f142ce68 100644 --- a/client/components/common/AtAndBrowserDetailsModal/index.jsx +++ b/client/components/common/AtAndBrowserDetailsModal/index.jsx @@ -5,629 +5,548 @@ import { Form, Alert } from 'react-bootstrap'; import styled from '@emotion/styled'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { - faInfoCircle, - faExclamationTriangle + faInfoCircle, + faExclamationTriangle } from '@fortawesome/free-solid-svg-icons'; import { useDetectUa } from '../../../hooks/useDetectUa'; import BasicModal from '../BasicModal'; const ModalInnerSectionContainer = styled.div` - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; `; const FieldsetRow = styled.fieldset` - display: grid; - grid-template-columns: 1fr 1fr; - grid-gap: 1rem; + display: grid; + grid-template-columns: 1fr 1fr; + grid-gap: 1rem; - legend { - float: inherit; - } + legend { + float: inherit; + } `; const ModalSubtitleStyle = styled.h2` - font-size: 0.8em; - margin: 0; - padding: 0; + font-size: 0.8em; + margin: 0; + padding: 0; `; const Required = styled.span` - color: #ce1b4c; + color: #ce1b4c; - :after { - content: '*'; - } + :after { + content: '*'; + } `; const AtAndBrowserDetailsModal = ({ - show = false, - isAdmin = false, - firstLoad = true, - atName = '', - atVersion = '', - atVersions = [], - browserName = '', - browserVersion = '', - patternName = '', // admin related prop - testerName = '', // admin related prop - handleAction = () => {}, - handleClose = () => {} + show = false, + isAdmin = false, + firstLoad = true, + atName = '', + atVersion = '', + atVersions = [], + browserName = '', + browserVersion = '', + patternName = '', // admin related prop + testerName = '', // admin related prop + handleAction = () => {}, + handleClose = () => {} }) => { - // Detect UA information - const { uaBrowser, uaMajor, uaMinor, uaPatch } = useDetectUa(); - - const navigate = useNavigate(); - - const updatedAtVersionDropdownRef = useRef(); - const updatedBrowserVersionTextRef = useRef(); - - const [showExitModal, setShowExitModal] = useState(false); - const [isFirstLoad, setIsFirstLoad] = useState(true); - const [updatedAtVersion, setUpdatedAtVersion] = - useState('Select a Version'); - const [updatedBrowserVersion, setUpdatedBrowserVersion] = useState(''); - - const [isAtVersionError, setIsAtVersionError] = useState(false); - const [isBrowserVersionError, setIsBrowserVersionError] = useState(false); - - const [ - forceBrowserVersionUpdateMessage, - setForceBrowserVersionUpdateMessage - ] = useState(false); - const [browserVersionMismatchMessage, setBrowserVersionMismatchMessage] = - useState(false); - - useEffect(() => { - setIsFirstLoad(firstLoad); - if (!firstLoad) { - setUpdatedAtVersion(atVersion); - setUpdatedBrowserVersion(browserVersion); - } - if (uaMajor === '0') { - setUpdatedBrowserVersion(''); - updatedBrowserVersionTextRef.current.focus(); - } + // Detect UA information + const { uaBrowser, uaMajor, uaMinor, uaPatch } = useDetectUa(); + + const navigate = useNavigate(); + + const updatedAtVersionDropdownRef = useRef(); + const updatedBrowserVersionTextRef = useRef(); + + const [showExitModal, setShowExitModal] = useState(false); + const [isFirstLoad, setIsFirstLoad] = useState(true); + const [updatedAtVersion, setUpdatedAtVersion] = useState('Select a Version'); + const [updatedBrowserVersion, setUpdatedBrowserVersion] = useState(''); + + const [isAtVersionError, setIsAtVersionError] = useState(false); + const [isBrowserVersionError, setIsBrowserVersionError] = useState(false); + + const [ + forceBrowserVersionUpdateMessage, + setForceBrowserVersionUpdateMessage + ] = useState(false); + const [browserVersionMismatchMessage, setBrowserVersionMismatchMessage] = + useState(false); + + useEffect(() => { + setIsFirstLoad(firstLoad); + if (!firstLoad) { + setUpdatedAtVersion(atVersion); + setUpdatedBrowserVersion(browserVersion); + } + if (uaMajor === '0') { + setUpdatedBrowserVersion(''); + updatedBrowserVersionTextRef.current.focus(); + } - const foundBrowserVersion = - uaBrowser === browserName && - uaMajor !== '0' && - `${uaMajor}.${uaMinor}.${uaPatch}`; - - if ( - // don't force browserVersion update with admin (unless first run) - (!isAdmin || (isAdmin && firstLoad)) && - // check that saved browserVersion is the same as detected - !browserVersion.includes(`${uaMajor}.${uaMinor}.${uaPatch}`) && - uaBrowser === browserName && - foundBrowserVersion - ) { - setForceBrowserVersionUpdateMessage(true); - setUpdatedBrowserVersion(foundBrowserVersion); - } - }, [uaBrowser, uaMajor, uaMinor, uaPatch]); - - useEffect(() => { - // check to support Tester Scenario 5 - if ( - uaMajor !== '0' && - !updatedBrowserVersion.includes(`${uaMajor}.${uaMinor}.${uaPatch}`) - ) - setBrowserVersionMismatchMessage(true); - else setBrowserVersionMismatchMessage(!isAdmin && false); - }, [updatedBrowserVersion, uaMajor, uaMinor, uaPatch]); - - useEffect(() => { - const forceFocusOnBrowserVersion = - !isFirstLoad && !isAdmin && forceBrowserVersionUpdateMessage; - - if (forceFocusOnBrowserVersion) - updatedBrowserVersionTextRef.current.focus(); - }, [forceBrowserVersionUpdateMessage]); - - const handleAtVersionChange = e => { - const value = e.target.value; - setUpdatedAtVersion(value); - setIsAtVersionError(false); - }; - - const handleBrowserVersionChange = e => { - const value = e.target.value; - - setUpdatedBrowserVersion(value); - - // remove message once browser has been changed - !isAdmin && setForceBrowserVersionUpdateMessage(false); - setIsBrowserVersionError(false); - }; - - const onSubmit = () => { - // Passed action prop should account for AtVersion & BrowserVersion - const updatedAtVersionError = updatedAtVersion === 'Select a Version'; - const isBrowserVersionTextError = !updatedBrowserVersion; - - if (updatedAtVersionError || isBrowserVersionTextError) { - setIsAtVersionError(updatedAtVersionError); - updatedAtVersionDropdownRef.current.focus(); - - setIsBrowserVersionError(isBrowserVersionTextError); - if (!updatedAtVersionError) - updatedBrowserVersionTextRef.current.focus(); - return; - } + const foundBrowserVersion = + uaBrowser === browserName && + uaMajor !== '0' && + `${uaMajor}.${uaMinor}.${uaPatch}`; + + if ( + // don't force browserVersion update with admin (unless first run) + (!isAdmin || (isAdmin && firstLoad)) && + // check that saved browserVersion is the same as detected + !browserVersion.includes(`${uaMajor}.${uaMinor}.${uaPatch}`) && + uaBrowser === browserName && + foundBrowserVersion + ) { + setForceBrowserVersionUpdateMessage(true); + setUpdatedBrowserVersion(foundBrowserVersion); + } + }, [uaBrowser, uaMajor, uaMinor, uaPatch]); + + useEffect(() => { + // check to support Tester Scenario 5 + if ( + uaMajor !== '0' && + !updatedBrowserVersion.includes(`${uaMajor}.${uaMinor}.${uaPatch}`) + ) + setBrowserVersionMismatchMessage(true); + else setBrowserVersionMismatchMessage(!isAdmin && false); + }, [updatedBrowserVersion, uaMajor, uaMinor, uaPatch]); + + useEffect(() => { + const forceFocusOnBrowserVersion = + !isFirstLoad && !isAdmin && forceBrowserVersionUpdateMessage; + + if (forceFocusOnBrowserVersion) + updatedBrowserVersionTextRef.current.focus(); + }, [forceBrowserVersionUpdateMessage]); + + const handleAtVersionChange = e => { + const value = e.target.value; + setUpdatedAtVersion(value); + setIsAtVersionError(false); + }; + + const handleBrowserVersionChange = e => { + const value = e.target.value; + + setUpdatedBrowserVersion(value); + + // remove message once browser has been changed + !isAdmin && setForceBrowserVersionUpdateMessage(false); + setIsBrowserVersionError(false); + }; + + const onSubmit = () => { + // Passed action prop should account for AtVersion & BrowserVersion + const updatedAtVersionError = updatedAtVersion === 'Select a Version'; + const isBrowserVersionTextError = !updatedBrowserVersion; + + if (updatedAtVersionError || isBrowserVersionTextError) { + setIsAtVersionError(updatedAtVersionError); + updatedAtVersionDropdownRef.current.focus(); + + setIsBrowserVersionError(isBrowserVersionTextError); + if (!updatedAtVersionError) updatedBrowserVersionTextRef.current.focus(); + return; + } - let updateMessage = null; - if (isFirstLoad) - updateMessage = - 'Your AT and Browser versions have been successfully saved.'; - else { - if ( - updatedAtVersion !== atVersion && - updatedBrowserVersion !== browserVersion - ) - updateMessage = ( - <> - Your version of {atName} has been updated to{' '} - {updatedAtVersion}. Your previous version was{' '} - {atVersion}. -
    - Your version of {browserName} has been updated to{' '} - {updatedBrowserVersion}. Your previous version - was {browserVersion}. - - ); - else if (updatedAtVersion !== atVersion) - updateMessage = ( - <> - Your version of {atName} has been updated to{' '} - {updatedAtVersion}. Your previous version was{' '} - {atVersion}. - - ); - else if (updatedBrowserVersion !== browserVersion) - updateMessage = ( - <> - Your version of {browserName} has been updated to{' '} - {updatedBrowserVersion}. Your previous version - was {browserVersion}. - - ); - } + let updateMessage = null; + if (isFirstLoad) + updateMessage = + 'Your AT and Browser versions have been successfully saved.'; + else { + if ( + updatedAtVersion !== atVersion && + updatedBrowserVersion !== browserVersion + ) + updateMessage = ( + <> + Your version of {atName} has been updated to{' '} + {updatedAtVersion}. Your previous version was{' '} + {atVersion}. +
    + Your version of {browserName} has been updated to{' '} + {updatedBrowserVersion}. Your previous version was{' '} + {browserVersion}. + + ); + else if (updatedAtVersion !== atVersion) + updateMessage = ( + <> + Your version of {atName} has been updated to{' '} + {updatedAtVersion}. Your previous version was{' '} + {atVersion}. + + ); + else if (updatedBrowserVersion !== browserVersion) + updateMessage = ( + <> + Your version of {browserName} has been updated to{' '} + {updatedBrowserVersion}. Your previous version was{' '} + {browserVersion}. + + ); + } - handleAction(updatedAtVersion, updatedBrowserVersion, updateMessage); - }; - - const handleHide = () => setShowExitModal(true); - - // All scenarios here are based on - // https://github.com/w3c/aria-at-app/issues/406 & - // https://github.com/w3c/aria-at-app/issues/436 - return ( - <> - - You will be taken back to the Test Queue. Any - changes you made to your Assistive Technology and - Browser versions will not be saved. - - } - actions={[ - { - label: 'Ok', - onClick: () => navigate('/test-queue') - } - ]} - closeLabel="Cancel" - handleClose={() => setShowExitModal(false)} - staticBackdrop={true} - /> - - {!showExitModal && ( - - {/* Admin Scenario 1 */} - {isAdmin && ( - - - - You are about to review{' '} - {patternName} as{' '} - {testerName}. Your Assistive - Technology and Browser might be - different. Please proceed with caution. - - - )} - Your Assistive Technology and Browser Details are - the following. Please make sure this information is - still accurate. -
    -
    - - - - Assistive Technology Details - - - {/* Tester Scenario 6 */} - {!isFirstLoad && - updatedAtVersion !== atVersion && ( - - - - You have selected{' '} - {updatedAtVersion} for{' '} - {atName}. This version is - different from the one - previously selected which was{' '} - {atVersion}. -
    -
    - This change doesn't affect - results that have already been - submitted for this plan. - However, results you submit - during this session will be - recorded with the versions - specified in this form. -
    -
    - )} - - - Assistive Technology Name - - - - - - - Assistive Technology Version - - - - {[ - 'Select a Version', - ...atVersions - ].map(item => ( - - ))} - - {isAtVersionError && ( - - Please select an Assistive - Technology Version. - - )} - -
    - - - - Browser Details - - - {/* Tester Scenario 1 */} - {isFirstLoad && - uaBrowser && - uaMajor !== '0' && ( - - - - We have automatically detected - your version of {uaBrowser} - - - )} - {/* Tester Scenario 3 */} - {!isFirstLoad && - !isAdmin && - forceBrowserVersionUpdateMessage && ( - - - - We have automatically detected - you are using a different - version of {uaBrowser}{' '} - and we have updated it below. - The previous version you were - using was{' '} - {browserVersion}. -
    -
    - This change doesn't affect - results that have already been - submitted for this plan. - However, results you submit - during this session will be - recorded with the versions - specified in this form. -
    -
    - )} - {isFirstLoad && - uaBrowser !== browserName && - uaMajor !== '0' && ( - - - - We have automatically detected - you are using{' '} - - {uaBrowser} {uaMajor}. - {uaMinor}.{uaPatch} - - . This test plan requires{' '} - {browserName}. If you are - recording results on behalf of - someone else, please provide the - Browser version below. - - - )} - {/* Tester Scenario 4 */} - {!isAdmin && - !isFirstLoad && - uaBrowser !== browserName && - uaMajor !== '0' && ( - - - - We have automatically detected - you are now using{' '} - - {uaBrowser} {uaMajor}. - {uaMinor}.{uaPatch} - - , which is a different browser - from the last one you were - testing with, which was{' '} - - {browserName}{' '} - {browserVersion} - - . -
    -
    - You can't edit your Browser - type, but you can continue with{' '} - - {uaBrowser} {uaMajor}. - {uaMinor}.{uaPatch} - - . Keep in mind that your test - results will be recorded as if - you were still using{' '} - - {browserName}{' '} - {browserVersion} - - . -
    -
    - )} - {/* Tester Scenario 5 */} - {!isAdmin && - uaBrowser === browserName && - browserVersionMismatchMessage && ( - - - - The version of {browserName} you - have set is different from the - one we have automatically - detected, which is{' '} - - {uaMajor}.{uaMinor}. - {uaPatch} - - . -
    -
    - This change doesn't affect - results that have already been - submitted for this plan. - However, results you submit - during this session will be - recorded with the versions - specified in this form. -
    -
    - )} - {/* Tester Scenario 7 */} - {uaMajor === '0' && ( - - - - We could not automatically detect - what version of {browserName}{' '} - you are using. Before continuing, - please provide your version number. - - - )} - {/* Admin Scenario 1 */} - {isAdmin && - (uaBrowser !== browserName || - browserVersionMismatchMessage) && ( - - - - We have automatically detected - you are using{' '} - - {uaBrowser} {uaMajor}. - {uaMinor}.{uaPatch} - - . This version is different than - what {testerName} was - using last time, which was{' '} - - {browserName}{' '} - {browserVersion} - - . -
    -
    - We have not updated this - information below. Please - proceed with caution. -
    -
    - )} - - Browser Name - - - - - - Browser Version - - - - {isBrowserVersionError && ( - - Please enter a valid Browser - Version. - - )} - -
    - - } - actions={[ - { - label: - updatedAtVersion !== atVersion || - updatedBrowserVersion !== browserVersion - ? 'Save and Continue' - : 'Continue', - onClick: - updatedAtVersion !== atVersion || - updatedBrowserVersion !== browserVersion - ? onSubmit - : handleClose - } - ]} - handleClose={!isFirstLoad ? handleClose : null} - handleHide={handleHide} - staticBackdrop={true} - useOnHide={true} - /> - )} - - ); + handleAction(updatedAtVersion, updatedBrowserVersion, updateMessage); + }; + + const handleHide = () => setShowExitModal(true); + + // All scenarios here are based on + // https://github.com/w3c/aria-at-app/issues/406 & + // https://github.com/w3c/aria-at-app/issues/436 + return ( + <> + + You will be taken back to the Test Queue. Any changes you + made to your Assistive Technology and Browser versions will not be + saved. + + } + actions={[ + { + label: 'Ok', + onClick: () => navigate('/test-queue') + } + ]} + closeLabel="Cancel" + handleClose={() => setShowExitModal(false)} + staticBackdrop={true} + /> + + {!showExitModal && ( + + {/* Admin Scenario 1 */} + {isAdmin && ( + + + + You are about to review {patternName} as{' '} + {testerName}. Your Assistive Technology and Browser + might be different. Please proceed with caution. + + + )} + Your Assistive Technology and Browser Details are the following. + Please make sure this information is still accurate. +
    +
    + + + + Assistive Technology Details + + + {/* Tester Scenario 6 */} + {!isFirstLoad && updatedAtVersion !== atVersion && ( + + + + You have selected {updatedAtVersion} for{' '} + {atName}. This version is different from the one + previously selected which was {atVersion}. +
    +
    + This change doesn't affect results that have already + been submitted for this plan. However, results you submit + during this session will be recorded with the versions + specified in this form. +
    +
    + )} + + Assistive Technology Name + + + + + + Assistive Technology Version + + + + {['Select a Version', ...atVersions].map(item => ( + + ))} + + {isAtVersionError && ( + + Please select an Assistive Technology Version. + + )} + +
    + + + Browser Details + + {/* Tester Scenario 1 */} + {isFirstLoad && uaBrowser && uaMajor !== '0' && ( + + + + We have automatically detected your version of {uaBrowser} + + + )} + {/* Tester Scenario 3 */} + {!isFirstLoad && + !isAdmin && + forceBrowserVersionUpdateMessage && ( + + + + We have automatically detected you are using a different + version of {uaBrowser} and we have updated it + below. The previous version you were using was{' '} + {browserVersion}. +
    +
    + This change doesn't affect results that have + already been submitted for this plan. However, results + you submit during this session will be recorded with the + versions specified in this form. +
    +
    + )} + {isFirstLoad && + uaBrowser !== browserName && + uaMajor !== '0' && ( + + + + We have automatically detected you are using{' '} + + {uaBrowser} {uaMajor}.{uaMinor}.{uaPatch} + + . This test plan requires {browserName}. If you + are recording results on behalf of someone else, please + provide the Browser version below. + + + )} + {/* Tester Scenario 4 */} + {!isAdmin && + !isFirstLoad && + uaBrowser !== browserName && + uaMajor !== '0' && ( + + + + We have automatically detected you are now using{' '} + + {uaBrowser} {uaMajor}.{uaMinor}.{uaPatch} + + , which is a different browser from the last one you + were testing with, which was{' '} + + {browserName} {browserVersion} + + . +
    +
    + You can't edit your Browser type, but you can + continue with{' '} + + {uaBrowser} {uaMajor}.{uaMinor}.{uaPatch} + + . Keep in mind that your test results will be recorded + as if you were still using{' '} + + {browserName} {browserVersion} + + . +
    +
    + )} + {/* Tester Scenario 5 */} + {!isAdmin && + uaBrowser === browserName && + browserVersionMismatchMessage && ( + + + + The version of {browserName} you have set is different + from the one we have automatically detected, which is{' '} + + {uaMajor}.{uaMinor}.{uaPatch} + + . +
    +
    + This change doesn't affect results that have + already been submitted for this plan. However, results + you submit during this session will be recorded with the + versions specified in this form. +
    +
    + )} + {/* Tester Scenario 7 */} + {uaMajor === '0' && ( + + + + We could not automatically detect what version of{' '} + {browserName} you are using. Before continuing, + please provide your version number. + + + )} + {/* Admin Scenario 1 */} + {isAdmin && + (uaBrowser !== browserName || + browserVersionMismatchMessage) && ( + + + + We have automatically detected you are using{' '} + + {uaBrowser} {uaMajor}.{uaMinor}.{uaPatch} + + . This version is different than what{' '} + {testerName} was using last time, which was{' '} + + {browserName} {browserVersion} + + . +
    +
    + We have not updated this information below. Please + proceed with caution. +
    +
    + )} + + Browser Name + + + + + + Browser Version + + + + {isBrowserVersionError && ( + + Please enter a valid Browser Version. + + )} + +
    + + } + actions={[ + { + label: + updatedAtVersion !== atVersion || + updatedBrowserVersion !== browserVersion + ? 'Save and Continue' + : 'Continue', + onClick: + updatedAtVersion !== atVersion || + updatedBrowserVersion !== browserVersion + ? onSubmit + : handleClose + } + ]} + handleClose={!isFirstLoad ? handleClose : null} + handleHide={handleHide} + staticBackdrop={true} + useOnHide={true} + /> + )} + + ); }; AtAndBrowserDetailsModal.propTypes = { - show: PropTypes.bool, - isAdmin: PropTypes.bool, - firstLoad: PropTypes.bool, - atName: PropTypes.string, - atVersion: PropTypes.string, - atVersions: PropTypes.arrayOf(PropTypes.string), - browserName: PropTypes.string, - browserVersion: PropTypes.string, - browserVersions: PropTypes.arrayOf(PropTypes.string), - patternName: PropTypes.string, - testerName: PropTypes.string, - handleClose: PropTypes.func, - handleAction: PropTypes.func + show: PropTypes.bool, + isAdmin: PropTypes.bool, + firstLoad: PropTypes.bool, + atName: PropTypes.string, + atVersion: PropTypes.string, + atVersions: PropTypes.arrayOf(PropTypes.string), + browserName: PropTypes.string, + browserVersion: PropTypes.string, + browserVersions: PropTypes.arrayOf(PropTypes.string), + patternName: PropTypes.string, + testerName: PropTypes.string, + handleClose: PropTypes.func, + handleAction: PropTypes.func }; export default AtAndBrowserDetailsModal; diff --git a/client/components/common/BasicModal/BasicModal.css b/client/components/common/BasicModal/BasicModal.css index c602831e3..37afcaa0c 100644 --- a/client/components/common/BasicModal/BasicModal.css +++ b/client/components/common/BasicModal/BasicModal.css @@ -1,19 +1,19 @@ /* Allow multiple dialogs to be open at the same time */ div[role='dialog'][aria-modal='true']:nth-last-child(1) { - z-index: 1125; + z-index: 1125; } .modal-backdrop.show:nth-last-child(2) { - z-index: 1100; + z-index: 1100; } div[role='dialog'][aria-modal='true']:nth-last-child(3) { - z-index: 1075; + z-index: 1075; } .modal-backdrop.show:nth-last-child(4) { - z-index: 1050; + z-index: 1050; } div[role='dialog'][aria-modal='true']:nth-last-child(5) { - z-index: 1025; + z-index: 1025; } .modal-backdrop.show:nth-last-child(6) { - z-index: 1000; + z-index: 1000; } diff --git a/client/components/common/BasicModal/index.jsx b/client/components/common/BasicModal/index.jsx index 89a59ee97..76a786d8f 100644 --- a/client/components/common/BasicModal/index.jsx +++ b/client/components/common/BasicModal/index.jsx @@ -8,147 +8,143 @@ import { uniqueId } from 'lodash'; import './BasicModal.css'; const ModalTitleStyle = styled.h1` - border: 0; - padding: 0; - font-size: 1.5rem; + border: 0; + padding: 0; + font-size: 1.5rem; `; const BasicModal = ({ - show = false, - centered = false, - animation = true, - closeButton = true, - cancelButton = true, - headerSep = true, - showFooter = true, - dialogClassName = '', - title = null, - content = null, - closeLabel = 'Cancel', - handleClose = null, - handleHide = null, - staticBackdrop = false, - useOnHide = false, - actions = [], - initialFocusRef = null + show = false, + centered = false, + animation = true, + closeButton = true, + cancelButton = true, + headerSep = true, + showFooter = true, + dialogClassName = '', + title = null, + content = null, + closeLabel = 'Cancel', + handleClose = null, + handleHide = null, + staticBackdrop = false, + useOnHide = false, + actions = [], + initialFocusRef = null }) => { - const headerRef = useRef(); + const headerRef = useRef(); - useEffect(() => { - if (!show) return; - if (initialFocusRef?.current) { - initialFocusRef.current.focus(); - } else { - headerRef.current.focus(); - } - }, [show]); + useEffect(() => { + if (!show) return; + if (initialFocusRef?.current) { + initialFocusRef.current.focus(); + } else { + headerRef.current.focus(); + } + }, [show]); - const id = useMemo(() => { - return uniqueId('modal-'); - }, []); + const id = useMemo(() => { + return uniqueId('modal-'); + }, []); - const renderAction = (action, index) => { - if (action.component) { - return React.createElement( - action.component, - { key: `CustomComponent_${index}`, ...action.props }, - null - ); - } else { - return ( - - ); - } - }; + const renderAction = (action, index) => { + if (action.component) { + return React.createElement( + action.component, + { key: `CustomComponent_${index}`, ...action.props }, + null + ); + } else { + return ( + + ); + } + }; - return ( - + + - - - - {title} - - - {content} - {showFooter && ( - - {cancelButton && handleClose && ( - - )} - {actions.map((action, index) => - renderAction(action, index) - )} - - )} - - - ); + + {title} + + + {content} + {showFooter && ( + + {cancelButton && handleClose && ( + + )} + {actions.map((action, index) => renderAction(action, index))} + + )} + + + ); }; BasicModal.propTypes = { - show: PropTypes.bool, - centered: PropTypes.bool, - animation: PropTypes.bool, - closeButton: PropTypes.bool, - cancelButton: PropTypes.bool, - headerSep: PropTypes.bool, - showFooter: PropTypes.bool, - dialogClassName: PropTypes.string, - title: PropTypes.node.isRequired, - content: PropTypes.node, - closeLabel: PropTypes.string, - handleClose: PropTypes.func, - 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, - component: PropTypes.elementType, - props: PropTypes.object - }) - ), - initialFocusRef: PropTypes.shape({ - current: PropTypes.any + show: PropTypes.bool, + centered: PropTypes.bool, + animation: PropTypes.bool, + closeButton: PropTypes.bool, + cancelButton: PropTypes.bool, + headerSep: PropTypes.bool, + showFooter: PropTypes.bool, + dialogClassName: PropTypes.string, + title: PropTypes.node.isRequired, + content: PropTypes.node, + closeLabel: PropTypes.string, + handleClose: PropTypes.func, + 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, + component: PropTypes.elementType, + props: PropTypes.object }) + ), + initialFocusRef: PropTypes.shape({ + current: PropTypes.any + }) }; export default BasicModal; diff --git a/client/components/common/BasicThemedModal/index.jsx b/client/components/common/BasicThemedModal/index.jsx index 788ac6966..d2dafffb2 100644 --- a/client/components/common/BasicThemedModal/index.jsx +++ b/client/components/common/BasicThemedModal/index.jsx @@ -7,132 +7,130 @@ import styled from '@emotion/styled'; import { uniqueId } from 'lodash'; const ModalTitleStyle = styled.h1` - border: 0; - padding: 0; - font-size: 1.5rem; + border: 0; + padding: 0; + font-size: 1.5rem; `; const ModalInnerSectionContainer = styled.div` - display: grid; - grid-auto-flow: column; + display: grid; + grid-auto-flow: column; - grid-template-columns: 50px auto; - grid-gap: 10px; + grid-template-columns: 50px auto; + grid-gap: 10px; `; const ColorStrip = styled.div` - width: 100%; - height: 10px; - ${props => props.hideHeadline && `display: none;`} - background-color: ${({ theme }) => - theme === 'danger' ? '#ce1b4c' : '#fab700'}; + width: 100%; + height: 10px; + ${props => props.hideHeadline && `display: none;`} + background-color: ${({ theme }) => + theme === 'danger' ? '#ce1b4c' : '#fab700'}; - border-top-left-radius: calc(0.3rem - 1px); - border-top-right-radius: calc(0.3rem - 1px); + border-top-left-radius: calc(0.3rem - 1px); + border-top-right-radius: calc(0.3rem - 1px); `; const BasicThemedModal = ({ - show = false, - centered = false, - animation = true, - theme = 'warning', // warning, danger - dialogClassName = '', - title = null, - content = null, - actionButtons = [], - closeLabel = 'Cancel', - handleClose = null, - showCloseAction = true + show = false, + centered = false, + animation = true, + theme = 'warning', // warning, danger + dialogClassName = '', + title = null, + content = null, + actionButtons = [], + closeLabel = 'Cancel', + handleClose = null, + showCloseAction = true }) => { - const headerRef = useRef(); + const headerRef = useRef(); - useEffect(() => { - if (!show) return; - headerRef.current.focus(); - }, [show]); + useEffect(() => { + if (!show) return; + headerRef.current.focus(); + }, [show]); - const id = useMemo(() => { - return uniqueId('modal-'); - }, []); + const id = useMemo(() => { + return uniqueId('modal-'); + }, []); - return ( - <> - + + + + + + + {title} + + + + + + <> +
    +
    {content}
    + + + + + {showCloseAction && ( + + )} + {actionButtons.map(({ action, text }) => ( + - )} - {actionButtons.map(({ action, text }) => ( - - ))} - - - - ); + {text} + + ))} + + + + ); }; BasicThemedModal.propTypes = { - show: PropTypes.bool, - centered: PropTypes.bool, - animation: PropTypes.bool, - theme: PropTypes.string, - dialogClassName: PropTypes.string, - title: PropTypes.node.isRequired, - content: PropTypes.node.isRequired, - actionButtons: PropTypes.arrayOf( - PropTypes.shape({ - text: PropTypes.string, - action: PropTypes.func - }) - ), - closeLabel: PropTypes.string, - handleClose: PropTypes.func, - showCloseAction: PropTypes.bool + show: PropTypes.bool, + centered: PropTypes.bool, + animation: PropTypes.bool, + theme: PropTypes.string, + dialogClassName: PropTypes.string, + title: PropTypes.node.isRequired, + content: PropTypes.node.isRequired, + actionButtons: PropTypes.arrayOf( + PropTypes.shape({ + text: PropTypes.string, + action: PropTypes.func + }) + ), + closeLabel: PropTypes.string, + handleClose: PropTypes.func, + showCloseAction: PropTypes.bool }; export default BasicThemedModal; diff --git a/client/components/common/ClippedProgressBar/ClippedProgressBar.css b/client/components/common/ClippedProgressBar/ClippedProgressBar.css index a0c483da1..d81763427 100644 --- a/client/components/common/ClippedProgressBar/ClippedProgressBar.css +++ b/client/components/common/ClippedProgressBar/ClippedProgressBar.css @@ -1,38 +1,38 @@ .progress { - height: 1.2rem; - border-radius: 1rem; - margin-top: 0.2em; - border: 1px solid gray; + height: 1.2rem; + border-radius: 1rem; + margin-top: 0.2em; + border: 1px solid gray; } .progress .progress-bar.bg-info { - background-color: #0b60ab !important; + background-color: #0b60ab !important; } .progress.clipped { - position: relative; - display: flex; - overflow: hidden; + position: relative; + display: flex; + overflow: hidden; } .progress.clipped .front { - position: absolute; - display: flex; - justify-content: center; - align-items: center; - left: 0; - right: 0; - top: 0; - bottom: 0; - background: #e9ecef; - color: black; + position: absolute; + display: flex; + justify-content: center; + align-items: center; + left: 0; + right: 0; + top: 0; + bottom: 0; + background: #e9ecef; + color: black; } .progress.clipped .back { - display: flex; - justify-content: center; - align-items: center; - width: 100%; - background: #0b60ab; - color: white; + display: flex; + justify-content: center; + align-items: center; + width: 100%; + background: #0b60ab; + color: white; } diff --git a/client/components/common/ClippedProgressBar/index.jsx b/client/components/common/ClippedProgressBar/index.jsx index f78ad28ef..8c82c2cc8 100644 --- a/client/components/common/ClippedProgressBar/index.jsx +++ b/client/components/common/ClippedProgressBar/index.jsx @@ -3,40 +3,40 @@ import PropTypes from 'prop-types'; import './ClippedProgressBar.css'; const ProgressBar = ({ progress = 0, label = '', clipped = true }) => { - return ( - <> - {clipped ? ( -
    -
    - {progress}% -
    -
    {progress}%
    -
    - ) : ( -
    -
    - {progress}% -
    -
    - )} - - ); + return ( + <> + {clipped ? ( +
    +
    + {progress}% +
    +
    {progress}%
    +
    + ) : ( +
    +
    + {progress}% +
    +
    + )} + + ); }; ProgressBar.propTypes = { - progress: PropTypes.number, - label: PropTypes.string, - clipped: PropTypes.bool + progress: PropTypes.number, + label: PropTypes.string, + clipped: PropTypes.bool }; export default ProgressBar; diff --git a/client/components/common/DeleteButton/index.jsx b/client/components/common/DeleteButton/index.jsx index 0bd9cc24d..73dfb203a 100644 --- a/client/components/common/DeleteButton/index.jsx +++ b/client/components/common/DeleteButton/index.jsx @@ -6,29 +6,29 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faTrash } from '@fortawesome/free-solid-svg-icons'; const StyledDeleteButton = styled(Button)` - color: #ce1b4c; + color: #ce1b4c; - &:hover { - background: #ce1b4c; - color: white; - } + &:hover { + background: #ce1b4c; + color: white; + } `; const DeleteButton = ({ onClick, ariaLabel }) => { - return ( - - Delete - - ); + return ( + + Delete + + ); }; DeleteButton.propTypes = { - onClick: PropTypes.func.isRequired, - ariaLabel: PropTypes.string.isRequired + onClick: PropTypes.func.isRequired, + ariaLabel: PropTypes.string.isRequired }; export default DeleteButton; diff --git a/client/components/common/DisclosureComponent/index.jsx b/client/components/common/DisclosureComponent/index.jsx index 4fcee9a3e..0de8f1a17 100644 --- a/client/components/common/DisclosureComponent/index.jsx +++ b/client/components/common/DisclosureComponent/index.jsx @@ -5,23 +5,23 @@ import { faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons'; import PropTypes from 'prop-types'; const DisclosureParent = styled.div` - border: 1px solid #d3d5da; - border-radius: 3px; - width: 100%; - - h1 { - margin: 0; - padding: 0; - } - - h3 { - margin: 0; - padding: 0; - } - - ${({ stacked }) => - stacked && - ` + border: 1px solid #d3d5da; + border-radius: 3px; + width: 100%; + + h1 { + margin: 0; + padding: 0; + } + + h3 { + margin: 0; + padding: 0; + } + + ${({ stacked }) => + stacked && + ` h1:not(:first-of-type) button, h2:not(:first-of-type) button, h3:not(:first-of-type) button, @@ -31,169 +31,165 @@ const DisclosureParent = styled.div` `; const DisclosureButton = styled.button` - position: relative; - width: 100%; - margin: 0; - padding: 1.25rem; - text-align: left; - font-size: 1rem; - font-weight: bold; - border: none; - border-radius: 3px; - background-color: transparent; - - ${({ stacked }) => - stacked && - ` + position: relative; + width: 100%; + margin: 0; + padding: 1.25rem; + text-align: left; + font-size: 1rem; + font-weight: bold; + border: none; + border-radius: 3px; + background-color: transparent; + + ${({ stacked }) => + stacked && + ` &:nth-last-of-type(1) { border-radius: 0 0 3px 3px; } `} - &:hover, + &:hover, &:focus { - padding: 1.25rem; - border: 0 solid #005a9c; - background-color: #def; - cursor: pointer; - } - - .disclosure-icon { - position: absolute; - margin: 0; - top: 50%; - right: 1.25rem; - - color: #969696; - transform: translateY(-50%); - } + padding: 1.25rem; + border: 0 solid #005a9c; + background-color: #def; + cursor: pointer; + } + + .disclosure-icon { + position: absolute; + margin: 0; + top: 50%; + right: 1.25rem; + + color: #969696; + transform: translateY(-50%); + } `; const DisclosureContainer = styled.div` - display: ${({ show, stacked }) => - show && stacked ? 'block' : show ? 'flex' : 'none'}; - flex-direction: ${({ stacked }) => !stacked && 'column'}; - gap: ${({ stacked }) => !stacked && '1.25rem'}; - - background-color: #f8f9fa; - padding: ${({ component }) => - component === 'test-management' ? '0' : '1.25rem'}; - border-top: 1px solid #d3d5da; + display: ${({ show, stacked }) => + show && stacked ? 'block' : show ? 'flex' : 'none'}; + flex-direction: ${({ stacked }) => !stacked && 'column'}; + gap: ${({ stacked }) => !stacked && '1.25rem'}; + + background-color: #f8f9fa; + padding: ${({ component }) => + component === 'test-management' ? '0' : '1.25rem'}; + border-top: 1px solid #d3d5da; `; const DisclosureComponent = ({ - componentId, - title = null, - disclosureContainerView = null, - onClick = null, - expanded = false, - stacked = false, - headingLevel = '3', - className = null + componentId, + title = null, + disclosureContainerView = null, + onClick = null, + expanded = false, + stacked = false, + headingLevel = '3', + className = null }) => { - const [isExpanded, setIsExpanded] = useState(expanded); - const Tag = `h${headingLevel}`; - - return ( - <> - {stacked ? ( - - {title.map((_, index) => { - const buttonTitle = title[index]; - const buttonExpanded = expanded[index]; - const buttonOnClick = onClick[index]; - const buttonDisclosureContainerView = - disclosureContainerView[index]; - - return ( - - - - {buttonTitle} - - - - - {buttonDisclosureContainerView} - - - ); - })} - - ) : ( - - - setIsExpanded(!isExpanded)} - > - {title} - - - - - {disclosureContainerView} - - - )} - - ); + const [isExpanded, setIsExpanded] = useState(expanded); + const Tag = `h${headingLevel}`; + + return ( + <> + {stacked ? ( + + {title.map((_, index) => { + const buttonTitle = title[index]; + const buttonExpanded = expanded[index]; + const buttonOnClick = onClick[index]; + const buttonDisclosureContainerView = + disclosureContainerView[index]; + + return ( + + + + {buttonTitle} + + + + + {buttonDisclosureContainerView} + + + ); + })} + + ) : ( + + + setIsExpanded(!isExpanded)} + > + {title} + + + + + {disclosureContainerView} + + + )} + + ); }; DisclosureComponent.propTypes = { - componentId: PropTypes.string, - title: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.node, - PropTypes.arrayOf(PropTypes.string), - PropTypes.arrayOf(PropTypes.node) - ]), - disclosureContainerView: PropTypes.oneOfType([ - PropTypes.node, - PropTypes.arrayOf(PropTypes.node) - ]), - onClick: PropTypes.oneOfType([ - PropTypes.func, - PropTypes.arrayOf(PropTypes.func) - ]), - expanded: PropTypes.oneOfType([ - PropTypes.bool, - PropTypes.arrayOf(PropTypes.bool) - ]), - stacked: PropTypes.bool, - headingLevel: PropTypes.string, - className: PropTypes.string + componentId: PropTypes.string, + title: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.node, + PropTypes.arrayOf(PropTypes.string), + PropTypes.arrayOf(PropTypes.node) + ]), + disclosureContainerView: PropTypes.oneOfType([ + PropTypes.node, + PropTypes.arrayOf(PropTypes.node) + ]), + onClick: PropTypes.oneOfType([ + PropTypes.func, + PropTypes.arrayOf(PropTypes.func) + ]), + expanded: PropTypes.oneOfType([ + PropTypes.bool, + PropTypes.arrayOf(PropTypes.bool) + ]), + stacked: PropTypes.bool, + headingLevel: PropTypes.string, + className: PropTypes.string }; export default DisclosureComponent; diff --git a/client/components/common/FilterButtons/index.jsx b/client/components/common/FilterButtons/index.jsx index d8938e81a..d9b35ea3c 100644 --- a/client/components/common/FilterButtons/index.jsx +++ b/client/components/common/FilterButtons/index.jsx @@ -4,64 +4,64 @@ import styled from '@emotion/styled'; import { Button } from 'react-bootstrap'; const StyledFilterButton = styled(Button)` - background: #e9ebee; - border-radius: 16px; - margin-left: 12px; - background-color: white; - font-weight: 400; + background: #e9ebee; + border-radius: 16px; + margin-left: 12px; + background-color: white; + font-weight: 400; - &.active, - &:active { - background: #eaf3fe !important; - border: #517dbc 2px solid !important; - box-shadow: none !important; + &.active, + &:active { + background: #eaf3fe !important; + border: #517dbc 2px solid !important; + box-shadow: none !important; - &:hover, - :focus { - box-shadow: 0 0 0 0.2rem rgba(103, 171, 197, 0.5) !important; - } + &:hover, + :focus { + box-shadow: 0 0 0 0.2rem rgba(103, 171, 197, 0.5) !important; } + } `; const FilterButtons = ({ - filterLabel, - filterAriaLabel, - filterOptions, - activeFilter, - onFilterChange + filterLabel, + filterAriaLabel, + filterOptions, + activeFilter, + onFilterChange }) => { - return ( -
      - - {Object.entries(filterOptions).map(([value, label]) => { - const isActive = activeFilter === value; - return ( -
    • - onFilterChange(value)} - > - {label} - -
    • - ); - })} -
    - ); + return ( +
      + + {Object.entries(filterOptions).map(([value, label]) => { + const isActive = activeFilter === value; + return ( +
    • + onFilterChange(value)} + > + {label} + +
    • + ); + })} +
    + ); }; FilterButtons.propTypes = { - filterLabel: PropTypes.string.isRequired, - filterAriaLabel: PropTypes.string, - filterOptions: PropTypes.objectOf(PropTypes.string).isRequired, - activeFilter: PropTypes.string.isRequired, - onFilterChange: PropTypes.func.isRequired + filterLabel: PropTypes.string.isRequired, + filterAriaLabel: PropTypes.string, + filterOptions: PropTypes.objectOf(PropTypes.string).isRequired, + activeFilter: PropTypes.string.isRequired, + onFilterChange: PropTypes.func.isRequired }; export default FilterButtons; diff --git a/client/components/common/FocusTrapper/index.jsx b/client/components/common/FocusTrapper/index.jsx index 60e27642f..af846e188 100644 --- a/client/components/common/FocusTrapper/index.jsx +++ b/client/components/common/FocusTrapper/index.jsx @@ -3,90 +3,89 @@ import PropTypes from 'prop-types'; import { useEffect, useRef } from 'react'; const FocusTrapper = ({ children, isActive, initialFocusRef, trappedElId }) => { - const focusableElsRef = useRef([]); - const updateFocusableElements = () => { - if (focusableElsRef.current.length > 0) return; + const focusableElsRef = useRef([]); + const updateFocusableElements = () => { + if (focusableElsRef.current.length > 0) return; - // Must use getElementById because a ref is not consistently populated - const el = document.getElementById(trappedElId); - if (!el) return; + // Must use getElementById because a ref is not consistently populated + const el = document.getElementById(trappedElId); + if (!el) return; - focusableElsRef.current = Array.from( - el.querySelectorAll( - 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' - ) - ); + focusableElsRef.current = Array.from( + el.querySelectorAll( + 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' + ) + ); - // Create two elements to trap focus before and after the dialog - // APG Example for Dialog used as reference - const before = document.createElement('div'); - const after = document.createElement('div'); - before.tabIndex = 0; - after.tabIndex = 0; - el.prepend(before); - el.append(after); + // Create two elements to trap focus before and after the dialog + // APG Example for Dialog used as reference + const before = document.createElement('div'); + const after = document.createElement('div'); + before.tabIndex = 0; + after.tabIndex = 0; + el.prepend(before); + el.append(after); - focusableElsRef.current.unshift(before); - focusableElsRef.current.push(after); - }; + focusableElsRef.current.unshift(before); + focusableElsRef.current.push(after); + }; - const trapFocus = event => { - const isTabPressed = event.key === 'Tab' || event.keyCode === 9; - if (!isTabPressed) return; + const trapFocus = event => { + const isTabPressed = event.key === 'Tab' || event.keyCode === 9; + if (!isTabPressed) return; - const focusableEls = focusableElsRef.current; + const focusableEls = focusableElsRef.current; - // First focusable element is after the blank 'before' div - const firstFocusableEl = focusableEls[1]; - // Last focusable element is before the blank 'after' div - const lastFocusableEl = focusableEls[focusableEls.length - 2]; - // When SHIFT + TAB is pressed and the active element is the first focusable element - if ( - event.shiftKey && - (document.activeElement === firstFocusableEl || - document.activeElement === focusableEls[0] || - document.activeElement === initialFocusRef.current) - ) { - lastFocusableEl.focus(); - event.preventDefault(); - } - // When TAB is pressed and the active element is the last focusable element - else if ( - !event.shiftKey && - (document.activeElement === lastFocusableEl || - document.activeElement === - focusableEls[focusableEls.length - 1]) - ) { - firstFocusableEl.focus(); - event.preventDefault(); - } - }; + // First focusable element is after the blank 'before' div + const firstFocusableEl = focusableEls[1]; + // Last focusable element is before the blank 'after' div + const lastFocusableEl = focusableEls[focusableEls.length - 2]; + // When SHIFT + TAB is pressed and the active element is the first focusable element + if ( + event.shiftKey && + (document.activeElement === firstFocusableEl || + document.activeElement === focusableEls[0] || + document.activeElement === initialFocusRef.current) + ) { + lastFocusableEl.focus(); + event.preventDefault(); + } + // When TAB is pressed and the active element is the last focusable element + else if ( + !event.shiftKey && + (document.activeElement === lastFocusableEl || + document.activeElement === focusableEls[focusableEls.length - 1]) + ) { + firstFocusableEl.focus(); + event.preventDefault(); + } + }; - useEffect(() => { - if (isActive) { - updateFocusableElements(); - document.addEventListener('keydown', trapFocus); - } else { - document.removeEventListener('keydown', trapFocus); - focusableElsRef.current = []; - } + useEffect(() => { + if (isActive) { + updateFocusableElements(); + document.addEventListener('keydown', trapFocus); + } else { + document.removeEventListener('keydown', trapFocus); + focusableElsRef.current = []; + } - return () => { - focusableElsRef.current = []; - document.removeEventListener('keydown', trapFocus); - }; - }, [isActive]); + return () => { + focusableElsRef.current = []; + document.removeEventListener('keydown', trapFocus); + }; + }, [isActive]); - return
    {children}
    ; + return
    {children}
    ; }; FocusTrapper.propTypes = { - children: PropTypes.node.isRequired, - isActive: PropTypes.bool.isRequired, - trappedElId: PropTypes.string.isRequired, - initialFocusRef: PropTypes.shape({ - current: PropTypes.object - }) + children: PropTypes.node.isRequired, + isActive: PropTypes.bool.isRequired, + trappedElId: PropTypes.string.isRequired, + initialFocusRef: PropTypes.shape({ + current: PropTypes.object + }) }; export default FocusTrapper; diff --git a/client/components/common/LoadingStatus/LoadingStatus.js b/client/components/common/LoadingStatus/LoadingStatus.js index c5da4f084..55af3d9df 100644 --- a/client/components/common/LoadingStatus/LoadingStatus.js +++ b/client/components/common/LoadingStatus/LoadingStatus.js @@ -5,52 +5,52 @@ import styled from '@emotion/styled'; import BasicModal from '../../common/BasicModal'; const Container = styled.div` - display: flex; - justify-content: center; + display: flex; + justify-content: center; `; const LoadingStatus = ({ message, children }) => { - const [isLoading, setIsLoading] = useState(false); + const [isLoading, setIsLoading] = useState(false); - useEffect(() => { - if (message) setIsLoading(true); - else setIsLoading(false); - }, [message]); + useEffect(() => { + if (message) setIsLoading(true); + else setIsLoading(false); + }, [message]); - return ( - <> - {isLoading && ( - - - - } - /> - )} - {children} - - ); + return ( + <> + {isLoading && ( + + + + } + /> + )} + {children} + + ); }; LoadingStatus.propTypes = { - message: PropTypes.string, - children: PropTypes.node + message: PropTypes.string, + children: PropTypes.node }; export default LoadingStatus; diff --git a/client/components/common/LoadingStatus/useTriggerLoad.js b/client/components/common/LoadingStatus/useTriggerLoad.js index 55e4889a2..8301b3d15 100644 --- a/client/components/common/LoadingStatus/useTriggerLoad.js +++ b/client/components/common/LoadingStatus/useTriggerLoad.js @@ -1,22 +1,22 @@ import { useState } from 'react'; export function useTriggerLoad() { - const [loadingMessage, setLoadingMessage] = useState(''); + const [loadingMessage, setLoadingMessage] = useState(''); - const triggerLoad = (loadFn, message) => { - return new Promise((resolve, reject) => { - setLoadingMessage(message); - loadFn() - .then(() => { - setLoadingMessage(''); - resolve(); - }) - .catch(e => { - setLoadingMessage(''); - reject(e); - }); + const triggerLoad = (loadFn, message) => { + return new Promise((resolve, reject) => { + setLoadingMessage(message); + loadFn() + .then(() => { + setLoadingMessage(''); + resolve(); + }) + .catch(e => { + setLoadingMessage(''); + reject(e); }); - }; + }); + }; - return { triggerLoad, loadingMessage }; + return { triggerLoad, loadingMessage }; } diff --git a/client/components/common/PageStatus/PageStatus.css b/client/components/common/PageStatus/PageStatus.css index f4dca95fe..59449a4e1 100644 --- a/client/components/common/PageStatus/PageStatus.css +++ b/client/components/common/PageStatus/PageStatus.css @@ -1,11 +1,11 @@ .loading { - display: inline-block; - clip-path: inset(0 1ch 0 0); - animation: dots 1s steps(4) infinite; + display: inline-block; + clip-path: inset(0 1ch 0 0); + animation: dots 1s steps(4) infinite; } @keyframes dots { - to { - clip-path: inset(0 -1ch 0 0); - } + to { + clip-path: inset(0 -1ch 0 0); + } } diff --git a/client/components/common/PageStatus/index.jsx b/client/components/common/PageStatus/index.jsx index 6886633ce..066dfd9f2 100644 --- a/client/components/common/PageStatus/index.jsx +++ b/client/components/common/PageStatus/index.jsx @@ -5,37 +5,37 @@ import { Helmet } from 'react-helmet'; import './PageStatus.css'; const Loading = ({ - title, - heading, - message = 'Loading ...', - isError = false + title, + heading, + message = 'Loading ...', + isError = false }) => { - let className = isError ? 'alert alert-danger' : ''; - className = message === 'Loading ...' ? `${className} loading` : className; + let className = isError ? 'alert alert-danger' : ''; + className = message === 'Loading ...' ? `${className} loading` : className; - return ( - - - {title} - -

    {heading}

    + return ( + + + {title} + +

    {heading}

    -
    - {message} -
    -
    - ); +
    + {message} +
    +
    + ); }; Loading.propTypes = { - title: PropTypes.string, - heading: PropTypes.string, - message: PropTypes.string, - isError: PropTypes.bool + title: PropTypes.string, + heading: PropTypes.string, + message: PropTypes.string, + isError: PropTypes.bool }; export default Loading; diff --git a/client/components/common/PhasePill/index.jsx b/client/components/common/PhasePill/index.jsx index 992dce3b8..15ee3ca22 100644 --- a/client/components/common/PhasePill/index.jsx +++ b/client/components/common/PhasePill/index.jsx @@ -4,63 +4,63 @@ import { derivePhaseName } from '@client/utils/aria'; import styled from '@emotion/styled'; const PhaseText = styled.span` - display: inline-block; - padding: 2px 4px; - border-radius: 14px; + display: inline-block; + padding: 2px 4px; + border-radius: 14px; - text-align: center; - overflow: hidden; - white-space: nowrap; - color: white; + text-align: center; + overflow: hidden; + white-space: nowrap; + color: white; - &.full-width { - width: 100%; - } - &:not(.full-width) { - width: min-content; - padding: 2px 15px; - vertical-align: middle; - position: relative; - top: -4px; - margin-top: 4px; /* Improve appearance when text wraps */ - } + &.full-width { + width: 100%; + } + &:not(.full-width) { + width: min-content; + padding: 2px 15px; + vertical-align: middle; + position: relative; + top: -4px; + margin-top: 4px; /* Improve appearance when text wraps */ + } - &.rd { - background: #4177de; - } + &.rd { + background: #4177de; + } - &.draft { - background: #818f98; - } + &.draft { + background: #818f98; + } - &.candidate { - background: #ff6c00; - } + &.candidate { + background: #ff6c00; + } - &.recommended { - background: #8441de; - } + &.recommended { + background: #8441de; + } - &.deprecated { - background: #ce1b4c; - } + &.deprecated { + background: #ce1b4c; + } `; const PhasePill = ({ fullWidth = true, children: phase }) => { - return ( - str) - .join(' ')} - > - {derivePhaseName(phase)} - - ); + return ( + str) + .join(' ')} + > + {derivePhaseName(phase)} + + ); }; PhasePill.propTypes = { - fullWidth: PropTypes.bool, - children: PropTypes.string.isRequired + fullWidth: PropTypes.bool, + children: PropTypes.string.isRequired }; export default PhasePill; diff --git a/client/components/common/ReportStatusDot/index.jsx b/client/components/common/ReportStatusDot/index.jsx index d369e91ad..7b2e98770 100644 --- a/client/components/common/ReportStatusDot/index.jsx +++ b/client/components/common/ReportStatusDot/index.jsx @@ -1,36 +1,36 @@ import styled from '@emotion/styled'; const ReportStatusDot = styled.span` - display: inline-block; - height: 10px; - width: 10px; - padding: 0; - margin-right: 8px; - border-radius: 50%; + display: inline-block; + height: 10px; + width: 10px; + padding: 0; + margin-right: 8px; + border-radius: 50%; - &.issues { - background: #f2ba00; - } + &.issues { + background: #f2ba00; + } - &.tests-skipped, - &.reports-not-started { - background: #7c7c7c; - } + &.tests-skipped, + &.reports-not-started { + background: #7c7c7c; + } - &.tests-queued, - &.reports-in-progress { - background: #3876e8; - } + &.tests-queued, + &.reports-in-progress { + background: #3876e8; + } - &.tests-complete, - &.reports-complete { - background: #2ba51c; - } + &.tests-complete, + &.reports-complete { + background: #2ba51c; + } - &.tests-cancelled, - &.reports-missing { - background: #ce1b4c; - } + &.tests-cancelled, + &.reports-missing { + background: #ce1b4c; + } `; export default ReportStatusDot; diff --git a/client/components/common/SortableTableHeader/index.js b/client/components/common/SortableTableHeader/index.js index b274d3079..c1fb828a2 100644 --- a/client/components/common/SortableTableHeader/index.js +++ b/client/components/common/SortableTableHeader/index.js @@ -4,141 +4,141 @@ import { Button } from 'react-bootstrap'; import styled from '@emotion/styled'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { - faArrowDownShortWide, - faArrowUpShortWide + faArrowDownShortWide, + faArrowUpShortWide } from '@fortawesome/free-solid-svg-icons'; import { useAriaLiveRegion } from '../../providers/AriaLiveRegionProvider'; const SortableTableHeaderWrapper = styled.th` - position: relative; - padding: 0; + position: relative; + padding: 0; `; const SortableTableHeaderButton = styled(Button)` + background: #e9ebee; + border: none; + color: black; + font-size: 1rem; + padding: 0; + font-weight: 700; + text-align: left; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + justify-content: space-between; + align-items: flex-end; + padding: 8px 12px; + border-radius: 0; + z-index: 0; + display: flex; + &:hover, + &:focus { background: #e9ebee; - border: none; - color: black; - font-size: 1rem; - padding: 0; - font-weight: 700; - text-align: left; - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - justify-content: space-between; - align-items: flex-end; - padding: 8px 12px; - border-radius: 0; - z-index: 0; - display: flex; - &:hover, - &:focus { - background: #e9ebee; - z-index: 1; - color: #0b60ab; - background-color: var(--bs-table-hover-bg); - } + z-index: 1; + color: #0b60ab; + background-color: var(--bs-table-hover-bg); + } - &:hover { - border: none; - } + &:hover { + border: none; + } `; const InactiveIcon = styled(FontAwesomeIcon)` - color: rgb(155, 155, 155); + color: rgb(155, 155, 155); `; export const TABLE_SORT_ORDERS = { - ASC: 'ASCENDING', - DESC: 'DESCENDING' + ASC: 'ASCENDING', + DESC: 'DESCENDING' }; const SortableTableHeader = ({ - title, - active, - onSort = () => {}, - initialSortDirection = TABLE_SORT_ORDERS.ASC + title, + active, + onSort = () => {}, + initialSortDirection = TABLE_SORT_ORDERS.ASC }) => { - const [currentSortOrder, setCurrentSortOrder] = - useState(initialSortDirection); - - const setAlertMessage = useAriaLiveRegion(); - - useEffect(() => { - if (active) { - const message = - `Test Plans Status Summary Table, now sorted by ${title} in ` + - `${currentSortOrder.toLowerCase()} order`; - setAlertMessage(message); - } - }, [active, currentSortOrder, setAlertMessage, title]); - - const handleClick = () => { - if (active) { - const newSortOrder = - currentSortOrder === TABLE_SORT_ORDERS.ASC - ? TABLE_SORT_ORDERS.DESC - : TABLE_SORT_ORDERS.ASC; - setCurrentSortOrder(newSortOrder); - onSort(newSortOrder); - } else { - onSort(currentSortOrder); - } - }; + const [currentSortOrder, setCurrentSortOrder] = + useState(initialSortDirection); - const getIcon = () => { - const icon = - currentSortOrder === TABLE_SORT_ORDERS.ASC - ? faArrowUpShortWide - : faArrowDownShortWide; - - const attribs = { - 'aria-hidden': 'true', - focusable: 'false', - icon: icon - }; - - if (active) { - return ; - } else { - return ; - } - }; + const setAlertMessage = useAriaLiveRegion(); - const getAriaSort = () => { - if (!active) { - return 'none'; - } else { - return currentSortOrder === TABLE_SORT_ORDERS.ASC - ? 'ascending' - : 'descending'; - } + useEffect(() => { + if (active) { + const message = + `Test Plans Status Summary Table, now sorted by ${title} in ` + + `${currentSortOrder.toLowerCase()} order`; + setAlertMessage(message); + } + }, [active, currentSortOrder, setAlertMessage, title]); + + const handleClick = () => { + if (active) { + const newSortOrder = + currentSortOrder === TABLE_SORT_ORDERS.ASC + ? TABLE_SORT_ORDERS.DESC + : TABLE_SORT_ORDERS.ASC; + setCurrentSortOrder(newSortOrder); + onSort(newSortOrder); + } else { + onSort(currentSortOrder); + } + }; + + const getIcon = () => { + const icon = + currentSortOrder === TABLE_SORT_ORDERS.ASC + ? faArrowUpShortWide + : faArrowDownShortWide; + + const attribs = { + 'aria-hidden': 'true', + focusable: 'false', + icon: icon }; - return ( - - - {title} - {getIcon()} - - - ); + if (active) { + return ; + } else { + return ; + } + }; + + const getAriaSort = () => { + if (!active) { + return 'none'; + } else { + return currentSortOrder === TABLE_SORT_ORDERS.ASC + ? 'ascending' + : 'descending'; + } + }; + + return ( + + + {title} + {getIcon()} + + + ); }; SortableTableHeader.propTypes = { - title: PropTypes.string.isRequired, - active: PropTypes.bool.isRequired, - onSort: PropTypes.func.isRequired, - initialSortDirection: PropTypes.oneOf([ - TABLE_SORT_ORDERS.ASC, - TABLE_SORT_ORDERS.DESC - ]) + title: PropTypes.string.isRequired, + active: PropTypes.bool.isRequired, + onSort: PropTypes.func.isRequired, + initialSortDirection: PropTypes.oneOf([ + TABLE_SORT_ORDERS.ASC, + TABLE_SORT_ORDERS.DESC + ]) }; export default SortableTableHeader; diff --git a/client/components/common/TestPlanResultsTable/TestPlanResultsTable.css b/client/components/common/TestPlanResultsTable/TestPlanResultsTable.css index 31b97fd63..a217a3beb 100644 --- a/client/components/common/TestPlanResultsTable/TestPlanResultsTable.css +++ b/client/components/common/TestPlanResultsTable/TestPlanResultsTable.css @@ -1,24 +1,24 @@ table.test-plan-results-table { - /* To override `caption-side: bottom;` coming from _reboot.scss */ - caption-side: unset; + /* To override `caption-side: bottom;` coming from _reboot.scss */ + caption-side: unset; } table.test-plan-unexpected-behaviors-table { - margin-top: 0.5rem; + margin-top: 0.5rem; } p.test-plan-results-response-p { - margin: 0; + margin: 0; } blockquote.test-plan-results-blockquote { - background: #f7f7f7; - border-left: 4px solid #d3d5d9; - margin: 0.5em 0; - padding: 0.5em; + background: #f7f7f7; + border-left: 4px solid #d3d5d9; + margin: 0.5em 0; + padding: 0.5em; } li.test-plan-results-li { - margin-left: 1rem; - list-style: disc; + margin-left: 1rem; + list-style: disc; } diff --git a/client/components/common/TestPlanResultsTable/index.jsx b/client/components/common/TestPlanResultsTable/index.jsx index 09598c78c..72937f414 100644 --- a/client/components/common/TestPlanResultsTable/index.jsx +++ b/client/components/common/TestPlanResultsTable/index.jsx @@ -6,203 +6,192 @@ import { getMetrics } from 'shared'; import './TestPlanResultsTable.css'; const renderAssertionRow = (assertionResult, priorityString) => { - return ( - - {priorityString} - {assertionResult.assertion.text} - {assertionResult.passed ? 'Passed' : 'Failed'} - - ); + return ( + + {priorityString} + {assertionResult.assertion.text} + {assertionResult.passed ? 'Passed' : 'Failed'} + + ); }; const TestPlanResultsTable = ({ - test, - testResult, - tableClassName = '', - optionalHeader = null, - commandHeadingLevel = 3 + test, + testResult, + tableClassName = '', + optionalHeader = null, + commandHeadingLevel = 3 }) => { - const CommandHeading = `h${commandHeadingLevel}`; + const CommandHeading = `h${commandHeadingLevel}`; - return ( - <> - {optionalHeader} - {testResult.scenarioResults.map((scenarioResult, index) => { - const { - assertionsPassedCount, - assertionsFailedCount, - severeImpactPassedAssertionCount, - moderateImpactPassedAssertionCount - } = getMetrics({ scenarioResult }); + return ( + <> + {optionalHeader} + {testResult.scenarioResults.map((scenarioResult, index) => { + const { + assertionsPassedCount, + assertionsFailedCount, + severeImpactPassedAssertionCount, + moderateImpactPassedAssertionCount + } = getMetrics({ scenarioResult }); - const hasNoSevereUnexpectedBehavior = - severeImpactPassedAssertionCount > 0; - const hasNoModerateUnexpectedBehavior = - moderateImpactPassedAssertionCount > 0; + const hasNoSevereUnexpectedBehavior = + severeImpactPassedAssertionCount > 0; + const hasNoModerateUnexpectedBehavior = + moderateImpactPassedAssertionCount > 0; - // Rows are sorted by priority descending, then result (failures then passes), then - // assertion order. Assertion order refers to the order of assertion columns in the - // tests.csv file. - // TODO: Update named references of REQUIRED to MUST - const requiredAssertionResults = - scenarioResult.requiredAssertionResults - .slice() - .sort((a, b) => - a.passed === b.passed ? 0 : a.passed ? 1 : -1 - ); + // Rows are sorted by priority descending, then result (failures then passes), then + // assertion order. Assertion order refers to the order of assertion columns in the + // tests.csv file. + // TODO: Update named references of REQUIRED to MUST + const requiredAssertionResults = scenarioResult.requiredAssertionResults + .slice() + .sort((a, b) => (a.passed === b.passed ? 0 : a.passed ? 1 : -1)); - // TODO: Update named references of OPTIONAL to SHOULD - const optionalAssertionResults = - scenarioResult.optionalAssertionResults - .slice() - .sort((a, b) => - a.passed === b.passed ? 0 : a.passed ? 1 : -1 - ); + // TODO: Update named references of OPTIONAL to SHOULD + const optionalAssertionResults = scenarioResult.optionalAssertionResults + .slice() + .sort((a, b) => (a.passed === b.passed ? 0 : a.passed ? 1 : -1)); - const mayAssertionResults = scenarioResult.mayAssertionResults - .slice() - .sort((a, b) => - a.passed === b.passed ? 0 : a.passed ? 1 : -1 - ); + const mayAssertionResults = scenarioResult.mayAssertionResults + .slice() + .sort((a, b) => (a.passed === b.passed ? 0 : a.passed ? 1 : -1)); - // Workaround: - // Remove instances of content inside '()' to address edge case of - // COMMAND_TEXT (OPERATING_MODE) then COMMAND_TEXT (OPERATING_MODE). - // OPERATING_MODE should only show once - const bracketsRegex = /\((.*?)\)/g; + // Workaround: + // Remove instances of content inside '()' to address edge case of + // COMMAND_TEXT (OPERATING_MODE) then COMMAND_TEXT (OPERATING_MODE). + // OPERATING_MODE should only show once + const bracketsRegex = /\((.*?)\)/g; - const commandsString = scenarioResult.scenario.commands - .map(({ text }, index) => { - if ( - index !== - scenarioResult.scenario.commands.length - 1 - ) - text = text.replace(bracketsRegex, ''); - return text.trim(); - }) - .join(' then '); + const commandsString = scenarioResult.scenario.commands + .map(({ text }, index) => { + if (index !== scenarioResult.scenario.commands.length - 1) + text = text.replace(bracketsRegex, ''); + return text.trim(); + }) + .join(' then '); - const sortedAssertionResults = [ - ...requiredAssertionResults.map(e => ({ - ...e, - priorityString: 'MUST' - })), - { - id: `UnexpectedBehavior_MUST_${nextId()}`, - assertion: { - text: 'Other behaviors that create severe negative impacts are not exhibited' - }, - passed: hasNoSevereUnexpectedBehavior, - priorityString: 'MUST' - }, - ...optionalAssertionResults.map(e => ({ - ...e, - priorityString: 'SHOULD' - })), - { - id: `UnexpectedBehavior_SHOULD_${nextId()}`, - assertion: { - text: 'Other behaviors that create moderate negative impacts are not exhibited' - }, - passed: hasNoModerateUnexpectedBehavior, - priorityString: 'SHOULD' - }, - ...mayAssertionResults.map(e => ({ - ...e, - priorityString: 'MAY' - })) - ].sort((a, b) => a.passed - b.passed); + const sortedAssertionResults = [ + ...requiredAssertionResults.map(e => ({ + ...e, + priorityString: 'MUST' + })), + { + id: `UnexpectedBehavior_MUST_${nextId()}`, + assertion: { + text: 'Other behaviors that create severe negative impacts are not exhibited' + }, + passed: hasNoSevereUnexpectedBehavior, + priorityString: 'MUST' + }, + ...optionalAssertionResults.map(e => ({ + ...e, + priorityString: 'SHOULD' + })), + { + id: `UnexpectedBehavior_SHOULD_${nextId()}`, + assertion: { + text: 'Other behaviors that create moderate negative impacts are not exhibited' + }, + passed: hasNoModerateUnexpectedBehavior, + priorityString: 'SHOULD' + }, + ...mayAssertionResults.map(e => ({ + ...e, + priorityString: 'MAY' + })) + ].sort((a, b) => a.passed - b.passed); - return ( - - - {commandsString} Results:  - {assertionsPassedCount} passed,  - {assertionsFailedCount} failed - -

    - {test.at?.name} Response: -

    -
    - {scenarioResult.output} -
    - - - - - - - - - - - {sortedAssertionResults.map(assertionResult => - renderAssertionRow( - assertionResult, - assertionResult.priorityString - ) - )} - -
    {commandsString} Results
    PriorityAssertionResult
    - Other behaviors that create negative impact:{' '} - {scenarioResult.unexpectedBehaviors.length ? ( - - - - - - - - - - {scenarioResult.unexpectedBehaviors.map( - ({ id, text, details, impact }) => ( - - - - - - ) - )} - -
    BehaviorDetailsImpact
    {text}{details}{impact}
    - ) : ( - 'None' - )} - {/* Do not show separator below last item */} - {index !== testResult.scenarioResults.length - 1 ? ( - - ) : null} -
    - ); - })} - - ); + return ( + + + {commandsString} Results:  + {assertionsPassedCount} passed,  + {assertionsFailedCount} failed + +

    + {test.at?.name} Response: +

    +
    + {scenarioResult.output} +
    + + + + + + + + + + + {sortedAssertionResults.map(assertionResult => + renderAssertionRow( + assertionResult, + assertionResult.priorityString + ) + )} + +
    {commandsString} Results
    PriorityAssertionResult
    + Other behaviors that create negative impact:{' '} + {scenarioResult.unexpectedBehaviors.length ? ( + + + + + + + + + + {scenarioResult.unexpectedBehaviors.map( + ({ id, text, details, impact }) => ( + + + + + + ) + )} + +
    BehaviorDetailsImpact
    {text}{details}{impact}
    + ) : ( + 'None' + )} + {/* Do not show separator below last item */} + {index !== testResult.scenarioResults.length - 1 ? ( + + ) : null} +
    + ); + })} + + ); }; TestPlanResultsTable.propTypes = { - test: PropTypes.shape({ - title: PropTypes.string.isRequired, - at: PropTypes.shape({ - name: PropTypes.string.isRequired - }).isRequired - }), - testResult: PropTypes.shape({ - scenarioResults: PropTypes.array.isRequired - }), - tableClassName: PropTypes.string, - optionalHeader: PropTypes.node, - commandHeadingLevel: PropTypes.number + test: PropTypes.shape({ + title: PropTypes.string.isRequired, + at: PropTypes.shape({ + name: PropTypes.string.isRequired + }).isRequired + }), + testResult: PropTypes.shape({ + scenarioResults: PropTypes.array.isRequired + }), + tableClassName: PropTypes.string, + optionalHeader: PropTypes.node, + commandHeadingLevel: PropTypes.number }; export default TestPlanResultsTable; diff --git a/client/components/common/ThemeTable/index.jsx b/client/components/common/ThemeTable/index.jsx index 12d2e739c..aef2a86e1 100644 --- a/client/components/common/ThemeTable/index.jsx +++ b/client/components/common/ThemeTable/index.jsx @@ -2,37 +2,37 @@ import { Table } from 'react-bootstrap'; import styled from '@emotion/styled'; export const ThemeTableHeaderH2 = styled.h2` - background-color: var(--bs-table-bg) !important; - font-size: 1.5rem; - font-weight: 600; - border: solid 1px #d2d5d9; - border-bottom: none; - padding: 0.5rem 1rem; - margin: 0.5rem 0 0 0; + background-color: var(--bs-table-bg) !important; + font-size: 1.5rem; + font-weight: 600; + border: solid 1px #d2d5d9; + border-bottom: none; + padding: 0.5rem 1rem; + margin: 0.5rem 0 0 0; `; export const ThemeTableHeaderH3 = styled.h3` - background-color: var(--bs-table-bg) !important; - font-size: 1.25rem; - font-weight: 600; - border: solid 1px #d2d5d9; - border-bottom: none; - padding: 0.5rem 1rem; - margin: 0.5rem 0 0 0; + background-color: var(--bs-table-bg) !important; + font-size: 1.25rem; + font-weight: 600; + border: solid 1px #d2d5d9; + border-bottom: none; + padding: 0.5rem 1rem; + margin: 0.5rem 0 0 0; `; export const ThemeTable = styled(Table)` - margin-bottom: 0; + margin-bottom: 0; - td, - th { - padding-left: 1rem; - min-width: 165px; - vertical-align: middle; - } + td, + th { + padding-left: 1rem; + min-width: 165px; + vertical-align: middle; + } `; export const ThemeTableUnavailable = styled.div` - border: solid 1px #d2d5d9; - padding: 0.5rem 1rem; + border: solid 1px #d2d5d9; + padding: 0.5rem 1rem; `; diff --git a/client/components/common/UpdateTargetDateModal/index.jsx b/client/components/common/UpdateTargetDateModal/index.jsx index 85105190e..17bc30929 100644 --- a/client/components/common/UpdateTargetDateModal/index.jsx +++ b/client/components/common/UpdateTargetDateModal/index.jsx @@ -6,138 +6,136 @@ import BasicModal from '../BasicModal'; import { convertDateToString, isValidDate } from '../../../utils/formatter'; const ModalInnerSectionContainer = styled.div` - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; `; const UpdateTargetDateModal = ({ - show = false, - title = null, - dateText = '', - handleAction = () => {}, - handleClose = () => {} + show = false, + title = null, + dateText = '', + handleAction = () => {}, + handleClose = () => {} }) => { - const dateTextRef = useRef(); + const dateTextRef = useRef(); - const [updatedDateText, setUpdatedDateText] = useState( - convertDateToString(dateText) - ); - const [isDateError, setIsDateError] = useState(false); + const [updatedDateText, setUpdatedDateText] = useState( + convertDateToString(dateText) + ); + const [isDateError, setIsDateError] = useState(false); - useEffect(() => { - setUpdatedDateText(convertDateToString(dateText)); - }, [dateText]); + useEffect(() => { + setUpdatedDateText(convertDateToString(dateText)); + }, [dateText]); - const handleDateTextChange = e => { - const value = e.target.value; - setIsDateError(false); - setUpdatedDateText(value); - }; + const handleDateTextChange = e => { + const value = e.target.value; + setIsDateError(false); + setUpdatedDateText(value); + }; - const handleDateTextKeyPress = e => { - /** - * Only accept the following ASCII characters: - * 45: - - * 48: 0 - * 49: 1 - * 50: 2 - * 51: 3 - * 52: 4 - * 53: 5 - * 54: 6 - * 55: 7 - * 56: 8 - * 57: 9 - */ - const HYPHEN = 45; - const DIGIT_ZERO = 48; - const DIGIT_NINE = 57; - if ( - (e.charCode < DIGIT_ZERO && e.charCode !== HYPHEN) || - e.charCode > DIGIT_NINE - ) { - e.preventDefault(); - } + const handleDateTextKeyPress = e => { + /** + * Only accept the following ASCII characters: + * 45: - + * 48: 0 + * 49: 1 + * 50: 2 + * 51: 3 + * 52: 4 + * 53: 5 + * 54: 6 + * 55: 7 + * 56: 8 + * 57: 9 + */ + const HYPHEN = 45; + const DIGIT_ZERO = 48; + const DIGIT_NINE = 57; + if ( + (e.charCode < DIGIT_ZERO && e.charCode !== HYPHEN) || + e.charCode > DIGIT_NINE + ) { + e.preventDefault(); + } - let input = e.target; - let inputLength = input.value.length; - if (inputLength !== 1 || inputLength !== 3) { - if (e.charCode === HYPHEN) e.preventDefault(); - } - if (inputLength === 2) input.value += '-'; - if (inputLength === 5) input.value += '-'; - }; + let input = e.target; + let inputLength = input.value.length; + if (inputLength !== 1 || inputLength !== 3) { + if (e.charCode === HYPHEN) e.preventDefault(); + } + if (inputLength === 2) input.value += '-'; + if (inputLength === 5) input.value += '-'; + }; - const onSubmit = () => { - // Passed handleAction prop should account for dateText - const dateTextError = - !updatedDateText || - updatedDateText.length !== 10 || - !isValidDate(updatedDateText); + const onSubmit = () => { + // Passed handleAction prop should account for dateText + const dateTextError = + !updatedDateText || + updatedDateText.length !== 10 || + !isValidDate(updatedDateText); - if (dateTextError) { - setIsDateError(dateTextError); - dateTextRef.current.focus(); - return; - } + if (dateTextError) { + setIsDateError(dateTextError); + dateTextRef.current.focus(); + return; + } - handleAction({ updatedDateText }); - }; + handleAction({ updatedDateText }); + }; - return ( - - - - Target Date - - - {isDateError && ( - - Please enter a valid date. - - )} - - - } - actions={[ - { - label: 'Save', - onClick: onSubmit - } - ]} - handleClose={handleClose} - useOnHide={true} - handleHide={handleClose} - initialFocusRef={dateTextRef} - /> - ); + return ( + + + Target Date + + {isDateError && ( + + Please enter a valid date. + + )} + + + } + actions={[ + { + label: 'Save', + onClick: onSubmit + } + ]} + handleClose={handleClose} + useOnHide={true} + handleHide={handleClose} + initialFocusRef={dateTextRef} + /> + ); }; UpdateTargetDateModal.propTypes = { - show: PropTypes.bool, - title: PropTypes.node.isRequired, - dateText: PropTypes.string, - handleAction: PropTypes.func, - handleClose: PropTypes.func + show: PropTypes.bool, + title: PropTypes.node.isRequired, + dateText: PropTypes.string, + handleAction: PropTypes.func, + handleClose: PropTypes.func }; export default UpdateTargetDateModal; diff --git a/client/components/common/UpdateVersionModal/index.jsx b/client/components/common/UpdateVersionModal/index.jsx index ab64c2401..83a5daad9 100644 --- a/client/components/common/UpdateVersionModal/index.jsx +++ b/client/components/common/UpdateVersionModal/index.jsx @@ -6,178 +6,174 @@ import BasicModal from '../BasicModal'; import { convertDateToString, isValidDate } from '../../../utils/formatter'; const ModalInnerSectionContainer = styled.div` - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; `; const UpdateVersionModal = ({ - show = false, - title = null, - actionType = 'add', // or edit - versionText = '', - dateAvailabilityText = '', - handleAction = () => {}, - handleClose = () => {} + show = false, + title = null, + actionType = 'add', // or edit + versionText = '', + dateAvailabilityText = '', + handleAction = () => {}, + handleClose = () => {} }) => { - const versionTextRef = useRef(); - const dateAvailabilityTextRef = useRef(); - - const [updatedVersionText, setUpdatedVersionText] = useState(versionText); - const [updatedDateAvailabilityText, setUpdatedDateAvailabilityText] = - useState(convertDateToString(dateAvailabilityText)); - const [isVersionError, setIsVersionError] = useState(false); - const [isDateError, setIsDateError] = useState(false); - - useEffect(() => { - setUpdatedVersionText(versionText); - setUpdatedDateAvailabilityText( - convertDateToString(dateAvailabilityText) - ); - }, [versionText, dateAvailabilityText]); - - const handleVersionTextChange = e => { - const value = e.target.value; - setIsVersionError(false); - setUpdatedVersionText(value); - }; - - const handleDateAvailabilityTextChange = e => { - const value = e.target.value; - setIsDateError(false); - setUpdatedDateAvailabilityText(value); - }; - - const handleDateAvailabilityTextKeyPress = e => { - /** - * Only accept the following ASCII characters: - * 45: - - * 48: 0 - * 49: 1 - * 50: 2 - * 51: 3 - * 52: 4 - * 53: 5 - * 54: 6 - * 55: 7 - * 56: 8 - * 57: 9 - */ - const HYPHEN = 45; - const DIGIT_ZERO = 48; - const DIGIT_NINE = 57; - if ( - (e.charCode < DIGIT_ZERO && e.charCode !== HYPHEN) || - e.charCode > DIGIT_NINE - ) { - e.preventDefault(); + const versionTextRef = useRef(); + const dateAvailabilityTextRef = useRef(); + + const [updatedVersionText, setUpdatedVersionText] = useState(versionText); + const [updatedDateAvailabilityText, setUpdatedDateAvailabilityText] = + useState(convertDateToString(dateAvailabilityText)); + const [isVersionError, setIsVersionError] = useState(false); + const [isDateError, setIsDateError] = useState(false); + + useEffect(() => { + setUpdatedVersionText(versionText); + setUpdatedDateAvailabilityText(convertDateToString(dateAvailabilityText)); + }, [versionText, dateAvailabilityText]); + + const handleVersionTextChange = e => { + const value = e.target.value; + setIsVersionError(false); + setUpdatedVersionText(value); + }; + + const handleDateAvailabilityTextChange = e => { + const value = e.target.value; + setIsDateError(false); + setUpdatedDateAvailabilityText(value); + }; + + const handleDateAvailabilityTextKeyPress = e => { + /** + * Only accept the following ASCII characters: + * 45: - + * 48: 0 + * 49: 1 + * 50: 2 + * 51: 3 + * 52: 4 + * 53: 5 + * 54: 6 + * 55: 7 + * 56: 8 + * 57: 9 + */ + const HYPHEN = 45; + const DIGIT_ZERO = 48; + const DIGIT_NINE = 57; + if ( + (e.charCode < DIGIT_ZERO && e.charCode !== HYPHEN) || + e.charCode > DIGIT_NINE + ) { + e.preventDefault(); + } + + let input = e.target; + let inputLength = input.value.length; + if (inputLength !== 1 || inputLength !== 3) { + if (e.charCode === HYPHEN) e.preventDefault(); + } + if (inputLength === 2) input.value += '-'; + if (inputLength === 5) input.value += '-'; + }; + + const onSubmit = () => { + // Passed action prop should account for actionType, versionText and dateAvailabilityText + const versionTextError = !updatedVersionText; + const dateTextError = + !updatedDateAvailabilityText || + updatedDateAvailabilityText.length !== 10 || + !isValidDate(updatedDateAvailabilityText); + + if (versionTextError || dateTextError) { + setIsVersionError(versionTextError); + versionTextRef.current.focus(); + + setIsDateError(dateTextError); + if (!versionTextError) dateAvailabilityTextRef.current.focus(); + return; + } + + handleAction(actionType, { + updatedVersionText, + updatedDateAvailabilityText + }); + }; + + return ( + + + Version Number + + {isVersionError && ( + + Please enter a valid version number. + + )} + + + + Approximate date of availability + + {isDateError && ( + + Please enter a valid date. + + )} + + + } + actions={[ + { + label: actionType === 'add' ? 'Add Version' : 'Save', + onClick: onSubmit } - - let input = e.target; - let inputLength = input.value.length; - if (inputLength !== 1 || inputLength !== 3) { - if (e.charCode === HYPHEN) e.preventDefault(); - } - if (inputLength === 2) input.value += '-'; - if (inputLength === 5) input.value += '-'; - }; - - const onSubmit = () => { - // Passed action prop should account for actionType, versionText and dateAvailabilityText - const versionTextError = !updatedVersionText; - const dateTextError = - !updatedDateAvailabilityText || - updatedDateAvailabilityText.length !== 10 || - !isValidDate(updatedDateAvailabilityText); - - if (versionTextError || dateTextError) { - setIsVersionError(versionTextError); - versionTextRef.current.focus(); - - setIsDateError(dateTextError); - if (!versionTextError) dateAvailabilityTextRef.current.focus(); - return; - } - - handleAction(actionType, { - updatedVersionText, - updatedDateAvailabilityText - }); - }; - - return ( - - - Version Number - - {isVersionError && ( - - Please enter a valid version number. - - )} - - - - - Approximate date of availability - - - {isDateError && ( - - Please enter a valid date. - - )} - - - } - actions={[ - { - label: actionType === 'add' ? 'Add Version' : 'Save', - onClick: onSubmit - } - ]} - handleClose={handleClose} - /> - ); + ]} + handleClose={handleClose} + /> + ); }; UpdateVersionModal.propTypes = { - show: PropTypes.bool, - title: PropTypes.node.isRequired, - actionType: PropTypes.string, - versionText: PropTypes.string, - dateAvailabilityText: PropTypes.string, - onVersionChange: PropTypes.func, - onDateAvailabilityChange: PropTypes.func, - handleAction: PropTypes.func, - handleClose: PropTypes.func + show: PropTypes.bool, + title: PropTypes.node.isRequired, + actionType: PropTypes.string, + versionText: PropTypes.string, + dateAvailabilityText: PropTypes.string, + onVersionChange: PropTypes.func, + onDateAvailabilityChange: PropTypes.func, + handleAction: PropTypes.func, + handleClose: PropTypes.func }; export default UpdateVersionModal; diff --git a/client/components/common/VersionString/index.js b/client/components/common/VersionString/index.js index 5b74cd837..4045d67f0 100644 --- a/client/components/common/VersionString/index.js +++ b/client/components/common/VersionString/index.js @@ -5,93 +5,93 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import styled from '@emotion/styled'; const StyledPill = styled.span` - display: inline-block; + display: inline-block; - line-height: 2rem; - border-radius: 4px; + line-height: 2rem; + border-radius: 4px; - background: #f6f8fa; - white-space: nowrap; - text-align: center; + background: #f6f8fa; + white-space: nowrap; + text-align: center; - // Needed for presenting component on Version History page - &.full-width { - width: 100%; + // Needed for presenting component on Version History page + &.full-width { + width: 100%; - /* Version strings can have different character counts and this keeps + /* Version strings can have different character counts and this keeps them lined up in lists */ - & b { - min-width: 6em; - display: inline-block; - text-align: left; - } + & b { + min-width: 6em; + display: inline-block; + text-align: left; } + } - &:not(.full-width) { - width: 8em; - margin-right: 10px; - } + &:not(.full-width) { + width: 8em; + margin-right: 10px; + } - // Needed for presenting component on Data Management page - // Override full-width's width if both are set - &.auto-width { - width: auto; - margin: 0.75rem; - } + // Needed for presenting component on Data Management page + // Override full-width's width if both are set + &.auto-width { + width: auto; + margin: 0.75rem; + } `; const VersionString = ({ - fullWidth = true, - autoWidth = true, - iconColor = '#818F98', - linkRef, - linkHref, - children: versionString, - ...restProps + fullWidth = true, + autoWidth = true, + iconColor = '#818F98', + linkRef, + linkHref, + children: versionString, + ...restProps }) => { - const body = ( - - - {versionString} - - ); + const body = ( + + + {versionString} + + ); - let possibleLink; - if (linkHref) { - if (linkRef) { - possibleLink = ( - - {body} - - ); - } else { - possibleLink = {body}; - } + let possibleLink; + if (linkHref) { + if (linkRef) { + possibleLink = ( + + {body} + + ); } else { - possibleLink = body; + possibleLink = {body}; } + } else { + possibleLink = body; + } - let classes = fullWidth ? 'full-width' : ''; - classes = autoWidth ? `${classes} auto-width` : classes; + let classes = fullWidth ? 'full-width' : ''; + classes = autoWidth ? `${classes} auto-width` : classes; - return ( - - {possibleLink} - - ); + return ( + + {possibleLink} + + ); }; VersionString.propTypes = { - fullWidth: PropTypes.bool, - autoWidth: PropTypes.bool, - iconColor: PropTypes.string, - linkRef: PropTypes.shape({ current: PropTypes.any }), - linkHref: PropTypes.string, - children: PropTypes.string + fullWidth: PropTypes.bool, + autoWidth: PropTypes.bool, + iconColor: PropTypes.string, + linkRef: PropTypes.shape({ current: PropTypes.any }), + linkHref: PropTypes.string, + children: PropTypes.string }; export default VersionString; diff --git a/client/components/providers/AriaLiveRegionProvider/index.js b/client/components/providers/AriaLiveRegionProvider/index.js index f32de8537..5a66230c0 100644 --- a/client/components/providers/AriaLiveRegionProvider/index.js +++ b/client/components/providers/AriaLiveRegionProvider/index.js @@ -5,39 +5,39 @@ import styled from '@emotion/styled'; const AriaLiveRegionContext = React.createContext(); const VisuallyHiddenAriaLiveRegion = styled.span` - border: 0; - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; `; export const useAriaLiveRegion = () => { - const context = useContext(AriaLiveRegionContext); - if (!context) { - throw new Error( - 'useAriaLiveRegion must be used within an AriaLiveRegionProvider' - ); - } - return context; + const context = useContext(AriaLiveRegionContext); + if (!context) { + throw new Error( + 'useAriaLiveRegion must be used within an AriaLiveRegionProvider' + ); + } + return context; }; export const AriaLiveRegionProvider = ({ children }) => { - const [alertMessage, setAlertMessage] = useState(''); + const [alertMessage, setAlertMessage] = useState(''); - return ( - - {children} - - {alertMessage} - - - ); + return ( + + {children} + + {alertMessage} + + + ); }; AriaLiveRegionProvider.propTypes = { - children: PropTypes.node.isRequired + children: PropTypes.node.isRequired }; diff --git a/client/hooks/useDetectUa.js b/client/hooks/useDetectUa.js index 3a6e787a5..b335684a8 100644 --- a/client/hooks/useDetectUa.js +++ b/client/hooks/useDetectUa.js @@ -2,24 +2,24 @@ import { useState, useEffect } from 'react'; import uaParser from 'ua-parser-js'; export function useDetectUa() { - const [uaBrowser, setUaBrowser] = useState(); - const [uaMajor, setUaMajor] = useState(); - const [uaMinor, setUaMinor] = useState(); - const [uaPatch, setUaPatch] = useState(); + const [uaBrowser, setUaBrowser] = useState(); + const [uaMajor, setUaMajor] = useState(); + const [uaMinor, setUaMinor] = useState(); + const [uaPatch, setUaPatch] = useState(); - useEffect(() => { - // Detect UA information - const ua = uaParser(); - const uaBrowser = ua?.browser?.name || 'Unknown'; - const uaMajor = ua?.browser?.major || '0'; - const uaMinor = ua?.browser?.version?.split('.')?.[1] || '0'; - const uaPatch = ua?.browser?.version?.split('.')?.[2] || '0'; + useEffect(() => { + // Detect UA information + const ua = uaParser(); + const uaBrowser = ua?.browser?.name || 'Unknown'; + const uaMajor = ua?.browser?.major || '0'; + const uaMinor = ua?.browser?.version?.split('.')?.[1] || '0'; + const uaPatch = ua?.browser?.version?.split('.')?.[2] || '0'; - setUaBrowser(uaBrowser); - setUaMajor(uaMajor); - setUaMinor(uaMinor); - setUaPatch(uaPatch); - }); + setUaBrowser(uaBrowser); + setUaMajor(uaMajor); + setUaMinor(uaMinor); + setUaPatch(uaPatch); + }); - return { uaBrowser, uaMajor, uaMinor, uaPatch }; + return { uaBrowser, uaMajor, uaMinor, uaPatch }; } diff --git a/client/hooks/useRouterQuery.js b/client/hooks/useRouterQuery.js index e9fd2f3ce..5c174b900 100644 --- a/client/hooks/useRouterQuery.js +++ b/client/hooks/useRouterQuery.js @@ -1,5 +1,5 @@ import { useLocation } from 'react-router-dom'; export default function useRouterQuery() { - return new URLSearchParams(useLocation().search); + return new URLSearchParams(useLocation().search); } diff --git a/client/hooks/useTestPlanRunIsFinished.js b/client/hooks/useTestPlanRunIsFinished.js index 2a32b27d0..af1909796 100644 --- a/client/hooks/useTestPlanRunIsFinished.js +++ b/client/hooks/useTestPlanRunIsFinished.js @@ -3,36 +3,36 @@ import { useMemo } from 'react'; const { gql, useQuery } = require('@apollo/client'); const TEST_PLAN_RUN_TEST_RESULTS_COMPLETION_STATUS = gql` - query TestPlanRunTestResultsCompletionStatus($testPlanRunId: ID!) { - testPlanRun(id: $testPlanRunId) { - id - testResults { - id - completedAt - } - } + query TestPlanRunTestResultsCompletionStatus($testPlanRunId: ID!) { + testPlanRun(id: $testPlanRunId) { + id + testResults { + id + completedAt + } } + } `; export const useTestPlanRunIsFinished = testPlanRunId => { - const { data: testPlanRunCompletionQuery } = useQuery( - TEST_PLAN_RUN_TEST_RESULTS_COMPLETION_STATUS, - { - variables: { - testPlanRunId - }, - fetchPolicy: 'cache-and-network' - } - ); + const { data: testPlanRunCompletionQuery } = useQuery( + TEST_PLAN_RUN_TEST_RESULTS_COMPLETION_STATUS, + { + variables: { + testPlanRunId + }, + fetchPolicy: 'cache-and-network' + } + ); - const runIsFinished = useMemo(() => { - if (!testPlanRunCompletionQuery?.testPlanRun?.testResults.length) { - return false; - } + const runIsFinished = useMemo(() => { + if (!testPlanRunCompletionQuery?.testPlanRun?.testResults.length) { + return false; + } - return testPlanRunCompletionQuery.testPlanRun.testResults.every( - testResult => testResult.completedAt !== null - ); - }, [testPlanRunId, testPlanRunCompletionQuery]); + return testPlanRunCompletionQuery.testPlanRun.testResults.every( + testResult => testResult.completedAt !== null + ); + }, [testPlanRunId, testPlanRunCompletionQuery]); - return { runIsFinished }; + return { runIsFinished }; }; diff --git a/client/hooks/useTestPlanRunValidatedAssertionCounts.js b/client/hooks/useTestPlanRunValidatedAssertionCounts.js index 6e229213f..64bb738a4 100644 --- a/client/hooks/useTestPlanRunValidatedAssertionCounts.js +++ b/client/hooks/useTestPlanRunValidatedAssertionCounts.js @@ -3,85 +3,84 @@ import { useQuery } from '@apollo/client'; import { TEST_PLAN_RUN_ASSERTION_RESULTS_QUERY } from '../components/TestQueueCompletionStatusListItem/queries'; export const useTestPlanRunValidatedAssertionCounts = ( - testPlanRun, - pollInterval = null + testPlanRun, + pollInterval = null ) => { - const { - data: testPlanRunAssertionsQueryResult, - startPolling, - stopPolling, - refetch - } = useQuery(TEST_PLAN_RUN_ASSERTION_RESULTS_QUERY, { - variables: { - testPlanRunId: testPlanRun.id - }, - fetchPolicy: 'cache-and-network', - pollInterval - }); - - const testResultsLength = useMemo(() => { - return ( - testPlanRunAssertionsQueryResult?.testPlanRun?.testResults - ?.length || 0 - ); - }, [testPlanRunAssertionsQueryResult]); + const { + data: testPlanRunAssertionsQueryResult, + startPolling, + stopPolling, + refetch + } = useQuery(TEST_PLAN_RUN_ASSERTION_RESULTS_QUERY, { + variables: { + testPlanRunId: testPlanRun.id + }, + fetchPolicy: 'cache-and-network', + pollInterval + }); - const totalPossibleAssertions = useMemo(() => { - if (testPlanRunAssertionsQueryResult) { - let count = 0; - if (!testPlanRunAssertionsQueryResult?.testPlanRun) { - return 0; - } - const { - testPlanRun: { testResults } - } = testPlanRunAssertionsQueryResult; - for (let i = 0; i < testResults.length; i++) { - const scenarios = testResults[i].scenarioResults; - for (let j = 0; j < scenarios.length; j++) { - const assertions = scenarios[j].assertionResults; - count += assertions.length; - } - } - return count; - } else { - return 0; - } - }, [testPlanRunAssertionsQueryResult]); + const testResultsLength = useMemo(() => { + return ( + testPlanRunAssertionsQueryResult?.testPlanRun?.testResults?.length || 0 + ); + }, [testPlanRunAssertionsQueryResult]); - const totalValidatedAssertions = useMemo(() => { - if (!testPlanRunAssertionsQueryResult?.testPlanRun) { - return 0; + const totalPossibleAssertions = useMemo(() => { + if (testPlanRunAssertionsQueryResult) { + let count = 0; + if (!testPlanRunAssertionsQueryResult?.testPlanRun) { + return 0; + } + const { + testPlanRun: { testResults } + } = testPlanRunAssertionsQueryResult; + for (let i = 0; i < testResults.length; i++) { + const scenarios = testResults[i].scenarioResults; + for (let j = 0; j < scenarios.length; j++) { + const assertions = scenarios[j].assertionResults; + count += assertions.length; } - - const { - testPlanRun: { testResults } - } = testPlanRunAssertionsQueryResult; - return testResults.reduce((acc, test) => { - return ( - acc + - (test.completedAt - ? test.scenarioResults.reduce((acc, scenario) => { - return acc + scenario.assertionResults.length; - }, 0) - : 0) - ); - }, 0); - }, [testPlanRunAssertionsQueryResult]); - if (pollInterval) { - return { - testResultsLength, - totalPossibleAssertions, - totalValidatedAssertions, - refetch, - stopPolling, - startPolling - }; + } + return count; } else { - return { - testResultsLength, - totalPossibleAssertions, - totalValidatedAssertions, - refetch - }; + return 0; } + }, [testPlanRunAssertionsQueryResult]); + + const totalValidatedAssertions = useMemo(() => { + if (!testPlanRunAssertionsQueryResult?.testPlanRun) { + return 0; + } + + const { + testPlanRun: { testResults } + } = testPlanRunAssertionsQueryResult; + return testResults.reduce((acc, test) => { + return ( + acc + + (test.completedAt + ? test.scenarioResults.reduce((acc, scenario) => { + return acc + scenario.assertionResults.length; + }, 0) + : 0) + ); + }, 0); + }, [testPlanRunAssertionsQueryResult]); + if (pollInterval) { + return { + testResultsLength, + totalPossibleAssertions, + totalValidatedAssertions, + refetch, + stopPolling, + startPolling + }; + } else { + return { + testResultsLength, + totalPossibleAssertions, + totalValidatedAssertions, + refetch + }; + } }; diff --git a/client/hooks/useThemedModal.js b/client/hooks/useThemedModal.js index a85b27b65..63a6f9240 100644 --- a/client/hooks/useThemedModal.js +++ b/client/hooks/useThemedModal.js @@ -2,60 +2,59 @@ import React, { useState, useRef, useEffect } from 'react'; import BasicThemedModal from '@components/common/BasicThemedModal'; const THEMES = { - WARNING: 'warning', - DANGER: 'danger' + WARNING: 'warning', + DANGER: 'danger' }; function useThemedModal({ show, type, title, content }) { - const focusElementRef = useRef(); - - const [showThemedModal, setShowThemedModal] = useState(false); - const [themedModalType, setThemedModalType] = useState(THEMES.WARNING); - const [themedModalTitle, setThemedModalTitle] = useState(''); - const [themedModalContent, setThemedModalContent] = useState(<>); - - useEffect(() => { - setShowThemedModal(showThemedModal || show); - setThemedModalType(themedModalType || type); - setThemedModalTitle(themedModalTitle || title); - setThemedModalContent(themedModalContent || content); - }); - - const onThemedModalClose = () => { - setShowThemedModal(false); - if (focusElementRef.current) focusElementRef.current.focus(); - }; - - const setFocusRef = focusElement => - (focusElementRef.current = focusElement); - - const themedModal = ( - - ); - - return { - setFocusRef, - themedModal, - showThemedModal, - setShowThemedModal, - setThemedModalType, - setThemedModalTitle, - setThemedModalContent - }; + const focusElementRef = useRef(); + + const [showThemedModal, setShowThemedModal] = useState(false); + const [themedModalType, setThemedModalType] = useState(THEMES.WARNING); + const [themedModalTitle, setThemedModalTitle] = useState(''); + const [themedModalContent, setThemedModalContent] = useState(<>); + + useEffect(() => { + setShowThemedModal(showThemedModal || show); + setThemedModalType(themedModalType || type); + setThemedModalTitle(themedModalTitle || title); + setThemedModalContent(themedModalContent || content); + }); + + const onThemedModalClose = () => { + setShowThemedModal(false); + if (focusElementRef.current) focusElementRef.current.focus(); + }; + + const setFocusRef = focusElement => (focusElementRef.current = focusElement); + + const themedModal = ( + + ); + + return { + setFocusRef, + themedModal, + showThemedModal, + setShowThemedModal, + setThemedModalType, + setThemedModalTitle, + setThemedModalContent + }; } export { useThemedModal, THEMES }; diff --git a/client/index.js b/client/index.js index 6cc1a86ea..4f1abe509 100644 --- a/client/index.js +++ b/client/index.js @@ -10,41 +10,41 @@ import { AriaLiveRegionProvider } from './components/providers/AriaLiveRegionPro const container = document.getElementById('root'); const root = createRoot(container); root.render( - - - - - - - + + + + + + + ); const signMeInCommon = async user => { - if (!user.username) throw new Error('Please provide a username'); + if (!user.username) throw new Error('Please provide a username'); - const response = await fetch('/api/auth/fake-user', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(user) - }); + const response = await fetch('/api/auth/fake-user', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(user) + }); - const responseText = await response.text(); - if (!response.ok) throw responseText; + const responseText = await response.text(); + if (!response.ok) throw responseText; - location.reload(); + location.reload(); }; window.signMeInAsAdmin = username => { - return signMeInCommon({ - username, - roles: [{ name: 'ADMIN' }, { name: 'TESTER' }, { name: 'VENDOR' }] - }); + return signMeInCommon({ + username, + roles: [{ name: 'ADMIN' }, { name: 'TESTER' }, { name: 'VENDOR' }] + }); }; window.signMeInAsTester = username => { - return signMeInCommon({ username, roles: [{ name: 'TESTER' }] }); + return signMeInCommon({ username, roles: [{ name: 'TESTER' }] }); }; window.signMeInAsVendor = username => { - return signMeInCommon({ username, roles: [{ name: 'VENDOR' }] }); + return signMeInCommon({ username, roles: [{ name: 'VENDOR' }] }); }; diff --git a/client/routes/index.js b/client/routes/index.js index a98bc63de..ffb92a6cc 100644 --- a/client/routes/index.js +++ b/client/routes/index.js @@ -16,70 +16,66 @@ import TestPlanVersionsPage from '../components/TestPlanVersionsPage'; import TestReview from '../components/TestReview'; export default () => ( - - } /> - } - /> - - - - } - /> - - - - } - /> - } /> - } - /> - - - - } - /> - } - /> - } /> - } /> - - - - } - /> - } /> - } - /> - } /> - } /> - } /> - + + } /> + } /> + + + + } + /> + + + + } + /> + } /> + } + /> + + + + } + /> + } + /> + } /> + } /> + + + + } + /> + } /> + } + /> + } /> + } /> + } /> + ); diff --git a/client/static/index.css b/client/static/index.css index ae5656889..1794ae56b 100644 --- a/client/static/index.css +++ b/client/static/index.css @@ -1,6 +1,6 @@ html, body { - width: 100%; - height: 100vh; - background: #eaeaea; + width: 100%; + height: 100vh; + background: #eaeaea; } diff --git a/client/stories/ProvideFeedbackModal.stories.jsx b/client/stories/ProvideFeedbackModal.stories.jsx index a2ed6ea9f..8abfee2b9 100644 --- a/client/stories/ProvideFeedbackModal.stories.jsx +++ b/client/stories/ProvideFeedbackModal.stories.jsx @@ -2,37 +2,37 @@ import React from 'react'; import ProvideFeedbackModal from '../components/CandidateReview/CandidateModals/ProvideFeedbackModal'; export default { - component: ProvideFeedbackModal, - title: 'ProvideFeedbackModal' + component: ProvideFeedbackModal, + title: 'ProvideFeedbackModal' }; const Template = args => ; export const Default = Template.bind({}); Default.args = { - at: 'JAWS', - changesRequestedIssues: [ - { author: 'evmiguel', feedbackType: 'feedback', link: 'link to issue' }, - { author: 'evmiguel', feedbackType: 'feedback', link: 'link to issue' } - ], - feedbackIssues: [ - { - author: 'evmiguel', - feedbackType: 'changes-requested', - link: 'link to issue' - }, - { - author: 'evmiguel', - feedbackType: 'changes-requested', - link: 'link to issue' - }, - { - author: 'evmiguel', - feedbackType: 'changes-requested', - link: 'link to issue' - } - ], - show: true, - testPlan: 'Disclosure Navigation Example', - username: 'evmiguel' + at: 'JAWS', + changesRequestedIssues: [ + { author: 'evmiguel', feedbackType: 'feedback', link: 'link to issue' }, + { author: 'evmiguel', feedbackType: 'feedback', link: 'link to issue' } + ], + feedbackIssues: [ + { + author: 'evmiguel', + feedbackType: 'changes-requested', + link: 'link to issue' + }, + { + author: 'evmiguel', + feedbackType: 'changes-requested', + link: 'link to issue' + }, + { + author: 'evmiguel', + feedbackType: 'changes-requested', + link: 'link to issue' + } + ], + show: true, + testPlan: 'Disclosure Navigation Example', + username: 'evmiguel' }; diff --git a/client/stories/ThankYouModal.stories.jsx b/client/stories/ThankYouModal.stories.jsx index 1c6828b62..c6ad4cd77 100644 --- a/client/stories/ThankYouModal.stories.jsx +++ b/client/stories/ThankYouModal.stories.jsx @@ -2,13 +2,13 @@ import React from 'react'; import ThankYouModal from '../components/CandidateReview/CandidateModals/ThankYouModal/index.jsx'; export default { - component: ThankYouModal, - title: 'ThankYouModal' + component: ThankYouModal, + title: 'ThankYouModal' }; const Template = args => ; export const Default = Template.bind({}); Default.args = { - show: true + show: true }; diff --git a/client/tests/AddTestToQueueWithConfirmation.test.jsx b/client/tests/AddTestToQueueWithConfirmation.test.jsx index 9580e7e66..55954b5ef 100644 --- a/client/tests/AddTestToQueueWithConfirmation.test.jsx +++ b/client/tests/AddTestToQueueWithConfirmation.test.jsx @@ -17,110 +17,108 @@ jest.mock('@apollo/client'); let mutationMock; let mockTestPlanVersion, - mockBrowser, - mockAt, - mockButtonText, - getByTestId, - findByRole; + mockBrowser, + mockAt, + mockButtonText, + getByTestId, + findByRole; const mockTestPlanReportsQueryResult = { - testPlanVersion: { - testPlanReports: [ - { - id: 'report1', - testPlanRun: { - id: 'testPlanRunId', - isInitiatedByAutomation: false, - markedFinalAt: null - }, - isFinal: false, - at: { - id: '1' - }, - browser: { - id: '2' - } - } - ] - } + testPlanVersion: { + testPlanReports: [ + { + id: 'report1', + testPlanRun: { + id: 'testPlanRunId', + isInitiatedByAutomation: false, + markedFinalAt: null + }, + isFinal: false, + at: { + id: '1' + }, + browser: { + id: '2' + } + } + ] + } }; const setup = (props, mockMutation) => { - useMutation.mockReturnValue([mockMutation, {}]); - useQuery.mockReturnValue({ - data: mockTestPlanReportsQueryResult - }); - return render( - - - - - - ); + useMutation.mockReturnValue([mockMutation, {}]); + useQuery.mockReturnValue({ + data: mockTestPlanReportsQueryResult + }); + return render( + + + + + + ); }; const commonSetup = mockMutation => { - mockTestPlanVersion = { id: 5 }; - mockBrowser = { id: 2 }; - mockAt = { id: 3 }; - mockButtonText = 'Add to Test Queue'; - - const renderResult = setup( - { - testPlanVersion: mockTestPlanVersion, - browser: mockBrowser, - at: mockAt, - buttonText: mockButtonText - }, - mockMutation - ); - - getByTestId = renderResult.getByTestId; - findByRole = renderResult.findByRole; + mockTestPlanVersion = { id: 5 }; + mockBrowser = { id: 2 }; + mockAt = { id: 3 }; + mockButtonText = 'Add to Test Queue'; + + const renderResult = setup( + { + testPlanVersion: mockTestPlanVersion, + browser: mockBrowser, + at: mockAt, + buttonText: mockButtonText + }, + mockMutation + ); + + getByTestId = renderResult.getByTestId; + findByRole = renderResult.findByRole; }; describe('AddTestToQueueWithConfirmation', () => { - beforeEach(() => { - mutationMock = jest.fn().mockResolvedValue(TEST_QUEUE_MUTATION_MOCK); - commonSetup(mutationMock); - }); - - test('renders Button without error', async () => { - await waitFor(() => - expect(getByTestId('add-button')).toBeInTheDocument() - ); - }); - - test('Button has correct text', async () => { - await waitFor(() => - expect(getByTestId('add-button')).toHaveTextContent(mockButtonText) - ); - }); + beforeEach(() => { + mutationMock = jest.fn().mockResolvedValue(TEST_QUEUE_MUTATION_MOCK); + commonSetup(mutationMock); + }); + + test('renders Button without error', async () => { + await waitFor(() => expect(getByTestId('add-button')).toBeInTheDocument()); + }); + + test('Button has correct text', async () => { + await waitFor(() => + expect(getByTestId('add-button')).toHaveTextContent(mockButtonText) + ); + }); - test('renders BasicModal without error', async () => { - fireEvent.click(getByTestId('add-button')); + test('renders BasicModal without error', async () => { + fireEvent.click(getByTestId('add-button')); - await waitFor(async () => { - const modal = await findByRole('dialog'); - expect(modal).toBeInTheDocument(); - }); + await waitFor(async () => { + const modal = await findByRole('dialog'); + expect(modal).toBeInTheDocument(); }); - - test('calls mutation on button click with correct variables', async () => { - fireEvent.click(getByTestId('add-button')); - - await waitFor(() => { - expect(mutationMock).toHaveBeenCalled(); - expect(mutationMock).toHaveBeenCalledWith({ - variables: { - testPlanVersionId: mockTestPlanVersion.id, - atId: mockAt.id, - browserId: mockBrowser.id - } - }); - }); + }); + + test('calls mutation on button click with correct variables', async () => { + fireEvent.click(getByTestId('add-button')); + + await waitFor(() => { + expect(mutationMock).toHaveBeenCalled(); + expect(mutationMock).toHaveBeenCalledWith({ + variables: { + testPlanVersionId: mockTestPlanVersion.id, + atId: mockAt.id, + browserId: mockBrowser.id + } + }); }); + }); }); diff --git a/client/tests/App.test.jsx b/client/tests/App.test.jsx index 45b5c66e1..8d8400f69 100644 --- a/client/tests/App.test.jsx +++ b/client/tests/App.test.jsx @@ -11,15 +11,15 @@ import GraphQLProvider from '../components/GraphQLProvider'; Enzyme.configure({ adapter: new EnzymeAdapter() }); const setup = () => { - const wrapper = shallow( - - - - ).dive(); - return wrapper; + const wrapper = shallow( + + + + ).dive(); + return wrapper; }; test('renders without crashing', () => { - const wrapper = setup(); - expect(wrapper).toBeTruthy(); + const wrapper = setup(); + expect(wrapper).toBeTruthy(); }); diff --git a/client/tests/AssignTesterDropdown.test.jsx b/client/tests/AssignTesterDropdown.test.jsx index 8852eb6ad..c639083ce 100644 --- a/client/tests/AssignTesterDropdown.test.jsx +++ b/client/tests/AssignTesterDropdown.test.jsx @@ -3,44 +3,44 @@ */ import React from 'react'; import { - render, - fireEvent, - waitFor, - screen, - cleanup + render, + fireEvent, + waitFor, + screen, + cleanup } from '@testing-library/react'; import { MockedProvider } from '@apollo/client/testing'; import AssignTesterDropdown from '../components/TestQueue/AssignTesterDropdown'; import { - ASSIGN_TESTER_MUTATION, - REMOVE_TESTER_MUTATION, - TEST_PLAN_REPORT_AT_BROWSER_QUERY + ASSIGN_TESTER_MUTATION, + REMOVE_TESTER_MUTATION, + TEST_PLAN_REPORT_AT_BROWSER_QUERY } from '../components/TestQueue/queries'; import { SCHEDULE_COLLECTION_JOB_MUTATION } from '../components/AddTestToQueueWithConfirmation/queries'; import '@testing-library/jest-dom/extend-expect'; jest.mock('@apollo/client', () => { - const original = jest.requireActual('@apollo/client'); - return { - ...original, - useMutation: jest.fn() - }; + const original = jest.requireActual('@apollo/client'); + return { + ...original, + useMutation: jest.fn() + }; }); const mockPossibleTesters = [ - { id: '1', username: 'bee' }, - { id: '2', username: 'puppy' }, - { id: '3', username: 'NVDA Bot' } + { id: '1', username: 'bee' }, + { id: '2', username: 'puppy' }, + { id: '3', username: 'NVDA Bot' } ]; const mockProps = { - testPlanReportId: 'report1', - possibleTesters: mockPossibleTesters, - onChange: jest.fn(), - testPlanRun: null, - draftTestPlanRuns: [], - label: 'Assign testers', - setAlertMessage: jest.fn() + testPlanReportId: 'report1', + possibleTesters: mockPossibleTesters, + onChange: jest.fn(), + testPlanRun: null, + draftTestPlanRuns: [], + label: 'Assign testers', + setAlertMessage: jest.fn() }; import { useMutation } from '@apollo/client'; @@ -48,233 +48,233 @@ import { act } from 'react-dom/test-utils'; // Mock useMutation hook useMutation.mockImplementation(mutation => { - let response; + let response; - if (mutation === ASSIGN_TESTER_MUTATION) { - response = 'ASSIGN'; - } else if (mutation === REMOVE_TESTER_MUTATION) { - response = 'REMOVE'; - } else if (mutation === SCHEDULE_COLLECTION_JOB_MUTATION) { - response = 'SCHEDULE'; - } + if (mutation === ASSIGN_TESTER_MUTATION) { + response = 'ASSIGN'; + } else if (mutation === REMOVE_TESTER_MUTATION) { + response = 'REMOVE'; + } else if (mutation === SCHEDULE_COLLECTION_JOB_MUTATION) { + response = 'SCHEDULE'; + } - return [jest.fn(() => response), { loading: false, error: null }]; + return [jest.fn(() => response), { loading: false, error: null }]; }); // Mocked GraphQL responses const mocks = [ - { - request: { - query: ASSIGN_TESTER_MUTATION, - variables: { - testReportId: 'report1', - testerId: '1' - } - }, - result: { - data: { - testPlanReport: { - assignTester: { - testPlanReport: { - draftTestPlanRuns: [ - { - initiatedByAutomation: false, - tester: { - id: '1', - username: 'bee' - } - } - ] - } - } + { + request: { + query: ASSIGN_TESTER_MUTATION, + variables: { + testReportId: 'report1', + testerId: '1' + } + }, + result: { + data: { + testPlanReport: { + assignTester: { + testPlanReport: { + draftTestPlanRuns: [ + { + initiatedByAutomation: false, + tester: { + id: '1', + username: 'bee' + } } + ] } + } } + } + } + }, + { + request: { + query: REMOVE_TESTER_MUTATION, + variables: { + testReportId: 'report1', + testerId: '1' + } }, - { - request: { - query: REMOVE_TESTER_MUTATION, - variables: { - testReportId: 'report1', - testerId: '1' - } - }, - result: { - data: { - testPlanReport: { - deleteTestPlanRun: { - testPlanReport: { - draftTestPlanRuns: [] - } - } - } + result: { + data: { + testPlanReport: { + deleteTestPlanRun: { + testPlanReport: { + draftTestPlanRuns: [] } + } } + } + } + }, + { + request: { + query: SCHEDULE_COLLECTION_JOB_MUTATION, + variables: { + testPlanReportId: 'report1' + } }, - { - request: { - query: SCHEDULE_COLLECTION_JOB_MUTATION, - variables: { - testPlanReportId: 'report1' - } - }, - result: { - data: { - scheduleCollectionJob: { - id: 'some-job-id', - status: 'pending' - } - } + result: { + data: { + scheduleCollectionJob: { + id: 'some-job-id', + status: 'pending' } + } + } + }, + { + request: { + query: TEST_PLAN_REPORT_AT_BROWSER_QUERY, + variables: { + testPlanReportId: 'report1' + } }, - { - request: { - query: TEST_PLAN_REPORT_AT_BROWSER_QUERY, - variables: { - testPlanReportId: 'report1' - } - }, - result: { - data: { - testPlanReport: { - id: 'report1', - at: { - id: 2, - name: 'NVDA' - }, - browser: { - id: 1, - name: 'Chrome' - } - } - } + result: { + data: { + testPlanReport: { + id: 'report1', + at: { + id: 2, + name: 'NVDA' + }, + browser: { + id: 1, + name: 'Chrome' + } } + } } + } ]; describe('AssignTesterDropdown', () => { - beforeEach(() => { - cleanup(); - }); + beforeEach(() => { + cleanup(); + }); - it('renders without crashing', () => { - render( - - - - ); - expect(screen.getByLabelText('Assign testers')).toBeInTheDocument(); - }); + it('renders without crashing', () => { + render( + + + + ); + expect(screen.getByLabelText('Assign testers')).toBeInTheDocument(); + }); - it('assigns tester correctly and calls assignTester mutation', async () => { - render( - - - - ); + it('assigns tester correctly and calls assignTester mutation', async () => { + render( + + + + ); - const button = await screen.getByRole('button', { - name: /assign testers/i - }); - fireEvent.click(button); + const button = await screen.getByRole('button', { + name: /assign testers/i + }); + fireEvent.click(button); - const items = await screen.findAllByText(/bee/); - expect(items.length).toBe(2); // One for display, one for sr-only - fireEvent.click(items[0]); + const items = await screen.findAllByText(/bee/); + expect(items.length).toBe(2); // One for display, one for sr-only + fireEvent.click(items[0]); - await waitFor(async () => { - expect(useMutation).toHaveBeenCalledWith(ASSIGN_TESTER_MUTATION); - expect(mockProps.onChange).toHaveBeenCalledTimes(1); - expect(mockProps.setAlertMessage).toHaveBeenCalledTimes(1); - expect(mockProps.setAlertMessage).toHaveBeenCalledWith( - expect.stringContaining('bee now checked') - ); - }); + await waitFor(async () => { + expect(useMutation).toHaveBeenCalledWith(ASSIGN_TESTER_MUTATION); + expect(mockProps.onChange).toHaveBeenCalledTimes(1); + expect(mockProps.setAlertMessage).toHaveBeenCalledTimes(1); + expect(mockProps.setAlertMessage).toHaveBeenCalledWith( + expect.stringContaining('bee now checked') + ); }); + }); - it('assigns bot correctly and calls scheduleCollection mutation', async () => { - render( - - - - ); + it('assigns bot correctly and calls scheduleCollection mutation', async () => { + render( + + + + ); - const button = await screen.getByRole('button', { - name: /assign testers/i - }); - fireEvent.click(button); + const button = await screen.getByRole('button', { + name: /assign testers/i + }); + fireEvent.click(button); - const items = await screen.findAllByText(/NVDA Bot/); - expect(items.length).toBe(2); // One for display, one for sr-only - fireEvent.click(items[0]); + const items = await screen.findAllByText(/NVDA Bot/); + expect(items.length).toBe(2); // One for display, one for sr-only + fireEvent.click(items[0]); - await waitFor(() => { - expect(useMutation).toHaveBeenCalledWith( - SCHEDULE_COLLECTION_JOB_MUTATION - ); - expect(mockProps.onChange).toHaveBeenCalledTimes(1); - }); + await waitFor(() => { + expect(useMutation).toHaveBeenCalledWith( + SCHEDULE_COLLECTION_JOB_MUTATION + ); + expect(mockProps.onChange).toHaveBeenCalledTimes(1); }); + }); - it('does not list bot when run does not support automation', async () => { - await act(async () => { - const jawsMock = [...mocks]; - jawsMock[3].result.data.testPlanReport.at.name = 'JAWS'; + it('does not list bot when run does not support automation', async () => { + await act(async () => { + const jawsMock = [...mocks]; + jawsMock[3].result.data.testPlanReport.at.name = 'JAWS'; - render( - - - - ); - }); - let button; - await waitFor(async () => { - button = await screen.getByRole('button', { - name: /assign testers/i - }); - }); + render( + + + + ); + }); + let button; + await waitFor(async () => { + button = await screen.getByRole('button', { + name: /assign testers/i + }); + }); - await act(async () => { - fireEvent.click(button); - }); + await act(async () => { + fireEvent.click(button); + }); - await waitFor(async () => { - const items = await screen.queryByText(/NVDA Bot/); - expect(items).toBeNull(); - }); + await waitFor(async () => { + const items = await screen.queryByText(/NVDA Bot/); + expect(items).toBeNull(); }); + }); - it('removes tester correctly and calls removeTester mutation', async () => { - mockProps.draftTestPlanRuns = [ - { - initiatedByAutomation: false, - tester: { - id: '1', - username: 'bee' - } - } - ]; + it('removes tester correctly and calls removeTester mutation', async () => { + mockProps.draftTestPlanRuns = [ + { + initiatedByAutomation: false, + tester: { + id: '1', + username: 'bee' + } + } + ]; - render( - - - - ); + render( + + + + ); - const button = await screen.getByRole('button', { - name: /assign testers/i - }); + const button = await screen.getByRole('button', { + name: /assign testers/i + }); - fireEvent.click(button); + fireEvent.click(button); - const items = await screen.findAllByText(/bee/); - fireEvent.click(items[0]); + const items = await screen.findAllByText(/bee/); + fireEvent.click(items[0]); - await waitFor(() => { - expect(useMutation).toHaveBeenCalledWith(REMOVE_TESTER_MUTATION); - expect(mockProps.setAlertMessage).toHaveBeenCalledWith( - expect.stringContaining('bee now unchecked') - ); - }); + await waitFor(() => { + expect(useMutation).toHaveBeenCalledWith(REMOVE_TESTER_MUTATION); + expect(mockProps.setAlertMessage).toHaveBeenCalledWith( + expect.stringContaining('bee now unchecked') + ); }); + }); }); diff --git a/client/tests/BasicModal.test.jsx b/client/tests/BasicModal.test.jsx index dc83d1518..370172efe 100644 --- a/client/tests/BasicModal.test.jsx +++ b/client/tests/BasicModal.test.jsx @@ -9,132 +9,124 @@ import BasicModal from '../components/common/BasicModal'; const MockCustomComponent = ({ customProp }) => ; // eslint-disable-line react/prop-types describe('BasicModal', () => { - test('renders modal when show is true', () => { - render( - - ); - expect(screen.getByRole('dialog')).toBeInTheDocument(); - }); + test('renders modal when show is true', () => { + render( + + ); + expect(screen.getByRole('dialog')).toBeInTheDocument(); + }); - test('does not render modal when show is false', () => { - render( - - ); - expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); - }); + test('does not render modal when show is false', () => { + render( + + ); + expect(screen.queryByRole('dialog')).not.toBeInTheDocument(); + }); - test('renders title and content correctly', () => { - render( - - ); - expect(screen.getByText('My Title')).toBeInTheDocument(); - expect(screen.getByText('My Content')).toBeInTheDocument(); - }); + test('renders title and content correctly', () => { + render(); + expect(screen.getByText('My Title')).toBeInTheDocument(); + expect(screen.getByText('My Content')).toBeInTheDocument(); + }); - test('multiple action buttons trigger correct functions', () => { - const saveFunction = jest.fn(); - const deleteFunction = jest.fn(); - render( - - ); - fireEvent.click(screen.getByText('Save')); - expect(saveFunction).toHaveBeenCalledTimes(1); - fireEvent.click(screen.getByText('Delete')); - expect(deleteFunction).toHaveBeenCalledTimes(1); - expect(saveFunction).toHaveBeenCalledTimes(1); - }); + test('multiple action buttons trigger correct functions', () => { + const saveFunction = jest.fn(); + const deleteFunction = jest.fn(); + render( + + ); + fireEvent.click(screen.getByText('Save')); + expect(saveFunction).toHaveBeenCalledTimes(1); + fireEvent.click(screen.getByText('Delete')); + expect(deleteFunction).toHaveBeenCalledTimes(1); + expect(saveFunction).toHaveBeenCalledTimes(1); + }); - test('close button triggers handleClose function', () => { - const handleClose = jest.fn(); - render( - - ); - fireEvent.click(screen.getByText('Cancel')); - expect(handleClose).toHaveBeenCalledTimes(1); - }); + test('close button triggers handleClose function', () => { + const handleClose = jest.fn(); + render( + + ); + fireEvent.click(screen.getByText('Cancel')); + expect(handleClose).toHaveBeenCalledTimes(1); + }); - test('cancel button triggers handleClose function when cancelButton is true', () => { - const handleClose = jest.fn(); - render( - - ); - fireEvent.click(screen.getByText('Cancel')); - expect(handleClose).toHaveBeenCalledTimes(1); - }); - test('renders custom component in actions', () => { - render( - - ); + test('cancel button triggers handleClose function when cancelButton is true', () => { + const handleClose = jest.fn(); + render( + + ); + fireEvent.click(screen.getByText('Cancel')); + expect(handleClose).toHaveBeenCalledTimes(1); + }); + test('renders custom component in actions', () => { + render( + + ); - expect(screen.getByText('Custom Button')).toBeInTheDocument(); - }); + expect(screen.getByText('Custom Button')).toBeInTheDocument(); + }); - test('custom component triggers appropriate action', () => { - const customAction = jest.fn(); + test('custom component triggers appropriate action', () => { + const customAction = jest.fn(); - render( - ( - - ), - props: {} - } - ]} - /> - ); + render( + ( + + ), + props: {} + } + ]} + /> + ); - fireEvent.click(screen.getByText('Custom Action')); - expect(customAction).toHaveBeenCalledTimes(1); - }); + fireEvent.click(screen.getByText('Custom Action')); + expect(customAction).toHaveBeenCalledTimes(1); + }); - test('has aria-labelledby matching the modal title id', () => { - const { getByRole, getByText } = render( - - ); + test('has aria-labelledby matching the modal title id', () => { + const { getByRole, getByText } = render( + + ); - const modal = getByRole('dialog'); - const title = getByText('Test Title'); + const modal = getByRole('dialog'); + const title = getByText('Test Title'); - expect(modal).toHaveAttribute('aria-labelledby', title.id); - }); + expect(modal).toHaveAttribute('aria-labelledby', title.id); + }); }); diff --git a/client/tests/BotRunTestStatusList.test.jsx b/client/tests/BotRunTestStatusList.test.jsx index 66b93e03d..098460889 100644 --- a/client/tests/BotRunTestStatusList.test.jsx +++ b/client/tests/BotRunTestStatusList.test.jsx @@ -6,174 +6,162 @@ import { render, waitFor } from '@testing-library/react'; import { MockedProvider } from '@apollo/client/testing'; import BotRunTestStatusList from '../components/BotRunTestStatusList'; import { - TEST_PLAN_RUNS_TEST_RESULTS_QUERY, - COLLECTION_JOB_STATUS_BY_TEST_PLAN_RUN_ID_QUERY + TEST_PLAN_RUNS_TEST_RESULTS_QUERY, + COLLECTION_JOB_STATUS_BY_TEST_PLAN_RUN_ID_QUERY } from '../components/BotRunTestStatusList/queries'; import '@testing-library/jest-dom/extend-expect'; const getMocks = (testPlanRuns, collectionJobStatuses) => { - const testPlanRunMock = { - request: { - query: TEST_PLAN_RUNS_TEST_RESULTS_QUERY, - variables: { testPlanReportId: '1' } - }, - result: { data: { testPlanRuns } } - }; - - const collectionJobStatusMocks = testPlanRuns.map((testRun, index) => ({ - request: { - query: COLLECTION_JOB_STATUS_BY_TEST_PLAN_RUN_ID_QUERY, - variables: { testPlanRunId: testRun.id } - }, - result: { - data: { - collectionJobByTestPlanRunId: { - status: collectionJobStatuses[index], - id: testRun.id - } - } + const testPlanRunMock = { + request: { + query: TEST_PLAN_RUNS_TEST_RESULTS_QUERY, + variables: { testPlanReportId: '1' } + }, + result: { data: { testPlanRuns } } + }; + + const collectionJobStatusMocks = testPlanRuns.map((testRun, index) => ({ + request: { + query: COLLECTION_JOB_STATUS_BY_TEST_PLAN_RUN_ID_QUERY, + variables: { testPlanRunId: testRun.id } + }, + result: { + data: { + collectionJobByTestPlanRunId: { + status: collectionJobStatuses[index], + id: testRun.id } - })); + } + } + })); - return [testPlanRunMock, ...collectionJobStatusMocks]; + return [testPlanRunMock, ...collectionJobStatusMocks]; }; test('correctly displays statuses for single COMPLETED test run', async () => { - const testPlanRuns = [ - { - id: '0', - testResults: new Array(3).fill(null), - tester: { username: 'bot' } - } - ]; - - const collectionJobStatuses = ['COMPLETED']; - - const mocks = getMocks(testPlanRuns, collectionJobStatuses); - - const { getByText } = render( - - - - ); - - await waitFor(() => { - expect(getByText('3 Tests Completed')).toBeInTheDocument(); - expect(getByText('0 Tests Queued')).toBeInTheDocument(); - expect(getByText('0 Tests Cancelled')).toBeInTheDocument(); - }); + const testPlanRuns = [ + { + id: '0', + testResults: new Array(3).fill(null), + tester: { username: 'bot' } + } + ]; + + const collectionJobStatuses = ['COMPLETED']; + + const mocks = getMocks(testPlanRuns, collectionJobStatuses); + + const { getByText } = render( + + + + ); + + await waitFor(() => { + expect(getByText('3 Tests Completed')).toBeInTheDocument(); + expect(getByText('0 Tests Queued')).toBeInTheDocument(); + expect(getByText('0 Tests Cancelled')).toBeInTheDocument(); + }); }); test('correctly ignores test results from a human-submitted test plan run', async () => { - const testPlanRuns = [ - { - id: '0', - testResults: new Array(2).fill(null), - tester: { username: 'bot' } - }, - { - id: '1', - testResults: new Array(2).fill(null), - tester: { username: 'human' } - } - ]; - - const collectionJobStatuses = ['COMPLETED', 'COMPLETED']; - - const mocks = getMocks(testPlanRuns, collectionJobStatuses); - - const { getByText } = render( - - - - ); - - await waitFor(async () => { - expect(getByText('2 Tests Completed')).toBeInTheDocument(); - expect(getByText('0 Tests Queued')).toBeInTheDocument(); - expect(getByText('0 Tests Cancelled')).toBeInTheDocument(); - }); + const testPlanRuns = [ + { + id: '0', + testResults: new Array(2).fill(null), + tester: { username: 'bot' } + }, + { + id: '1', + testResults: new Array(2).fill(null), + tester: { username: 'human' } + } + ]; + + const collectionJobStatuses = ['COMPLETED', 'COMPLETED']; + + const mocks = getMocks(testPlanRuns, collectionJobStatuses); + + const { getByText } = render( + + + + ); + + await waitFor(async () => { + expect(getByText('2 Tests Completed')).toBeInTheDocument(); + expect(getByText('0 Tests Queued')).toBeInTheDocument(); + expect(getByText('0 Tests Cancelled')).toBeInTheDocument(); + }); }); test('correctly displays statuses for CANCELLED test run', async () => { - const testPlanRuns = [ - { - id: '0', - testResults: new Array(2).fill(null), - tester: { username: 'bot' } - } - ]; - - const collectionJobStatuses = ['CANCELLED']; - - const mocks = getMocks(testPlanRuns, collectionJobStatuses); - - const { getByText } = render( - - - - ); - - await waitFor(() => { - expect(getByText('2 Tests Completed')).toBeInTheDocument(); - expect(getByText('0 Tests Queued')).toBeInTheDocument(); - expect(getByText('1 Test Cancelled')).toBeInTheDocument(); - }); + const testPlanRuns = [ + { + id: '0', + testResults: new Array(2).fill(null), + tester: { username: 'bot' } + } + ]; + + const collectionJobStatuses = ['CANCELLED']; + + const mocks = getMocks(testPlanRuns, collectionJobStatuses); + + const { getByText } = render( + + + + ); + + await waitFor(() => { + expect(getByText('2 Tests Completed')).toBeInTheDocument(); + expect(getByText('0 Tests Queued')).toBeInTheDocument(); + expect(getByText('1 Test Cancelled')).toBeInTheDocument(); + }); }); test('correctly displays statuses for multiple RUNNING and QUEUED test runs', async () => { - const testPlanRuns = [ - { - id: '0', - testResults: new Array(2).fill(null), - tester: { username: 'bot' } - }, - { - id: '1', - testResults: new Array(2).fill(null), - tester: { username: 'bot' } - }, - { - id: '2', - testResults: [null], - tester: { username: 'bot' } - }, - { - id: '3', - testResults: new Array(2).fill(null), - tester: { username: 'human' } - } - ]; - - const collectionJobStatuses = ['RUNNING', 'RUNNING', 'CANCELLED']; - - const mocks = getMocks(testPlanRuns, collectionJobStatuses); - - const { getByText } = render( - - - - ); - - await waitFor(async () => { - // Wait for the component to update - // Imperfect but prevents needing to detect loading removal - await setTimeout(() => { - expect(getByText('2 Tests Completed')).toBeInTheDocument(); - expect(getByText('1 Test Queued')).toBeInTheDocument(); - expect(getByText('1 Test Cancelled')).toBeInTheDocument(); - }, 500); - }); + const testPlanRuns = [ + { + id: '0', + testResults: new Array(2).fill(null), + tester: { username: 'bot' } + }, + { + id: '1', + testResults: new Array(2).fill(null), + tester: { username: 'bot' } + }, + { + id: '2', + testResults: [null], + tester: { username: 'bot' } + }, + { + id: '3', + testResults: new Array(2).fill(null), + tester: { username: 'human' } + } + ]; + + const collectionJobStatuses = ['RUNNING', 'RUNNING', 'CANCELLED']; + + const mocks = getMocks(testPlanRuns, collectionJobStatuses); + + const { getByText } = render( + + + + ); + + await waitFor(async () => { + // Wait for the component to update + // Imperfect but prevents needing to detect loading removal + await setTimeout(() => { + expect(getByText('2 Tests Completed')).toBeInTheDocument(); + expect(getByText('1 Test Queued')).toBeInTheDocument(); + expect(getByText('1 Test Cancelled')).toBeInTheDocument(); + }, 500); + }); }); diff --git a/client/tests/DataManagement.test.jsx b/client/tests/DataManagement.test.jsx index 73a46fadb..8a2f508ed 100644 --- a/client/tests/DataManagement.test.jsx +++ b/client/tests/DataManagement.test.jsx @@ -15,287 +15,281 @@ import DataManagement from '../components/DataManagement'; import { DATA_MANAGEMENT_PAGE_POPULATED_MOCK_DATA } from './__mocks__/GraphQLMocks'; import { act } from 'react-dom/test-utils'; import { - useDataManagementTableFiltering, - useDataManagementTableSorting, - useDerivedActivePhasesByTestPlanId, - useTestPlanVersionsByPhase, - useTestPlansByPhase + useDataManagementTableFiltering, + useDataManagementTableSorting, + useDerivedActivePhasesByTestPlanId, + useTestPlanVersionsByPhase, + useTestPlansByPhase } from '../components/DataManagement/filterSortHooks'; import { - DATA_MANAGEMENT_TABLE_FILTER_OPTIONS, - DATA_MANAGEMENT_TABLE_SORT_OPTIONS + DATA_MANAGEMENT_TABLE_FILTER_OPTIONS, + DATA_MANAGEMENT_TABLE_SORT_OPTIONS } from '../components/DataManagement/utils'; import { TABLE_SORT_ORDERS } from '../components/common/SortableTableHeader'; import { AriaLiveRegionProvider } from '../components/providers/AriaLiveRegionProvider'; const setup = (mocks = []) => { - return render( - - - - - - - - ); + return render( + + + + + + + + ); }; describe('Data Management page', () => { - let wrapper; + let wrapper; - beforeEach(() => { - wrapper = setup(DATA_MANAGEMENT_PAGE_POPULATED_MOCK_DATA); - }); + beforeEach(() => { + wrapper = setup(DATA_MANAGEMENT_PAGE_POPULATED_MOCK_DATA); + }); - it('renders loading state on initialization', async () => { - const { getByTestId } = wrapper; - const element = getByTestId('page-status'); + it('renders loading state on initialization', async () => { + const { getByTestId } = wrapper; + const element = getByTestId('page-status'); - expect(element).toBeTruthy(); - expect(element).toHaveTextContent('Loading'); - }); + expect(element).toBeTruthy(); + expect(element).toHaveTextContent('Loading'); + }); - it('renders Status Summary component', async () => { - // allow page time to load - await waitFor(() => new Promise(res => setTimeout(res, 0))); + it('renders Status Summary component', async () => { + // allow page time to load + await waitFor(() => new Promise(res => setTimeout(res, 0))); - const { queryAllByText } = wrapper; - const statusSummaryElement = queryAllByText( - /Test Plans Status Summary/i - ); - const testPlanElement = queryAllByText(/Test Plan/i); - const coveredAtElement = queryAllByText(/Covered AT/i); - const overallStatusElement = queryAllByText(/Overall Status/i); - const rdElement = queryAllByText(/R&D Version/i); - const draftElement = queryAllByText(/Draft Review/i); - const candidateElement = queryAllByText(/Candidate Review/i); - const recommendedElement = queryAllByText(/Recommended Version/i); + const { queryAllByText } = wrapper; + const statusSummaryElement = queryAllByText(/Test Plans Status Summary/i); + const testPlanElement = queryAllByText(/Test Plan/i); + const coveredAtElement = queryAllByText(/Covered AT/i); + const overallStatusElement = queryAllByText(/Overall Status/i); + const rdElement = queryAllByText(/R&D Version/i); + const draftElement = queryAllByText(/Draft Review/i); + const candidateElement = queryAllByText(/Candidate Review/i); + const recommendedElement = queryAllByText(/Recommended Version/i); - expect(statusSummaryElement.length).toBeGreaterThanOrEqual(1); - expect(testPlanElement.length).toBeGreaterThanOrEqual(1); - expect(coveredAtElement.length).toBeGreaterThanOrEqual(1); - expect(overallStatusElement.length).toBeGreaterThanOrEqual(1); - expect(rdElement.length).toBeGreaterThanOrEqual(1); - expect(draftElement.length).toBeGreaterThanOrEqual(1); - expect(candidateElement.length).toBeGreaterThanOrEqual(1); - expect(recommendedElement.length).toBeGreaterThanOrEqual(1); - }); + expect(statusSummaryElement.length).toBeGreaterThanOrEqual(1); + expect(testPlanElement.length).toBeGreaterThanOrEqual(1); + expect(coveredAtElement.length).toBeGreaterThanOrEqual(1); + expect(overallStatusElement.length).toBeGreaterThanOrEqual(1); + expect(rdElement.length).toBeGreaterThanOrEqual(1); + expect(draftElement.length).toBeGreaterThanOrEqual(1); + expect(candidateElement.length).toBeGreaterThanOrEqual(1); + expect(recommendedElement.length).toBeGreaterThanOrEqual(1); + }); }); const testPlans = [ - { title: 'Test A', directory: 'dirA', id: '1' }, - { title: 'Test B', directory: 'dirB', id: '2' }, - { title: 'Test C', directory: 'dirC', id: '3' }, - { title: 'Test D', directory: 'dirD', id: '4' } + { title: 'Test A', directory: 'dirA', id: '1' }, + { title: 'Test B', directory: 'dirB', id: '2' }, + { title: 'Test C', directory: 'dirC', id: '3' }, + { title: 'Test D', directory: 'dirD', id: '4' } ]; const testPlanVersions = [ - { - phase: 'RD', - id: '101', - testPlan: { directory: 'dirA' }, - updatedAt: '2022-03-17T18:34:51.000Z' - }, - { - phase: 'DRAFT', - id: '102', - testPlan: { directory: 'dirB' }, - draftStatusReachedAt: '2022-05-18T20:51:40.000Z' - }, - { - phase: 'CANDIDATE', - id: '103', - testPlan: { directory: 'dirC' }, - candidatePhaseReachedAt: '2022-04-10T00:00:00.000Z' - }, - { - phase: 'RD', - id: '104', - testPlan: { directory: 'dirD' }, - updatedAt: '2022-03-18T18:34:51.000Z' - }, - { - phase: 'RECOMMENDED', - id: '105', - testPlan: { directory: 'dirD' }, - recommendedPhaseReachedAt: '2022-05-18T20:51:40.000Z' - }, - { - phase: 'DRAFT', - id: '106', - testPlan: { directory: 'dirD' }, - draftStatusReachedAt: '2024-01-08T20:51:40.000Z' - } + { + phase: 'RD', + id: '101', + testPlan: { directory: 'dirA' }, + updatedAt: '2022-03-17T18:34:51.000Z' + }, + { + phase: 'DRAFT', + id: '102', + testPlan: { directory: 'dirB' }, + draftStatusReachedAt: '2022-05-18T20:51:40.000Z' + }, + { + phase: 'CANDIDATE', + id: '103', + testPlan: { directory: 'dirC' }, + candidatePhaseReachedAt: '2022-04-10T00:00:00.000Z' + }, + { + phase: 'RD', + id: '104', + testPlan: { directory: 'dirD' }, + updatedAt: '2022-03-18T18:34:51.000Z' + }, + { + phase: 'RECOMMENDED', + id: '105', + testPlan: { directory: 'dirD' }, + recommendedPhaseReachedAt: '2022-05-18T20:51:40.000Z' + }, + { + phase: 'DRAFT', + id: '106', + testPlan: { directory: 'dirD' }, + draftStatusReachedAt: '2024-01-08T20:51:40.000Z' + } ]; const ats = []; // ATs are stubbed until this model is defined describe('useDataManagementTableSorting hook', () => { - it('sorts by phase by default', () => { - const { result } = renderHook(() => - useDataManagementTableSorting( - testPlans, - testPlanVersions, - ats, - TABLE_SORT_ORDERS.DESC - ) - ); - expect(result.current.sortedTestPlans).toEqual([ - testPlans[3], // RECOMMENDED - testPlans[2], // CANDIDATE - testPlans[1], // DRAFT - testPlans[0] // RD - ]); - }); + it('sorts by phase by default', () => { + const { result } = renderHook(() => + useDataManagementTableSorting( + testPlans, + testPlanVersions, + ats, + TABLE_SORT_ORDERS.DESC + ) + ); + expect(result.current.sortedTestPlans).toEqual([ + testPlans[3], // RECOMMENDED + testPlans[2], // CANDIDATE + testPlans[1], // DRAFT + testPlans[0] // RD + ]); + }); - it('can sort by name', () => { - const { result } = renderHook(() => - useDataManagementTableSorting(testPlans, testPlanVersions, ats) - ); - act(() => - result.current.updateSort({ - key: DATA_MANAGEMENT_TABLE_SORT_OPTIONS.NAME, - direction: TABLE_SORT_ORDERS.ASC - }) - ); - expect(result.current.sortedTestPlans).toEqual(testPlans); - }); + it('can sort by name', () => { + const { result } = renderHook(() => + useDataManagementTableSorting(testPlans, testPlanVersions, ats) + ); + act(() => + result.current.updateSort({ + key: DATA_MANAGEMENT_TABLE_SORT_OPTIONS.NAME, + direction: TABLE_SORT_ORDERS.ASC + }) + ); + expect(result.current.sortedTestPlans).toEqual(testPlans); + }); }); describe('useDataManagementTableFiltering hook', () => { - it('shows all plans by default', () => { - const { result } = renderHook(() => - useDataManagementTableFiltering( - testPlans, - testPlanVersions, - DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.ALL - ) - ); - expect(result.current.filteredTestPlans).toEqual(testPlans); - expect( - result.current.filterLabels[ - DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.ALL - ] - ).toEqual(`All Plans (${testPlans.length})`); - }); + it('shows all plans by default', () => { + const { result } = renderHook(() => + useDataManagementTableFiltering( + testPlans, + testPlanVersions, + DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.ALL + ) + ); + expect(result.current.filteredTestPlans).toEqual(testPlans); + expect( + result.current.filterLabels[DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.ALL] + ).toEqual(`All Plans (${testPlans.length})`); + }); - it('can filter by RD phase', () => { - const { result } = renderHook(() => - useDataManagementTableFiltering( - testPlans, - testPlanVersions, - DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.RD - ) - ); - expect(result.current.filteredTestPlans).toEqual([ - testPlans[0], // RD - testPlans[3] - ]); - expect( - result.current.filterLabels[DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.RD] - ).toEqual(`R&D Complete (2)`); - }); + it('can filter by RD phase', () => { + const { result } = renderHook(() => + useDataManagementTableFiltering( + testPlans, + testPlanVersions, + DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.RD + ) + ); + expect(result.current.filteredTestPlans).toEqual([ + testPlans[0], // RD + testPlans[3] + ]); + expect( + result.current.filterLabels[DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.RD] + ).toEqual(`R&D Complete (2)`); + }); - it('can filter by DRAFT phase', () => { - const { result } = renderHook(() => - useDataManagementTableFiltering( - testPlans, - testPlanVersions, - DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.DRAFT - ) - ); - expect(result.current.filteredTestPlans).toEqual([ - testPlans[1], // DRAFT - testPlans[3] // DRAFT - ]); - expect( - result.current.filterLabels[ - DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.DRAFT - ] - ).toEqual(`In Draft Review (2)`); // Test plan 106 is in DRAFT while the overall plan is RECOMMENDED - }); + it('can filter by DRAFT phase', () => { + const { result } = renderHook(() => + useDataManagementTableFiltering( + testPlans, + testPlanVersions, + DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.DRAFT + ) + ); + expect(result.current.filteredTestPlans).toEqual([ + testPlans[1], // DRAFT + testPlans[3] // DRAFT + ]); + expect( + result.current.filterLabels[DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.DRAFT] + ).toEqual(`In Draft Review (2)`); // Test plan 106 is in DRAFT while the overall plan is RECOMMENDED + }); - it('can filter by CANDIDATE phase', () => { - const { result } = renderHook(() => - useDataManagementTableFiltering( - testPlans, - testPlanVersions, - DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.CANDIDATE - ) - ); - expect(result.current.filteredTestPlans).toEqual([ - testPlans[2] // CANDIDATE - ]); - expect( - result.current.filterLabels[ - DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.CANDIDATE - ] - ).toEqual(`In Candidate Review (1)`); - }); + it('can filter by CANDIDATE phase', () => { + const { result } = renderHook(() => + useDataManagementTableFiltering( + testPlans, + testPlanVersions, + DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.CANDIDATE + ) + ); + expect(result.current.filteredTestPlans).toEqual([ + testPlans[2] // CANDIDATE + ]); + expect( + result.current.filterLabels[ + DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.CANDIDATE + ] + ).toEqual(`In Candidate Review (1)`); + }); - it('can filter by RECOMMENDED phase', () => { - const { result } = renderHook(() => - useDataManagementTableFiltering( - testPlans, - testPlanVersions, - DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.RECOMMENDED - ) - ); - expect(result.current.filteredTestPlans).toEqual([ - testPlans[3] // RECOMMENDED - ]); - expect( - result.current.filterLabels[ - DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.RECOMMENDED - ] - ).toEqual(`Recommended Plans (1)`); - }); + it('can filter by RECOMMENDED phase', () => { + const { result } = renderHook(() => + useDataManagementTableFiltering( + testPlans, + testPlanVersions, + DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.RECOMMENDED + ) + ); + expect(result.current.filteredTestPlans).toEqual([ + testPlans[3] // RECOMMENDED + ]); + expect( + result.current.filterLabels[ + DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.RECOMMENDED + ] + ).toEqual(`Recommended Plans (1)`); + }); }); describe('useTestPlanVersionsByPhase hook', () => { - it('returns an object with test plan versions grouped by phase', () => { - const { result } = renderHook(() => - useTestPlanVersionsByPhase(testPlanVersions) - ); - const { testPlanVersionsByPhase } = result.current; - expect(testPlanVersionsByPhase).toEqual({ - RD: [testPlanVersions[0], testPlanVersions[3]], - DRAFT: [testPlanVersions[1], testPlanVersions[5]], - CANDIDATE: [testPlanVersions[2]], - RECOMMENDED: [testPlanVersions[4]] - }); + it('returns an object with test plan versions grouped by phase', () => { + const { result } = renderHook(() => + useTestPlanVersionsByPhase(testPlanVersions) + ); + const { testPlanVersionsByPhase } = result.current; + expect(testPlanVersionsByPhase).toEqual({ + RD: [testPlanVersions[0], testPlanVersions[3]], + DRAFT: [testPlanVersions[1], testPlanVersions[5]], + CANDIDATE: [testPlanVersions[2]], + RECOMMENDED: [testPlanVersions[4]] }); + }); }); describe('useDerivedTestPlanOverallPhase hook', () => { - it('returns an object with the active phases mapped to each test plan id', () => { - const { result } = renderHook(() => - useDerivedActivePhasesByTestPlanId(testPlans, testPlanVersions) - ); - const { derivedActivePhasesByTestPlanId } = result.current; - expect(derivedActivePhasesByTestPlanId).toEqual({ - 1: ['RD'], - 2: ['DRAFT'], - 3: ['CANDIDATE'], - 4: ['RECOMMENDED', 'DRAFT', 'RD'] - }); + it('returns an object with the active phases mapped to each test plan id', () => { + const { result } = renderHook(() => + useDerivedActivePhasesByTestPlanId(testPlans, testPlanVersions) + ); + const { derivedActivePhasesByTestPlanId } = result.current; + expect(derivedActivePhasesByTestPlanId).toEqual({ + 1: ['RD'], + 2: ['DRAFT'], + 3: ['CANDIDATE'], + 4: ['RECOMMENDED', 'DRAFT', 'RD'] }); + }); }); describe('useTestPlansByPhase hook', () => { - it('returns an object with test plans with an array of active Test Plan Versions', () => { - const { result } = renderHook(() => - useTestPlansByPhase(testPlans, testPlanVersions) - ); - const { testPlansByPhase } = result.current; - expect(testPlansByPhase).toEqual({ - RD: [testPlans[0], testPlans[3]], - DRAFT: [testPlans[1], testPlans[3]], - CANDIDATE: [testPlans[2]], - RECOMMENDED: [testPlans[3]] - }); + it('returns an object with test plans with an array of active Test Plan Versions', () => { + const { result } = renderHook(() => + useTestPlansByPhase(testPlans, testPlanVersions) + ); + const { testPlansByPhase } = result.current; + expect(testPlansByPhase).toEqual({ + RD: [testPlans[0], testPlans[3]], + DRAFT: [testPlans[1], testPlans[3]], + CANDIDATE: [testPlans[2]], + RECOMMENDED: [testPlans[3]] }); + }); }); diff --git a/client/tests/FilterButtons.test.jsx b/client/tests/FilterButtons.test.jsx index 26a43cc63..8edf3d32d 100644 --- a/client/tests/FilterButtons.test.jsx +++ b/client/tests/FilterButtons.test.jsx @@ -9,54 +9,52 @@ import FilterButtons from '../components/common/FilterButtons'; import { DATA_MANAGEMENT_TABLE_FILTER_OPTIONS } from '../components/DataManagement/utils'; describe('FilterButtons', () => { - const filterOptions = { - [DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.RD]: `R&D Complete`, - [DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.DRAFT]: `In Draft Review`, - [DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.CANDIDATE]: `In Candidate Review`, - [DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.RECOMMENDED]: `Recommended Plans`, - [DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.ALL]: `All Plans` - }; - const defaultProps = { - filterOptions, - filterLabel: 'Filter', - activeFilter: DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.ALL, - onFilterChange: () => {} - }; + const filterOptions = { + [DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.RD]: `R&D Complete`, + [DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.DRAFT]: `In Draft Review`, + [DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.CANDIDATE]: `In Candidate Review`, + [DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.RECOMMENDED]: `Recommended Plans`, + [DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.ALL]: `All Plans` + }; + const defaultProps = { + filterOptions, + filterLabel: 'Filter', + activeFilter: DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.ALL, + onFilterChange: () => {} + }; - it('should render without crashing', () => { - render(); - expect(screen.getByRole('group')).toBeInTheDocument(); - }); + it('should render without crashing', () => { + render(); + expect(screen.getByRole('group')).toBeInTheDocument(); + }); - it('should render the correct filter labels', () => { - render(); - Object.values(filterOptions).forEach(label => { - expect(screen.getByText(label)).toBeInTheDocument(); - }); + it('should render the correct filter labels', () => { + render(); + Object.values(filterOptions).forEach(label => { + expect(screen.getByText(label)).toBeInTheDocument(); }); + }); - it('should render the active filter with correct styles', () => { - render(); - const activeButton = screen - .getByText(filterOptions[DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.ALL]) - .closest('button'); - expect(activeButton).toHaveAttribute('aria-pressed', 'true'); - expect(activeButton).toHaveClass('active'); - }); + it('should render the active filter with correct styles', () => { + render(); + const activeButton = screen + .getByText(filterOptions[DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.ALL]) + .closest('button'); + expect(activeButton).toHaveAttribute('aria-pressed', 'true'); + expect(activeButton).toHaveClass('active'); + }); - it('should change filter on button click', () => { - const onFilterChange = jest.fn(); - render( - - ); - const button = screen - .getByText( - filterOptions[DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.RECOMMENDED] - ) - .closest('button'); - fireEvent.click(button); - expect(onFilterChange).toHaveBeenCalledWith( - DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.RECOMMENDED - ); - }); + it('should change filter on button click', () => { + const onFilterChange = jest.fn(); + render(); + const button = screen + .getByText( + filterOptions[DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.RECOMMENDED] + ) + .closest('button'); + fireEvent.click(button); + expect(onFilterChange).toHaveBeenCalledWith( + DATA_MANAGEMENT_TABLE_FILTER_OPTIONS.RECOMMENDED + ); + }); }); diff --git a/client/tests/FocusTrapper.test.jsx b/client/tests/FocusTrapper.test.jsx index a4c114d85..aa252755d 100644 --- a/client/tests/FocusTrapper.test.jsx +++ b/client/tests/FocusTrapper.test.jsx @@ -6,120 +6,116 @@ import { render, fireEvent, act } from '@testing-library/react'; import FocusTrapper from '../components/common/FocusTrapper'; describe('FocusTrapper', () => { - let trappedDiv, initialFocusRef; - - beforeEach(() => { - trappedDiv = document.createElement('div'); - trappedDiv.id = 'trapped-div'; - document.body.appendChild(trappedDiv); - }); - - afterEach(() => { - document.body.removeChild(trappedDiv); + let trappedDiv, initialFocusRef; + + beforeEach(() => { + trappedDiv = document.createElement('div'); + trappedDiv.id = 'trapped-div'; + document.body.appendChild(trappedDiv); + }); + + afterEach(() => { + document.body.removeChild(trappedDiv); + }); + + const renderEls = async () => { + initialFocusRef = React.createRef(); + return render( + +

    + Modal Header +

    + + Link +
    , + { container: document.body.appendChild(trappedDiv) } + ); + }; + + it('should identify focusable elements', async () => { + await renderEls(); + + const focusables = trappedDiv.querySelectorAll( + 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' + ); + + // Two original focusable elements plus 2 for before and after trap + expect(focusables.length).toBe(4); + }); + + it('should trap focus and allow forward navigation when isActive is true', async () => { + await renderEls(); + + const container = document.getElementById('trapped-div'); + + const firstFocusable = container.querySelector('button'); + const lastFocusable = container.querySelector('a'); + + act(() => { + lastFocusable.focus(); }); - const renderEls = async () => { - initialFocusRef = React.createRef(); - return render( - -

    - Modal Header -

    - - Link -
    , - { container: document.body.appendChild(trappedDiv) } - ); - }; - - it('should identify focusable elements', async () => { - await renderEls(); - - const focusables = trappedDiv.querySelectorAll( - 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' - ); - - // Two original focusable elements plus 2 for before and after trap - expect(focusables.length).toBe(4); + act(() => { + fireEvent.keyDown(container, { + key: 'Tab', + code: 9, + shiftKey: false + }); }); - it('should trap focus and allow forward navigation when isActive is true', async () => { - await renderEls(); - - const container = document.getElementById('trapped-div'); + expect(document.activeElement).toBe(firstFocusable); + }); - const firstFocusable = container.querySelector('button'); - const lastFocusable = container.querySelector('a'); + it('should trap focus when and allow backward navigation when isActive is true', async () => { + await renderEls(); - act(() => { - lastFocusable.focus(); - }); + const container = document.getElementById('trapped-div'); - act(() => { - fireEvent.keyDown(container, { - key: 'Tab', - code: 9, - shiftKey: false - }); - }); + const lastFocusable = container.querySelector('a'); - expect(document.activeElement).toBe(firstFocusable); + act(() => { + initialFocusRef.current.focus(); }); - it('should trap focus when and allow backward navigation when isActive is true', async () => { - await renderEls(); - - const container = document.getElementById('trapped-div'); + act(() => { + fireEvent.keyDown(container, { + key: 'Tab', + code: 9, + shiftKey: true + }); + }); - const lastFocusable = container.querySelector('a'); + expect(document.activeElement).toBe(lastFocusable); + }); - act(() => { - initialFocusRef.current.focus(); - }); + it('should not trap focus when isActive is false', async () => { + const { container } = render( + + + + , + { container: document.body.appendChild(trappedDiv) } + ); - act(() => { - fireEvent.keyDown(container, { - key: 'Tab', - code: 9, - shiftKey: true - }); - }); + const firstFocusable = container.querySelector('button'); + const lastFocusable = container.querySelector('input'); - expect(document.activeElement).toBe(lastFocusable); + act(() => { + firstFocusable.focus(); }); - it('should not trap focus when isActive is false', async () => { - const { container } = render( - - - - , - { container: document.body.appendChild(trappedDiv) } - ); - - const firstFocusable = container.querySelector('button'); - const lastFocusable = container.querySelector('input'); - - act(() => { - firstFocusable.focus(); - }); - - act(() => { - fireEvent.keyDown(container, { - key: 'Tab', - code: 9, - shiftKey: true - }); - }); - - expect(document.activeElement).not.toBe(lastFocusable); + act(() => { + fireEvent.keyDown(container, { + key: 'Tab', + code: 9, + shiftKey: true + }); }); + + expect(document.activeElement).not.toBe(lastFocusable); + }); }); diff --git a/client/tests/SortableTableHeader.test.jsx b/client/tests/SortableTableHeader.test.jsx index 84829dcef..37a2bfa1e 100644 --- a/client/tests/SortableTableHeader.test.jsx +++ b/client/tests/SortableTableHeader.test.jsx @@ -5,71 +5,71 @@ import React from 'react'; import { render, fireEvent, screen } from '@testing-library/react'; import SortableTableHeader, { - TABLE_SORT_ORDERS + TABLE_SORT_ORDERS } from '../components/common/SortableTableHeader'; import '@testing-library/jest-dom'; import { AriaLiveRegionProvider } from '../components/providers/AriaLiveRegionProvider'; const renderComponent = props => - render( - - - - - - - -
    -
    - ); + render( + + + + + + + +
    +
    + ); const getAriaSort = (active, sortOrder) => - active - ? sortOrder === TABLE_SORT_ORDERS.ASC - ? 'ascending' - : 'descending' - : 'none'; + active + ? sortOrder === TABLE_SORT_ORDERS.ASC + ? 'ascending' + : 'descending' + : 'none'; describe('SortableTableHeader component', () => { - const defaultProps = { title: 'Header', active: false, onSort: () => {} }; + const defaultProps = { title: 'Header', active: false, onSort: () => {} }; - it('should render without crashing', () => { - renderComponent(defaultProps); - expect(screen.getByRole('columnheader')).toBeInTheDocument(); - }); + it('should render without crashing', () => { + renderComponent(defaultProps); + expect(screen.getByRole('columnheader')).toBeInTheDocument(); + }); - it('should render the correct title', () => { - renderComponent(defaultProps); - expect(screen.getByText('Header')).toBeInTheDocument(); - }); + it('should render the correct title', () => { + renderComponent(defaultProps); + expect(screen.getByText('Header')).toBeInTheDocument(); + }); - it('should render the inactive icon when active is false', () => { - renderComponent(defaultProps); - expect(screen.getByRole('img', { hidden: true })).toBeInTheDocument(); - }); + it('should render the inactive icon when active is false', () => { + renderComponent(defaultProps); + expect(screen.getByRole('img', { hidden: true })).toBeInTheDocument(); + }); - it('should handle sorting order and aria-sort attribute when active is true and clicked', () => { - const onSort = jest.fn(); - renderComponent({ ...defaultProps, active: true, onSort }); - const button = screen.getByRole('button'); + it('should handle sorting order and aria-sort attribute when active is true and clicked', () => { + const onSort = jest.fn(); + renderComponent({ ...defaultProps, active: true, onSort }); + const button = screen.getByRole('button'); - expect(screen.getByRole('columnheader')).toHaveAttribute( - 'aria-sort', - getAriaSort(true, TABLE_SORT_ORDERS.ASC) - ); + expect(screen.getByRole('columnheader')).toHaveAttribute( + 'aria-sort', + getAriaSort(true, TABLE_SORT_ORDERS.ASC) + ); - fireEvent.click(button); - expect(onSort).toHaveBeenCalledWith(TABLE_SORT_ORDERS.DESC); - expect(screen.getByRole('columnheader')).toHaveAttribute( - 'aria-sort', - getAriaSort(true, TABLE_SORT_ORDERS.DESC) - ); + fireEvent.click(button); + expect(onSort).toHaveBeenCalledWith(TABLE_SORT_ORDERS.DESC); + expect(screen.getByRole('columnheader')).toHaveAttribute( + 'aria-sort', + getAriaSort(true, TABLE_SORT_ORDERS.DESC) + ); - fireEvent.click(button); - expect(onSort).toHaveBeenCalledWith(TABLE_SORT_ORDERS.ASC); - expect(screen.getByRole('columnheader')).toHaveAttribute( - 'aria-sort', - getAriaSort(true, TABLE_SORT_ORDERS.ASC) - ); - }); + fireEvent.click(button); + expect(onSort).toHaveBeenCalledWith(TABLE_SORT_ORDERS.ASC); + expect(screen.getByRole('columnheader')).toHaveAttribute( + 'aria-sort', + getAriaSort(true, TABLE_SORT_ORDERS.ASC) + ); + }); }); diff --git a/client/tests/TestPlanReportStatusDialog.test.jsx b/client/tests/TestPlanReportStatusDialog.test.jsx index 5e3064ccf..c542a01c3 100644 --- a/client/tests/TestPlanReportStatusDialog.test.jsx +++ b/client/tests/TestPlanReportStatusDialog.test.jsx @@ -16,61 +16,59 @@ import { TEST_PLAN_REPORT_STATUS_DIALOG_MOCK_DATA } from './__mocks__/GraphQLMoc import { mockedTestPlanVersion } from './__mocks__/GraphQLMocks/TestPlanReportStatusDialogMock'; const setup = (props, mocks = []) => { - return render( - - - - - - ); + return render( + + + + + + ); }; describe('TestPlanReportStatusDialog', () => { - let getByRole, getByText; + let getByRole, getByText; - beforeEach(() => { - const show = true; - const handleHide = jest.fn(); - const testPlanVersion = mockedTestPlanVersion; - const [ - , - { - result: { - data: { ats } - } - } - ] = TEST_PLAN_REPORT_STATUS_DIALOG_MOCK_DATA; + beforeEach(() => { + const show = true; + const handleHide = jest.fn(); + const testPlanVersion = mockedTestPlanVersion; + const [ + , + { + result: { + data: { ats } + } + } + ] = TEST_PLAN_REPORT_STATUS_DIALOG_MOCK_DATA; - const result = setup( - { testPlanVersion, show, ats, handleHide }, - TEST_PLAN_REPORT_STATUS_DIALOG_MOCK_DATA - ); + const result = setup( + { testPlanVersion, show, ats, handleHide }, + TEST_PLAN_REPORT_STATUS_DIALOG_MOCK_DATA + ); - getByRole = result.getByRole; - getByText = result.getByText; - }); + getByRole = result.getByRole; + getByText = result.getByText; + }); - test('renders without error', async () => { - await waitFor(() => expect(getByRole('dialog')).toBeInTheDocument()); - }); + test('renders without error', async () => { + await waitFor(() => expect(getByRole('dialog')).toBeInTheDocument()); + }); - test('displays the dialog title', async () => { - await waitFor(() => { - expect( - getByText('Report Status for the Test Plan') - ).toBeInTheDocument(); - }); + test('displays the dialog title', async () => { + await waitFor(() => { + expect(getByText('Report Status for the Test Plan')).toBeInTheDocument(); }); + }); - test('displays the table headers', async () => { - await waitFor(() => { - expect(getByText('Required')).toBeInTheDocument(); - expect(getByText('AT')).toBeInTheDocument(); - expect(getByText('Browser')).toBeInTheDocument(); - expect(getByText('Report Status')).toBeInTheDocument(); - }); + test('displays the table headers', async () => { + await waitFor(() => { + expect(getByText('Required')).toBeInTheDocument(); + expect(getByText('AT')).toBeInTheDocument(); + expect(getByText('Browser')).toBeInTheDocument(); + expect(getByText('Report Status')).toBeInTheDocument(); }); + }); }); diff --git a/client/tests/TestQueue.test.jsx b/client/tests/TestQueue.test.jsx index f349ae3bd..e1e252e2d 100644 --- a/client/tests/TestQueue.test.jsx +++ b/client/tests/TestQueue.test.jsx @@ -13,310 +13,298 @@ import TestQueue from '../components/TestQueue'; // eslint-disable-next-line jest/no-mocks-import import { - TEST_QUEUE_PAGE_ADMIN_NOT_POPULATED_MOCK_DATA, - TEST_QUEUE_PAGE_TESTER_NOT_POPULATED_MOCK_DATA, - TEST_QUEUE_PAGE_ADMIN_POPULATED_MOCK_DATA, - TEST_QUEUE_PAGE_TESTER_POPULATED_MOCK_DATA, - TEST_QUEUE_PAGE_BASE_MOCK_DATA + TEST_QUEUE_PAGE_ADMIN_NOT_POPULATED_MOCK_DATA, + TEST_QUEUE_PAGE_TESTER_NOT_POPULATED_MOCK_DATA, + TEST_QUEUE_PAGE_ADMIN_POPULATED_MOCK_DATA, + TEST_QUEUE_PAGE_TESTER_POPULATED_MOCK_DATA, + TEST_QUEUE_PAGE_BASE_MOCK_DATA } from './__mocks__/GraphQLMocks'; import { AriaLiveRegionProvider } from '../components/providers/AriaLiveRegionProvider'; const setup = (mocks = []) => { - const mergedMocks = [...TEST_QUEUE_PAGE_BASE_MOCK_DATA, ...mocks]; - return render( - - - - - - - - ); + const mergedMocks = [...TEST_QUEUE_PAGE_BASE_MOCK_DATA, ...mocks]; + return render( + + + + + + + + ); }; describe('Render TestQueue/index.jsx', () => { - let wrapper; - - describe('[NOT ADMIN] when no test plan reports exist', () => { - beforeEach(() => { - wrapper = setup(TEST_QUEUE_PAGE_TESTER_NOT_POPULATED_MOCK_DATA); - }); - - it('renders loading state on initialization', async () => { - const { getByTestId } = wrapper; - const element = getByTestId('page-status'); - - expect(element).toBeTruthy(); - expect(element).toHaveTextContent('Loading'); - }); - - // TODO: Revise timeout with pageReady check - it.skip('renders Test Queue page instructions', async () => { - // allow page time to load - - await waitFor(() => new Promise(res => setTimeout(res, 0))); - - const { queryByTestId, getByTestId } = wrapper; - const loadingElement = queryByTestId('page-status'); - const element = getByTestId('test-queue-no-test-plans-p'); - - expect(loadingElement).not.toBeInTheDocument(); - expect(element).toBeTruthy(); - expect(element).toHaveTextContent( - /Please configure your preferred Assistive Technologies in/i - ); - }); - - it('renders no AT-specific sections', async () => { - // allow page time to load - await waitFor(() => new Promise(res => setTimeout(res, 0))); - - const { queryAllByText } = wrapper; - const nvdaElements = queryAllByText(/nvda/i); - const jawsElements = queryAllByText(/jaws/i); - const voiceOverElements = queryAllByText(/voiceover/i); - - expect(nvdaElements.length).toEqual(0); - expect(jawsElements.length).toEqual(0); - expect(voiceOverElements.length).toEqual(0); - }); - - it('does not render add test plan modal button', async () => { - // allow page time to load - await waitFor(() => new Promise(res => setTimeout(res, 0))); - - const { queryByTestId } = wrapper; - const button = queryByTestId( - 'test-queue-add-test-plan-to-queue-button' - ); - - expect(button).not.toBeTruthy(); - }); + let wrapper; + + describe('[NOT ADMIN] when no test plan reports exist', () => { + beforeEach(() => { + wrapper = setup(TEST_QUEUE_PAGE_TESTER_NOT_POPULATED_MOCK_DATA); + }); + + it('renders loading state on initialization', async () => { + const { getByTestId } = wrapper; + const element = getByTestId('page-status'); + + expect(element).toBeTruthy(); + expect(element).toHaveTextContent('Loading'); + }); + + // TODO: Revise timeout with pageReady check + it.skip('renders Test Queue page instructions', async () => { + // allow page time to load + + await waitFor(() => new Promise(res => setTimeout(res, 0))); + + const { queryByTestId, getByTestId } = wrapper; + const loadingElement = queryByTestId('page-status'); + const element = getByTestId('test-queue-no-test-plans-p'); + + expect(loadingElement).not.toBeInTheDocument(); + expect(element).toBeTruthy(); + expect(element).toHaveTextContent( + /Please configure your preferred Assistive Technologies in/i + ); + }); + + it('renders no AT-specific sections', async () => { + // allow page time to load + await waitFor(() => new Promise(res => setTimeout(res, 0))); + + const { queryAllByText } = wrapper; + const nvdaElements = queryAllByText(/nvda/i); + const jawsElements = queryAllByText(/jaws/i); + const voiceOverElements = queryAllByText(/voiceover/i); + + expect(nvdaElements.length).toEqual(0); + expect(jawsElements.length).toEqual(0); + expect(voiceOverElements.length).toEqual(0); + }); + + it('does not render add test plan modal button', async () => { + // allow page time to load + await waitFor(() => new Promise(res => setTimeout(res, 0))); + + const { queryByTestId } = wrapper; + const button = queryByTestId('test-queue-add-test-plan-to-queue-button'); + + expect(button).not.toBeTruthy(); + }); + }); + + describe('[NOT ADMIN] when test plan reports exist', () => { + beforeEach(() => { + wrapper = setup(TEST_QUEUE_PAGE_TESTER_POPULATED_MOCK_DATA); + }); + + it('renders loading state on initialization', async () => { + const { getByTestId } = wrapper; + const element = getByTestId('page-status'); + + expect(element).toBeTruthy(); + expect(element).toHaveTextContent('Loading'); + }); + + it.skip('renders Test Queue page instructions', async () => { + // allow page time to load + await waitFor(() => new Promise(res => setTimeout(res, 0))); + + const { queryByTestId, getByTestId } = wrapper; + const loadingElement = queryByTestId('page-status'); + const element = getByTestId('test-queue-instructions'); + + expect(loadingElement).not.toBeInTheDocument(); + expect(element).toBeTruthy(); + expect(element).toHaveTextContent( + 'Assign yourself a test plan or start executing one that is already assigned to you.' + ); + }); + + it('renders AT-specific sections', async () => { + // allow page time to load + await waitFor(() => new Promise(res => setTimeout(res, 0))); + + const { queryAllByText } = wrapper; + const nvdaElements = queryAllByText(/nvda/i); + const jawsElements = queryAllByText(/jaws/i); + const voiceOverElements = queryAllByText(/voiceover/i); + + expect(nvdaElements.length).toBeGreaterThanOrEqual(1); + expect(jawsElements.length).toBeGreaterThanOrEqual(1); + expect(voiceOverElements.length).toBeGreaterThanOrEqual(1); + }); + + it('renders testers are assigned to Test Plans', async () => { + // allow page time to load + await waitFor(() => new Promise(res => setTimeout(res, 0))); + + const { queryAllByText } = wrapper; + const userAAssignedElements = queryAllByText(/foo-bar/i); + const userBAssignedElements = queryAllByText(/bar-foo/i); + const userCAssignedElements = queryAllByText(/boo-far/i); + const assignedTestsElements = queryAllByText( + /\d+ of \d+ tests complete/i + ); + + expect(userAAssignedElements.length).toBeGreaterThanOrEqual(1); + expect(userBAssignedElements.length).toBeGreaterThanOrEqual(1); + expect(userCAssignedElements.length).toBeGreaterThanOrEqual(1); + expect(assignedTestsElements.length).toBeGreaterThanOrEqual(1); + }); + + it('does not render add test plan modal button', async () => { + // allow page time to load + await waitFor(() => new Promise(res => setTimeout(res, 0))); + + const { queryByTestId } = wrapper; + const button = queryByTestId('test-queue-add-test-plan-to-queue-button'); + + expect(button).not.toBeTruthy(); }); + }); - describe('[NOT ADMIN] when test plan reports exist', () => { - beforeEach(() => { - wrapper = setup(TEST_QUEUE_PAGE_TESTER_POPULATED_MOCK_DATA); - }); - - it('renders loading state on initialization', async () => { - const { getByTestId } = wrapper; - const element = getByTestId('page-status'); - - expect(element).toBeTruthy(); - expect(element).toHaveTextContent('Loading'); - }); - - it.skip('renders Test Queue page instructions', async () => { - // allow page time to load - await waitFor(() => new Promise(res => setTimeout(res, 0))); - - const { queryByTestId, getByTestId } = wrapper; - const loadingElement = queryByTestId('page-status'); - const element = getByTestId('test-queue-instructions'); - - expect(loadingElement).not.toBeInTheDocument(); - expect(element).toBeTruthy(); - expect(element).toHaveTextContent( - 'Assign yourself a test plan or start executing one that is already assigned to you.' - ); - }); - - it('renders AT-specific sections', async () => { - // allow page time to load - await waitFor(() => new Promise(res => setTimeout(res, 0))); - - const { queryAllByText } = wrapper; - const nvdaElements = queryAllByText(/nvda/i); - const jawsElements = queryAllByText(/jaws/i); - const voiceOverElements = queryAllByText(/voiceover/i); - - expect(nvdaElements.length).toBeGreaterThanOrEqual(1); - expect(jawsElements.length).toBeGreaterThanOrEqual(1); - expect(voiceOverElements.length).toBeGreaterThanOrEqual(1); - }); - - it('renders testers are assigned to Test Plans', async () => { - // allow page time to load - await waitFor(() => new Promise(res => setTimeout(res, 0))); - - const { queryAllByText } = wrapper; - const userAAssignedElements = queryAllByText(/foo-bar/i); - const userBAssignedElements = queryAllByText(/bar-foo/i); - const userCAssignedElements = queryAllByText(/boo-far/i); - const assignedTestsElements = queryAllByText( - /\d+ of \d+ tests complete/i - ); - - expect(userAAssignedElements.length).toBeGreaterThanOrEqual(1); - expect(userBAssignedElements.length).toBeGreaterThanOrEqual(1); - expect(userCAssignedElements.length).toBeGreaterThanOrEqual(1); - expect(assignedTestsElements.length).toBeGreaterThanOrEqual(1); - }); - - it('does not render add test plan modal button', async () => { - // allow page time to load - await waitFor(() => new Promise(res => setTimeout(res, 0))); - - const { queryByTestId } = wrapper; - const button = queryByTestId( - 'test-queue-add-test-plan-to-queue-button' - ); - - expect(button).not.toBeTruthy(); - }); + describe('[IS ADMIN] when no test plan reports exist', () => { + beforeEach(() => { + wrapper = setup(TEST_QUEUE_PAGE_ADMIN_NOT_POPULATED_MOCK_DATA); }); - describe('[IS ADMIN] when no test plan reports exist', () => { - beforeEach(() => { - wrapper = setup(TEST_QUEUE_PAGE_ADMIN_NOT_POPULATED_MOCK_DATA); - }); - - it('renders loading state on initialization', async () => { - const { getByTestId } = wrapper; - const element = getByTestId('page-status'); - - expect(element).toBeTruthy(); - expect(element).toHaveTextContent('Loading'); - }); - - it('renders Test Queue page instructions', async () => { - // allow page time to load - await waitFor(() => new Promise(res => setTimeout(res, 0))); - - const { queryByTestId, getByTestId } = wrapper; - const loadingElement = queryByTestId('page-status'); - const element = getByTestId('test-queue-no-test-plans-p'); - - expect(loadingElement).not.toBeInTheDocument(); - expect(element).toBeTruthy(); - expect(element).toHaveTextContent(/Add a Test Plan to the Queue/i); - }); - - it('renders no AT-specific sections', async () => { - // allow page time to load - await waitFor(() => new Promise(res => setTimeout(res, 0))); - - const { queryAllByText } = wrapper; - const nvdaElements = queryAllByText(/nvda/i); - const jawsElements = queryAllByText(/jaws/i); - const voiceOverElements = queryAllByText(/voiceover/i); - - expect(nvdaElements.length).toEqual(0); - expect(jawsElements.length).toEqual(0); - expect(voiceOverElements.length).toEqual(0); - }); - - it.skip('renders add test plan modal on button click', async () => { - // allow page time to load - await waitFor(() => new Promise(res => setTimeout(res, 0))); - - const { queryByTestId } = wrapper; - const button = queryByTestId( - 'test-queue-add-test-plan-to-queue-button' - ); - - expect(button).toBeTruthy(); - - // opens modal - fireEvent.click(button); - - expect( - screen.getByText('Select an AT and Version') - ).toBeInTheDocument(); - expect( - screen.getByText('Select a Browser and Version') - ).toBeInTheDocument(); - expect( - screen.getByText('Select a Test Plan and Version') - ).toBeInTheDocument(); - }); + it('renders loading state on initialization', async () => { + const { getByTestId } = wrapper; + const element = getByTestId('page-status'); + + expect(element).toBeTruthy(); + expect(element).toHaveTextContent('Loading'); + }); + + it('renders Test Queue page instructions', async () => { + // allow page time to load + await waitFor(() => new Promise(res => setTimeout(res, 0))); + + const { queryByTestId, getByTestId } = wrapper; + const loadingElement = queryByTestId('page-status'); + const element = getByTestId('test-queue-no-test-plans-p'); + + expect(loadingElement).not.toBeInTheDocument(); + expect(element).toBeTruthy(); + expect(element).toHaveTextContent(/Add a Test Plan to the Queue/i); + }); + + it('renders no AT-specific sections', async () => { + // allow page time to load + await waitFor(() => new Promise(res => setTimeout(res, 0))); + + const { queryAllByText } = wrapper; + const nvdaElements = queryAllByText(/nvda/i); + const jawsElements = queryAllByText(/jaws/i); + const voiceOverElements = queryAllByText(/voiceover/i); + + expect(nvdaElements.length).toEqual(0); + expect(jawsElements.length).toEqual(0); + expect(voiceOverElements.length).toEqual(0); + }); + + it.skip('renders add test plan modal on button click', async () => { + // allow page time to load + await waitFor(() => new Promise(res => setTimeout(res, 0))); + + const { queryByTestId } = wrapper; + const button = queryByTestId('test-queue-add-test-plan-to-queue-button'); + + expect(button).toBeTruthy(); + + // opens modal + fireEvent.click(button); + + expect(screen.getByText('Select an AT and Version')).toBeInTheDocument(); + expect( + screen.getByText('Select a Browser and Version') + ).toBeInTheDocument(); + expect( + screen.getByText('Select a Test Plan and Version') + ).toBeInTheDocument(); + }); + }); + + describe('[IS ADMIN] when test plan reports exist', () => { + beforeEach(() => { + wrapper = setup(TEST_QUEUE_PAGE_ADMIN_POPULATED_MOCK_DATA); + }); + + it('renders loading state on initialization', async () => { + const { getByTestId } = wrapper; + const element = getByTestId('page-status'); + + expect(element).toBeTruthy(); + expect(element).toHaveTextContent('Loading'); + }); + + it.skip('renders Test Queue page instructions', async () => { + // allow page time to load + await waitFor(() => new Promise(res => setTimeout(res, 0))); + + const { queryByTestId, getByTestId } = wrapper; + const loadingElement = queryByTestId('page-status'); + const element = getByTestId('test-queue-instructions'); + + expect(loadingElement).not.toBeInTheDocument(); + expect(element).toBeTruthy(); + expect(element).toHaveTextContent( + 'Assign yourself a test plan or start executing one that is already assigned to you.' + ); + }); + + it('renders AT-specific sections', async () => { + // allow page time to load + await waitFor(() => new Promise(res => setTimeout(res, 0))); + + const { queryAllByText } = wrapper; + const nvdaElements = queryAllByText(/nvda/i); + const jawsElements = queryAllByText(/jaws/i); + const voiceOverElements = queryAllByText(/voiceover/i); + + expect(nvdaElements.length).toBeGreaterThanOrEqual(1); + expect(jawsElements.length).toBeGreaterThanOrEqual(1); + expect(voiceOverElements.length).toBeGreaterThanOrEqual(1); + }); + + it('renders testers are assigned to Test Plans', async () => { + // allow page time to load + await waitFor(() => new Promise(res => setTimeout(res, 0))); + + const { queryAllByText } = wrapper; + const userAAssignedElements = queryAllByText(/esmeralda-baggins/i); + const userBAssignedElements = queryAllByText(/tom-proudfeet/i); + const assignedTestsElements = queryAllByText( + /\d+ of \d+ tests complete/i + ); + + expect(userAAssignedElements.length).toBeGreaterThanOrEqual(1); + expect(userBAssignedElements.length).toBeGreaterThanOrEqual(1); + expect(assignedTestsElements.length).toBeGreaterThanOrEqual(1); }); - describe('[IS ADMIN] when test plan reports exist', () => { - beforeEach(() => { - wrapper = setup(TEST_QUEUE_PAGE_ADMIN_POPULATED_MOCK_DATA); - }); - - it('renders loading state on initialization', async () => { - const { getByTestId } = wrapper; - const element = getByTestId('page-status'); - - expect(element).toBeTruthy(); - expect(element).toHaveTextContent('Loading'); - }); - - it.skip('renders Test Queue page instructions', async () => { - // allow page time to load - await waitFor(() => new Promise(res => setTimeout(res, 0))); - - const { queryByTestId, getByTestId } = wrapper; - const loadingElement = queryByTestId('page-status'); - const element = getByTestId('test-queue-instructions'); - - expect(loadingElement).not.toBeInTheDocument(); - expect(element).toBeTruthy(); - expect(element).toHaveTextContent( - 'Assign yourself a test plan or start executing one that is already assigned to you.' - ); - }); - - it('renders AT-specific sections', async () => { - // allow page time to load - await waitFor(() => new Promise(res => setTimeout(res, 0))); - - const { queryAllByText } = wrapper; - const nvdaElements = queryAllByText(/nvda/i); - const jawsElements = queryAllByText(/jaws/i); - const voiceOverElements = queryAllByText(/voiceover/i); - - expect(nvdaElements.length).toBeGreaterThanOrEqual(1); - expect(jawsElements.length).toBeGreaterThanOrEqual(1); - expect(voiceOverElements.length).toBeGreaterThanOrEqual(1); - }); - - it('renders testers are assigned to Test Plans', async () => { - // allow page time to load - await waitFor(() => new Promise(res => setTimeout(res, 0))); - - const { queryAllByText } = wrapper; - const userAAssignedElements = queryAllByText(/esmeralda-baggins/i); - const userBAssignedElements = queryAllByText(/tom-proudfeet/i); - const assignedTestsElements = queryAllByText( - /\d+ of \d+ tests complete/i - ); - - expect(userAAssignedElements.length).toBeGreaterThanOrEqual(1); - expect(userBAssignedElements.length).toBeGreaterThanOrEqual(1); - expect(assignedTestsElements.length).toBeGreaterThanOrEqual(1); - }); - - it.skip('renders add test plan modal on button click', async () => { - // allow page time to load - await waitFor(() => new Promise(res => setTimeout(res, 0))); - - const { queryByTestId } = wrapper; - const button = queryByTestId( - 'test-queue-add-test-plan-to-queue-button' - ); - - expect(button).toBeTruthy(); - - // opens modal - fireEvent.click(button); - - expect( - screen.getByText('Select an AT and Version') - ).toBeInTheDocument(); - expect( - screen.getByText('Select a Browser and Version') - ).toBeInTheDocument(); - expect( - screen.getByText('Select a Test Plan and Version') - ).toBeInTheDocument(); - }); + it.skip('renders add test plan modal on button click', async () => { + // allow page time to load + await waitFor(() => new Promise(res => setTimeout(res, 0))); + + const { queryByTestId } = wrapper; + const button = queryByTestId('test-queue-add-test-plan-to-queue-button'); + + expect(button).toBeTruthy(); + + // opens modal + fireEvent.click(button); + + expect(screen.getByText('Select an AT and Version')).toBeInTheDocument(); + expect( + screen.getByText('Select a Browser and Version') + ).toBeInTheDocument(); + expect( + screen.getByText('Select a Test Plan and Version') + ).toBeInTheDocument(); }); + }); }); diff --git a/client/tests/TestRenderer/OutputTextArea.test.jsx b/client/tests/TestRenderer/OutputTextArea.test.jsx index 4a466a714..4bf397603 100644 --- a/client/tests/TestRenderer/OutputTextArea.test.jsx +++ b/client/tests/TestRenderer/OutputTextArea.test.jsx @@ -9,130 +9,130 @@ import '@testing-library/jest-dom/extend-expect'; import { NO_OUTPUT_STRING } from '../../components/TestRenderer/OutputTextArea/constants'; describe('OutputTextArea', () => { - let atOutputMock; - const change = value => { - atOutputMock.value = value; - }; + let atOutputMock; + const change = value => { + atOutputMock.value = value; + }; - atOutputMock = { - description: [ - 'Description', - { - required: true, - highlightRequired: true, - description: 'Highlight Description' - } - ], - value: '', - change: change, - focus: false - }; + atOutputMock = { + description: [ + 'Description', + { + required: true, + highlightRequired: true, + description: 'Highlight Description' + } + ], + value: '', + change: change, + focus: false + }; - it('should render with default settings', () => { - render( - - ); - expect(screen.getByLabelText('Description')).toBeInTheDocument(); - expect(screen.getByLabelText('No output')).not.toBeChecked(); - }); + it('should render with default settings', () => { + render( + + ); + expect(screen.getByLabelText('Description')).toBeInTheDocument(); + expect(screen.getByLabelText('No output')).not.toBeChecked(); + }); - it('should render correct label and checkbox', () => { - render( - - ); - expect(screen.getByLabelText('Description')).toBeInTheDocument(); - expect(screen.getByLabelText('No output')).toBeInTheDocument(); - }); + it('should render correct label and checkbox', () => { + render( + + ); + expect(screen.getByLabelText('Description')).toBeInTheDocument(); + expect(screen.getByLabelText('No output')).toBeInTheDocument(); + }); - it('should update the textarea with the correct value when checkbox is checked', () => { - render( - - ); - const checkbox = screen.getByLabelText('No output'); - const textarea = screen.getByLabelText('Description'); + it('should update the textarea with the correct value when checkbox is checked', () => { + render( + + ); + const checkbox = screen.getByLabelText('No output'); + const textarea = screen.getByLabelText('Description'); - expect(textarea.value).toBe(''); + expect(textarea.value).toBe(''); - fireEvent.click(checkbox); - expect(atOutputMock.value).toBe(NO_OUTPUT_STRING); - }); + fireEvent.click(checkbox); + expect(atOutputMock.value).toBe(NO_OUTPUT_STRING); + }); - it('should handle textarea change', () => { - render( - - ); - const textarea = screen.getByLabelText('Description'); - fireEvent.change(textarea, { target: { value: 'test value' } }); - expect(atOutputMock.value).toBe('test value'); - }); + it('should handle textarea change', () => { + render( + + ); + const textarea = screen.getByLabelText('Description'); + fireEvent.change(textarea, { target: { value: 'test value' } }); + expect(atOutputMock.value).toBe('test value'); + }); - it('should disable the textarea when the checkbox is checked', () => { - render( - - ); - const checkbox = screen.getByLabelText('No output'); - const textarea = screen.getByLabelText('Description'); + it('should disable the textarea when the checkbox is checked', () => { + render( + + ); + const checkbox = screen.getByLabelText('No output'); + const textarea = screen.getByLabelText('Description'); - expect(textarea).not.toBeDisabled(); - fireEvent.click(checkbox); - expect(textarea).toBeDisabled(); - }); + expect(textarea).not.toBeDisabled(); + fireEvent.click(checkbox); + expect(textarea).toBeDisabled(); + }); - it('should have associated label for textarea', () => { - render( - - ); - const textarea = screen.getByLabelText('Description'); - expect(textarea).toHaveAttribute('id', 'speechoutput-0'); - }); + it('should have associated label for textarea', () => { + render( + + ); + const textarea = screen.getByLabelText('Description'); + expect(textarea).toHaveAttribute('id', 'speechoutput-0'); + }); - it('should disable checkbox when textarea has a value', () => { - const prefilledMock = { ...atOutputMock, value: 'test value' }; - render( - - ); - const checkbox = screen.getByLabelText('No output'); - expect(checkbox).toBeDisabled(); - }); + it('should disable checkbox when textarea has a value', () => { + const prefilledMock = { ...atOutputMock, value: 'test value' }; + render( + + ); + const checkbox = screen.getByLabelText('No output'); + expect(checkbox).toBeDisabled(); + }); - it('should enable checkbox when textarea loads with no output default value', () => { - const prefilledMock = { ...atOutputMock, value: NO_OUTPUT_STRING }; - render( - - ); - const checkbox = screen.getByLabelText('No output'); - expect(checkbox).not.toBeDisabled(); - }); + it('should enable checkbox when textarea loads with no output default value', () => { + const prefilledMock = { ...atOutputMock, value: NO_OUTPUT_STRING }; + render( + + ); + const checkbox = screen.getByLabelText('No output'); + expect(checkbox).not.toBeDisabled(); + }); }); diff --git a/client/tests/TestRun.test.jsx b/client/tests/TestRun.test.jsx index b4359669a..d74b000d5 100644 --- a/client/tests/TestRun.test.jsx +++ b/client/tests/TestRun.test.jsx @@ -10,40 +10,40 @@ import { findByTestAttr } from './util'; import TestRun from '../components/TestRun'; const setup = () => { - // Step into the higher order connected component and step into the contents of the UserSettings component - const wrapper = shallow( - - ) - .dive() - .dive(); - return wrapper; + // Step into the higher order connected component and step into the contents of the UserSettings component + const wrapper = shallow( + + ) + .dive() + .dive(); + return wrapper; }; describe.skip('render', () => { - describe('loading when there are no tests', () => { - let wrapper; - beforeEach(() => { - wrapper = setup(); - }); - test('renders not logged in text', () => { - const component = findByTestAttr(wrapper, 'test-run-page-status'); - expect(component.text()).toContain('Loading'); - }); + describe('loading when there are no tests', () => { + let wrapper; + beforeEach(() => { + wrapper = setup(); }); - describe('tests are loaded', () => { - let wrapper; - beforeEach(() => { - wrapper = setup(); - wrapper.setState({ currentTestIndex: 1 }); - }); - test('renders testing headings', () => { - let component = findByTestAttr(wrapper, 'apg-example-name'); - expect(component.length).toBe(1); - expect(component.text()).toContain('Test Plan'); + test('renders not logged in text', () => { + const component = findByTestAttr(wrapper, 'test-run-page-status'); + expect(component.text()).toContain('Loading'); + }); + }); + describe('tests are loaded', () => { + let wrapper; + beforeEach(() => { + wrapper = setup(); + wrapper.setState({ currentTestIndex: 1 }); + }); + test('renders testing headings', () => { + let component = findByTestAttr(wrapper, 'apg-example-name'); + expect(component.length).toBe(1); + expect(component.text()).toContain('Test Plan'); - component = findByTestAttr(wrapper, 'at-browser'); - expect(component.length).toBe(1); - expect(component.text()).toContain('with'); - }); + component = findByTestAttr(wrapper, 'at-browser'); + expect(component.length).toBe(1); + expect(component.text()).toContain('with'); }); + }); }); diff --git a/client/tests/UserSettings.test.jsx b/client/tests/UserSettings.test.jsx index f639c453f..6eed0a264 100644 --- a/client/tests/UserSettings.test.jsx +++ b/client/tests/UserSettings.test.jsx @@ -6,50 +6,44 @@ import { findByTestAttr } from './util'; import UserSettings from '../components/UserSettings'; const setup = () => { - // Step into the higher order connected component and step into the contents of the UserSettings component - const wrapper = shallow() - .dive() - .dive(); - return wrapper; + // Step into the higher order connected component and step into the contents of the UserSettings component + const wrapper = shallow() + .dive() + .dive(); + return wrapper; }; describe.skip('render', () => { - describe('user is not signed in', () => { - let wrapper; - beforeEach(() => { - wrapper = setup(); - }); - test('renders component without error', () => { - const component = findByTestAttr(wrapper, 'user-settings-contents'); - expect(component.length).toBe(1); - }); - test('renders not signed in text', () => { - const component = findByTestAttr( - wrapper, - 'user-settings-unauthorized' - ); - expect(component.length).toBe(1); - }); + describe('user is not signed in', () => { + let wrapper; + beforeEach(() => { + wrapper = setup(); }); - describe('user is signed in', () => { - let wrapper; - beforeEach(() => { - wrapper = setup(); - }); - test('renders component without error', () => { - const component = findByTestAttr(wrapper, 'user-settings-contents'); - expect(component.length).toBe(1); - }); - test('renders username', () => { - const component = findByTestAttr( - wrapper, - 'user-settings-authorized' - ); - expect(component.length).toBe(1); - expect(component.text()).toContain('User Details'); - expect(component.find('a').at(0).props().href).toContain( - 'https://github.com' - ); - }); + test('renders component without error', () => { + const component = findByTestAttr(wrapper, 'user-settings-contents'); + expect(component.length).toBe(1); }); + test('renders not signed in text', () => { + const component = findByTestAttr(wrapper, 'user-settings-unauthorized'); + expect(component.length).toBe(1); + }); + }); + describe('user is signed in', () => { + let wrapper; + beforeEach(() => { + wrapper = setup(); + }); + test('renders component without error', () => { + const component = findByTestAttr(wrapper, 'user-settings-contents'); + expect(component.length).toBe(1); + }); + test('renders username', () => { + const component = findByTestAttr(wrapper, 'user-settings-authorized'); + expect(component.length).toBe(1); + expect(component.text()).toContain('User Details'); + expect(component.find('a').at(0).props().href).toContain( + 'https://github.com' + ); + }); + }); }); diff --git a/client/tests/__mocks__/GraphQLMocks/DataManagementPagePopulatedMock.js b/client/tests/__mocks__/GraphQLMocks/DataManagementPagePopulatedMock.js index 01c5c8c2c..d19cddd71 100644 --- a/client/tests/__mocks__/GraphQLMocks/DataManagementPagePopulatedMock.js +++ b/client/tests/__mocks__/GraphQLMocks/DataManagementPagePopulatedMock.js @@ -1,4180 +1,4058 @@ export default ( - meQuery, - dataManagementPageQuery, - testPlanReportStatusDialogQuery + meQuery, + dataManagementPageQuery, + testPlanReportStatusDialogQuery ) => [ - { - request: { - query: meQuery - }, - result: { - data: { - me: { - id: '1', - username: 'foo-bar', - roles: ['ADMIN', 'TESTER'] - } - } + { + request: { + query: meQuery + }, + result: { + data: { + me: { + id: '1', + username: 'foo-bar', + roles: ['ADMIN', 'TESTER'] } + } + } + }, + { + request: { + query: dataManagementPageQuery }, - { - request: { - query: dataManagementPageQuery + result: { + data: { + me: { + id: '1', + username: 'foo-bar', + roles: ['ADMIN', 'TESTER'] }, - result: { - data: { - me: { - id: '1', - username: 'foo-bar', - roles: ['ADMIN', 'TESTER'] + ats: [ + { + id: '1', + name: 'JAWS', + atVersions: [ + { + id: '1', + name: '2021.2111.13', + releasedAt: '2021-11-01T04:00:00.000Z' + } + ], + browsers: [ + { + id: '2', + name: 'Chrome' + }, + { + id: '1', + name: 'Firefox' + } + ], + candidateBrowsers: [{ id: '2' }], + recommendedBrowsers: [{ id: '1' }, { id: '2' }] + }, + { + id: '2', + name: 'NVDA', + atVersions: [ + { + id: '2', + name: '2020.4', + releasedAt: '2021-02-19T05:00:00.000Z' + } + ], + browsers: [ + { + id: '2', + name: 'Chrome' + }, + { + id: '1', + name: 'Firefox' + } + ], + candidateBrowsers: [{ id: '2' }], + recommendedBrowsers: [{ id: '1' }, { id: '2' }] + }, + { + id: '3', + name: 'VoiceOver for macOS', + atVersions: [ + { + id: '3', + name: '11.6 (20G165)', + releasedAt: '2019-09-01T04:00:00.000Z' + } + ], + browsers: [ + { + id: '2', + name: 'Chrome' + }, + { + id: '1', + name: 'Firefox' + }, + { + id: '3', + name: 'Safari' + } + ], + candidateBrowsers: [{ id: '3' }], + recommendedBrowsers: [{ id: '2' }, { id: '3' }] + } + ], + testPlans: [ + { + id: '27', + directory: 'radiogroup-aria-activedescendant', + title: 'Radio Group Example Using aria-activedescendant' + }, + { + id: '28', + directory: 'radiogroup-roving-tabindex', + title: 'Radio Group Example Using Roving tabindex' + }, + { + id: '31', + directory: 'slider-multithumb', + title: 'Horizontal Multi-Thumb Slider' + }, + { + id: '16', + directory: 'link-css', + title: + 'Link Example 3 (CSS :before content property on a span element)' + }, + { + id: '17', + directory: 'link-img-alt', + title: 'Link Example 2 (img element with alt attribute)' + }, + { + id: '1', + directory: 'alert', + title: 'Alert Example' + }, + { + id: '13', + directory: 'disclosure-navigation', + title: 'Disclosure Navigation Menu Example' + }, + { + id: '5', + directory: 'checkbox-tri-state', + title: 'Checkbox Example (Mixed-State)' + }, + { + id: '3', + directory: 'breadcrumb', + title: 'Breadcrumb Example' + }, + { + id: '19', + directory: 'main', + title: 'Main Landmark' + }, + { + id: '24', + directory: 'meter', + title: 'Meter' + }, + { + id: '32', + directory: 'switch', + title: 'Switch Example' + }, + { + id: '26', + directory: 'modal-dialog', + title: 'Modal Dialog Example' + }, + { + id: '22', + directory: 'menu-button-navigation', + title: 'Navigation Menu Button' + }, + { + id: '34', + directory: 'toggle-button', + title: 'Toggle Button' + }, + { + id: '18', + directory: 'link-span-text', + title: 'Link Example 1 (span element with text content)' + }, + { + id: '8', + directory: 'command-button', + title: 'Command Button Example' + }, + { + id: '15', + directory: 'horizontal-slider', + title: 'Color Viewer Slider' + }, + { + id: '6', + directory: 'combobox-autocomplete-both-updated', + title: 'Combobox with Both List and Inline Autocomplete Example' + }, + { + id: '7', + directory: 'combobox-select-only', + title: 'Select Only Combobox Example' + }, + { + id: '4', + directory: 'checkbox', + title: 'Checkbox Example (Two State)' + }, + { + id: '9', + directory: 'complementary', + title: 'Complementary Landmark' + }, + { + id: '10', + directory: 'contentinfo', + title: 'Contentinfo Landmark' + }, + { + id: '11', + directory: 'datepicker-spin-button', + title: 'Date Picker Spin Button Example' + }, + { + id: '12', + directory: 'disclosure-faq', + title: 'Disclosure of Answers to Frequently Asked Questions Example' + }, + { + id: '14', + directory: 'form', + title: 'Form Landmark' + }, + { + id: '20', + directory: 'menu-button-actions', + title: 'Action Menu Button Example Using element.focus()' + }, + { + id: '21', + directory: 'menu-button-actions-active-descendant', + title: 'Action Menu Button Example Using aria-activedescendant' + }, + { + id: '23', + directory: 'menubar-editor', + title: 'Editor Menubar Example' + }, + { + id: '25', + directory: 'minimal-data-grid', + title: 'Data Grid Example 1: Minimal Data Grid' + }, + { + id: '29', + directory: 'rating-slider', + title: 'Rating Slider' + }, + { + id: '30', + directory: 'seek-slider', + title: 'Media Seek Slider' + }, + { + id: '33', + directory: 'tabs-manual-activation', + title: 'Tabs with Manual Activation' + }, + { + id: '35', + directory: 'vertical-temperature-slider', + title: 'Vertical Temperature Slider' + }, + { + id: '2', + directory: 'banner', + title: 'Banner Landmark' + } + ], + testPlanVersions: [ + { + id: '28', + title: 'Radio Group Example Using Roving tabindex', + phase: 'RD', + gitSha: '1768070bd68beefef29284b568d2da910b449c14', + gitMessage: + 'Remove Tab and Shift+Tab from radiogroup tests when navigating out of the start and end of a radio group (reading mode and VoiceOver only) (#928)', + updatedAt: '2023-04-10T18:22:22.000Z', + versionString: 'V23.04.10', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'radiogroup-roving-tabindex' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '27', + title: 'Radio Group Example Using aria-activedescendant', + phase: 'RD', + gitSha: '1768070bd68beefef29284b568d2da910b449c14', + gitMessage: + 'Remove Tab and Shift+Tab from radiogroup tests when navigating out of the start and end of a radio group (reading mode and VoiceOver only) (#928)', + updatedAt: '2023-04-10T18:22:22.000Z', + versionString: 'V23.04.10', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'radiogroup-aria-activedescendant' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '31', + title: 'Horizontal Multi-Thumb Slider', + phase: 'RD', + gitSha: 'b5fe3efd569518e449ef9a0978b0dec1f2a08bd6', + gitMessage: + 'Create tests for APG design pattern example: Horizontal Multi-Thumb Slider (#511)', + updatedAt: '2023-03-20T21:24:41.000Z', + versionString: 'V23.03.20', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'slider-multithumb' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '16', + title: + 'Link Example 3 (CSS :before content property on a span element)', + phase: 'RD', + gitSha: '7a8454bca6de980199868101431817cea03cce35', + gitMessage: + 'Create tests for APG design pattern example: Link Example 3 (CSS :before content property on a span element) (#518)', + updatedAt: '2023-03-13T22:10:13.000Z', + versionString: 'V23.03.13', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'link-css' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '17', + title: 'Link Example 2 (img element with alt attribute)', + phase: 'RD', + gitSha: 'dc637636cff74b51f5c468ff3b81bd1f38aefbb2', + gitMessage: + 'Create tests for APG design pattern example: Link Example 2 (img element with alt attribute) (#516)', + updatedAt: '2023-03-13T19:51:48.000Z', + versionString: 'V23.03.13', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'link-img-alt' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '1', + title: 'Alert Example', + phase: 'DRAFT', + gitSha: '0928bcf530efcf4faa677285439701537674e014', + gitMessage: 'Alert and Radiogroup/activedescendent updates (#865)', + updatedAt: '2022-12-08T21:47:42.000Z', + versionString: 'V22.12.08', + draftPhaseReachedAt: '2022-07-06T00:00:00.000Z', + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'alert' + }, + testPlanReports: [ + { + id: '7', + metrics: {}, + markedFinalAt: null, + isFinal: false, + at: { + id: '3', + name: 'VoiceOver for macOS' }, - ats: [ - { - id: '1', - name: 'JAWS', - atVersions: [ - { - id: '1', - name: '2021.2111.13', - releasedAt: '2021-11-01T04:00:00.000Z' - } - ], - browsers: [ - { - id: '2', - name: 'Chrome' - }, - { - id: '1', - name: 'Firefox' - } - ], - candidateBrowsers: [{ id: '2' }], - recommendedBrowsers: [{ id: '1' }, { id: '2' }] - }, - { - id: '2', - name: 'NVDA', - atVersions: [ - { - id: '2', - name: '2020.4', - releasedAt: '2021-02-19T05:00:00.000Z' - } - ], - browsers: [ - { - id: '2', - name: 'Chrome' - }, - { - id: '1', - name: 'Firefox' - } - ], - candidateBrowsers: [{ id: '2' }], - recommendedBrowsers: [{ id: '1' }, { id: '2' }] - }, - { + browser: { + id: '1', + name: 'Firefox' + }, + issues: [], + draftTestPlanRuns: [] + } + ], + metadata: {} + }, + { + id: '13', + title: 'Disclosure Navigation Menu Example', + phase: 'RD', + gitSha: '179ba0f438aaa5781b3ec8a4033d6bf9f757360b', + gitMessage: + 'Delete up arrow command for VoiceOver when navigating backwards to a disclosure button (#845)', + updatedAt: '2022-10-31T19:29:17.000Z', + versionString: 'V22.10.31', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'disclosure-navigation' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '3', + title: 'Breadcrumb Example', + phase: 'RD', + gitSha: '1aa3b74d24d340362e9f511eae33788d55487d12', + gitMessage: + 'Add down arrow command to the Navigate forwards out of the Breadcrumb navigation landmark task for JAWS (#803)', + updatedAt: '2022-08-10T18:44:16.000Z', + versionString: 'V22.08.10', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'breadcrumb' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '19', + title: 'Main Landmark', + phase: 'RD', + gitSha: 'c87a66ea13a2b6fac6d79fe1fb0b7a2f721dcd22', + gitMessage: + 'Create updated tests for APG design pattern example: Main landmark (#707)', + updatedAt: '2022-08-05T17:46:37.000Z', + versionString: 'V22.08.05', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'main' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '24', + title: 'Meter', + phase: 'RD', + gitSha: '32d2d9db48becfc008fc566b569ac1563576ceb9', + gitMessage: + 'Create updated tests for APG design pattern example: Meter (#692)', + updatedAt: '2022-08-05T17:02:59.000Z', + versionString: 'V22.08.05', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'meter' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '32', + title: 'Switch Example', + phase: 'RD', + gitSha: '9d0e4e3d1040d64d9db69647e615c4ec0be723c2', + gitMessage: + 'Create updated tests for APG design pattern example: Switch (#691)', + updatedAt: '2022-08-05T16:13:44.000Z', + versionString: 'V22.08.05', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'switch' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '22', + title: 'Navigation Menu Button', + phase: 'RD', + gitSha: 'ecf05f484292189789f4db8b1ec41b19db38e567', + gitMessage: + 'Tasks 4, 5 and 6: corrected link name "Navigate backwards from here" (#734)', + updatedAt: '2022-05-26T16:14:17.000Z', + versionString: 'V22.05.26', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'menu-button-navigation' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '34', + title: 'Toggle Button', + phase: 'DRAFT', + gitSha: '022340081280b8cafb8ae0716a5b67e9ab942ef4', + gitMessage: + 'Delete duplicated assertion for operating a not pressed togle button (VoiceOver) (#716)', + updatedAt: '2022-05-18T20:51:40.000Z', + versionString: 'V22.05.18', + draftPhaseReachedAt: '2022-07-06T00:00:00.000Z', + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'toggle-button' + }, + testPlanReports: [ + { + id: '1', + metrics: { + testsCount: 16, + supportLevel: 'FAILING', + conflictsCount: 0, + supportPercent: 93, + testsFailedCount: 14, + testsPassedCount: 2, + optionalFormatted: false, + requiredFormatted: '28 of 30 passed', + optionalAssertionsCount: 0, + requiredAssertionsCount: 30, + unexpectedBehaviorCount: 1, + unexpectedBehaviorsFormatted: '1 found', + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 0, + requiredAssertionsFailedCount: 2, + requiredAssertionsPassedCount: 28 + }, + markedFinalAt: null, + isFinal: false, + at: { + id: '1', + name: 'JAWS' + }, + browser: { + id: '2', + name: 'Chrome' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'esmeralda-baggins' + }, + testPlanReport: { + id: '1' + }, + testResults: [ + { + test: { + id: 'OWY5NeyIyIjoiMzQifQTRmOD' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:07.154Z' + }, + { + test: { + id: 'NGFjMeyIyIjoiMzQifQjQxY2' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: null + }, + { + test: { + id: 'NTAwOeyIyIjoiMzQifQWI5YT' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: null + }, + { + test: { + id: 'YThjMeyIyIjoiMzQifQzIyYT' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: null + }, + { + test: { + id: 'YTgxMeyIyIjoiMzQifQzExOW' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:07.381Z' + }, + { + test: { + id: 'NGMwNeyIyIjoiMzQifQ2IwN2' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:07.464Z' + }, + { + test: { + id: 'YzQxNeyIyIjoiMzQifQjY5ND' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:07.537Z' + }, + { + test: { + id: 'MjgwNeyIyIjoiMzQifQzk3YT' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:07.610Z' + } + ] + } + ] + } + ], + metadata: {} + }, + { + id: '8', + title: 'Command Button Example', + phase: 'RD', + gitSha: '0c466eec96c8cafc9961232c85e14758c4589525', + gitMessage: + 'Fix navigation link positions in three test plans: link, command button and toggle button (#709)', + updatedAt: '2022-05-04T21:33:31.000Z', + versionString: 'V22.05.04', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'command-button' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '18', + title: 'Link Example 1 (span element with text content)', + phase: 'RD', + gitSha: '0c466eec96c8cafc9961232c85e14758c4589525', + gitMessage: + 'Fix navigation link positions in three test plans: link, command button and toggle button (#709)', + updatedAt: '2022-05-04T21:33:31.000Z', + versionString: 'V22.05.04', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'link-span-text' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '15', + title: 'Color Viewer Slider', + phase: 'RD', + gitSha: '1c6ef2fbef5fc056c622c802bebedaa14f2c8d40', + gitMessage: + 'Create updated tests for APG design pattern example: Color Viewer Slider (#686)', + updatedAt: '2022-04-14T18:06:40.000Z', + versionString: 'V22.04.14', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'horizontal-slider' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '6', + title: 'Combobox with Both List and Inline Autocomplete Example', + phase: 'RD', + gitSha: '6b2cbcbdbd5f6867cd3c9e96362817c353335187', + gitMessage: "typo: double word 'the' (#595)", + updatedAt: '2022-03-29T16:02:56.000Z', + versionString: 'V22.03.29', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'combobox-autocomplete-both-updated' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '21', + title: 'Action Menu Button Example Using aria-activedescendant', + phase: 'RD', + gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', + gitMessage: + 'Generate html source script to support aria-at-app (#646)', + updatedAt: '2022-03-17T18:34:51.000Z', + versionString: 'V22.03.17', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'menu-button-actions-active-descendant' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '20', + title: 'Action Menu Button Example Using element.focus()', + phase: 'RD', + gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', + gitMessage: + 'Generate html source script to support aria-at-app (#646)', + updatedAt: '2022-03-17T18:34:51.000Z', + versionString: 'V22.03.17', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'menu-button-actions' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '2', + title: 'Banner Landmark', + phase: 'RD', + gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', + gitMessage: + 'Generate html source script to support aria-at-app (#646)', + updatedAt: '2022-03-17T18:34:51.000Z', + versionString: 'V22.03.17', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'banner' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '4', + title: 'Checkbox Example (Two State)', + phase: 'RD', + gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', + gitMessage: + 'Generate html source script to support aria-at-app (#646)', + updatedAt: '2022-03-17T18:34:51.000Z', + versionString: 'V22.03.17', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'checkbox' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '9', + title: 'Complementary Landmark', + phase: 'RD', + gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', + gitMessage: + 'Generate html source script to support aria-at-app (#646)', + updatedAt: '2022-03-17T18:34:51.000Z', + versionString: 'V22.03.17', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'complementary' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '10', + title: 'Contentinfo Landmark', + phase: 'RD', + gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', + gitMessage: + 'Generate html source script to support aria-at-app (#646)', + updatedAt: '2022-03-17T18:34:51.000Z', + versionString: 'V22.03.17', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'contentinfo' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '25', + title: 'Data Grid Example 1: Minimal Data Grid', + phase: 'RD', + gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', + gitMessage: + 'Generate html source script to support aria-at-app (#646)', + updatedAt: '2022-03-17T18:34:51.000Z', + versionString: 'V22.03.17', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'minimal-data-grid' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '11', + title: 'Date Picker Spin Button Example', + phase: 'RD', + gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', + gitMessage: + 'Generate html source script to support aria-at-app (#646)', + updatedAt: '2022-03-17T18:34:51.000Z', + versionString: 'V22.03.17', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'datepicker-spin-button' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '12', + title: + 'Disclosure of Answers to Frequently Asked Questions Example', + phase: 'RD', + gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', + gitMessage: + 'Generate html source script to support aria-at-app (#646)', + updatedAt: '2022-03-17T18:34:51.000Z', + versionString: 'V22.03.17', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'disclosure-faq' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '23', + title: 'Editor Menubar Example', + phase: 'RD', + gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', + gitMessage: + 'Generate html source script to support aria-at-app (#646)', + updatedAt: '2022-03-17T18:34:51.000Z', + versionString: 'V22.03.17', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'menubar-editor' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '14', + title: 'Form Landmark', + phase: 'RD', + gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', + gitMessage: + 'Generate html source script to support aria-at-app (#646)', + updatedAt: '2022-03-17T18:34:51.000Z', + versionString: 'V22.03.17', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'form' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '30', + title: 'Media Seek Slider', + phase: 'RD', + gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', + gitMessage: + 'Generate html source script to support aria-at-app (#646)', + updatedAt: '2022-03-17T18:34:51.000Z', + versionString: 'V22.03.17', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'seek-slider' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '29', + title: 'Rating Slider', + phase: 'RD', + gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', + gitMessage: + 'Generate html source script to support aria-at-app (#646)', + updatedAt: '2022-03-17T18:34:51.000Z', + versionString: 'V22.03.17', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'rating-slider' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '7', + title: 'Select Only Combobox Example', + phase: 'DRAFT', + gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', + gitMessage: + 'Generate html source script to support aria-at-app (#646)', + updatedAt: '2022-03-17T18:34:51.000Z', + versionString: 'V22.03.17', + draftPhaseReachedAt: '2022-07-06T00:00:00.000Z', + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'combobox-select-only' + }, + testPlanReports: [ + { + id: '2', + metrics: { + testsCount: 21, + supportLevel: 'FAILING', + conflictsCount: 5, + supportPercent: 96, + testsFailedCount: 16, + testsPassedCount: 5, + optionalFormatted: '3 of 3 passed', + requiredFormatted: '48 of 50 passed', + optionalAssertionsCount: 3, + requiredAssertionsCount: 50, + unexpectedBehaviorCount: 3, + unexpectedBehaviorsFormatted: '3 found', + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 3, + requiredAssertionsFailedCount: 2, + requiredAssertionsPassedCount: 48 + }, + markedFinalAt: null, + isFinal: false, + at: { + id: '2', + name: 'NVDA' + }, + browser: { + id: '1', + name: 'Firefox' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'tom-proudfeet' + }, + testPlanReport: { + id: '2' + }, + testResults: [ + { + test: { + id: 'Nzg5NeyIyIjoiNyJ9zNjZj' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.240Z' + }, + { + test: { + id: 'MmY0YeyIyIjoiNyJ9jRkZD' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.332Z' + }, + { + test: { + id: 'ZjUwNeyIyIjoiNyJ9mE2ZT' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.412Z' + }, + { + test: { + id: 'MDNiMeyIyIjoiNyJ9Dk1MT' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.501Z' + }, + { + test: { + id: 'MjRmNeyIyIjoiNyJ92MyMT' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.593Z' + }, + { + test: { + id: 'ZmVlMeyIyIjoiNyJ9mUyYj' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: null + }, + { + test: { + id: 'YWFiNeyIyIjoiNyJ9zE2Zj' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.811Z' + }, + { + test: { + id: 'YjZkYeyIyIjoiNyJ9WIxZm' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.902Z' + }, + { + test: { + id: 'ZmIzMeyIyIjoiNyJ9TQ1NW' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.996Z' + } + ] + }, + { + tester: { + username: 'esmeralda-baggins' + }, + testPlanReport: { + id: '2' + }, + testResults: [ + { + test: { + id: 'Nzg5NeyIyIjoiNyJ9zNjZj' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:07.718Z' + }, + { + test: { + id: 'MmY0YeyIyIjoiNyJ9jRkZD' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:07.813Z' + }, + { + test: { + id: 'ZjUwNeyIyIjoiNyJ9mE2ZT' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:07.914Z' + }, + { + test: { + id: 'MDNiMeyIyIjoiNyJ9Dk1MT' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:07.988Z' + }, + { + test: { + id: 'MjRmNeyIyIjoiNyJ92MyMT' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.074Z' + }, + { + test: { + id: 'ZmVlMeyIyIjoiNyJ9mUyYj' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: null + } + ] + } + ] + } + ], + metadata: {} + }, + { + id: '33', + title: 'Tabs with Manual Activation', + phase: 'RD', + gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', + gitMessage: + 'Generate html source script to support aria-at-app (#646)', + updatedAt: '2022-03-17T18:34:51.000Z', + versionString: 'V22.03.17', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'tabs-manual-activation' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '35', + title: 'Vertical Temperature Slider', + phase: 'RD', + gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', + gitMessage: + 'Generate html source script to support aria-at-app (#646)', + updatedAt: '2022-03-17T18:34:51.000Z', + versionString: 'V22.03.17', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'vertical-temperature-slider' + }, + testPlanReports: [], + metadata: {} + }, + { + id: '5', + title: 'Checkbox Example (Mixed-State)', + phase: 'RECOMMENDED', + gitSha: 'b3d0576a2901ea7f100f49a994b64edbecf81cff', + gitMessage: 'Modify VoiceOver commands for task 7 (#842)', + updatedAt: '2022-10-24T21:33:12.000Z', + versionString: 'V22.10.24', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: '2022-07-06T00:00:00.000Z', + recommendedPhaseTargetDate: '2023-01-02T00:00:00.000Z', + recommendedPhaseReachedAt: '2023-01-03T00:00:00.000Z', + testPlan: { + directory: 'checkbox-tri-state' + }, + testPlanReports: [ + { + id: '6', + metrics: { + testsCount: 7, + supportLevel: 'FAILING', + conflictsCount: 0, + supportPercent: 96, + testsFailedCount: 3, + testsPassedCount: 4, + optionalFormatted: '4 of 4 passed', + requiredFormatted: '44 of 46 passed', + optionalAssertionsCount: 4, + requiredAssertionsCount: 46, + unexpectedBehaviorCount: 0, + unexpectedBehaviorsFormatted: false, + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 4, + requiredAssertionsFailedCount: 2, + requiredAssertionsPassedCount: 44 + }, + markedFinalAt: '2022-07-06T00:00:00.000Z', + isFinal: true, + at: { + id: '3', + name: 'VoiceOver for macOS' + }, + browser: { + id: '3', + name: 'Safari' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'tom-proudfeet' + }, + testPlanReport: { + id: '6' + }, + testResults: [ + { + test: { + id: 'YTE3NeyIyIjoiNSJ9WJlMj' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-18T03:17:10.341Z' + }, + { + test: { + id: 'YWJiOeyIyIjoiNSJ9GQ5Zm' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-18T03:17:10.405Z' + }, + { + test: { + id: 'ZGFlYeyIyIjoiNSJ9TJlMW' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-18T03:17:10.474Z' + }, + { + test: { + id: 'YjI2MeyIyIjoiNSJ9WE1OT' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-18T03:17:10.537Z' + }, + { + test: { + id: 'ZjAwZeyIyIjoiNSJ9TZmZj' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-18T03:17:10.605Z' + }, + { + test: { + id: 'MGRjZeyIyIjoiNSJ9WNiZD' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-18T03:17:10.670Z' + }, + { + test: { + id: 'OTZmYeyIyIjoiNSJ9TU5Ym' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-18T03:17:10.739Z' + } + ] + } + ] + }, + { + id: '12', + metrics: { + testsCount: 14, + supportLevel: 'FULL', + conflictsCount: 0, + supportPercent: 100, + testsFailedCount: 12, + testsPassedCount: 2, + optionalFormatted: false, + requiredFormatted: '25 of 25 passed', + optionalAssertionsCount: 0, + requiredAssertionsCount: 25, + unexpectedBehaviorCount: 0, + unexpectedBehaviorsFormatted: false, + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 0, + requiredAssertionsFailedCount: 0, + requiredAssertionsPassedCount: 25 + }, + markedFinalAt: null, + isFinal: false, + at: { + id: '1', + name: 'JAWS' + }, + browser: { + id: '2', + name: 'Chrome' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'esmeralda-baggins' + }, + testPlanReport: { + id: '12' + }, + testResults: [ + { + test: { + id: 'MTVlZeyIyIjoiNSJ9DUzMz' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:11.764Z' + }, + { + test: { + id: 'OThhMeyIyIjoiNSJ9WMxM2' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:11.828Z' + }, + { + test: { + id: 'YWNhNeyIyIjoiNSJ9TliN2' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:11.892Z' + } + ] + } + ] + }, + { + id: '13', + metrics: { + testsCount: 14, + supportLevel: 'FULL', + conflictsCount: 0, + supportPercent: 100, + testsFailedCount: 12, + testsPassedCount: 2, + optionalFormatted: false, + requiredFormatted: '25 of 25 passed', + optionalAssertionsCount: 0, + requiredAssertionsCount: 25, + unexpectedBehaviorCount: 0, + unexpectedBehaviorsFormatted: false, + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 0, + requiredAssertionsFailedCount: 0, + requiredAssertionsPassedCount: 25 + }, + markedFinalAt: null, + isFinal: false, + at: { + id: '2', + name: 'NVDA' + }, + browser: { + id: '2', + name: 'Chrome' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'esmeralda-baggins' + }, + testPlanReport: { + id: '13' + }, + testResults: [ + { + test: { + id: 'MTVlZeyIyIjoiNSJ9DUzMz' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:11.955Z' + }, + { + test: { + id: 'OThhMeyIyIjoiNSJ9WMxM2' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:12.017Z' + }, + { + test: { + id: 'YWNhNeyIyIjoiNSJ9TliN2' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:12.083Z' + } + ] + } + ] + } + ], + metadata: {} + }, + { + id: '26', + title: 'Modal Dialog Example', + phase: 'CANDIDATE', + gitSha: 'd0e16b42179de6f6c070da2310e99de837c71215', + gitMessage: + 'Delete down arrow command for navigating to the beginning of a dialog with JAWS and add the ESC command to exit forms or focus mode (#759)', + updatedAt: '2022-06-22T17:56:16.000Z', + versionString: 'V22.06.22', + draftPhaseReachedAt: '2022-07-06T00:00:00.000Z', + candidatePhaseReachedAt: '2022-07-06T00:00:00.000Z', + recommendedPhaseTargetDate: '2023-01-02T00:00:00.000Z', + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'modal-dialog' + }, + testPlanReports: [ + { + id: '10', + metrics: { + testsCount: 11, + supportLevel: 'FULL', + conflictsCount: 0, + supportPercent: 100, + testsFailedCount: 9, + testsPassedCount: 2, + optionalFormatted: false, + requiredFormatted: '14 of 14 passed', + optionalAssertionsCount: 0, + requiredAssertionsCount: 14, + unexpectedBehaviorCount: 0, + unexpectedBehaviorsFormatted: false, + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 0, + requiredAssertionsFailedCount: 0, + requiredAssertionsPassedCount: 14 + }, + markedFinalAt: null, + isFinal: false, + at: { + id: '3', + name: 'VoiceOver for macOS' + }, + browser: { + id: '1', + name: 'Firefox' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'esmeralda-baggins' + }, + testPlanReport: { + id: '10' + }, + testResults: [ + { + test: { + id: 'MzlmYeyIyIjoiMjYifQzIxY2' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:11.295Z' + }, + { + test: { + id: 'N2FkZeyIyIjoiMjYifQDQ5NT' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:11.369Z' + }, + { + test: { + id: 'ZDJkYeyIyIjoiMjYifQzRkYj' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:11.450Z' + } + ] + } + ] + }, + { + id: '9', + metrics: { + testsCount: 18, + supportLevel: 'FULL', + conflictsCount: 0, + supportPercent: 100, + testsFailedCount: 16, + testsPassedCount: 2, + optionalFormatted: false, + requiredFormatted: '16 of 16 passed', + optionalAssertionsCount: 0, + requiredAssertionsCount: 16, + unexpectedBehaviorCount: 0, + unexpectedBehaviorsFormatted: false, + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 0, + requiredAssertionsFailedCount: 0, + requiredAssertionsPassedCount: 16 + }, + markedFinalAt: null, + isFinal: false, + at: { + id: '2', + name: 'NVDA' + }, + browser: { + id: '1', + name: 'Firefox' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'esmeralda-baggins' + }, + testPlanReport: { + id: '9' + }, + testResults: [ + { + test: { + id: 'MThhNeyIyIjoiMjYifQmEyMj' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:11.059Z' + }, + { + test: { + id: 'ODY5MeyIyIjoiMjYifQzhmNW' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:11.137Z' + }, + { + test: { + id: 'NWVkNeyIyIjoiMjYifQTZkOT' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:11.218Z' + } + ] + } + ] + }, + { + id: '3', + metrics: { + testsCount: 18, + supportLevel: 'FAILING', + conflictsCount: 0, + supportPercent: 88, + testsFailedCount: 16, + testsPassedCount: 2, + optionalFormatted: false, + requiredFormatted: '14 of 16 passed', + optionalAssertionsCount: 0, + requiredAssertionsCount: 16, + unexpectedBehaviorCount: 1, + unexpectedBehaviorsFormatted: '1 found', + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 0, + requiredAssertionsFailedCount: 2, + requiredAssertionsPassedCount: 14 + }, + markedFinalAt: '2022-07-06T00:00:00.000Z', + isFinal: true, + at: { + id: '1', + name: 'JAWS' + }, + browser: { + id: '2', + name: 'Chrome' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'esmeralda-baggins' + }, + testPlanReport: { + id: '3' + }, + testResults: [ + { + test: { + id: 'MThhNeyIyIjoiMjYifQmEyMj' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.074Z' + }, + { + test: { + id: 'NWVkNeyIyIjoiMjYifQTZkOT' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.134Z' + }, + { + test: { + id: 'NWM4NeyIyIjoiMjYifQDEwM2' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.202Z' + }, + { + test: { + id: 'NGFiZeyIyIjoiMjYifQWZiYW' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.268Z' + }, + { + test: { + id: 'MzQzYeyIyIjoiMjYifQzU5Zm' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.336Z' + } + ] + } + ] + }, + { + id: '11', + metrics: { + testsCount: 11, + supportLevel: 'FULL', + conflictsCount: 0, + supportPercent: 100, + testsFailedCount: 9, + testsPassedCount: 2, + optionalFormatted: false, + requiredFormatted: '14 of 14 passed', + optionalAssertionsCount: 0, + requiredAssertionsCount: 14, + unexpectedBehaviorCount: 0, + unexpectedBehaviorsFormatted: false, + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 0, + requiredAssertionsFailedCount: 0, + requiredAssertionsPassedCount: 14 + }, + markedFinalAt: null, + isFinal: false, + at: { + id: '3', + name: 'VoiceOver for macOS' + }, + browser: { + id: '2', + name: 'Chrome' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'esmeralda-baggins' + }, + testPlanReport: { + id: '11' + }, + testResults: [ + { + test: { + id: 'MzlmYeyIyIjoiMjYifQzIxY2' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:11.532Z' + }, + { + test: { + id: 'N2FkZeyIyIjoiMjYifQDQ5NT' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:11.611Z' + }, + { + test: { + id: 'ZDJkYeyIyIjoiMjYifQzRkYj' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:11.696Z' + } + ] + } + ] + }, + { + id: '4', + metrics: { + testsCount: 18, + supportLevel: 'FAILING', + conflictsCount: 0, + supportPercent: 91, + testsFailedCount: 14, + testsPassedCount: 4, + optionalFormatted: false, + requiredFormatted: '20 of 22 passed', + optionalAssertionsCount: 0, + requiredAssertionsCount: 22, + unexpectedBehaviorCount: 1, + unexpectedBehaviorsFormatted: '1 found', + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 0, + requiredAssertionsFailedCount: 2, + requiredAssertionsPassedCount: 20 + }, + markedFinalAt: '2022-07-06T00:00:00.000Z', + isFinal: true, + at: { + id: '2', + name: 'NVDA' + }, + browser: { + id: '2', + name: 'Chrome' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'esmeralda-baggins' + }, + testPlanReport: { + id: '4' + }, + testResults: [ + { + test: { + id: 'MThhNeyIyIjoiMjYifQmEyMj' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.409Z' + }, + { + test: { + id: 'NWVkNeyIyIjoiMjYifQTZkOT' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.478Z' + }, + { + test: { + id: 'NWM4NeyIyIjoiMjYifQDEwM2' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.551Z' + }, + { + test: { + id: 'NGFiZeyIyIjoiMjYifQWZiYW' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.629Z' + }, + { + test: { + id: 'MzQzYeyIyIjoiMjYifQzU5Zm' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.704Z' + }, + { + test: { + id: 'MmI1MeyIyIjoiMjYifQmU3Yz' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.777Z' + }, + { + test: { + id: 'YmRmYeyIyIjoiMjYifQjEyMT' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.852Z' + } + ] + } + ] + }, + { + id: '5', + metrics: { + testsCount: 11, + supportLevel: 'FAILING', + conflictsCount: 0, + supportPercent: 92, + testsFailedCount: 8, + testsPassedCount: 3, + optionalFormatted: false, + requiredFormatted: '23 of 25 passed', + optionalAssertionsCount: 0, + requiredAssertionsCount: 25, + unexpectedBehaviorCount: 1, + unexpectedBehaviorsFormatted: '1 found', + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 0, + requiredAssertionsFailedCount: 2, + requiredAssertionsPassedCount: 23 + }, + markedFinalAt: '2022-07-06T00:00:00.000Z', + isFinal: true, + at: { + id: '3', + name: 'VoiceOver for macOS' + }, + browser: { + id: '3', + name: 'Safari' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'esmeralda-baggins' + }, + testPlanReport: { + id: '5' + }, + testResults: [ + { + test: { + id: 'MzlmYeyIyIjoiMjYifQzIxY2' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-18T03:17:09.923Z' + }, + { + test: { + id: 'ZDJkYeyIyIjoiMjYifQzRkYj' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-18T03:17:09.991Z' + }, + { + test: { + id: 'ZmQyNeyIyIjoiMjYifQ2M2ND' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-18T03:17:10.059Z' + }, + { + test: { + id: 'OGE3YeyIyIjoiMjYifQjU1ND' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-18T03:17:10.129Z' + }, + { + test: { + id: 'YWI3OeyIyIjoiMjYifQWJlNW' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-18T03:17:10.198Z' + }, + { + test: { + id: 'M2RiOeyIyIjoiMjYifQGY1Nj' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-18T03:17:10.272Z' + } + ] + } + ] + }, + { + id: '8', + metrics: { + testsCount: 18, + supportLevel: 'FULL', + conflictsCount: 0, + supportPercent: 100, + testsFailedCount: 16, + testsPassedCount: 2, + optionalFormatted: false, + requiredFormatted: '16 of 16 passed', + optionalAssertionsCount: 0, + requiredAssertionsCount: 16, + unexpectedBehaviorCount: 0, + unexpectedBehaviorsFormatted: false, + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 0, + requiredAssertionsFailedCount: 0, + requiredAssertionsPassedCount: 16 + }, + markedFinalAt: null, + isFinal: false, + at: { + id: '1', + name: 'JAWS' + }, + browser: { + id: '1', + name: 'Firefox' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'esmeralda-baggins' + }, + testPlanReport: { + id: '8' + }, + testResults: [ + { + test: { + id: 'MThhNeyIyIjoiMjYifQmEyMj' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:10.817Z' + }, + { + test: { + id: 'ODY5MeyIyIjoiMjYifQzhmNW' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:10.894Z' + }, + { + test: { + id: 'NWVkNeyIyIjoiMjYifQTZkOT' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:10.979Z' + } + ] + } + ] + } + ], + metadata: {} + } + ] + } + } + }, + { + request: { + query: testPlanReportStatusDialogQuery, + variables: { testPlanVersionId: '1' } + }, + result: { + data: { + testPlanVersion: { + id: '1', + title: 'Alert Example', + phase: 'DRAFT', + gitSha: '0928bcf530efcf4faa677285439701537674e014', + gitMessage: 'Alert and Radiogroup/activedescendent updates (#865)', + updatedAt: '2022-12-08T21:47:42.000Z', + versionString: 'V22.12.08', + draftPhaseReachedAt: '2022-07-06T00:00:00.000Z', + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'alert' + }, + testPlanReports: [ + { + id: '7', + metrics: {}, + markedFinalAt: null, + isFinal: false, + at: { + id: '3', + name: 'VoiceOver for macOS' + }, + browser: { + id: '1', + name: 'Firefox' + }, + issues: [], + draftTestPlanRuns: [] + } + ], + metadata: {} + } + } + } + }, + { + request: { + query: testPlanReportStatusDialogQuery, + variables: { testPlanVersionId: '5' } + }, + result: { + data: { + testPlanVersion: { + id: '5', + title: 'Checkbox Example (Mixed-State)', + phase: 'RECOMMENDED', + gitSha: '836fb2a997f5b2844035b8c934f8fda9833cd5b2', + gitMessage: 'Validation for test csv formats (#980)', + updatedAt: '2023-08-23T20:30:34.000Z', + draftPhaseReachedAt: null, + candidatePhaseReachedAt: '2022-07-06T00:00:00.000Z', + recommendedPhaseTargetDate: '2023-01-02T00:00:00.000Z', + recommendedPhaseReachedAt: '2023-01-03T00:00:00.000Z', + testPlan: { + directory: 'checkbox-tri-state' + }, + testPlanReports: [ + { + id: '6', + metrics: { + testsCount: 7, + supportLevel: 'FAILING', + conflictsCount: 0, + supportPercent: 96, + testsFailedCount: 3, + testsPassedCount: 4, + optionalFormatted: '4 of 4 passed', + requiredFormatted: '44 of 46 passed', + optionalAssertionsCount: 4, + requiredAssertionsCount: 46, + unexpectedBehaviorCount: 0, + unexpectedBehaviorsFormatted: false, + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 4, + requiredAssertionsFailedCount: 2, + requiredAssertionsPassedCount: 44 + }, + markedFinalAt: '2022-07-06T00:00:00.000Z', + isFinal: true, + at: { + id: '3', + name: 'VoiceOver for macOS' + }, + browser: { + id: '3', + name: 'Safari' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'tom-proudfeet' + }, + testPlanReport: { + id: '6' + }, + testResults: [ + { + test: { + id: 'YTE3NeyIyIjoiNSJ9WJlMj' + }, + atVersion: { id: '3', - name: 'VoiceOver for macOS', - atVersions: [ - { - id: '3', - name: '11.6 (20G165)', - releasedAt: '2019-09-01T04:00:00.000Z' - } - ], - browsers: [ - { - id: '2', - name: 'Chrome' - }, - { - id: '1', - name: 'Firefox' - }, - { - id: '3', - name: 'Safari' - } - ], - candidateBrowsers: [{ id: '3' }], - recommendedBrowsers: [{ id: '2' }, { id: '3' }] - } - ], - testPlans: [ - { - id: '27', - directory: 'radiogroup-aria-activedescendant', - title: 'Radio Group Example Using aria-activedescendant' - }, - { - id: '28', - directory: 'radiogroup-roving-tabindex', - title: 'Radio Group Example Using Roving tabindex' - }, - { - id: '31', - directory: 'slider-multithumb', - title: 'Horizontal Multi-Thumb Slider' - }, - { - id: '16', - directory: 'link-css', - title: 'Link Example 3 (CSS :before content property on a span element)' - }, - { - id: '17', - directory: 'link-img-alt', - title: 'Link Example 2 (img element with alt attribute)' - }, - { - id: '1', - directory: 'alert', - title: 'Alert Example' - }, - { - id: '13', - directory: 'disclosure-navigation', - title: 'Disclosure Navigation Menu Example' - }, - { - id: '5', - directory: 'checkbox-tri-state', - title: 'Checkbox Example (Mixed-State)' + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-30T13:23:57.070Z' }, { + test: { + id: 'YWJiOeyIyIjoiNSJ9GQ5Zm' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { id: '3', - directory: 'breadcrumb', - title: 'Breadcrumb Example' + name: '14.1.2' + }, + completedAt: '2023-08-30T13:23:57.142Z' }, { - id: '19', - directory: 'main', - title: 'Main Landmark' + test: { + id: 'ZGFlYeyIyIjoiNSJ9TJlMW' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-30T13:23:57.204Z' }, { - id: '24', - directory: 'meter', - title: 'Meter' + test: { + id: 'YjI2MeyIyIjoiNSJ9WE1OT' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-30T13:23:57.275Z' }, { - id: '32', - directory: 'switch', - title: 'Switch Example' + test: { + id: 'ZjAwZeyIyIjoiNSJ9TZmZj' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-30T13:23:57.330Z' }, { - id: '26', - directory: 'modal-dialog', - title: 'Modal Dialog Example' + test: { + id: 'MGRjZeyIyIjoiNSJ9WNiZD' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-30T13:23:57.382Z' }, { - id: '22', - directory: 'menu-button-navigation', - title: 'Navigation Menu Button' + test: { + id: 'OTZmYeyIyIjoiNSJ9TU5Ym' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-30T13:23:57.439Z' + } + ] + } + ] + }, + { + id: '12', + metrics: { + testsCount: 14, + supportLevel: 'FULL', + conflictsCount: 0, + supportPercent: 100, + testsFailedCount: 12, + testsPassedCount: 2, + optionalFormatted: false, + requiredFormatted: '25 of 25 passed', + optionalAssertionsCount: 0, + requiredAssertionsCount: 25, + unexpectedBehaviorCount: 0, + unexpectedBehaviorsFormatted: false, + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 0, + requiredAssertionsFailedCount: 0, + requiredAssertionsPassedCount: 25 + }, + markedFinalAt: '2022-07-06T00:00:00.000Z', + isFinal: true, + at: { + id: '1', + name: 'JAWS' + }, + browser: { + id: '2', + name: 'Chrome' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'esmeralda-baggins' + }, + testPlanReport: { + id: '12' + }, + testResults: [ + { + test: { + id: 'MTVlZeyIyIjoiNSJ9DUzMz' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-30T13:23:58.343Z' }, { - id: '34', - directory: 'toggle-button', - title: 'Toggle Button' + test: { + id: 'OThhMeyIyIjoiNSJ9WMxM2' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-30T13:23:58.404Z' }, { - id: '18', - directory: 'link-span-text', - title: 'Link Example 1 (span element with text content)' + test: { + id: 'YWNhNeyIyIjoiNSJ9TliN2' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-30T13:23:58.472Z' + } + ] + } + ] + }, + { + id: '13', + metrics: { + testsCount: 14, + supportLevel: 'FULL', + conflictsCount: 0, + supportPercent: 100, + testsFailedCount: 12, + testsPassedCount: 2, + optionalFormatted: false, + requiredFormatted: '25 of 25 passed', + optionalAssertionsCount: 0, + requiredAssertionsCount: 25, + unexpectedBehaviorCount: 0, + unexpectedBehaviorsFormatted: false, + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 0, + requiredAssertionsFailedCount: 0, + requiredAssertionsPassedCount: 25 + }, + markedFinalAt: '2022-07-07T00:00:00.000Z', + isFinal: true, + at: { + id: '2', + name: 'NVDA' + }, + browser: { + id: '2', + name: 'Chrome' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'esmeralda-baggins' + }, + testPlanReport: { + id: '13' + }, + testResults: [ + { + test: { + id: 'MTVlZeyIyIjoiNSJ9DUzMz' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-30T13:23:58.531Z' }, { - id: '8', - directory: 'command-button', - title: 'Command Button Example' + test: { + id: 'OThhMeyIyIjoiNSJ9WMxM2' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-30T13:23:58.593Z' }, { - id: '15', - directory: 'horizontal-slider', - title: 'Color Viewer Slider' + test: { + id: 'YWNhNeyIyIjoiNSJ9TliN2' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-30T13:23:58.655Z' + } + ] + } + ] + } + ], + metadata: {} + } + } + } + }, + { + request: { + query: testPlanReportStatusDialogQuery, + variables: { testPlanVersionId: '7' } + }, + result: { + data: { + testPlanVersion: { + id: '7', + title: 'Select Only Combobox Example', + phase: 'DRAFT', + gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', + gitMessage: + 'Generate html source script to support aria-at-app (#646)', + updatedAt: '2022-03-17T18:34:51.000Z', + draftPhaseReachedAt: '2022-07-06T00:00:00.000Z', + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'combobox-select-only' + }, + testPlanReports: [ + { + id: '2', + metrics: { + testsCount: 21, + supportLevel: 'FAILING', + conflictsCount: 5, + supportPercent: 96, + testsFailedCount: 16, + testsPassedCount: 5, + optionalFormatted: '3 of 3 passed', + requiredFormatted: '48 of 50 passed', + optionalAssertionsCount: 3, + requiredAssertionsCount: 50, + unexpectedBehaviorCount: 3, + unexpectedBehaviorsFormatted: '3 found', + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 3, + requiredAssertionsFailedCount: 2, + requiredAssertionsPassedCount: 48 + }, + markedFinalAt: null, + isFinal: false, + at: { + id: '2', + name: 'NVDA' + }, + browser: { + id: '1', + name: 'Firefox' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'tom-proudfeet' + }, + testPlanReport: { + id: '2' + }, + testResults: [ + { + test: { + id: 'Nzg5NeyIyIjoiNyJ9zNjZj' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.240Z' }, { - id: '6', - directory: 'combobox-autocomplete-both-updated', - title: 'Combobox with Both List and Inline Autocomplete Example' + test: { + id: 'MmY0YeyIyIjoiNyJ9jRkZD' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.332Z' }, { - id: '7', - directory: 'combobox-select-only', - title: 'Select Only Combobox Example' + test: { + id: 'ZjUwNeyIyIjoiNyJ9mE2ZT' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.412Z' }, { - id: '4', - directory: 'checkbox', - title: 'Checkbox Example (Two State)' + test: { + id: 'MDNiMeyIyIjoiNyJ9Dk1MT' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.501Z' }, { - id: '9', - directory: 'complementary', - title: 'Complementary Landmark' + test: { + id: 'MjRmNeyIyIjoiNyJ92MyMT' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.593Z' }, { - id: '10', - directory: 'contentinfo', - title: 'Contentinfo Landmark' + test: { + id: 'ZmVlMeyIyIjoiNyJ9mUyYj' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: null }, { - id: '11', - directory: 'datepicker-spin-button', - title: 'Date Picker Spin Button Example' + test: { + id: 'YWFiNeyIyIjoiNyJ9zE2Zj' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.811Z' }, { - id: '12', - directory: 'disclosure-faq', - title: 'Disclosure of Answers to Frequently Asked Questions Example' + test: { + id: 'YjZkYeyIyIjoiNyJ9WIxZm' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.902Z' }, { - id: '14', - directory: 'form', - title: 'Form Landmark' + test: { + id: 'ZmIzMeyIyIjoiNyJ9TQ1NW' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.996Z' + } + ] + }, + { + tester: { + username: 'esmeralda-baggins' + }, + testPlanReport: { + id: '2' + }, + testResults: [ + { + test: { + id: 'Nzg5NeyIyIjoiNyJ9zNjZj' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:07.718Z' }, { - id: '20', - directory: 'menu-button-actions', - title: 'Action Menu Button Example Using element.focus()' + test: { + id: 'MmY0YeyIyIjoiNyJ9jRkZD' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:07.813Z' }, { - id: '21', - directory: 'menu-button-actions-active-descendant', - title: 'Action Menu Button Example Using aria-activedescendant' + test: { + id: 'ZjUwNeyIyIjoiNyJ9mE2ZT' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:07.914Z' }, { - id: '23', - directory: 'menubar-editor', - title: 'Editor Menubar Example' + test: { + id: 'MDNiMeyIyIjoiNyJ9Dk1MT' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:07.988Z' }, { - id: '25', - directory: 'minimal-data-grid', - title: 'Data Grid Example 1: Minimal Data Grid' + test: { + id: 'MjRmNeyIyIjoiNyJ92MyMT' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.074Z' }, { - id: '29', - directory: 'rating-slider', - title: 'Rating Slider' + test: { + id: 'ZmVlMeyIyIjoiNyJ9mUyYj' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: null + } + ] + } + ] + } + ], + metadata: {} + } + } + } + }, + { + request: { + query: testPlanReportStatusDialogQuery, + variables: { testPlanVersionId: '26' } + }, + result: { + data: { + testPlanVersion: { + id: '26', + title: 'Modal Dialog Example', + phase: 'CANDIDATE', + gitSha: 'd0e16b42179de6f6c070da2310e99de837c71215', + gitMessage: + 'Delete down arrow command for navigating to the beginning of a dialog with JAWS and add the ESC command to exit forms or focus mode (#759)', + updatedAt: '2022-06-22T17:56:16.000Z', + draftPhaseReachedAt: '2022-07-06T00:00:00.000Z', + candidatePhaseReachedAt: '2022-07-06T00:00:00.000Z', + recommendedPhaseTargetDate: '2023-01-02T00:00:00.000Z', + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'modal-dialog' + }, + testPlanReports: [ + { + id: '10', + metrics: { + testsCount: 11, + supportLevel: 'FULL', + conflictsCount: 0, + supportPercent: 100, + testsFailedCount: 9, + testsPassedCount: 2, + optionalFormatted: false, + requiredFormatted: '14 of 14 passed', + optionalAssertionsCount: 0, + requiredAssertionsCount: 14, + unexpectedBehaviorCount: 0, + unexpectedBehaviorsFormatted: false, + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 0, + requiredAssertionsFailedCount: 0, + requiredAssertionsPassedCount: 14 + }, + markedFinalAt: null, + isFinal: false, + at: { + id: '3', + name: 'VoiceOver for macOS' + }, + browser: { + id: '1', + name: 'Firefox' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'esmeralda-baggins' + }, + testPlanReport: { + id: '10' + }, + testResults: [ + { + test: { + id: 'MzlmYeyIyIjoiMjYifQzIxY2' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:11.295Z' }, { - id: '30', - directory: 'seek-slider', - title: 'Media Seek Slider' + test: { + id: 'N2FkZeyIyIjoiMjYifQDQ5NT' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:11.369Z' }, { - id: '33', - directory: 'tabs-manual-activation', - title: 'Tabs with Manual Activation' + test: { + id: 'ZDJkYeyIyIjoiMjYifQzRkYj' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:11.450Z' + } + ] + } + ] + }, + { + id: '9', + metrics: { + testsCount: 18, + supportLevel: 'FULL', + conflictsCount: 0, + supportPercent: 100, + testsFailedCount: 16, + testsPassedCount: 2, + optionalFormatted: false, + requiredFormatted: '16 of 16 passed', + optionalAssertionsCount: 0, + requiredAssertionsCount: 16, + unexpectedBehaviorCount: 0, + unexpectedBehaviorsFormatted: false, + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 0, + requiredAssertionsFailedCount: 0, + requiredAssertionsPassedCount: 16 + }, + markedFinalAt: null, + isFinal: false, + at: { + id: '2', + name: 'NVDA' + }, + browser: { + id: '1', + name: 'Firefox' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'esmeralda-baggins' + }, + testPlanReport: { + id: '9' + }, + testResults: [ + { + test: { + id: 'MThhNeyIyIjoiMjYifQmEyMj' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:11.059Z' }, { - id: '35', - directory: 'vertical-temperature-slider', - title: 'Vertical Temperature Slider' + test: { + id: 'ODY5MeyIyIjoiMjYifQzhmNW' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:11.137Z' }, { + test: { + id: 'NWVkNeyIyIjoiMjYifQTZkOT' + }, + atVersion: { id: '2', - directory: 'banner', - title: 'Banner Landmark' + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:11.218Z' } - ], - testPlanVersions: [ - { - id: '28', - title: 'Radio Group Example Using Roving tabindex', - phase: 'RD', - gitSha: '1768070bd68beefef29284b568d2da910b449c14', - gitMessage: - 'Remove Tab and Shift+Tab from radiogroup tests when navigating out of the start and end of a radio group (reading mode and VoiceOver only) (#928)', - updatedAt: '2023-04-10T18:22:22.000Z', - versionString: 'V23.04.10', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'radiogroup-roving-tabindex' - }, - testPlanReports: [], - metadata: {} - }, - { - id: '27', - title: 'Radio Group Example Using aria-activedescendant', - phase: 'RD', - gitSha: '1768070bd68beefef29284b568d2da910b449c14', - gitMessage: - 'Remove Tab and Shift+Tab from radiogroup tests when navigating out of the start and end of a radio group (reading mode and VoiceOver only) (#928)', - updatedAt: '2023-04-10T18:22:22.000Z', - versionString: 'V23.04.10', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'radiogroup-aria-activedescendant' - }, - testPlanReports: [], - metadata: {} - }, - { - id: '31', - title: 'Horizontal Multi-Thumb Slider', - phase: 'RD', - gitSha: 'b5fe3efd569518e449ef9a0978b0dec1f2a08bd6', - gitMessage: - 'Create tests for APG design pattern example: Horizontal Multi-Thumb Slider (#511)', - updatedAt: '2023-03-20T21:24:41.000Z', - versionString: 'V23.03.20', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'slider-multithumb' - }, - testPlanReports: [], - metadata: {} - }, - { - id: '16', - title: 'Link Example 3 (CSS :before content property on a span element)', - phase: 'RD', - gitSha: '7a8454bca6de980199868101431817cea03cce35', - gitMessage: - 'Create tests for APG design pattern example: Link Example 3 (CSS :before content property on a span element) (#518)', - updatedAt: '2023-03-13T22:10:13.000Z', - versionString: 'V23.03.13', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'link-css' - }, - testPlanReports: [], - metadata: {} + ] + } + ] + }, + { + id: '3', + metrics: { + testsCount: 18, + supportLevel: 'FAILING', + conflictsCount: 0, + supportPercent: 88, + testsFailedCount: 16, + testsPassedCount: 2, + optionalFormatted: false, + requiredFormatted: '14 of 16 passed', + optionalAssertionsCount: 0, + requiredAssertionsCount: 16, + unexpectedBehaviorCount: 1, + unexpectedBehaviorsFormatted: '1 found', + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 0, + requiredAssertionsFailedCount: 2, + requiredAssertionsPassedCount: 14 + }, + markedFinalAt: '2022-07-06T00:00:00.000Z', + isFinal: true, + at: { + id: '1', + name: 'JAWS' + }, + browser: { + id: '2', + name: 'Chrome' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'esmeralda-baggins' + }, + testPlanReport: { + id: '3' + }, + testResults: [ + { + test: { + id: 'MThhNeyIyIjoiMjYifQmEyMj' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.074Z' }, { - id: '17', - title: 'Link Example 2 (img element with alt attribute)', - phase: 'RD', - gitSha: 'dc637636cff74b51f5c468ff3b81bd1f38aefbb2', - gitMessage: - 'Create tests for APG design pattern example: Link Example 2 (img element with alt attribute) (#516)', - updatedAt: '2023-03-13T19:51:48.000Z', - versionString: 'V23.03.13', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'link-img-alt' - }, - testPlanReports: [], - metadata: {} + test: { + id: 'NWVkNeyIyIjoiMjYifQTZkOT' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.134Z' }, { + test: { + id: 'NWM4NeyIyIjoiMjYifQDEwM2' + }, + atVersion: { id: '1', - title: 'Alert Example', - phase: 'DRAFT', - gitSha: '0928bcf530efcf4faa677285439701537674e014', - gitMessage: - 'Alert and Radiogroup/activedescendent updates (#865)', - updatedAt: '2022-12-08T21:47:42.000Z', - versionString: 'V22.12.08', - draftPhaseReachedAt: '2022-07-06T00:00:00.000Z', - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'alert' - }, - testPlanReports: [ - { - id: '7', - metrics: {}, - markedFinalAt: null, - isFinal: false, - at: { - id: '3', - name: 'VoiceOver for macOS' - }, - browser: { - id: '1', - name: 'Firefox' - }, - issues: [], - draftTestPlanRuns: [] - } - ], - metadata: {} + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.202Z' }, { - id: '13', - title: 'Disclosure Navigation Menu Example', - phase: 'RD', - gitSha: '179ba0f438aaa5781b3ec8a4033d6bf9f757360b', - gitMessage: - 'Delete up arrow command for VoiceOver when navigating backwards to a disclosure button (#845)', - updatedAt: '2022-10-31T19:29:17.000Z', - versionString: 'V22.10.31', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'disclosure-navigation' - }, - testPlanReports: [], - metadata: {} + test: { + id: 'NGFiZeyIyIjoiMjYifQWZiYW' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.268Z' }, { + test: { + id: 'MzQzYeyIyIjoiMjYifQzU5Zm' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.336Z' + } + ] + } + ] + }, + { + id: '11', + metrics: { + testsCount: 11, + supportLevel: 'FULL', + conflictsCount: 0, + supportPercent: 100, + testsFailedCount: 9, + testsPassedCount: 2, + optionalFormatted: false, + requiredFormatted: '14 of 14 passed', + optionalAssertionsCount: 0, + requiredAssertionsCount: 14, + unexpectedBehaviorCount: 0, + unexpectedBehaviorsFormatted: false, + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 0, + requiredAssertionsFailedCount: 0, + requiredAssertionsPassedCount: 14 + }, + markedFinalAt: null, + isFinal: false, + at: { + id: '3', + name: 'VoiceOver for macOS' + }, + browser: { + id: '2', + name: 'Chrome' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'esmeralda-baggins' + }, + testPlanReport: { + id: '11' + }, + testResults: [ + { + test: { + id: 'MzlmYeyIyIjoiMjYifQzIxY2' + }, + atVersion: { id: '3', - title: 'Breadcrumb Example', - phase: 'RD', - gitSha: '1aa3b74d24d340362e9f511eae33788d55487d12', - gitMessage: - 'Add down arrow command to the Navigate forwards out of the Breadcrumb navigation landmark task for JAWS (#803)', - updatedAt: '2022-08-10T18:44:16.000Z', - versionString: 'V22.08.10', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'breadcrumb' - }, - testPlanReports: [], - metadata: {} - }, - { - id: '19', - title: 'Main Landmark', - phase: 'RD', - gitSha: 'c87a66ea13a2b6fac6d79fe1fb0b7a2f721dcd22', - gitMessage: - 'Create updated tests for APG design pattern example: Main landmark (#707)', - updatedAt: '2022-08-05T17:46:37.000Z', - versionString: 'V22.08.05', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'main' - }, - testPlanReports: [], - metadata: {} - }, - { - id: '24', - title: 'Meter', - phase: 'RD', - gitSha: '32d2d9db48becfc008fc566b569ac1563576ceb9', - gitMessage: - 'Create updated tests for APG design pattern example: Meter (#692)', - updatedAt: '2022-08-05T17:02:59.000Z', - versionString: 'V22.08.05', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'meter' - }, - testPlanReports: [], - metadata: {} - }, - { - id: '32', - title: 'Switch Example', - phase: 'RD', - gitSha: '9d0e4e3d1040d64d9db69647e615c4ec0be723c2', - gitMessage: - 'Create updated tests for APG design pattern example: Switch (#691)', - updatedAt: '2022-08-05T16:13:44.000Z', - versionString: 'V22.08.05', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'switch' - }, - testPlanReports: [], - metadata: {} - }, - { - id: '22', - title: 'Navigation Menu Button', - phase: 'RD', - gitSha: 'ecf05f484292189789f4db8b1ec41b19db38e567', - gitMessage: - 'Tasks 4, 5 and 6: corrected link name "Navigate backwards from here" (#734)', - updatedAt: '2022-05-26T16:14:17.000Z', - versionString: 'V22.05.26', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'menu-button-navigation' - }, - testPlanReports: [], - metadata: {} - }, - { - id: '34', - title: 'Toggle Button', - phase: 'DRAFT', - gitSha: '022340081280b8cafb8ae0716a5b67e9ab942ef4', - gitMessage: - 'Delete duplicated assertion for operating a not pressed togle button (VoiceOver) (#716)', - updatedAt: '2022-05-18T20:51:40.000Z', - versionString: 'V22.05.18', - draftPhaseReachedAt: '2022-07-06T00:00:00.000Z', - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'toggle-button' - }, - testPlanReports: [ - { - id: '1', - metrics: { - testsCount: 16, - supportLevel: 'FAILING', - conflictsCount: 0, - supportPercent: 93, - testsFailedCount: 14, - testsPassedCount: 2, - optionalFormatted: false, - requiredFormatted: '28 of 30 passed', - optionalAssertionsCount: 0, - requiredAssertionsCount: 30, - unexpectedBehaviorCount: 1, - unexpectedBehaviorsFormatted: '1 found', - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 0, - requiredAssertionsFailedCount: 2, - requiredAssertionsPassedCount: 28 - }, - markedFinalAt: null, - isFinal: false, - at: { - id: '1', - name: 'JAWS' - }, - browser: { - id: '2', - name: 'Chrome' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'esmeralda-baggins' - }, - testPlanReport: { - id: '1' - }, - testResults: [ - { - test: { - id: 'OWY5NeyIyIjoiMzQifQTRmOD' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:07.154Z' - }, - { - test: { - id: 'NGFjMeyIyIjoiMzQifQjQxY2' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: null - }, - { - test: { - id: 'NTAwOeyIyIjoiMzQifQWI5YT' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: null - }, - { - test: { - id: 'YThjMeyIyIjoiMzQifQzIyYT' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: null - }, - { - test: { - id: 'YTgxMeyIyIjoiMzQifQzExOW' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:07.381Z' - }, - { - test: { - id: 'NGMwNeyIyIjoiMzQifQ2IwN2' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:07.464Z' - }, - { - test: { - id: 'YzQxNeyIyIjoiMzQifQjY5ND' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:07.537Z' - }, - { - test: { - id: 'MjgwNeyIyIjoiMzQifQzk3YT' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:07.610Z' - } - ] - } - ] - } - ], - metadata: {} + name: '11.6 (20G165)' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:11.532Z' }, { - id: '8', - title: 'Command Button Example', - phase: 'RD', - gitSha: '0c466eec96c8cafc9961232c85e14758c4589525', - gitMessage: - 'Fix navigation link positions in three test plans: link, command button and toggle button (#709)', - updatedAt: '2022-05-04T21:33:31.000Z', - versionString: 'V22.05.04', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'command-button' - }, - testPlanReports: [], - metadata: {} + test: { + id: 'N2FkZeyIyIjoiMjYifQDQ5NT' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:11.611Z' }, { - id: '18', - title: 'Link Example 1 (span element with text content)', - phase: 'RD', - gitSha: '0c466eec96c8cafc9961232c85e14758c4589525', - gitMessage: - 'Fix navigation link positions in three test plans: link, command button and toggle button (#709)', - updatedAt: '2022-05-04T21:33:31.000Z', - versionString: 'V22.05.04', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'link-span-text' - }, - testPlanReports: [], - metadata: {} + test: { + id: 'ZDJkYeyIyIjoiMjYifQzRkYj' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:11.696Z' + } + ] + } + ] + }, + { + id: '4', + metrics: { + testsCount: 18, + supportLevel: 'FAILING', + conflictsCount: 0, + supportPercent: 91, + testsFailedCount: 14, + testsPassedCount: 4, + optionalFormatted: false, + requiredFormatted: '20 of 22 passed', + optionalAssertionsCount: 0, + requiredAssertionsCount: 22, + unexpectedBehaviorCount: 1, + unexpectedBehaviorsFormatted: '1 found', + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 0, + requiredAssertionsFailedCount: 2, + requiredAssertionsPassedCount: 20 + }, + markedFinalAt: '2022-07-06T00:00:00.000Z', + isFinal: true, + at: { + id: '2', + name: 'NVDA' + }, + browser: { + id: '2', + name: 'Chrome' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'esmeralda-baggins' + }, + testPlanReport: { + id: '4' + }, + testResults: [ + { + test: { + id: 'MThhNeyIyIjoiMjYifQmEyMj' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.409Z' }, { - id: '15', - title: 'Color Viewer Slider', - phase: 'RD', - gitSha: '1c6ef2fbef5fc056c622c802bebedaa14f2c8d40', - gitMessage: - 'Create updated tests for APG design pattern example: Color Viewer Slider (#686)', - updatedAt: '2022-04-14T18:06:40.000Z', - versionString: 'V22.04.14', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'horizontal-slider' - }, - testPlanReports: [], - metadata: {} + test: { + id: 'NWVkNeyIyIjoiMjYifQTZkOT' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.478Z' }, { - id: '6', - title: 'Combobox with Both List and Inline Autocomplete Example', - phase: 'RD', - gitSha: '6b2cbcbdbd5f6867cd3c9e96362817c353335187', - gitMessage: "typo: double word 'the' (#595)", - updatedAt: '2022-03-29T16:02:56.000Z', - versionString: 'V22.03.29', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'combobox-autocomplete-both-updated' - }, - testPlanReports: [], - metadata: {} + test: { + id: 'NWM4NeyIyIjoiMjYifQDEwM2' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.551Z' }, { - id: '21', - title: 'Action Menu Button Example Using aria-activedescendant', - phase: 'RD', - gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', - gitMessage: - 'Generate html source script to support aria-at-app (#646)', - updatedAt: '2022-03-17T18:34:51.000Z', - versionString: 'V22.03.17', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'menu-button-actions-active-descendant' - }, - testPlanReports: [], - metadata: {} + test: { + id: 'NGFiZeyIyIjoiMjYifQWZiYW' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.629Z' }, { - id: '20', - title: 'Action Menu Button Example Using element.focus()', - phase: 'RD', - gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', - gitMessage: - 'Generate html source script to support aria-at-app (#646)', - updatedAt: '2022-03-17T18:34:51.000Z', - versionString: 'V22.03.17', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'menu-button-actions' - }, - testPlanReports: [], - metadata: {} + test: { + id: 'MzQzYeyIyIjoiMjYifQzU5Zm' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.704Z' }, { + test: { + id: 'MmI1MeyIyIjoiMjYifQmU3Yz' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { id: '2', - title: 'Banner Landmark', - phase: 'RD', - gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', - gitMessage: - 'Generate html source script to support aria-at-app (#646)', - updatedAt: '2022-03-17T18:34:51.000Z', - versionString: 'V22.03.17', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'banner' - }, - testPlanReports: [], - metadata: {} + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.777Z' }, { - id: '4', - title: 'Checkbox Example (Two State)', - phase: 'RD', - gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', - gitMessage: - 'Generate html source script to support aria-at-app (#646)', - updatedAt: '2022-03-17T18:34:51.000Z', - versionString: 'V22.03.17', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'checkbox' - }, - testPlanReports: [], - metadata: {} + test: { + id: 'YmRmYeyIyIjoiMjYifQjEyMT' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:09.852Z' + } + ] + } + ] + }, + { + id: '5', + metrics: { + testsCount: 11, + supportLevel: 'FAILING', + conflictsCount: 0, + supportPercent: 92, + testsFailedCount: 8, + testsPassedCount: 3, + optionalFormatted: false, + requiredFormatted: '23 of 25 passed', + optionalAssertionsCount: 0, + requiredAssertionsCount: 25, + unexpectedBehaviorCount: 1, + unexpectedBehaviorsFormatted: '1 found', + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 0, + requiredAssertionsFailedCount: 2, + requiredAssertionsPassedCount: 23 + }, + markedFinalAt: '2022-07-06T00:00:00.000Z', + isFinal: true, + at: { + id: '3', + name: 'VoiceOver for macOS' + }, + browser: { + id: '3', + name: 'Safari' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'esmeralda-baggins' + }, + testPlanReport: { + id: '5' + }, + testResults: [ + { + test: { + id: 'MzlmYeyIyIjoiMjYifQzIxY2' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-18T03:17:09.923Z' }, { - id: '9', - title: 'Complementary Landmark', - phase: 'RD', - gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', - gitMessage: - 'Generate html source script to support aria-at-app (#646)', - updatedAt: '2022-03-17T18:34:51.000Z', - versionString: 'V22.03.17', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'complementary' - }, - testPlanReports: [], - metadata: {} + test: { + id: 'ZDJkYeyIyIjoiMjYifQzRkYj' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-18T03:17:09.991Z' }, { - id: '10', - title: 'Contentinfo Landmark', - phase: 'RD', - gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', - gitMessage: - 'Generate html source script to support aria-at-app (#646)', - updatedAt: '2022-03-17T18:34:51.000Z', - versionString: 'V22.03.17', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'contentinfo' - }, - testPlanReports: [], - metadata: {} + test: { + id: 'ZmQyNeyIyIjoiMjYifQ2M2ND' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-18T03:17:10.059Z' }, { - id: '25', - title: 'Data Grid Example 1: Minimal Data Grid', - phase: 'RD', - gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', - gitMessage: - 'Generate html source script to support aria-at-app (#646)', - updatedAt: '2022-03-17T18:34:51.000Z', - versionString: 'V22.03.17', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'minimal-data-grid' - }, - testPlanReports: [], - metadata: {} + test: { + id: 'OGE3YeyIyIjoiMjYifQjU1ND' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-18T03:17:10.129Z' }, { - id: '11', - title: 'Date Picker Spin Button Example', - phase: 'RD', - gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', - gitMessage: - 'Generate html source script to support aria-at-app (#646)', - updatedAt: '2022-03-17T18:34:51.000Z', - versionString: 'V22.03.17', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'datepicker-spin-button' - }, - testPlanReports: [], - metadata: {} + test: { + id: 'YWI3OeyIyIjoiMjYifQWJlNW' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-18T03:17:10.198Z' }, { - id: '12', - title: 'Disclosure of Answers to Frequently Asked Questions Example', - phase: 'RD', - gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', - gitMessage: - 'Generate html source script to support aria-at-app (#646)', - updatedAt: '2022-03-17T18:34:51.000Z', - versionString: 'V22.03.17', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'disclosure-faq' - }, - testPlanReports: [], - metadata: {} + test: { + id: 'M2RiOeyIyIjoiMjYifQGY1Nj' + }, + atVersion: { + id: '3', + name: '11.6 (20G165)' + }, + browserVersion: { + id: '3', + name: '14.1.2' + }, + completedAt: '2023-08-18T03:17:10.272Z' + } + ] + } + ] + }, + { + id: '8', + metrics: { + testsCount: 18, + supportLevel: 'FULL', + conflictsCount: 0, + supportPercent: 100, + testsFailedCount: 16, + testsPassedCount: 2, + optionalFormatted: false, + requiredFormatted: '16 of 16 passed', + optionalAssertionsCount: 0, + requiredAssertionsCount: 16, + unexpectedBehaviorCount: 0, + unexpectedBehaviorsFormatted: false, + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 0, + requiredAssertionsFailedCount: 0, + requiredAssertionsPassedCount: 16 + }, + markedFinalAt: null, + isFinal: false, + at: { + id: '1', + name: 'JAWS' + }, + browser: { + id: '1', + name: 'Firefox' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'esmeralda-baggins' + }, + testPlanReport: { + id: '8' + }, + testResults: [ + { + test: { + id: 'MThhNeyIyIjoiMjYifQmEyMj' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:10.817Z' }, { - id: '23', - title: 'Editor Menubar Example', - phase: 'RD', - gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', - gitMessage: - 'Generate html source script to support aria-at-app (#646)', - updatedAt: '2022-03-17T18:34:51.000Z', - versionString: 'V22.03.17', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'menubar-editor' - }, - testPlanReports: [], - metadata: {} + test: { + id: 'ODY5MeyIyIjoiMjYifQzhmNW' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:10.894Z' }, { - id: '14', - title: 'Form Landmark', - phase: 'RD', - gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', - gitMessage: - 'Generate html source script to support aria-at-app (#646)', - updatedAt: '2022-03-17T18:34:51.000Z', - versionString: 'V22.03.17', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'form' - }, - testPlanReports: [], - metadata: {} + test: { + id: 'NWVkNeyIyIjoiMjYifQTZkOT' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:10.979Z' + } + ] + } + ] + } + ], + metadata: {} + } + } + } + }, + { + request: { + query: testPlanReportStatusDialogQuery, + variables: { testPlanVersionId: '34' } + }, + result: { + data: { + testPlanVersion: { + id: '34', + title: 'Toggle Button', + phase: 'DRAFT', + gitSha: '022340081280b8cafb8ae0716a5b67e9ab942ef4', + gitMessage: + 'Delete duplicated assertion for operating a not pressed togle button (VoiceOver) (#716)', + updatedAt: '2022-05-18T20:51:40.000Z', + draftPhaseReachedAt: '2022-07-06T00:00:00.000Z', + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'toggle-button' + }, + testPlanReports: [ + { + id: '1', + metrics: { + testsCount: 16, + supportLevel: 'FAILING', + conflictsCount: 0, + supportPercent: 93, + testsFailedCount: 14, + testsPassedCount: 2, + optionalFormatted: false, + requiredFormatted: '28 of 30 passed', + optionalAssertionsCount: 0, + requiredAssertionsCount: 30, + unexpectedBehaviorCount: 1, + unexpectedBehaviorsFormatted: '1 found', + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 0, + requiredAssertionsFailedCount: 2, + requiredAssertionsPassedCount: 28 + }, + markedFinalAt: null, + isFinal: false, + at: { + id: '1', + name: 'JAWS' + }, + browser: { + id: '2', + name: 'Chrome' + }, + issues: [], + draftTestPlanRuns: [ + { + tester: { + username: 'esmeralda-baggins' + }, + testPlanReport: { + id: '1' + }, + testResults: [ + { + test: { + id: 'OWY5NeyIyIjoiMzQifQTRmOD' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:07.154Z' }, { - id: '30', - title: 'Media Seek Slider', - phase: 'RD', - gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', - gitMessage: - 'Generate html source script to support aria-at-app (#646)', - updatedAt: '2022-03-17T18:34:51.000Z', - versionString: 'V22.03.17', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'seek-slider' - }, - testPlanReports: [], - metadata: {} + test: { + id: 'NGFjMeyIyIjoiMzQifQjQxY2' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: null }, { - id: '29', - title: 'Rating Slider', - phase: 'RD', - gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', - gitMessage: - 'Generate html source script to support aria-at-app (#646)', - updatedAt: '2022-03-17T18:34:51.000Z', - versionString: 'V22.03.17', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'rating-slider' - }, - testPlanReports: [], - metadata: {} + test: { + id: 'NTAwOeyIyIjoiMzQifQWI5YT' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: null }, { - id: '7', - title: 'Select Only Combobox Example', - phase: 'DRAFT', - gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', - gitMessage: - 'Generate html source script to support aria-at-app (#646)', - updatedAt: '2022-03-17T18:34:51.000Z', - versionString: 'V22.03.17', - draftPhaseReachedAt: '2022-07-06T00:00:00.000Z', - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'combobox-select-only' - }, - testPlanReports: [ - { - id: '2', - metrics: { - testsCount: 21, - supportLevel: 'FAILING', - conflictsCount: 5, - supportPercent: 96, - testsFailedCount: 16, - testsPassedCount: 5, - optionalFormatted: '3 of 3 passed', - requiredFormatted: '48 of 50 passed', - optionalAssertionsCount: 3, - requiredAssertionsCount: 50, - unexpectedBehaviorCount: 3, - unexpectedBehaviorsFormatted: '3 found', - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 3, - requiredAssertionsFailedCount: 2, - requiredAssertionsPassedCount: 48 - }, - markedFinalAt: null, - isFinal: false, - at: { - id: '2', - name: 'NVDA' - }, - browser: { - id: '1', - name: 'Firefox' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'tom-proudfeet' - }, - testPlanReport: { - id: '2' - }, - testResults: [ - { - test: { - id: 'Nzg5NeyIyIjoiNyJ9zNjZj' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:08.240Z' - }, - { - test: { - id: 'MmY0YeyIyIjoiNyJ9jRkZD' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:08.332Z' - }, - { - test: { - id: 'ZjUwNeyIyIjoiNyJ9mE2ZT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:08.412Z' - }, - { - test: { - id: 'MDNiMeyIyIjoiNyJ9Dk1MT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:08.501Z' - }, - { - test: { - id: 'MjRmNeyIyIjoiNyJ92MyMT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:08.593Z' - }, - { - test: { - id: 'ZmVlMeyIyIjoiNyJ9mUyYj' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: null - }, - { - test: { - id: 'YWFiNeyIyIjoiNyJ9zE2Zj' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:08.811Z' - }, - { - test: { - id: 'YjZkYeyIyIjoiNyJ9WIxZm' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:08.902Z' - }, - { - test: { - id: 'ZmIzMeyIyIjoiNyJ9TQ1NW' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:08.996Z' - } - ] - }, - { - tester: { - username: 'esmeralda-baggins' - }, - testPlanReport: { - id: '2' - }, - testResults: [ - { - test: { - id: 'Nzg5NeyIyIjoiNyJ9zNjZj' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:07.718Z' - }, - { - test: { - id: 'MmY0YeyIyIjoiNyJ9jRkZD' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:07.813Z' - }, - { - test: { - id: 'ZjUwNeyIyIjoiNyJ9mE2ZT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:07.914Z' - }, - { - test: { - id: 'MDNiMeyIyIjoiNyJ9Dk1MT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:07.988Z' - }, - { - test: { - id: 'MjRmNeyIyIjoiNyJ92MyMT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:08.074Z' - }, - { - test: { - id: 'ZmVlMeyIyIjoiNyJ9mUyYj' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: null - } - ] - } - ] - } - ], - metadata: {} + test: { + id: 'YThjMeyIyIjoiMzQifQzIyYT' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: null }, { - id: '33', - title: 'Tabs with Manual Activation', - phase: 'RD', - gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', - gitMessage: - 'Generate html source script to support aria-at-app (#646)', - updatedAt: '2022-03-17T18:34:51.000Z', - versionString: 'V22.03.17', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'tabs-manual-activation' - }, - testPlanReports: [], - metadata: {} + test: { + id: 'YTgxMeyIyIjoiMzQifQzExOW' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:07.381Z' }, { - id: '35', - title: 'Vertical Temperature Slider', - phase: 'RD', - gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', - gitMessage: - 'Generate html source script to support aria-at-app (#646)', - updatedAt: '2022-03-17T18:34:51.000Z', - versionString: 'V22.03.17', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'vertical-temperature-slider' - }, - testPlanReports: [], - metadata: {} + test: { + id: 'NGMwNeyIyIjoiMzQifQ2IwN2' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:07.464Z' }, { - id: '5', - title: 'Checkbox Example (Mixed-State)', - phase: 'RECOMMENDED', - gitSha: 'b3d0576a2901ea7f100f49a994b64edbecf81cff', - gitMessage: - 'Modify VoiceOver commands for task 7 (#842)', - updatedAt: '2022-10-24T21:33:12.000Z', - versionString: 'V22.10.24', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: '2022-07-06T00:00:00.000Z', - recommendedPhaseTargetDate: '2023-01-02T00:00:00.000Z', - recommendedPhaseReachedAt: '2023-01-03T00:00:00.000Z', - testPlan: { - directory: 'checkbox-tri-state' - }, - testPlanReports: [ - { - id: '6', - metrics: { - testsCount: 7, - supportLevel: 'FAILING', - conflictsCount: 0, - supportPercent: 96, - testsFailedCount: 3, - testsPassedCount: 4, - optionalFormatted: '4 of 4 passed', - requiredFormatted: '44 of 46 passed', - optionalAssertionsCount: 4, - requiredAssertionsCount: 46, - unexpectedBehaviorCount: 0, - unexpectedBehaviorsFormatted: false, - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 4, - requiredAssertionsFailedCount: 2, - requiredAssertionsPassedCount: 44 - }, - markedFinalAt: '2022-07-06T00:00:00.000Z', - isFinal: true, - at: { - id: '3', - name: 'VoiceOver for macOS' - }, - browser: { - id: '3', - name: 'Safari' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'tom-proudfeet' - }, - testPlanReport: { - id: '6' - }, - testResults: [ - { - test: { - id: 'YTE3NeyIyIjoiNSJ9WJlMj' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-18T03:17:10.341Z' - }, - { - test: { - id: 'YWJiOeyIyIjoiNSJ9GQ5Zm' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-18T03:17:10.405Z' - }, - { - test: { - id: 'ZGFlYeyIyIjoiNSJ9TJlMW' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-18T03:17:10.474Z' - }, - { - test: { - id: 'YjI2MeyIyIjoiNSJ9WE1OT' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-18T03:17:10.537Z' - }, - { - test: { - id: 'ZjAwZeyIyIjoiNSJ9TZmZj' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-18T03:17:10.605Z' - }, - { - test: { - id: 'MGRjZeyIyIjoiNSJ9WNiZD' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-18T03:17:10.670Z' - }, - { - test: { - id: 'OTZmYeyIyIjoiNSJ9TU5Ym' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-18T03:17:10.739Z' - } - ] - } - ] - }, - { - id: '12', - metrics: { - testsCount: 14, - supportLevel: 'FULL', - conflictsCount: 0, - supportPercent: 100, - testsFailedCount: 12, - testsPassedCount: 2, - optionalFormatted: false, - requiredFormatted: '25 of 25 passed', - optionalAssertionsCount: 0, - requiredAssertionsCount: 25, - unexpectedBehaviorCount: 0, - unexpectedBehaviorsFormatted: false, - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 0, - requiredAssertionsFailedCount: 0, - requiredAssertionsPassedCount: 25 - }, - markedFinalAt: null, - isFinal: false, - at: { - id: '1', - name: 'JAWS' - }, - browser: { - id: '2', - name: 'Chrome' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'esmeralda-baggins' - }, - testPlanReport: { - id: '12' - }, - testResults: [ - { - test: { - id: 'MTVlZeyIyIjoiNSJ9DUzMz' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:11.764Z' - }, - { - test: { - id: 'OThhMeyIyIjoiNSJ9WMxM2' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:11.828Z' - }, - { - test: { - id: 'YWNhNeyIyIjoiNSJ9TliN2' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:11.892Z' - } - ] - } - ] - }, - { - id: '13', - metrics: { - testsCount: 14, - supportLevel: 'FULL', - conflictsCount: 0, - supportPercent: 100, - testsFailedCount: 12, - testsPassedCount: 2, - optionalFormatted: false, - requiredFormatted: '25 of 25 passed', - optionalAssertionsCount: 0, - requiredAssertionsCount: 25, - unexpectedBehaviorCount: 0, - unexpectedBehaviorsFormatted: false, - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 0, - requiredAssertionsFailedCount: 0, - requiredAssertionsPassedCount: 25 - }, - markedFinalAt: null, - isFinal: false, - at: { - id: '2', - name: 'NVDA' - }, - browser: { - id: '2', - name: 'Chrome' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'esmeralda-baggins' - }, - testPlanReport: { - id: '13' - }, - testResults: [ - { - test: { - id: 'MTVlZeyIyIjoiNSJ9DUzMz' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:11.955Z' - }, - { - test: { - id: 'OThhMeyIyIjoiNSJ9WMxM2' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:12.017Z' - }, - { - test: { - id: 'YWNhNeyIyIjoiNSJ9TliN2' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:12.083Z' - } - ] - } - ] - } - ], - metadata: {} + test: { + id: 'YzQxNeyIyIjoiMzQifQjY5ND' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:07.537Z' }, { - id: '26', - title: 'Modal Dialog Example', - phase: 'CANDIDATE', - gitSha: 'd0e16b42179de6f6c070da2310e99de837c71215', - gitMessage: - 'Delete down arrow command for navigating to the beginning of a dialog with JAWS and add the ESC command to exit forms or focus mode (#759)', - updatedAt: '2022-06-22T17:56:16.000Z', - versionString: 'V22.06.22', - draftPhaseReachedAt: '2022-07-06T00:00:00.000Z', - candidatePhaseReachedAt: '2022-07-06T00:00:00.000Z', - recommendedPhaseTargetDate: '2023-01-02T00:00:00.000Z', - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'modal-dialog' - }, - testPlanReports: [ - { - id: '10', - metrics: { - testsCount: 11, - supportLevel: 'FULL', - conflictsCount: 0, - supportPercent: 100, - testsFailedCount: 9, - testsPassedCount: 2, - optionalFormatted: false, - requiredFormatted: '14 of 14 passed', - optionalAssertionsCount: 0, - requiredAssertionsCount: 14, - unexpectedBehaviorCount: 0, - unexpectedBehaviorsFormatted: false, - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 0, - requiredAssertionsFailedCount: 0, - requiredAssertionsPassedCount: 14 - }, - markedFinalAt: null, - isFinal: false, - at: { - id: '3', - name: 'VoiceOver for macOS' - }, - browser: { - id: '1', - name: 'Firefox' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'esmeralda-baggins' - }, - testPlanReport: { - id: '10' - }, - testResults: [ - { - test: { - id: 'MzlmYeyIyIjoiMjYifQzIxY2' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:11.295Z' - }, - { - test: { - id: 'N2FkZeyIyIjoiMjYifQDQ5NT' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:11.369Z' - }, - { - test: { - id: 'ZDJkYeyIyIjoiMjYifQzRkYj' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:11.450Z' - } - ] - } - ] - }, - { - id: '9', - metrics: { - testsCount: 18, - supportLevel: 'FULL', - conflictsCount: 0, - supportPercent: 100, - testsFailedCount: 16, - testsPassedCount: 2, - optionalFormatted: false, - requiredFormatted: '16 of 16 passed', - optionalAssertionsCount: 0, - requiredAssertionsCount: 16, - unexpectedBehaviorCount: 0, - unexpectedBehaviorsFormatted: false, - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 0, - requiredAssertionsFailedCount: 0, - requiredAssertionsPassedCount: 16 - }, - markedFinalAt: null, - isFinal: false, - at: { - id: '2', - name: 'NVDA' - }, - browser: { - id: '1', - name: 'Firefox' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'esmeralda-baggins' - }, - testPlanReport: { - id: '9' - }, - testResults: [ - { - test: { - id: 'MThhNeyIyIjoiMjYifQmEyMj' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:11.059Z' - }, - { - test: { - id: 'ODY5MeyIyIjoiMjYifQzhmNW' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:11.137Z' - }, - { - test: { - id: 'NWVkNeyIyIjoiMjYifQTZkOT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:11.218Z' - } - ] - } - ] - }, - { - id: '3', - metrics: { - testsCount: 18, - supportLevel: 'FAILING', - conflictsCount: 0, - supportPercent: 88, - testsFailedCount: 16, - testsPassedCount: 2, - optionalFormatted: false, - requiredFormatted: '14 of 16 passed', - optionalAssertionsCount: 0, - requiredAssertionsCount: 16, - unexpectedBehaviorCount: 1, - unexpectedBehaviorsFormatted: '1 found', - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 0, - requiredAssertionsFailedCount: 2, - requiredAssertionsPassedCount: 14 - }, - markedFinalAt: '2022-07-06T00:00:00.000Z', - isFinal: true, - at: { - id: '1', - name: 'JAWS' - }, - browser: { - id: '2', - name: 'Chrome' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'esmeralda-baggins' - }, - testPlanReport: { - id: '3' - }, - testResults: [ - { - test: { - id: 'MThhNeyIyIjoiMjYifQmEyMj' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.074Z' - }, - { - test: { - id: 'NWVkNeyIyIjoiMjYifQTZkOT' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.134Z' - }, - { - test: { - id: 'NWM4NeyIyIjoiMjYifQDEwM2' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.202Z' - }, - { - test: { - id: 'NGFiZeyIyIjoiMjYifQWZiYW' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.268Z' - }, - { - test: { - id: 'MzQzYeyIyIjoiMjYifQzU5Zm' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.336Z' - } - ] - } - ] - }, - { - id: '11', - metrics: { - testsCount: 11, - supportLevel: 'FULL', - conflictsCount: 0, - supportPercent: 100, - testsFailedCount: 9, - testsPassedCount: 2, - optionalFormatted: false, - requiredFormatted: '14 of 14 passed', - optionalAssertionsCount: 0, - requiredAssertionsCount: 14, - unexpectedBehaviorCount: 0, - unexpectedBehaviorsFormatted: false, - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 0, - requiredAssertionsFailedCount: 0, - requiredAssertionsPassedCount: 14 - }, - markedFinalAt: null, - isFinal: false, - at: { - id: '3', - name: 'VoiceOver for macOS' - }, - browser: { - id: '2', - name: 'Chrome' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'esmeralda-baggins' - }, - testPlanReport: { - id: '11' - }, - testResults: [ - { - test: { - id: 'MzlmYeyIyIjoiMjYifQzIxY2' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:11.532Z' - }, - { - test: { - id: 'N2FkZeyIyIjoiMjYifQDQ5NT' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:11.611Z' - }, - { - test: { - id: 'ZDJkYeyIyIjoiMjYifQzRkYj' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:11.696Z' - } - ] - } - ] - }, - { - id: '4', - metrics: { - testsCount: 18, - supportLevel: 'FAILING', - conflictsCount: 0, - supportPercent: 91, - testsFailedCount: 14, - testsPassedCount: 4, - optionalFormatted: false, - requiredFormatted: '20 of 22 passed', - optionalAssertionsCount: 0, - requiredAssertionsCount: 22, - unexpectedBehaviorCount: 1, - unexpectedBehaviorsFormatted: '1 found', - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 0, - requiredAssertionsFailedCount: 2, - requiredAssertionsPassedCount: 20 - }, - markedFinalAt: '2022-07-06T00:00:00.000Z', - isFinal: true, - at: { - id: '2', - name: 'NVDA' - }, - browser: { - id: '2', - name: 'Chrome' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'esmeralda-baggins' - }, - testPlanReport: { - id: '4' - }, - testResults: [ - { - test: { - id: 'MThhNeyIyIjoiMjYifQmEyMj' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.409Z' - }, - { - test: { - id: 'NWVkNeyIyIjoiMjYifQTZkOT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.478Z' - }, - { - test: { - id: 'NWM4NeyIyIjoiMjYifQDEwM2' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.551Z' - }, - { - test: { - id: 'NGFiZeyIyIjoiMjYifQWZiYW' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.629Z' - }, - { - test: { - id: 'MzQzYeyIyIjoiMjYifQzU5Zm' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.704Z' - }, - { - test: { - id: 'MmI1MeyIyIjoiMjYifQmU3Yz' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.777Z' - }, - { - test: { - id: 'YmRmYeyIyIjoiMjYifQjEyMT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.852Z' - } - ] - } - ] - }, - { - id: '5', - metrics: { - testsCount: 11, - supportLevel: 'FAILING', - conflictsCount: 0, - supportPercent: 92, - testsFailedCount: 8, - testsPassedCount: 3, - optionalFormatted: false, - requiredFormatted: '23 of 25 passed', - optionalAssertionsCount: 0, - requiredAssertionsCount: 25, - unexpectedBehaviorCount: 1, - unexpectedBehaviorsFormatted: '1 found', - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 0, - requiredAssertionsFailedCount: 2, - requiredAssertionsPassedCount: 23 - }, - markedFinalAt: '2022-07-06T00:00:00.000Z', - isFinal: true, - at: { - id: '3', - name: 'VoiceOver for macOS' - }, - browser: { - id: '3', - name: 'Safari' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'esmeralda-baggins' - }, - testPlanReport: { - id: '5' - }, - testResults: [ - { - test: { - id: 'MzlmYeyIyIjoiMjYifQzIxY2' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-18T03:17:09.923Z' - }, - { - test: { - id: 'ZDJkYeyIyIjoiMjYifQzRkYj' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-18T03:17:09.991Z' - }, - { - test: { - id: 'ZmQyNeyIyIjoiMjYifQ2M2ND' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-18T03:17:10.059Z' - }, - { - test: { - id: 'OGE3YeyIyIjoiMjYifQjU1ND' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-18T03:17:10.129Z' - }, - { - test: { - id: 'YWI3OeyIyIjoiMjYifQWJlNW' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-18T03:17:10.198Z' - }, - { - test: { - id: 'M2RiOeyIyIjoiMjYifQGY1Nj' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-18T03:17:10.272Z' - } - ] - } - ] - }, - { - id: '8', - metrics: { - testsCount: 18, - supportLevel: 'FULL', - conflictsCount: 0, - supportPercent: 100, - testsFailedCount: 16, - testsPassedCount: 2, - optionalFormatted: false, - requiredFormatted: '16 of 16 passed', - optionalAssertionsCount: 0, - requiredAssertionsCount: 16, - unexpectedBehaviorCount: 0, - unexpectedBehaviorsFormatted: false, - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 0, - requiredAssertionsFailedCount: 0, - requiredAssertionsPassedCount: 16 - }, - markedFinalAt: null, - isFinal: false, - at: { - id: '1', - name: 'JAWS' - }, - browser: { - id: '1', - name: 'Firefox' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'esmeralda-baggins' - }, - testPlanReport: { - id: '8' - }, - testResults: [ - { - test: { - id: 'MThhNeyIyIjoiMjYifQmEyMj' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:10.817Z' - }, - { - test: { - id: 'ODY5MeyIyIjoiMjYifQzhmNW' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:10.894Z' - }, - { - test: { - id: 'NWVkNeyIyIjoiMjYifQTZkOT' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:10.979Z' - } - ] - } - ] - } - ], - metadata: {} + test: { + id: 'MjgwNeyIyIjoiMzQifQzk3YT' + }, + atVersion: { + id: '1', + name: '2021.2111.13' + }, + browserVersion: { + id: '2', + name: '99.0.4844.84' + }, + completedAt: '2023-08-18T03:17:07.610Z' } - ] - } - } - }, - { - request: { - query: testPlanReportStatusDialogQuery, - variables: { testPlanVersionId: '1' } - }, - result: { - data: { - testPlanVersion: { - id: '1', - title: 'Alert Example', - phase: 'DRAFT', - gitSha: '0928bcf530efcf4faa677285439701537674e014', - gitMessage: - 'Alert and Radiogroup/activedescendent updates (#865)', - updatedAt: '2022-12-08T21:47:42.000Z', - versionString: 'V22.12.08', - draftPhaseReachedAt: '2022-07-06T00:00:00.000Z', - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'alert' - }, - testPlanReports: [ - { - id: '7', - metrics: {}, - markedFinalAt: null, - isFinal: false, - at: { - id: '3', - name: 'VoiceOver for macOS' - }, - browser: { - id: '1', - name: 'Firefox' - }, - issues: [], - draftTestPlanRuns: [] - } - ], - metadata: {} - } - } - } - }, - { - request: { - query: testPlanReportStatusDialogQuery, - variables: { testPlanVersionId: '5' } - }, - result: { - data: { - testPlanVersion: { - id: '5', - title: 'Checkbox Example (Mixed-State)', - phase: 'RECOMMENDED', - gitSha: '836fb2a997f5b2844035b8c934f8fda9833cd5b2', - gitMessage: 'Validation for test csv formats (#980)', - updatedAt: '2023-08-23T20:30:34.000Z', - draftPhaseReachedAt: null, - candidatePhaseReachedAt: '2022-07-06T00:00:00.000Z', - recommendedPhaseTargetDate: '2023-01-02T00:00:00.000Z', - recommendedPhaseReachedAt: '2023-01-03T00:00:00.000Z', - testPlan: { - directory: 'checkbox-tri-state' - }, - testPlanReports: [ - { - id: '6', - metrics: { - testsCount: 7, - supportLevel: 'FAILING', - conflictsCount: 0, - supportPercent: 96, - testsFailedCount: 3, - testsPassedCount: 4, - optionalFormatted: '4 of 4 passed', - requiredFormatted: '44 of 46 passed', - optionalAssertionsCount: 4, - requiredAssertionsCount: 46, - unexpectedBehaviorCount: 0, - unexpectedBehaviorsFormatted: false, - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 4, - requiredAssertionsFailedCount: 2, - requiredAssertionsPassedCount: 44 - }, - markedFinalAt: '2022-07-06T00:00:00.000Z', - isFinal: true, - at: { - id: '3', - name: 'VoiceOver for macOS' - }, - browser: { - id: '3', - name: 'Safari' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'tom-proudfeet' - }, - testPlanReport: { - id: '6' - }, - testResults: [ - { - test: { - id: 'YTE3NeyIyIjoiNSJ9WJlMj' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-30T13:23:57.070Z' - }, - { - test: { - id: 'YWJiOeyIyIjoiNSJ9GQ5Zm' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-30T13:23:57.142Z' - }, - { - test: { - id: 'ZGFlYeyIyIjoiNSJ9TJlMW' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-30T13:23:57.204Z' - }, - { - test: { - id: 'YjI2MeyIyIjoiNSJ9WE1OT' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-30T13:23:57.275Z' - }, - { - test: { - id: 'ZjAwZeyIyIjoiNSJ9TZmZj' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-30T13:23:57.330Z' - }, - { - test: { - id: 'MGRjZeyIyIjoiNSJ9WNiZD' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-30T13:23:57.382Z' - }, - { - test: { - id: 'OTZmYeyIyIjoiNSJ9TU5Ym' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-30T13:23:57.439Z' - } - ] - } - ] - }, - { - id: '12', - metrics: { - testsCount: 14, - supportLevel: 'FULL', - conflictsCount: 0, - supportPercent: 100, - testsFailedCount: 12, - testsPassedCount: 2, - optionalFormatted: false, - requiredFormatted: '25 of 25 passed', - optionalAssertionsCount: 0, - requiredAssertionsCount: 25, - unexpectedBehaviorCount: 0, - unexpectedBehaviorsFormatted: false, - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 0, - requiredAssertionsFailedCount: 0, - requiredAssertionsPassedCount: 25 - }, - markedFinalAt: '2022-07-06T00:00:00.000Z', - isFinal: true, - at: { - id: '1', - name: 'JAWS' - }, - browser: { - id: '2', - name: 'Chrome' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'esmeralda-baggins' - }, - testPlanReport: { - id: '12' - }, - testResults: [ - { - test: { - id: 'MTVlZeyIyIjoiNSJ9DUzMz' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-30T13:23:58.343Z' - }, - { - test: { - id: 'OThhMeyIyIjoiNSJ9WMxM2' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-30T13:23:58.404Z' - }, - { - test: { - id: 'YWNhNeyIyIjoiNSJ9TliN2' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-30T13:23:58.472Z' - } - ] - } - ] - }, - { - id: '13', - metrics: { - testsCount: 14, - supportLevel: 'FULL', - conflictsCount: 0, - supportPercent: 100, - testsFailedCount: 12, - testsPassedCount: 2, - optionalFormatted: false, - requiredFormatted: '25 of 25 passed', - optionalAssertionsCount: 0, - requiredAssertionsCount: 25, - unexpectedBehaviorCount: 0, - unexpectedBehaviorsFormatted: false, - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 0, - requiredAssertionsFailedCount: 0, - requiredAssertionsPassedCount: 25 - }, - markedFinalAt: '2022-07-07T00:00:00.000Z', - isFinal: true, - at: { - id: '2', - name: 'NVDA' - }, - browser: { - id: '2', - name: 'Chrome' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'esmeralda-baggins' - }, - testPlanReport: { - id: '13' - }, - testResults: [ - { - test: { - id: 'MTVlZeyIyIjoiNSJ9DUzMz' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-30T13:23:58.531Z' - }, - { - test: { - id: 'OThhMeyIyIjoiNSJ9WMxM2' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-30T13:23:58.593Z' - }, - { - test: { - id: 'YWNhNeyIyIjoiNSJ9TliN2' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-30T13:23:58.655Z' - } - ] - } - ] - } - ], - metadata: {} - } - } - } - }, - { - request: { - query: testPlanReportStatusDialogQuery, - variables: { testPlanVersionId: '7' } - }, - result: { - data: { - testPlanVersion: { - id: '7', - title: 'Select Only Combobox Example', - phase: 'DRAFT', - gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', - gitMessage: - 'Generate html source script to support aria-at-app (#646)', - updatedAt: '2022-03-17T18:34:51.000Z', - draftPhaseReachedAt: '2022-07-06T00:00:00.000Z', - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'combobox-select-only' - }, - testPlanReports: [ - { - id: '2', - metrics: { - testsCount: 21, - supportLevel: 'FAILING', - conflictsCount: 5, - supportPercent: 96, - testsFailedCount: 16, - testsPassedCount: 5, - optionalFormatted: '3 of 3 passed', - requiredFormatted: '48 of 50 passed', - optionalAssertionsCount: 3, - requiredAssertionsCount: 50, - unexpectedBehaviorCount: 3, - unexpectedBehaviorsFormatted: '3 found', - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 3, - requiredAssertionsFailedCount: 2, - requiredAssertionsPassedCount: 48 - }, - markedFinalAt: null, - isFinal: false, - at: { - id: '2', - name: 'NVDA' - }, - browser: { - id: '1', - name: 'Firefox' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'tom-proudfeet' - }, - testPlanReport: { - id: '2' - }, - testResults: [ - { - test: { - id: 'Nzg5NeyIyIjoiNyJ9zNjZj' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:08.240Z' - }, - { - test: { - id: 'MmY0YeyIyIjoiNyJ9jRkZD' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:08.332Z' - }, - { - test: { - id: 'ZjUwNeyIyIjoiNyJ9mE2ZT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:08.412Z' - }, - { - test: { - id: 'MDNiMeyIyIjoiNyJ9Dk1MT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:08.501Z' - }, - { - test: { - id: 'MjRmNeyIyIjoiNyJ92MyMT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:08.593Z' - }, - { - test: { - id: 'ZmVlMeyIyIjoiNyJ9mUyYj' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: null - }, - { - test: { - id: 'YWFiNeyIyIjoiNyJ9zE2Zj' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:08.811Z' - }, - { - test: { - id: 'YjZkYeyIyIjoiNyJ9WIxZm' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:08.902Z' - }, - { - test: { - id: 'ZmIzMeyIyIjoiNyJ9TQ1NW' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:08.996Z' - } - ] - }, - { - tester: { - username: 'esmeralda-baggins' - }, - testPlanReport: { - id: '2' - }, - testResults: [ - { - test: { - id: 'Nzg5NeyIyIjoiNyJ9zNjZj' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:07.718Z' - }, - { - test: { - id: 'MmY0YeyIyIjoiNyJ9jRkZD' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:07.813Z' - }, - { - test: { - id: 'ZjUwNeyIyIjoiNyJ9mE2ZT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:07.914Z' - }, - { - test: { - id: 'MDNiMeyIyIjoiNyJ9Dk1MT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:07.988Z' - }, - { - test: { - id: 'MjRmNeyIyIjoiNyJ92MyMT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:08.074Z' - }, - { - test: { - id: 'ZmVlMeyIyIjoiNyJ9mUyYj' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: null - } - ] - } - ] - } - ], - metadata: {} - } - } - } - }, - { - request: { - query: testPlanReportStatusDialogQuery, - variables: { testPlanVersionId: '26' } - }, - result: { - data: { - testPlanVersion: { - id: '26', - title: 'Modal Dialog Example', - phase: 'CANDIDATE', - gitSha: 'd0e16b42179de6f6c070da2310e99de837c71215', - gitMessage: - 'Delete down arrow command for navigating to the beginning of a dialog with JAWS and add the ESC command to exit forms or focus mode (#759)', - updatedAt: '2022-06-22T17:56:16.000Z', - draftPhaseReachedAt: '2022-07-06T00:00:00.000Z', - candidatePhaseReachedAt: '2022-07-06T00:00:00.000Z', - recommendedPhaseTargetDate: '2023-01-02T00:00:00.000Z', - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'modal-dialog' - }, - testPlanReports: [ - { - id: '10', - metrics: { - testsCount: 11, - supportLevel: 'FULL', - conflictsCount: 0, - supportPercent: 100, - testsFailedCount: 9, - testsPassedCount: 2, - optionalFormatted: false, - requiredFormatted: '14 of 14 passed', - optionalAssertionsCount: 0, - requiredAssertionsCount: 14, - unexpectedBehaviorCount: 0, - unexpectedBehaviorsFormatted: false, - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 0, - requiredAssertionsFailedCount: 0, - requiredAssertionsPassedCount: 14 - }, - markedFinalAt: null, - isFinal: false, - at: { - id: '3', - name: 'VoiceOver for macOS' - }, - browser: { - id: '1', - name: 'Firefox' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'esmeralda-baggins' - }, - testPlanReport: { - id: '10' - }, - testResults: [ - { - test: { - id: 'MzlmYeyIyIjoiMjYifQzIxY2' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:11.295Z' - }, - { - test: { - id: 'N2FkZeyIyIjoiMjYifQDQ5NT' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:11.369Z' - }, - { - test: { - id: 'ZDJkYeyIyIjoiMjYifQzRkYj' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:11.450Z' - } - ] - } - ] - }, - { - id: '9', - metrics: { - testsCount: 18, - supportLevel: 'FULL', - conflictsCount: 0, - supportPercent: 100, - testsFailedCount: 16, - testsPassedCount: 2, - optionalFormatted: false, - requiredFormatted: '16 of 16 passed', - optionalAssertionsCount: 0, - requiredAssertionsCount: 16, - unexpectedBehaviorCount: 0, - unexpectedBehaviorsFormatted: false, - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 0, - requiredAssertionsFailedCount: 0, - requiredAssertionsPassedCount: 16 - }, - markedFinalAt: null, - isFinal: false, - at: { - id: '2', - name: 'NVDA' - }, - browser: { - id: '1', - name: 'Firefox' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'esmeralda-baggins' - }, - testPlanReport: { - id: '9' - }, - testResults: [ - { - test: { - id: 'MThhNeyIyIjoiMjYifQmEyMj' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:11.059Z' - }, - { - test: { - id: 'ODY5MeyIyIjoiMjYifQzhmNW' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:11.137Z' - }, - { - test: { - id: 'NWVkNeyIyIjoiMjYifQTZkOT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:11.218Z' - } - ] - } - ] - }, - { - id: '3', - metrics: { - testsCount: 18, - supportLevel: 'FAILING', - conflictsCount: 0, - supportPercent: 88, - testsFailedCount: 16, - testsPassedCount: 2, - optionalFormatted: false, - requiredFormatted: '14 of 16 passed', - optionalAssertionsCount: 0, - requiredAssertionsCount: 16, - unexpectedBehaviorCount: 1, - unexpectedBehaviorsFormatted: '1 found', - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 0, - requiredAssertionsFailedCount: 2, - requiredAssertionsPassedCount: 14 - }, - markedFinalAt: '2022-07-06T00:00:00.000Z', - isFinal: true, - at: { - id: '1', - name: 'JAWS' - }, - browser: { - id: '2', - name: 'Chrome' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'esmeralda-baggins' - }, - testPlanReport: { - id: '3' - }, - testResults: [ - { - test: { - id: 'MThhNeyIyIjoiMjYifQmEyMj' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.074Z' - }, - { - test: { - id: 'NWVkNeyIyIjoiMjYifQTZkOT' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.134Z' - }, - { - test: { - id: 'NWM4NeyIyIjoiMjYifQDEwM2' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.202Z' - }, - { - test: { - id: 'NGFiZeyIyIjoiMjYifQWZiYW' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.268Z' - }, - { - test: { - id: 'MzQzYeyIyIjoiMjYifQzU5Zm' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.336Z' - } - ] - } - ] - }, - { - id: '11', - metrics: { - testsCount: 11, - supportLevel: 'FULL', - conflictsCount: 0, - supportPercent: 100, - testsFailedCount: 9, - testsPassedCount: 2, - optionalFormatted: false, - requiredFormatted: '14 of 14 passed', - optionalAssertionsCount: 0, - requiredAssertionsCount: 14, - unexpectedBehaviorCount: 0, - unexpectedBehaviorsFormatted: false, - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 0, - requiredAssertionsFailedCount: 0, - requiredAssertionsPassedCount: 14 - }, - markedFinalAt: null, - isFinal: false, - at: { - id: '3', - name: 'VoiceOver for macOS' - }, - browser: { - id: '2', - name: 'Chrome' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'esmeralda-baggins' - }, - testPlanReport: { - id: '11' - }, - testResults: [ - { - test: { - id: 'MzlmYeyIyIjoiMjYifQzIxY2' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:11.532Z' - }, - { - test: { - id: 'N2FkZeyIyIjoiMjYifQDQ5NT' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:11.611Z' - }, - { - test: { - id: 'ZDJkYeyIyIjoiMjYifQzRkYj' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:11.696Z' - } - ] - } - ] - }, - { - id: '4', - metrics: { - testsCount: 18, - supportLevel: 'FAILING', - conflictsCount: 0, - supportPercent: 91, - testsFailedCount: 14, - testsPassedCount: 4, - optionalFormatted: false, - requiredFormatted: '20 of 22 passed', - optionalAssertionsCount: 0, - requiredAssertionsCount: 22, - unexpectedBehaviorCount: 1, - unexpectedBehaviorsFormatted: '1 found', - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 0, - requiredAssertionsFailedCount: 2, - requiredAssertionsPassedCount: 20 - }, - markedFinalAt: '2022-07-06T00:00:00.000Z', - isFinal: true, - at: { - id: '2', - name: 'NVDA' - }, - browser: { - id: '2', - name: 'Chrome' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'esmeralda-baggins' - }, - testPlanReport: { - id: '4' - }, - testResults: [ - { - test: { - id: 'MThhNeyIyIjoiMjYifQmEyMj' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.409Z' - }, - { - test: { - id: 'NWVkNeyIyIjoiMjYifQTZkOT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.478Z' - }, - { - test: { - id: 'NWM4NeyIyIjoiMjYifQDEwM2' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.551Z' - }, - { - test: { - id: 'NGFiZeyIyIjoiMjYifQWZiYW' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.629Z' - }, - { - test: { - id: 'MzQzYeyIyIjoiMjYifQzU5Zm' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.704Z' - }, - { - test: { - id: 'MmI1MeyIyIjoiMjYifQmU3Yz' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.777Z' - }, - { - test: { - id: 'YmRmYeyIyIjoiMjYifQjEyMT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:09.852Z' - } - ] - } - ] - }, - { - id: '5', - metrics: { - testsCount: 11, - supportLevel: 'FAILING', - conflictsCount: 0, - supportPercent: 92, - testsFailedCount: 8, - testsPassedCount: 3, - optionalFormatted: false, - requiredFormatted: '23 of 25 passed', - optionalAssertionsCount: 0, - requiredAssertionsCount: 25, - unexpectedBehaviorCount: 1, - unexpectedBehaviorsFormatted: '1 found', - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 0, - requiredAssertionsFailedCount: 2, - requiredAssertionsPassedCount: 23 - }, - markedFinalAt: '2022-07-06T00:00:00.000Z', - isFinal: true, - at: { - id: '3', - name: 'VoiceOver for macOS' - }, - browser: { - id: '3', - name: 'Safari' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'esmeralda-baggins' - }, - testPlanReport: { - id: '5' - }, - testResults: [ - { - test: { - id: 'MzlmYeyIyIjoiMjYifQzIxY2' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-18T03:17:09.923Z' - }, - { - test: { - id: 'ZDJkYeyIyIjoiMjYifQzRkYj' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-18T03:17:09.991Z' - }, - { - test: { - id: 'ZmQyNeyIyIjoiMjYifQ2M2ND' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-18T03:17:10.059Z' - }, - { - test: { - id: 'OGE3YeyIyIjoiMjYifQjU1ND' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-18T03:17:10.129Z' - }, - { - test: { - id: 'YWI3OeyIyIjoiMjYifQWJlNW' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-18T03:17:10.198Z' - }, - { - test: { - id: 'M2RiOeyIyIjoiMjYifQGY1Nj' - }, - atVersion: { - id: '3', - name: '11.6 (20G165)' - }, - browserVersion: { - id: '3', - name: '14.1.2' - }, - completedAt: - '2023-08-18T03:17:10.272Z' - } - ] - } - ] - }, - { - id: '8', - metrics: { - testsCount: 18, - supportLevel: 'FULL', - conflictsCount: 0, - supportPercent: 100, - testsFailedCount: 16, - testsPassedCount: 2, - optionalFormatted: false, - requiredFormatted: '16 of 16 passed', - optionalAssertionsCount: 0, - requiredAssertionsCount: 16, - unexpectedBehaviorCount: 0, - unexpectedBehaviorsFormatted: false, - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 0, - requiredAssertionsFailedCount: 0, - requiredAssertionsPassedCount: 16 - }, - markedFinalAt: null, - isFinal: false, - at: { - id: '1', - name: 'JAWS' - }, - browser: { - id: '1', - name: 'Firefox' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'esmeralda-baggins' - }, - testPlanReport: { - id: '8' - }, - testResults: [ - { - test: { - id: 'MThhNeyIyIjoiMjYifQmEyMj' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:10.817Z' - }, - { - test: { - id: 'ODY5MeyIyIjoiMjYifQzhmNW' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:10.894Z' - }, - { - test: { - id: 'NWVkNeyIyIjoiMjYifQTZkOT' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: - '2023-08-18T03:17:10.979Z' - } - ] - } - ] - } - ], - metadata: {} - } - } - } - }, - { - request: { - query: testPlanReportStatusDialogQuery, - variables: { testPlanVersionId: '34' } - }, - result: { - data: { - testPlanVersion: { - id: '34', - title: 'Toggle Button', - phase: 'DRAFT', - gitSha: '022340081280b8cafb8ae0716a5b67e9ab942ef4', - gitMessage: - 'Delete duplicated assertion for operating a not pressed togle button (VoiceOver) (#716)', - updatedAt: '2022-05-18T20:51:40.000Z', - draftPhaseReachedAt: '2022-07-06T00:00:00.000Z', - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'toggle-button' - }, - testPlanReports: [ - { - id: '1', - metrics: { - testsCount: 16, - supportLevel: 'FAILING', - conflictsCount: 0, - supportPercent: 93, - testsFailedCount: 14, - testsPassedCount: 2, - optionalFormatted: false, - requiredFormatted: '28 of 30 passed', - optionalAssertionsCount: 0, - requiredAssertionsCount: 30, - unexpectedBehaviorCount: 1, - unexpectedBehaviorsFormatted: '1 found', - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 0, - requiredAssertionsFailedCount: 2, - requiredAssertionsPassedCount: 28 - }, - markedFinalAt: null, - isFinal: false, - at: { - id: '1', - name: 'JAWS' - }, - browser: { - id: '2', - name: 'Chrome' - }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'esmeralda-baggins' - }, - testPlanReport: { - id: '1' - }, - testResults: [ - { - test: { - id: 'OWY5NeyIyIjoiMzQifQTRmOD' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:07.154Z' - }, - { - test: { - id: 'NGFjMeyIyIjoiMzQifQjQxY2' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: null - }, - { - test: { - id: 'NTAwOeyIyIjoiMzQifQWI5YT' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: null - }, - { - test: { - id: 'YThjMeyIyIjoiMzQifQzIyYT' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: null - }, - { - test: { - id: 'YTgxMeyIyIjoiMzQifQzExOW' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:07.381Z' - }, - { - test: { - id: 'NGMwNeyIyIjoiMzQifQ2IwN2' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:07.464Z' - }, - { - test: { - id: 'YzQxNeyIyIjoiMzQifQjY5ND' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:07.537Z' - }, - { - test: { - id: 'MjgwNeyIyIjoiMzQifQzk3YT' - }, - atVersion: { - id: '1', - name: '2021.2111.13' - }, - browserVersion: { - id: '2', - name: '99.0.4844.84' - }, - completedAt: - '2023-08-18T03:17:07.610Z' - } - ] - } - ] - } - ], - metadata: {} + ] } + ] } + ], + metadata: {} } + } } + } ]; diff --git a/client/tests/__mocks__/GraphQLMocks/TestPlanReportStatusDialogMock.js b/client/tests/__mocks__/GraphQLMocks/TestPlanReportStatusDialogMock.js index f1371705e..e64c9f9a5 100644 --- a/client/tests/__mocks__/GraphQLMocks/TestPlanReportStatusDialogMock.js +++ b/client/tests/__mocks__/GraphQLMocks/TestPlanReportStatusDialogMock.js @@ -1,418 +1,418 @@ export const mockedTestPlanVersion = { - id: '7', - title: 'Select Only Combobox Example', - phase: 'DRAFT', - gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', - gitMessage: 'Generate html source script to support aria-at-app (#646)', - updatedAt: '2022-03-17T18:34:51.000Z', - draftPhaseReachedAt: '2022-07-06T00:00:00.000Z', - candidatePhaseReachedAt: null, - recommendedPhaseTargetDate: null, - recommendedPhaseReachedAt: null, - testPlan: { - directory: 'combobox-select-only' - }, - testPlanReports: [ + id: '7', + title: 'Select Only Combobox Example', + phase: 'DRAFT', + gitSha: '7c4b5dce23c74fcf280ed164bdb903e02e0e7726', + gitMessage: 'Generate html source script to support aria-at-app (#646)', + updatedAt: '2022-03-17T18:34:51.000Z', + draftPhaseReachedAt: '2022-07-06T00:00:00.000Z', + candidatePhaseReachedAt: null, + recommendedPhaseTargetDate: null, + recommendedPhaseReachedAt: null, + testPlan: { + directory: 'combobox-select-only' + }, + testPlanReports: [ + { + id: '2', + metrics: { + testsCount: 21, + supportLevel: 'FAILING', + conflictsCount: 5, + supportPercent: 96, + testsFailedCount: 16, + testsPassedCount: 5, + optionalFormatted: '3 of 3 passed', + requiredFormatted: '48 of 50 passed', + optionalAssertionsCount: 3, + requiredAssertionsCount: 50, + unexpectedBehaviorCount: 3, + unexpectedBehaviorsFormatted: '3 found', + optionalAssertionsFailedCount: 0, + optionalAssertionsPassedCount: 3, + requiredAssertionsFailedCount: 2, + requiredAssertionsPassedCount: 48 + }, + markedFinalAt: null, + at: { + id: '2', + name: 'NVDA' + }, + browser: { + id: '1', + name: 'Firefox' + }, + issues: [], + draftTestPlanRuns: [ { - id: '2', - metrics: { - testsCount: 21, - supportLevel: 'FAILING', - conflictsCount: 5, - supportPercent: 96, - testsFailedCount: 16, - testsPassedCount: 5, - optionalFormatted: '3 of 3 passed', - requiredFormatted: '48 of 50 passed', - optionalAssertionsCount: 3, - requiredAssertionsCount: 50, - unexpectedBehaviorCount: 3, - unexpectedBehaviorsFormatted: '3 found', - optionalAssertionsFailedCount: 0, - optionalAssertionsPassedCount: 3, - requiredAssertionsFailedCount: 2, - requiredAssertionsPassedCount: 48 + tester: { + username: 'tom-proudfeet' + }, + testPlanReport: { + id: '2' + }, + testResults: [ + { + test: { + id: 'Nzg5NeyIyIjoiNyJ9zNjZj' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.240Z' }, - markedFinalAt: null, - at: { + { + test: { + id: 'MmY0YeyIyIjoiNyJ9jRkZD' + }, + atVersion: { id: '2', - name: 'NVDA' + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.332Z' }, - browser: { + { + test: { + id: 'ZjUwNeyIyIjoiNyJ9mE2ZT' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { id: '1', - name: 'Firefox' + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.412Z' + }, + { + test: { + id: 'MDNiMeyIyIjoiNyJ9Dk1MT' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.501Z' + }, + { + test: { + id: 'MjRmNeyIyIjoiNyJ92MyMT' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.593Z' + }, + { + test: { + id: 'ZmVlMeyIyIjoiNyJ9mUyYj' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: null + }, + { + test: { + id: 'YWFiNeyIyIjoiNyJ9zE2Zj' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.811Z' + }, + { + test: { + id: 'YjZkYeyIyIjoiNyJ9WIxZm' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.902Z' + }, + { + test: { + id: 'ZmIzMeyIyIjoiNyJ9TQ1NW' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.996Z' + } + ] + }, + { + tester: { + username: 'esmeralda-baggins' + }, + testPlanReport: { + id: '2' + }, + testResults: [ + { + test: { + id: 'Nzg5NeyIyIjoiNyJ9zNjZj' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:07.718Z' + }, + { + test: { + id: 'MmY0YeyIyIjoiNyJ9jRkZD' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:07.813Z' + }, + { + test: { + id: 'ZjUwNeyIyIjoiNyJ9mE2ZT' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:07.914Z' }, - issues: [], - draftTestPlanRuns: [ - { - tester: { - username: 'tom-proudfeet' - }, - testPlanReport: { - id: '2' - }, - testResults: [ - { - test: { - id: 'Nzg5NeyIyIjoiNyJ9zNjZj' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: '2023-08-18T03:17:08.240Z' - }, - { - test: { - id: 'MmY0YeyIyIjoiNyJ9jRkZD' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: '2023-08-18T03:17:08.332Z' - }, - { - test: { - id: 'ZjUwNeyIyIjoiNyJ9mE2ZT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: '2023-08-18T03:17:08.412Z' - }, - { - test: { - id: 'MDNiMeyIyIjoiNyJ9Dk1MT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: '2023-08-18T03:17:08.501Z' - }, - { - test: { - id: 'MjRmNeyIyIjoiNyJ92MyMT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: '2023-08-18T03:17:08.593Z' - }, - { - test: { - id: 'ZmVlMeyIyIjoiNyJ9mUyYj' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: null - }, - { - test: { - id: 'YWFiNeyIyIjoiNyJ9zE2Zj' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: '2023-08-18T03:17:08.811Z' - }, - { - test: { - id: 'YjZkYeyIyIjoiNyJ9WIxZm' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: '2023-08-18T03:17:08.902Z' - }, - { - test: { - id: 'ZmIzMeyIyIjoiNyJ9TQ1NW' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: '2023-08-18T03:17:08.996Z' - } - ] - }, - { - tester: { - username: 'esmeralda-baggins' - }, - testPlanReport: { - id: '2' - }, - testResults: [ - { - test: { - id: 'Nzg5NeyIyIjoiNyJ9zNjZj' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: '2023-08-18T03:17:07.718Z' - }, - { - test: { - id: 'MmY0YeyIyIjoiNyJ9jRkZD' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: '2023-08-18T03:17:07.813Z' - }, - { - test: { - id: 'ZjUwNeyIyIjoiNyJ9mE2ZT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: '2023-08-18T03:17:07.914Z' - }, - { - test: { - id: 'MDNiMeyIyIjoiNyJ9Dk1MT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: '2023-08-18T03:17:07.988Z' - }, - { - test: { - id: 'MjRmNeyIyIjoiNyJ92MyMT' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: '2023-08-18T03:17:08.074Z' - }, - { - test: { - id: 'ZmVlMeyIyIjoiNyJ9mUyYj' - }, - atVersion: { - id: '2', - name: '2020.4' - }, - browserVersion: { - id: '1', - name: '99.0.1' - }, - completedAt: null - } - ] - } - ] + { + test: { + id: 'MDNiMeyIyIjoiNyJ9Dk1MT' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:07.988Z' + }, + { + test: { + id: 'MjRmNeyIyIjoiNyJ92MyMT' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: '2023-08-18T03:17:08.074Z' + }, + { + test: { + id: 'ZmVlMeyIyIjoiNyJ9mUyYj' + }, + atVersion: { + id: '2', + name: '2020.4' + }, + browserVersion: { + id: '1', + name: '99.0.1' + }, + completedAt: null + } + ] } - ] + ] + } + ] }; export default ( - meQuery, - testPlanReportStatusDialogQuery, - initiatedByAutomationQuery + meQuery, + testPlanReportStatusDialogQuery, + initiatedByAutomationQuery ) => [ - { - request: { - query: meQuery - }, - result: { - data: { - me: { - id: '1', - username: 'foo-bar', - roles: ['ADMIN', 'TESTER'] - } - } - } + { + request: { + query: meQuery }, - { - request: { - query: testPlanReportStatusDialogQuery, - variables: { testPlanVersionId: '7' } - }, - result: { - data: { - testPlanVersion: mockedTestPlanVersion, - ats: [ - { - id: '1', - name: 'JAWS', - atVersions: [ - { - id: '1', - name: '2021.2111.13', - releasedAt: '2021-11-01T04:00:00.000Z' - } - ], - browsers: [ - { - id: '2', - name: 'Chrome' - }, - { - id: '1', - name: 'Firefox' - } - ], - candidateBrowsers: [{ id: '2' }], - recommendedBrowsers: [{ id: '1' }, { id: '2' }] - }, - { - id: '2', - name: 'NVDA', - atVersions: [ - { - id: '2', - name: '2020.4', - releasedAt: '2021-02-19T05:00:00.000Z' - } - ], - browsers: [ - { - id: '2', - name: 'Chrome' - }, - { - id: '1', - name: 'Firefox' - } - ], - candidateBrowsers: [{ id: '2' }], - recommendedBrowsers: [{ id: '1' }, { id: '2' }] - }, - { - id: '3', - name: 'VoiceOver for macOS', - atVersions: [ - { - id: '3', - name: '11.6 (20G165)', - releasedAt: '2019-09-01T04:00:00.000Z' - } - ], - browsers: [ - { - id: '2', - name: 'Chrome' - }, - { - id: '1', - name: 'Firefox' - }, - { - id: '3', - name: 'Safari' - } - ], - candidateBrowsers: [{ id: '3' }], - recommendedBrowsers: [{ id: '2' }, { id: '3' }] - } - ] - } + result: { + data: { + me: { + id: '1', + username: 'foo-bar', + roles: ['ADMIN', 'TESTER'] } + } + } + }, + { + request: { + query: testPlanReportStatusDialogQuery, + variables: { testPlanVersionId: '7' } }, - { - request: { - query: initiatedByAutomationQuery, - variables: { - testPlanVersionId: '7' - } - }, - result: { - data: { - testPlanVersion: { - id: '7', - testPlanReports: [ - { - id: '1', - markedFinalAt: '2021-01-01T00:00:00.000Z', - isFinal: true, - draftTestPlanRuns: { - initiatedByAutomation: true - }, - at: { - id: '1' - }, - browser: { - id: '2' - } - } - ] - } + result: { + data: { + testPlanVersion: mockedTestPlanVersion, + ats: [ + { + id: '1', + name: 'JAWS', + atVersions: [ + { + id: '1', + name: '2021.2111.13', + releasedAt: '2021-11-01T04:00:00.000Z' + } + ], + browsers: [ + { + id: '2', + name: 'Chrome' + }, + { + id: '1', + name: 'Firefox' + } + ], + candidateBrowsers: [{ id: '2' }], + recommendedBrowsers: [{ id: '1' }, { id: '2' }] + }, + { + id: '2', + name: 'NVDA', + atVersions: [ + { + id: '2', + name: '2020.4', + releasedAt: '2021-02-19T05:00:00.000Z' + } + ], + browsers: [ + { + id: '2', + name: 'Chrome' + }, + { + id: '1', + name: 'Firefox' + } + ], + candidateBrowsers: [{ id: '2' }], + recommendedBrowsers: [{ id: '1' }, { id: '2' }] + }, + { + id: '3', + name: 'VoiceOver for macOS', + atVersions: [ + { + id: '3', + name: '11.6 (20G165)', + releasedAt: '2019-09-01T04:00:00.000Z' + } + ], + browsers: [ + { + id: '2', + name: 'Chrome' + }, + { + id: '1', + name: 'Firefox' + }, + { + id: '3', + name: 'Safari' + } + ], + candidateBrowsers: [{ id: '3' }], + recommendedBrowsers: [{ id: '2' }, { id: '3' }] + } + ] + } + } + }, + { + request: { + query: initiatedByAutomationQuery, + variables: { + testPlanVersionId: '7' + } + }, + result: { + data: { + testPlanVersion: { + id: '7', + testPlanReports: [ + { + id: '1', + markedFinalAt: '2021-01-01T00:00:00.000Z', + isFinal: true, + draftTestPlanRuns: { + initiatedByAutomation: true + }, + at: { + id: '1' + }, + browser: { + id: '2' + } } + ] } + } } + } ]; diff --git a/client/tests/__mocks__/GraphQLMocks/TestQueuePageAdminNotPopulatedMock.js b/client/tests/__mocks__/GraphQLMocks/TestQueuePageAdminNotPopulatedMock.js index f5243b0df..c43f26cde 100644 --- a/client/tests/__mocks__/GraphQLMocks/TestQueuePageAdminNotPopulatedMock.js +++ b/client/tests/__mocks__/GraphQLMocks/TestQueuePageAdminNotPopulatedMock.js @@ -1,39 +1,39 @@ export default testQueuePageQuery => [ - { - request: { - query: testQueuePageQuery + { + request: { + query: testQueuePageQuery + }, + result: { + data: { + me: { + id: '1', + username: 'foo-bar', + roles: ['ADMIN', 'TESTER'], + __typename: 'User' }, - result: { - data: { - me: { - id: '1', - username: 'foo-bar', - roles: ['ADMIN', 'TESTER'], - __typename: 'User' - }, - ats: [], - browsers: [], - users: [ - { - id: '1', - username: 'foo-bar', - roles: ['ADMIN', 'TESTER'] - }, - { - id: '4', - username: 'bar-foo', - roles: ['TESTER'] - }, - { - id: '5', - username: 'boo-far', - roles: ['TESTER'] - } - ], - testPlanVersions: [], - testPlanReports: [], - testPlans: [] - } - } + ats: [], + browsers: [], + users: [ + { + id: '1', + username: 'foo-bar', + roles: ['ADMIN', 'TESTER'] + }, + { + id: '4', + username: 'bar-foo', + roles: ['TESTER'] + }, + { + id: '5', + username: 'boo-far', + roles: ['TESTER'] + } + ], + testPlanVersions: [], + testPlanReports: [], + testPlans: [] + } } + } ]; diff --git a/client/tests/__mocks__/GraphQLMocks/TestQueuePageAdminPopulatedMock.js b/client/tests/__mocks__/GraphQLMocks/TestQueuePageAdminPopulatedMock.js index fad26ed4d..0dee6c226 100644 --- a/client/tests/__mocks__/GraphQLMocks/TestQueuePageAdminPopulatedMock.js +++ b/client/tests/__mocks__/GraphQLMocks/TestQueuePageAdminPopulatedMock.js @@ -1,328 +1,328 @@ export default testQueuePageQuery => [ - { - request: { - query: testQueuePageQuery + { + request: { + query: testQueuePageQuery + }, + result: { + data: { + me: { + id: '101', + username: 'alflennik', + roles: ['ADMIN', 'TESTER'] }, - result: { - data: { - me: { - id: '101', - username: 'alflennik', - roles: ['ADMIN', 'TESTER'] + ats: [ + { + id: '1', + name: 'JAWS', + atVersions: [ + { + id: '1', + name: '2021.2111.13', + releasedAt: '2021-11-01T04:00:00.000Z' + } + ], + browsers: [ + { + id: '3', + name: 'Safari' + }, + { + id: '1', + name: 'Firefox' + }, + { + id: '2', + name: 'Chrome' + } + ], + candidateBrowsers: [ + { + id: '2', + name: 'Chrome' + } + ], + recommendedBrowsers: [ + { + id: '1', + name: 'Firefox' + }, + { + id: '2', + name: 'Chrome' + } + ] + }, + { + id: '2', + name: 'NVDA', + atVersions: [ + { + id: '5', + name: '2020.4', + releasedAt: '2022-01-01T12:00:00.000Z' + }, + { + id: '4', + name: '2020.3', + releasedAt: '2022-01-01T12:00:00.000Z' + }, + { + id: '3', + name: '2020.2', + releasedAt: '2022-01-01T12:00:00.000Z' + }, + { + id: '2', + name: '2020.1', + releasedAt: '2022-01-01T12:00:00.000Z' + }, + { + id: '1', + name: '2019.3', + releasedAt: '2022-01-01T12:00:00.000Z' + } + ], + browsers: [ + { + id: '3', + name: 'Safari' + }, + { + id: '1', + name: 'Firefox' + }, + { + id: '2', + name: 'Chrome' + } + ], + candidateBrowsers: [ + { + id: '2', + name: 'Chrome' + } + ], + recommendedBrowsers: [ + { + id: '1', + name: 'Firefox' + }, + { + id: '2', + name: 'Chrome' + } + ] + }, + { + id: '3', + name: 'VoiceOver for macOS', + atVersions: [ + { + id: '3', + name: '11.6 (20G165)', + releasedAt: '2019-09-01T04:00:00.000Z' + } + ], + browsers: [ + { + id: '3', + name: 'Safari' + }, + { + id: '1', + name: 'Firefox' + }, + { + id: '2', + name: 'Chrome' + } + ], + candidateBrowsers: [ + { + id: '3', + name: 'Safari' + } + ], + recommendedBrowsers: [ + { + id: '3', + name: 'Safari' + }, + { + id: '2', + name: 'Chrome' + } + ] + } + ], + browsers: [ + { + id: '2', + name: 'Chrome' + }, + { + id: '1', + name: 'Firefox' + }, + { + id: '3', + name: 'Safari' + } + ], + users: [ + { + id: '1', + username: 'esmeralda-baggins', + roles: ['TESTER', 'ADMIN'] + }, + { id: '2', username: 'tom-proudfeet', roles: ['TESTER'] }, + { + id: '101', + username: 'alflennik', + roles: ['TESTER', 'ADMIN'] + } + ], + testPlanVersions: [ + { + id: '1', + title: 'Alert Example', + phase: 'DRAFT', + gitSha: '97d4bd6c2078849ad4ee01eeeb3667767ca6f992', + gitMessage: + 'Create tests for APG design pattern example: Navigation Menu Button (#524)', + testPlan: { + directory: 'alert' + }, + updatedAt: '2022-04-15T19:09:53.000Z' + }, + { + id: '2', + title: 'Banner Landmark', + phase: 'DRAFT', + gitSha: '97d4bd6c2078849ad4ee01eeeb3667767ca6f992', + gitMessage: + 'Create tests for APG design pattern example: Navigation Menu Button (#524)', + testPlan: { + directory: 'banner' + }, + updatedAt: '2022-04-15T19:09:53.000Z' + }, + { + id: '3', + title: 'Breadcrumb Example', + phase: 'DRAFT', + gitSha: '97d4bd6c2078849ad4ee01eeeb3667767ca6f992', + gitMessage: + 'Create tests for APG design pattern example: Navigation Menu Button (#524)', + testPlan: { + directory: 'breadcrumb' + }, + updatedAt: '2022-04-15T19:09:53.000Z' + } + ], + testPlanReports: [ + { + id: '1', + status: 'DRAFT', + conflictsLength: 0, + runnableTestsLength: 17, + markedFinalAt: null, + at: { id: '1', name: 'JAWS' }, + browser: { id: '2', name: 'Chrome' }, + testPlanVersion: { + id: '1', + title: 'Checkbox Example (Two State)', + phase: 'DRAFT', + gitSha: 'b7078039f789c125e269cb8f8632f57a03d4c50b', + gitMessage: 'The message for this SHA', + testPlan: { directory: 'checkbox' }, + versionString: 'V21.11.30' + }, + draftTestPlanRuns: [ + { + id: '1', + tester: { + id: '1', + username: 'esmeralda-baggins' }, - ats: [ - { - id: '1', - name: 'JAWS', - atVersions: [ - { - id: '1', - name: '2021.2111.13', - releasedAt: '2021-11-01T04:00:00.000Z' - } - ], - browsers: [ - { - id: '3', - name: 'Safari' - }, - { - id: '1', - name: 'Firefox' - }, - { - id: '2', - name: 'Chrome' - } - ], - candidateBrowsers: [ - { - id: '2', - name: 'Chrome' - } - ], - recommendedBrowsers: [ - { - id: '1', - name: 'Firefox' - }, - { - id: '2', - name: 'Chrome' - } - ] - }, - { - id: '2', - name: 'NVDA', - atVersions: [ - { - id: '5', - name: '2020.4', - releasedAt: '2022-01-01T12:00:00.000Z' - }, - { - id: '4', - name: '2020.3', - releasedAt: '2022-01-01T12:00:00.000Z' - }, - { - id: '3', - name: '2020.2', - releasedAt: '2022-01-01T12:00:00.000Z' - }, - { - id: '2', - name: '2020.1', - releasedAt: '2022-01-01T12:00:00.000Z' - }, - { - id: '1', - name: '2019.3', - releasedAt: '2022-01-01T12:00:00.000Z' - } - ], - browsers: [ - { - id: '3', - name: 'Safari' - }, - { - id: '1', - name: 'Firefox' - }, - { - id: '2', - name: 'Chrome' - } - ], - candidateBrowsers: [ - { - id: '2', - name: 'Chrome' - } - ], - recommendedBrowsers: [ - { - id: '1', - name: 'Firefox' - }, - { - id: '2', - name: 'Chrome' - } - ] - }, - { - id: '3', - name: 'VoiceOver for macOS', - atVersions: [ - { - id: '3', - name: '11.6 (20G165)', - releasedAt: '2019-09-01T04:00:00.000Z' - } - ], - browsers: [ - { - id: '3', - name: 'Safari' - }, - { - id: '1', - name: 'Firefox' - }, - { - id: '2', - name: 'Chrome' - } - ], - candidateBrowsers: [ - { - id: '3', - name: 'Safari' - } - ], - recommendedBrowsers: [ - { - id: '3', - name: 'Safari' - }, - { - id: '2', - name: 'Chrome' - } - ] - } - ], - browsers: [ - { - id: '2', - name: 'Chrome' - }, - { - id: '1', - name: 'Firefox' - }, - { - id: '3', - name: 'Safari' - } - ], - users: [ - { - id: '1', - username: 'esmeralda-baggins', - roles: ['TESTER', 'ADMIN'] - }, - { id: '2', username: 'tom-proudfeet', roles: ['TESTER'] }, - { - id: '101', - username: 'alflennik', - roles: ['TESTER', 'ADMIN'] - } - ], - testPlanVersions: [ - { - id: '1', - title: 'Alert Example', - phase: 'DRAFT', - gitSha: '97d4bd6c2078849ad4ee01eeeb3667767ca6f992', - gitMessage: - 'Create tests for APG design pattern example: Navigation Menu Button (#524)', - testPlan: { - directory: 'alert' - }, - updatedAt: '2022-04-15T19:09:53.000Z' - }, - { - id: '2', - title: 'Banner Landmark', - phase: 'DRAFT', - gitSha: '97d4bd6c2078849ad4ee01eeeb3667767ca6f992', - gitMessage: - 'Create tests for APG design pattern example: Navigation Menu Button (#524)', - testPlan: { - directory: 'banner' - }, - updatedAt: '2022-04-15T19:09:53.000Z' - }, - { - id: '3', - title: 'Breadcrumb Example', - phase: 'DRAFT', - gitSha: '97d4bd6c2078849ad4ee01eeeb3667767ca6f992', - gitMessage: - 'Create tests for APG design pattern example: Navigation Menu Button (#524)', - testPlan: { - directory: 'breadcrumb' - }, - updatedAt: '2022-04-15T19:09:53.000Z' - } - ], - testPlanReports: [ - { - id: '1', - status: 'DRAFT', - conflictsLength: 0, - runnableTestsLength: 17, - markedFinalAt: null, - at: { id: '1', name: 'JAWS' }, - browser: { id: '2', name: 'Chrome' }, - testPlanVersion: { - id: '1', - title: 'Checkbox Example (Two State)', - phase: 'DRAFT', - gitSha: 'b7078039f789c125e269cb8f8632f57a03d4c50b', - gitMessage: 'The message for this SHA', - testPlan: { directory: 'checkbox' }, - versionString: 'V21.11.30' - }, - draftTestPlanRuns: [ - { - id: '1', - tester: { - id: '1', - username: 'esmeralda-baggins' - }, - testResultsLength: 0, - initiatedByAutomation: false - } - ] - }, - { - id: '2', - status: 'DRAFT', - conflictsLength: 0, - runnableTestsLength: 17, - markedFinalAt: null, - at: { id: '3', name: 'VoiceOver for macOS' }, - browser: { id: '3', name: 'Safari' }, - testPlanVersion: { - id: '1', - title: 'Checkbox Example (Two State)', - phase: 'DRAFT', - gitSha: 'b7078039f789c125e269cb8f8632f57a03d4c50b', - gitMessage: 'The message for this SHA', - testPlan: { directory: 'checkbox' }, - versionString: 'V21.11.30' - }, - draftTestPlanRuns: [ - { - id: '1', - tester: { - id: '1', - username: 'esmeralda-baggins' - }, - testResultsLength: 0, - initiatedByAutomation: false - } - ] - }, - { - id: '3', - status: 'DRAFT', - conflictsLength: 3, - runnableTestsLength: 17, - markedFinalAt: null, - at: { id: '2', name: 'NVDA' }, - browser: { id: '1', name: 'Firefox' }, - testPlanVersion: { - id: '1', - title: 'Checkbox Example (Two State)', - phase: 'DRAFT', - gitSha: 'b7078039f789c125e269cb8f8632f57a03d4c50b', - gitMessage: 'The message for this SHA', - testPlan: { directory: 'checkbox' }, - versionString: 'V21.11.30' - }, - draftTestPlanRuns: [ - { - id: '3', - tester: { id: '2', username: 'tom-proudfeet' }, - testResultsLength: 3, - initiatedByAutomation: false - }, - { - id: '101', - tester: { id: '101', username: 'alflennik' }, - testResultsLength: 1, - initiatedByAutomation: false - }, - { - id: '2', - tester: { - id: '1', - username: 'esmeralda-baggins' - }, - testResultsLength: 3, - initiatedByAutomation: false - } - ] - } - ], - testPlans: [] - } - } + testResultsLength: 0, + initiatedByAutomation: false + } + ] + }, + { + id: '2', + status: 'DRAFT', + conflictsLength: 0, + runnableTestsLength: 17, + markedFinalAt: null, + at: { id: '3', name: 'VoiceOver for macOS' }, + browser: { id: '3', name: 'Safari' }, + testPlanVersion: { + id: '1', + title: 'Checkbox Example (Two State)', + phase: 'DRAFT', + gitSha: 'b7078039f789c125e269cb8f8632f57a03d4c50b', + gitMessage: 'The message for this SHA', + testPlan: { directory: 'checkbox' }, + versionString: 'V21.11.30' + }, + draftTestPlanRuns: [ + { + id: '1', + tester: { + id: '1', + username: 'esmeralda-baggins' + }, + testResultsLength: 0, + initiatedByAutomation: false + } + ] + }, + { + id: '3', + status: 'DRAFT', + conflictsLength: 3, + runnableTestsLength: 17, + markedFinalAt: null, + at: { id: '2', name: 'NVDA' }, + browser: { id: '1', name: 'Firefox' }, + testPlanVersion: { + id: '1', + title: 'Checkbox Example (Two State)', + phase: 'DRAFT', + gitSha: 'b7078039f789c125e269cb8f8632f57a03d4c50b', + gitMessage: 'The message for this SHA', + testPlan: { directory: 'checkbox' }, + versionString: 'V21.11.30' + }, + draftTestPlanRuns: [ + { + id: '3', + tester: { id: '2', username: 'tom-proudfeet' }, + testResultsLength: 3, + initiatedByAutomation: false + }, + { + id: '101', + tester: { id: '101', username: 'alflennik' }, + testResultsLength: 1, + initiatedByAutomation: false + }, + { + id: '2', + tester: { + id: '1', + username: 'esmeralda-baggins' + }, + testResultsLength: 3, + initiatedByAutomation: false + } + ] + } + ], + testPlans: [] + } } + } ]; diff --git a/client/tests/__mocks__/GraphQLMocks/TestQueuePageBaseMock.js b/client/tests/__mocks__/GraphQLMocks/TestQueuePageBaseMock.js index adef2575c..555c252f9 100644 --- a/client/tests/__mocks__/GraphQLMocks/TestQueuePageBaseMock.js +++ b/client/tests/__mocks__/GraphQLMocks/TestQueuePageBaseMock.js @@ -1,105 +1,105 @@ export default ( - testPlanReportAtBrowserQuery, - initiatedByAutomationRunQuery + testPlanReportAtBrowserQuery, + initiatedByAutomationRunQuery ) => [ - { - request: { - query: testPlanReportAtBrowserQuery, - variables: { - testPlanReportId: '3' - } - }, - result: { - data: { - testPlanReport: { - id: '3', - at: { - id: '1', - name: 'JAWS' - }, - browser: { - id: '2', - name: 'Chrome' - } - } - } + { + request: { + query: testPlanReportAtBrowserQuery, + variables: { + testPlanReportId: '3' + } + }, + result: { + data: { + testPlanReport: { + id: '3', + at: { + id: '1', + name: 'JAWS' + }, + browser: { + id: '2', + name: 'Chrome' + } } + } + } + }, + { + request: { + query: testPlanReportAtBrowserQuery, + variables: { + testPlanReportId: '2' + } }, - { - request: { - query: testPlanReportAtBrowserQuery, - variables: { - testPlanReportId: '2' - } - }, - result: { - data: { - testPlanReport: { - id: '2', - at: { - id: '2', - name: 'NVDA' - }, - browser: { - id: '1', - name: 'Firefox' - } - } - } + result: { + data: { + testPlanReport: { + id: '2', + at: { + id: '2', + name: 'NVDA' + }, + browser: { + id: '1', + name: 'Firefox' + } } + } + } + }, + { + request: { + query: testPlanReportAtBrowserQuery, + variables: { + testPlanReportId: '1' + } }, - { - request: { - query: testPlanReportAtBrowserQuery, - variables: { - testPlanReportId: '1' - } - }, - result: { - data: { - testPlanReport: { - id: '1', - at: { - id: '1', - name: 'JAWS' - }, - browser: { - id: '2', - name: 'Chrome' - } - } - } + result: { + data: { + testPlanReport: { + id: '1', + at: { + id: '1', + name: 'JAWS' + }, + browser: { + id: '2', + name: 'Chrome' + } } + } + } + }, + { + request: { + query: initiatedByAutomationRunQuery, + variables: { + testPlanVersionId: '1' + } }, - { - request: { - query: initiatedByAutomationRunQuery, - variables: { - testPlanVersionId: '1' - } - }, - result: { - data: { - testPlanVersion: { - id: '1', - testPlanReports: [ - { - id: '1', - markedFinalAt: '2021-01-01T00:00:00.000Z', - isFinal: true, - draftTestPlanRuns: { - initiatedByAutomation: true - }, - at: { - id: '1' - }, - browser: { - id: '2' - } - } - ] - } + result: { + data: { + testPlanVersion: { + id: '1', + testPlanReports: [ + { + id: '1', + markedFinalAt: '2021-01-01T00:00:00.000Z', + isFinal: true, + draftTestPlanRuns: { + initiatedByAutomation: true + }, + at: { + id: '1' + }, + browser: { + id: '2' + } } + ] } + } } + } ]; diff --git a/client/tests/__mocks__/GraphQLMocks/TestQueuePageTesterNotPopulatedMock.js b/client/tests/__mocks__/GraphQLMocks/TestQueuePageTesterNotPopulatedMock.js index fe03d4e0e..031d28cd7 100644 --- a/client/tests/__mocks__/GraphQLMocks/TestQueuePageTesterNotPopulatedMock.js +++ b/client/tests/__mocks__/GraphQLMocks/TestQueuePageTesterNotPopulatedMock.js @@ -1,42 +1,42 @@ export default testQueuePageQuery => [ - { - request: { - query: testQueuePageQuery + { + request: { + query: testQueuePageQuery + }, + result: { + data: { + me: { + id: '4', + username: 'bar-foo', + roles: ['TESTER'], + __typename: 'User' }, - result: { - data: { - me: { - id: '4', - username: 'bar-foo', - roles: ['TESTER'], - __typename: 'User' - }, - ats: [], - browsers: [], - users: [ - { - id: '1', - username: 'foo-bar', - roles: ['ADMIN', 'TESTER'], - __typename: 'User' - }, - { - id: '4', - username: 'bar-foo', - roles: ['TESTER'], - __typename: 'User' - }, - { - id: '5', - username: 'boo-far', - roles: ['TESTER'], - __typename: 'User' - } - ], - testPlanVersions: [], - testPlanReports: [], - testPlans: [] - } - } + ats: [], + browsers: [], + users: [ + { + id: '1', + username: 'foo-bar', + roles: ['ADMIN', 'TESTER'], + __typename: 'User' + }, + { + id: '4', + username: 'bar-foo', + roles: ['TESTER'], + __typename: 'User' + }, + { + id: '5', + username: 'boo-far', + roles: ['TESTER'], + __typename: 'User' + } + ], + testPlanVersions: [], + testPlanReports: [], + testPlans: [] + } } + } ]; diff --git a/client/tests/__mocks__/GraphQLMocks/TestQueuePageTesterPopulatedMock.js b/client/tests/__mocks__/GraphQLMocks/TestQueuePageTesterPopulatedMock.js index 31f3a1808..65876d31d 100644 --- a/client/tests/__mocks__/GraphQLMocks/TestQueuePageTesterPopulatedMock.js +++ b/client/tests/__mocks__/GraphQLMocks/TestQueuePageTesterPopulatedMock.js @@ -1,344 +1,344 @@ export default testQueuePageQuery => [ - { - request: { - query: testQueuePageQuery + { + request: { + query: testQueuePageQuery + }, + result: { + data: { + me: { + id: '4', + username: 'bar-foo', + roles: ['TESTER'], + __typename: 'User' }, - result: { - data: { - me: { - id: '4', - username: 'bar-foo', - roles: ['TESTER'], - __typename: 'User' + ats: [ + { + id: '1', + name: 'JAWS', + atVersions: [ + { + id: '1', + name: '2021.2111.13', + releasedAt: '2021-11-01T04:00:00.000Z' + } + ], + browsers: [ + { + id: '3', + name: 'Safari' + }, + { + id: '1', + name: 'Firefox' + }, + { + id: '2', + name: 'Chrome' + } + ], + candidateBrowsers: [ + { + id: '2', + name: 'Chrome' + } + ], + recommendedBrowsers: [ + { + id: '1', + name: 'Firefox' + }, + { + id: '2', + name: 'Chrome' + } + ] + }, + { + id: '2', + name: 'NVDA', + atVersions: [ + { + id: '5', + name: '2020.4', + releasedAt: '2022-01-01T12:00:00.000Z' + }, + { + id: '4', + name: '2020.3', + releasedAt: '2022-01-01T12:00:00.000Z' + }, + { + id: '3', + name: '2020.2', + releasedAt: '2022-01-01T12:00:00.000Z' + }, + { + id: '2', + name: '2020.1', + releasedAt: '2022-01-01T12:00:00.000Z' + }, + { + id: '1', + name: '2019.3', + releasedAt: '2022-01-01T12:00:00.000Z' + } + ], + browsers: [ + { + id: '3', + name: 'Safari' + }, + { + id: '1', + name: 'Firefox' + }, + { + id: '2', + name: 'Chrome' + } + ], + candidateBrowsers: [ + { + id: '2', + name: 'Chrome' + } + ], + recommendedBrowsers: [ + { + id: '1', + name: 'Firefox' + }, + { + id: '2', + name: 'Chrome' + } + ] + }, + { + id: '3', + name: 'VoiceOver for macOS', + atVersions: [ + { + id: '3', + name: '11.6 (20G165)', + releasedAt: '2019-09-01T04:00:00.000Z' + } + ], + browsers: [ + { + id: '3', + name: 'Safari' + }, + { + id: '1', + name: 'Firefox' + }, + { + id: '2', + name: 'Chrome' + } + ], + candidateBrowsers: [ + { + id: '3', + name: 'Safari' + } + ], + recommendedBrowsers: [ + { + id: '3', + name: 'Safari' + }, + { + id: '2', + name: 'Chrome' + } + ] + } + ], + browsers: [ + { + id: '2', + name: 'Chrome' + }, + { + id: '1', + name: 'Firefox' + }, + { + id: '3', + name: 'Safari' + } + ], + users: [ + { + id: '1', + username: 'foo-bar', + roles: ['ADMIN', 'TESTER'] + }, + { + id: '4', + username: 'bar-foo', + roles: ['TESTER'] + }, + { + id: '5', + username: 'boo-far', + roles: ['TESTER'] + } + ], + testPlanVersions: [ + { + id: '1', + title: 'Alert Example', + phase: 'DRAFT', + gitSha: '97d4bd6c2078849ad4ee01eeeb3667767ca6f992', + gitMessage: + 'Create tests for APG design pattern example: Navigation Menu Button (#524)', + testPlan: { + directory: 'alert' + }, + updatedAt: '2022-04-15T19:09:53.000Z' + }, + { + id: '2', + title: 'Banner Landmark', + phase: 'DRAFT', + gitSha: '97d4bd6c2078849ad4ee01eeeb3667767ca6f992', + gitMessage: + 'Create tests for APG design pattern example: Navigation Menu Button (#524)', + testPlan: { + directory: 'banner' + }, + updatedAt: '2022-04-15T19:09:53.000Z' + }, + { + id: '3', + title: 'Breadcrumb Example', + phase: 'DRAFT', + gitSha: '97d4bd6c2078849ad4ee01eeeb3667767ca6f992', + gitMessage: + 'Create tests for APG design pattern example: Navigation Menu Button (#524)', + testPlan: { + directory: 'breadcrumb' + }, + updatedAt: '2022-04-15T19:09:53.000Z' + } + ], + testPlanReports: [ + { + id: '10', + status: 'DRAFT', + conflictsLength: 0, + runnableTestsLength: 17, + markedFinalAt: null, + at: { + id: '2', + name: 'NVDA' + }, + browser: { + id: '1', + name: 'Firefox' + }, + testPlanVersion: { + id: '65', + title: 'Checkbox Example (Two State)', + phase: 'DRAFT', + gitSha: 'aea64f84b8fa8b21e94f5d9afd7035570bc1bed3', + gitMessage: 'The message for this SHA', + testPlan: { + directory: 'checkbox' + }, + versionString: 'V21-11-30' + }, + draftTestPlanRuns: [ + { + id: '18', + tester: { + id: '1', + username: 'foo-bar' }, - ats: [ - { - id: '1', - name: 'JAWS', - atVersions: [ - { - id: '1', - name: '2021.2111.13', - releasedAt: '2021-11-01T04:00:00.000Z' - } - ], - browsers: [ - { - id: '3', - name: 'Safari' - }, - { - id: '1', - name: 'Firefox' - }, - { - id: '2', - name: 'Chrome' - } - ], - candidateBrowsers: [ - { - id: '2', - name: 'Chrome' - } - ], - recommendedBrowsers: [ - { - id: '1', - name: 'Firefox' - }, - { - id: '2', - name: 'Chrome' - } - ] - }, - { - id: '2', - name: 'NVDA', - atVersions: [ - { - id: '5', - name: '2020.4', - releasedAt: '2022-01-01T12:00:00.000Z' - }, - { - id: '4', - name: '2020.3', - releasedAt: '2022-01-01T12:00:00.000Z' - }, - { - id: '3', - name: '2020.2', - releasedAt: '2022-01-01T12:00:00.000Z' - }, - { - id: '2', - name: '2020.1', - releasedAt: '2022-01-01T12:00:00.000Z' - }, - { - id: '1', - name: '2019.3', - releasedAt: '2022-01-01T12:00:00.000Z' - } - ], - browsers: [ - { - id: '3', - name: 'Safari' - }, - { - id: '1', - name: 'Firefox' - }, - { - id: '2', - name: 'Chrome' - } - ], - candidateBrowsers: [ - { - id: '2', - name: 'Chrome' - } - ], - recommendedBrowsers: [ - { - id: '1', - name: 'Firefox' - }, - { - id: '2', - name: 'Chrome' - } - ] - }, - { - id: '3', - name: 'VoiceOver for macOS', - atVersions: [ - { - id: '3', - name: '11.6 (20G165)', - releasedAt: '2019-09-01T04:00:00.000Z' - } - ], - browsers: [ - { - id: '3', - name: 'Safari' - }, - { - id: '1', - name: 'Firefox' - }, - { - id: '2', - name: 'Chrome' - } - ], - candidateBrowsers: [ - { - id: '3', - name: 'Safari' - } - ], - recommendedBrowsers: [ - { - id: '3', - name: 'Safari' - }, - { - id: '2', - name: 'Chrome' - } - ] - } - ], - browsers: [ - { - id: '2', - name: 'Chrome' - }, - { - id: '1', - name: 'Firefox' - }, - { - id: '3', - name: 'Safari' - } - ], - users: [ - { - id: '1', - username: 'foo-bar', - roles: ['ADMIN', 'TESTER'] - }, - { - id: '4', - username: 'bar-foo', - roles: ['TESTER'] - }, - { - id: '5', - username: 'boo-far', - roles: ['TESTER'] - } - ], - testPlanVersions: [ - { - id: '1', - title: 'Alert Example', - phase: 'DRAFT', - gitSha: '97d4bd6c2078849ad4ee01eeeb3667767ca6f992', - gitMessage: - 'Create tests for APG design pattern example: Navigation Menu Button (#524)', - testPlan: { - directory: 'alert' - }, - updatedAt: '2022-04-15T19:09:53.000Z' - }, - { - id: '2', - title: 'Banner Landmark', - phase: 'DRAFT', - gitSha: '97d4bd6c2078849ad4ee01eeeb3667767ca6f992', - gitMessage: - 'Create tests for APG design pattern example: Navigation Menu Button (#524)', - testPlan: { - directory: 'banner' - }, - updatedAt: '2022-04-15T19:09:53.000Z' - }, - { - id: '3', - title: 'Breadcrumb Example', - phase: 'DRAFT', - gitSha: '97d4bd6c2078849ad4ee01eeeb3667767ca6f992', - gitMessage: - 'Create tests for APG design pattern example: Navigation Menu Button (#524)', - testPlan: { - directory: 'breadcrumb' - }, - updatedAt: '2022-04-15T19:09:53.000Z' - } - ], - testPlanReports: [ - { - id: '10', - status: 'DRAFT', - conflictsLength: 0, - runnableTestsLength: 17, - markedFinalAt: null, - at: { - id: '2', - name: 'NVDA' - }, - browser: { - id: '1', - name: 'Firefox' - }, - testPlanVersion: { - id: '65', - title: 'Checkbox Example (Two State)', - phase: 'DRAFT', - gitSha: 'aea64f84b8fa8b21e94f5d9afd7035570bc1bed3', - gitMessage: 'The message for this SHA', - testPlan: { - directory: 'checkbox' - }, - versionString: 'V21-11-30' - }, - draftTestPlanRuns: [ - { - id: '18', - tester: { - id: '1', - username: 'foo-bar' - }, - testResultsLength: 0, - initiatedByAutomation: false - }, - { - id: '19', - tester: { - id: '4', - username: 'bar-foo' - }, - testResultsLength: 0, - initiatedByAutomation: false - } - ] - }, - { - id: '11', - status: 'DRAFT', - conflictsLength: 0, - runnableTestsLength: 17, - markedFinalAt: null, - at: { - id: '2', - name: 'JAWS' - }, - browser: { - id: '1', - name: 'Firefox' - }, - testPlanVersion: { - id: '65', - title: 'Checkbox Example (Two State)', - phase: 'DRAFT', - gitSha: 'aea64f84b8fa8b21e94f5d9afd7035570bc1bed3', - gitMessage: 'The message for this SHA', - testPlan: { - directory: 'checkbox' - }, - versionString: 'V21-11-30' - }, - draftTestPlanRuns: [ - { - id: '20', - tester: { - id: '5', - username: 'boo-far' - }, - testResultsLength: 0, - initiatedByAutomation: false - } - ] - }, - { - id: '12', - status: 'DRAFT', - conflictsLength: 0, - runnableTestsLength: 15, - markedFinalAt: null, - at: { - id: '3', - name: 'VoiceOver for macOS' - }, - browser: { - id: '1', - name: 'Firefox' - }, - testPlanVersion: { - id: '74', - title: 'Editor Menubar Example', - phase: 'DRAFT', - gitSha: 'aea64f84b8fa8b21e94f5d9afd7035570bc1bed3', - gitMessage: 'The message for this SHA', - testPlan: { - directory: 'menubar-editor' - }, - versionString: 'V21-11-30' - }, - draftTestPlanRuns: [] - } - ], - testPlans: [] - } - } + testResultsLength: 0, + initiatedByAutomation: false + }, + { + id: '19', + tester: { + id: '4', + username: 'bar-foo' + }, + testResultsLength: 0, + initiatedByAutomation: false + } + ] + }, + { + id: '11', + status: 'DRAFT', + conflictsLength: 0, + runnableTestsLength: 17, + markedFinalAt: null, + at: { + id: '2', + name: 'JAWS' + }, + browser: { + id: '1', + name: 'Firefox' + }, + testPlanVersion: { + id: '65', + title: 'Checkbox Example (Two State)', + phase: 'DRAFT', + gitSha: 'aea64f84b8fa8b21e94f5d9afd7035570bc1bed3', + gitMessage: 'The message for this SHA', + testPlan: { + directory: 'checkbox' + }, + versionString: 'V21-11-30' + }, + draftTestPlanRuns: [ + { + id: '20', + tester: { + id: '5', + username: 'boo-far' + }, + testResultsLength: 0, + initiatedByAutomation: false + } + ] + }, + { + id: '12', + status: 'DRAFT', + conflictsLength: 0, + runnableTestsLength: 15, + markedFinalAt: null, + at: { + id: '3', + name: 'VoiceOver for macOS' + }, + browser: { + id: '1', + name: 'Firefox' + }, + testPlanVersion: { + id: '74', + title: 'Editor Menubar Example', + phase: 'DRAFT', + gitSha: 'aea64f84b8fa8b21e94f5d9afd7035570bc1bed3', + gitMessage: 'The message for this SHA', + testPlan: { + directory: 'menubar-editor' + }, + versionString: 'V21-11-30' + }, + draftTestPlanRuns: [] + } + ], + testPlans: [] + } } + } ]; diff --git a/client/tests/__mocks__/GraphQLMocks/index.js b/client/tests/__mocks__/GraphQLMocks/index.js index 395e83e9b..4f83f5e1e 100644 --- a/client/tests/__mocks__/GraphQLMocks/index.js +++ b/client/tests/__mocks__/GraphQLMocks/index.js @@ -14,32 +14,32 @@ import TestPlanReportStatusDialogMock from './TestPlanReportStatusDialogMock'; import TestQueuePageBaseMock from './TestQueuePageBaseMock'; export const TEST_QUEUE_PAGE_ADMIN_NOT_POPULATED_MOCK_DATA = - TestQueuePageAdminNotPopulatedMock(TEST_QUEUE_PAGE_QUERY); + TestQueuePageAdminNotPopulatedMock(TEST_QUEUE_PAGE_QUERY); export const TEST_QUEUE_PAGE_ADMIN_POPULATED_MOCK_DATA = - TestQueuePageAdminPopulatedMock(TEST_QUEUE_PAGE_QUERY); + TestQueuePageAdminPopulatedMock(TEST_QUEUE_PAGE_QUERY); export const TEST_QUEUE_PAGE_TESTER_NOT_POPULATED_MOCK_DATA = - TestQueuePageTesterNotPopulatedMock(TEST_QUEUE_PAGE_QUERY); + TestQueuePageTesterNotPopulatedMock(TEST_QUEUE_PAGE_QUERY); export const TEST_QUEUE_PAGE_TESTER_POPULATED_MOCK_DATA = - TestQueuePageTesterPopulatedMock(TEST_QUEUE_PAGE_QUERY); + TestQueuePageTesterPopulatedMock(TEST_QUEUE_PAGE_QUERY); export const TEST_QUEUE_PAGE_BASE_MOCK_DATA = TestQueuePageBaseMock( - TEST_PLAN_REPORT_AT_BROWSER_QUERY, - EXISTING_TEST_PLAN_REPORTS + TEST_PLAN_REPORT_AT_BROWSER_QUERY, + EXISTING_TEST_PLAN_REPORTS ); export const DATA_MANAGEMENT_PAGE_POPULATED_MOCK_DATA = - DataManagementPagePopulatedMock( - ME_QUERY, - DATA_MANAGEMENT_PAGE_QUERY, - TEST_PLAN_REPORT_STATUS_DIALOG_QUERY - ); + DataManagementPagePopulatedMock( + ME_QUERY, + DATA_MANAGEMENT_PAGE_QUERY, + TEST_PLAN_REPORT_STATUS_DIALOG_QUERY + ); export const TEST_PLAN_REPORT_STATUS_DIALOG_MOCK_DATA = - TestPlanReportStatusDialogMock( - ME_QUERY, - TEST_PLAN_REPORT_STATUS_DIALOG_QUERY, - EXISTING_TEST_PLAN_REPORTS - ); + TestPlanReportStatusDialogMock( + ME_QUERY, + TEST_PLAN_REPORT_STATUS_DIALOG_QUERY, + EXISTING_TEST_PLAN_REPORTS + ); diff --git a/client/tests/calculateTestPlanReportCompletionPercentage.test.js b/client/tests/calculateTestPlanReportCompletionPercentage.test.js index f03b7593f..5b3d5de46 100644 --- a/client/tests/calculateTestPlanReportCompletionPercentage.test.js +++ b/client/tests/calculateTestPlanReportCompletionPercentage.test.js @@ -1,57 +1,57 @@ import { calculateTestPlanReportCompletionPercentage } from '../components/TestPlanReportStatusDialog/calculateTestPlanReportCompletionPercentage'; describe('calculateTestPlanReportCompletionPercentage', () => { - test('returns 0 when metrics or draftTestPlanRuns is not defined', () => { - expect(calculateTestPlanReportCompletionPercentage({})).toBe(0); - expect( - calculateTestPlanReportCompletionPercentage({ metrics: {} }) - ).toBe(0); - expect( - calculateTestPlanReportCompletionPercentage({ - draftTestPlanRuns: [] - }) - ).toBe(0); - }); + test('returns 0 when metrics or draftTestPlanRuns is not defined', () => { + expect(calculateTestPlanReportCompletionPercentage({})).toBe(0); + expect(calculateTestPlanReportCompletionPercentage({ metrics: {} })).toBe( + 0 + ); + expect( + calculateTestPlanReportCompletionPercentage({ + draftTestPlanRuns: [] + }) + ).toBe(0); + }); - test('returns 0 when draftTestPlanRuns is empty', () => { - expect( - calculateTestPlanReportCompletionPercentage({ - metrics: { testsCount: 5 }, - draftTestPlanRuns: [] - }) - ).toBe(0); - }); + test('returns 0 when draftTestPlanRuns is empty', () => { + expect( + calculateTestPlanReportCompletionPercentage({ + metrics: { testsCount: 5 }, + draftTestPlanRuns: [] + }) + ).toBe(0); + }); - test('returns 0 and not Infinity when total tests possible is 0', () => { - const metrics = { testsCount: 0 }; - const draftTestPlanRuns = [ - { testResults: [1, 2, 3] }, - { testResults: [1, 2, 3, 4, 5] } - ]; + test('returns 0 and not Infinity when total tests possible is 0', () => { + const metrics = { testsCount: 0 }; + const draftTestPlanRuns = [ + { testResults: [1, 2, 3] }, + { testResults: [1, 2, 3, 4, 5] } + ]; - expect( - calculateTestPlanReportCompletionPercentage({ - metrics, - draftTestPlanRuns - }) - ).toBe(0); - }); + expect( + calculateTestPlanReportCompletionPercentage({ + metrics, + draftTestPlanRuns + }) + ).toBe(0); + }); - test('calculates and returns the correct percentage when draftTestPlanRuns has testResults', () => { - const metrics = { testsCount: 5 }; - const draftTestPlanRuns = [ - { testResults: [1, 2] }, - { testResults: [1, 2, 3] } - ]; + test('calculates and returns the correct percentage when draftTestPlanRuns has testResults', () => { + const metrics = { testsCount: 5 }; + const draftTestPlanRuns = [ + { testResults: [1, 2] }, + { testResults: [1, 2, 3] } + ]; - // Output should follow this formula: - // (NUMBER_COMPLETED_TESTS_BY_ALL_TESTERS / (NUMBER_ASSIGNED_TESTERS * NUMBER_TESTS_IN_PLAN)) * 100 - // (5 / (2 * 5)) * 100 = 50 - expect( - calculateTestPlanReportCompletionPercentage({ - metrics, - draftTestPlanRuns - }) - ).toBe(50); - }); + // Output should follow this formula: + // (NUMBER_COMPLETED_TESTS_BY_ALL_TESTERS / (NUMBER_ASSIGNED_TESTERS * NUMBER_TESTS_IN_PLAN)) * 100 + // (5 / (2 * 5)) * 100 = 50 + expect( + calculateTestPlanReportCompletionPercentage({ + metrics, + draftTestPlanRuns + }) + ).toBe(50); + }); }); diff --git a/client/tests/smokeTest.test.js b/client/tests/smokeTest.test.js index e30143a68..56cf0c8f6 100644 --- a/client/tests/smokeTest.test.js +++ b/client/tests/smokeTest.test.js @@ -11,78 +11,74 @@ here: https://github.com/w3c/aria-at-app/pull/895 */ describe('smoke test', () => { - beforeAll(async () => { - await setup(); - }, 30000); + beforeAll(async () => { + await setup(); + }, 30000); - afterAll(async () => { - await teardown(); - }, 30000); + afterAll(async () => { + await teardown(); + }, 30000); - it('can sign in as admin, tester, vendor, or logged out', async () => { - await Promise.all([ - getPage({ role: 'admin', url: '/test-queue' }, async page => { - // Only admins can remove rows from the test queue - await page.waitForSelector('td.actions ::-p-text(Remove)'); - }), + it('can sign in as admin, tester, vendor, or logged out', async () => { + await Promise.all([ + getPage({ role: 'admin', url: '/test-queue' }, async page => { + // Only admins can remove rows from the test queue + await page.waitForSelector('td.actions ::-p-text(Remove)'); + }), - getPage({ role: 'tester', url: '/test-queue' }, async page => { - // Testers can assign themselves - await page.waitForSelector('table ::-p-text(Assign Yourself)'); - const adminOnlyRemoveButton = await page.$( - 'td.actions ::-p-text(Remove)' - ); - expect(adminOnlyRemoveButton).toBe(null); - }), + getPage({ role: 'tester', url: '/test-queue' }, async page => { + // Testers can assign themselves + await page.waitForSelector('table ::-p-text(Assign Yourself)'); + const adminOnlyRemoveButton = await page.$( + 'td.actions ::-p-text(Remove)' + ); + expect(adminOnlyRemoveButton).toBe(null); + }), - getPage( - { role: 'vendor', url: '/test-queue' }, - async (page, { baseUrl }) => { - // Vendors get the same test queue as signed-out users - await page.waitForSelector( - 'td.actions ::-p-text(View tests)' - ); - // Unlike signed-out users, they will get tables on this page - await page.goto(`${baseUrl}/candidate-review`); - await page.waitForSelector('table'); - } - ), + getPage( + { role: 'vendor', url: '/test-queue' }, + async (page, { baseUrl }) => { + // Vendors get the same test queue as signed-out users + await page.waitForSelector('td.actions ::-p-text(View tests)'); + // Unlike signed-out users, they will get tables on this page + await page.goto(`${baseUrl}/candidate-review`); + await page.waitForSelector('table'); + } + ), - getPage({ role: false, url: '/test-queue' }, async page => { - // Signed-out users can only view tests, not run them - await page.waitForSelector('td.actions ::-p-text(View tests)'); - }) - ]); - }, 10000); + getPage({ role: false, url: '/test-queue' }, async page => { + // Signed-out users can only view tests, not run them + await page.waitForSelector('td.actions ::-p-text(View tests)'); + }) + ]); + }, 10000); - it('loads various pages without crashing', async () => { - await Promise.all([ - getPage({ role: false, url: '/' }, async page => { - await page.waitForSelector('h1'); - const h1Handle = await page.waitForSelector('h1'); - const h1Text = await h1Handle.evaluate(h1 => h1.innerText); - expect(h1Text).toBe( - 'Enabling Interoperability for Assistive Technology Users' - ); - }), - getPage({ role: false, url: '/reports' }, async page => { - // Wait for an h2 because an h1 will show while the page is - // still loading - await page.waitForSelector('h2'); - const h1Handle = await page.waitForSelector('h1'); - const h1Text = await h1Handle.evaluate(h1 => h1.innerText); - expect(h1Text).toBe( - 'Assistive Technology Interoperability Reports' - ); - }), - getPage({ role: false, url: '/data-management' }, async page => { - // Wait for an h2 because an h1 will show while the page is - // still loading - await page.waitForSelector('h2'); - const h1Handle = await page.waitForSelector('h1'); - const h1Text = await h1Handle.evaluate(h1 => h1.innerText); - expect(h1Text).toBe('Data Management'); - }) - ]); - }, 10000); + it('loads various pages without crashing', async () => { + await Promise.all([ + getPage({ role: false, url: '/' }, async page => { + await page.waitForSelector('h1'); + const h1Handle = await page.waitForSelector('h1'); + const h1Text = await h1Handle.evaluate(h1 => h1.innerText); + expect(h1Text).toBe( + 'Enabling Interoperability for Assistive Technology Users' + ); + }), + getPage({ role: false, url: '/reports' }, async page => { + // Wait for an h2 because an h1 will show while the page is + // still loading + await page.waitForSelector('h2'); + const h1Handle = await page.waitForSelector('h1'); + const h1Text = await h1Handle.evaluate(h1 => h1.innerText); + expect(h1Text).toBe('Assistive Technology Interoperability Reports'); + }), + getPage({ role: false, url: '/data-management' }, async page => { + // Wait for an h2 because an h1 will show while the page is + // still loading + await page.waitForSelector('h2'); + const h1Handle = await page.waitForSelector('h1'); + const h1Text = await h1Handle.evaluate(h1 => h1.innerText); + expect(h1Text).toBe('Data Management'); + }) + ]); + }, 10000); }); diff --git a/client/tests/util/getPage.js b/client/tests/util/getPage.js index 13cc8d5af..060d55717 100644 --- a/client/tests/util/getPage.js +++ b/client/tests/util/getPage.js @@ -13,74 +13,72 @@ const AUTOMATION_SCHEDULER_PORT = 8833; const baseUrl = `http://localhost:${CLIENT_PORT}`; const startServer = async serverOrClient => { - return new Promise(resolve => { - const server = spawn('yarn', ['workspace', serverOrClient, 'dev'], { - cwd: path.resolve(__dirname, '../../'), - env: { - PATH: process.env.PATH, - PORT, - CLIENT_PORT, - AUTOMATION_SCHEDULER_PORT, - API_SERVER: `http://localhost:${PORT}`, - APP_SERVER: baseUrl, - AUTOMATION_SCHEDULER_URL: `http://localhost:${AUTOMATION_SCHEDULER_PORT}`, - PGDATABASE: 'aria_at_report_test', - PGPORT: 5432, - ENVIRONMENT: 'test' - } - }); + return new Promise(resolve => { + const server = spawn('yarn', ['workspace', serverOrClient, 'dev'], { + cwd: path.resolve(__dirname, '../../'), + env: { + PATH: process.env.PATH, + PORT, + CLIENT_PORT, + AUTOMATION_SCHEDULER_PORT, + API_SERVER: `http://localhost:${PORT}`, + APP_SERVER: baseUrl, + AUTOMATION_SCHEDULER_URL: `http://localhost:${AUTOMATION_SCHEDULER_PORT}`, + PGDATABASE: 'aria_at_report_test', + PGPORT: 5432, + ENVIRONMENT: 'test' + } + }); - const killServer = async () => { - await new Promise((resolve, reject) => { - treeKill(server.pid, error => { - if (error) return reject(error); - resolve(); - }); - }); - }; - - server.stdout.on('data', data => { - const output = data.toString(); - console.info(output); // eslint-disable-line no-console - - if ( - (serverOrClient === 'server' && - output.includes(`Listening on ${PORT}`)) || - (serverOrClient === 'client' && - output.includes('compiled successfully')) - ) { - resolve({ close: killServer }); - } + const killServer = async () => { + await new Promise((resolve, reject) => { + treeKill(server.pid, error => { + if (error) return reject(error); + resolve(); }); + }); + }; + + server.stdout.on('data', data => { + const output = data.toString(); + console.info(output); // eslint-disable-line no-console + + if ( + (serverOrClient === 'server' && + output.includes(`Listening on ${PORT}`)) || + (serverOrClient === 'client' && + output.includes('compiled successfully')) + ) { + resolve({ close: killServer }); + } + }); - server.stderr.on('data', data => { - const output = data.toString(); - console.info(output); // eslint-disable-line no-console - }); + server.stderr.on('data', data => { + const output = data.toString(); + console.info(output); // eslint-disable-line no-console }); + }); }; const setup = async () => { - // eslint-disable-next-line no-console - console.info( - 'Starting dev servers. This is required for end-to-end testing' - ); - [clientServer, backendServer] = await Promise.all([ - startServer('client'), - startServer('server') - ]); - - browser = await puppeteer.launch({ - headless: 'new', - args: ['--no-sandbox'] // Required for GitHub environment - }); + // eslint-disable-next-line no-console + console.info('Starting dev servers. This is required for end-to-end testing'); + [clientServer, backendServer] = await Promise.all([ + startServer('client'), + startServer('server') + ]); + + browser = await puppeteer.launch({ + headless: 'new', + args: ['--no-sandbox'] // Required for GitHub environment + }); }; const teardown = async () => { - await Promise.all([backendServer.close(), clientServer.close()]); + await Promise.all([backendServer.close(), clientServer.close()]); - // Browser might not be defined, if it failed to start - if (browser) await browser.close(); + // Browser might not be defined, if it failed to start + if (browser) await browser.close(); }; let incognitoContexts = {}; @@ -97,45 +95,45 @@ let incognitoContexts = {}; * needed for navigation. */ const getPage = async (options, callback) => { - const { role, url } = options; - if (role == null || !['admin', 'tester', 'vendor', false].includes(role)) { - throw new Error('Please provide a valid role'); - } + const { role, url } = options; + if (role == null || !['admin', 'tester', 'vendor', false].includes(role)) { + throw new Error('Please provide a valid role'); + } - if (!incognitoContexts[role]) { - incognitoContexts[role] = await browser.createIncognitoBrowserContext(); - } - const incognitoContext = incognitoContexts[role]; - - const page = await incognitoContext.newPage(); + if (!incognitoContexts[role]) { + incognitoContexts[role] = await browser.createIncognitoBrowserContext(); + } + const incognitoContext = incognitoContexts[role]; - if (!url) { - throw new Error('Please provide a URL, even if it it is simply "/"'); - } + const page = await incognitoContext.newPage(); - await page.goto(`http://localhost:${CLIENT_PORT}${url}`); + if (!url) { + throw new Error('Please provide a URL, even if it it is simply "/"'); + } - if (role) { - await page.waitForSelector('::-p-text(Sign in with GitHub)'); + await page.goto(`http://localhost:${CLIENT_PORT}${url}`); - const username = `joe-the-${role}`; + if (role) { + await page.waitForSelector('::-p-text(Sign in with GitHub)'); - if (role === 'admin') { - await page.evaluate(`signMeInAsAdmin("${username}")`); - } - if (role === 'tester') { - await page.evaluate(`signMeInAsTester("${username}")`); - } - if (role === 'vendor') { - await page.evaluate(`signMeInAsVendor("${username}")`); - } + const username = `joe-the-${role}`; - await page.waitForSelector('::-p-text(Signed in)'); + if (role === 'admin') { + await page.evaluate(`signMeInAsAdmin("${username}")`); } + if (role === 'tester') { + await page.evaluate(`signMeInAsTester("${username}")`); + } + if (role === 'vendor') { + await page.evaluate(`signMeInAsVendor("${username}")`); + } + + await page.waitForSelector('::-p-text(Signed in)'); + } - await callback(page, { baseUrl }); + await callback(page, { baseUrl }); - await page.close(); + await page.close(); }; export default getPage; diff --git a/client/tests/util/index.js b/client/tests/util/index.js index a527bf716..96c576e9f 100644 --- a/client/tests/util/index.js +++ b/client/tests/util/index.js @@ -1,3 +1,3 @@ export const findByTestAttr = function (wrapper, val) { - return wrapper.find(`[data-test="${val}"]`); + return wrapper.find(`[data-test="${val}"]`); }; diff --git a/client/utils/DisplayNone.jsx b/client/utils/DisplayNone.jsx index 6a3888df4..83f7322fb 100644 --- a/client/utils/DisplayNone.jsx +++ b/client/utils/DisplayNone.jsx @@ -2,11 +2,11 @@ import React from 'react'; import PropTypes from 'prop-types'; const DisplayNone = ({ children }) => { - return
    {children}
    ; + return
    {children}
    ; }; DisplayNone.propTypes = { - children: PropTypes.node.isRequired + children: PropTypes.node.isRequired }; export default DisplayNone; diff --git a/client/utils/ScrollFixer.jsx b/client/utils/ScrollFixer.jsx index aec5334f4..3f84f6d5b 100644 --- a/client/utils/ScrollFixer.jsx +++ b/client/utils/ScrollFixer.jsx @@ -9,61 +9,61 @@ import { useLocation } from 'react-router'; * that it must be inside React Router's Router component. */ const ScrollFixer = ({ children }) => { - const location = useLocation(); + const location = useLocation(); - useLayoutEffect(() => { - const scrollTop = () => { - window.scroll(0, 0); - // When switching pages, the focus should jump to the top. Otherwise - // screen readers' focus might be lingering in a nonsensical - // location partly down the page. - document.querySelector('a').focus(); - }; - if (!location.hash) return scrollTop(); - (async () => { - // The point at which the window jumping down the page would become - // disorienting. This must include time for the page's API requests - // to complete. - const timeout = 8000; - const element = await pollForElement(location.hash, { timeout }); - if (!element) return scrollTop(); - element.scrollIntoView(); - element.focus(); - })(); - }, [location]); + useLayoutEffect(() => { + const scrollTop = () => { + window.scroll(0, 0); + // When switching pages, the focus should jump to the top. Otherwise + // screen readers' focus might be lingering in a nonsensical + // location partly down the page. + document.querySelector('a').focus(); + }; + if (!location.hash) return scrollTop(); + (async () => { + // The point at which the window jumping down the page would become + // disorienting. This must include time for the page's API requests + // to complete. + const timeout = 8000; + const element = await pollForElement(location.hash, { timeout }); + if (!element) return scrollTop(); + element.scrollIntoView(); + element.focus(); + })(); + }, [location]); - return children; + return children; }; ScrollFixer.propTypes = { - children: PropTypes.node.isRequired + children: PropTypes.node.isRequired }; const pollForElement = async (selector, { timeout }) => { - let element = document.querySelector(selector); - if (element) return element; + let element = document.querySelector(selector); + if (element) return element; - let timeoutExceeded = false; - window.setTimeout(() => { - timeoutExceeded = true; - }, timeout); + let timeoutExceeded = false; + window.setTimeout(() => { + timeoutExceeded = true; + }, timeout); - return new Promise(resolve => { - const interval = window.setInterval(() => { - element = document.querySelector(selector); + return new Promise(resolve => { + const interval = window.setInterval(() => { + element = document.querySelector(selector); - if (element) { - clearInterval(interval); - resolve(element); - return; - } + if (element) { + clearInterval(interval); + resolve(element); + return; + } - if (timeoutExceeded) { - clearInterval(interval); - resolve(null); - } - }, 10); - }); + if (timeoutExceeded) { + clearInterval(interval); + resolve(null); + } + }, 10); + }); }; export default ScrollFixer; diff --git a/client/utils/alphabetizeObjectBy.js b/client/utils/alphabetizeObjectBy.js index 9d4968f36..5a26a2319 100644 --- a/client/utils/alphabetizeObjectBy.js +++ b/client/utils/alphabetizeObjectBy.js @@ -11,12 +11,12 @@ * @returns - The same object but with its keys sorted. */ const alphabetizeObjectBy = (object, getString) => { - return Object.fromEntries( - Object.entries(object).sort((a, b) => { - // https://stackoverflow.com/a/45544166/3888572 - return getString(a).localeCompare(getString(b)); - }) - ); + return Object.fromEntries( + Object.entries(object).sort((a, b) => { + // https://stackoverflow.com/a/45544166/3888572 + return getString(a).localeCompare(getString(b)); + }) + ); }; export default alphabetizeObjectBy; diff --git a/client/utils/alphabetizeObjectBy.test.js b/client/utils/alphabetizeObjectBy.test.js index 419e3ff4d..8b801727d 100644 --- a/client/utils/alphabetizeObjectBy.test.js +++ b/client/utils/alphabetizeObjectBy.test.js @@ -1,22 +1,22 @@ import alphabetizeObjectBy from './alphabetizeObjectBy'; describe('alphabetizeObjectBy', () => { - it('alphabetizes an object', () => { - const before = { z: 1, y: 2, x: 3 }; - const after = alphabetizeObjectBy(before, ([key]) => key); - expect(Object.entries(after)).toEqual([ - ['x', 3], - ['y', 2], - ['z', 1] - ]); - }); + it('alphabetizes an object', () => { + const before = { z: 1, y: 2, x: 3 }; + const after = alphabetizeObjectBy(before, ([key]) => key); + expect(Object.entries(after)).toEqual([ + ['x', 3], + ['y', 2], + ['z', 1] + ]); + }); - it('returns a shallow copy', () => { - const identicalObject = {}; - const before = { c: 1, b: 2, a: identicalObject }; - const after = alphabetizeObjectBy(before, ([key]) => key); - identicalObject.testAddingAProperty = true; - expect(after.a).toBe(identicalObject); - expect(after.a.testAddingAProperty).toBe(true); - }); + it('returns a shallow copy', () => { + const identicalObject = {}; + const before = { c: 1, b: 2, a: identicalObject }; + const after = alphabetizeObjectBy(before, ([key]) => key); + identicalObject.testAddingAProperty = true; + expect(after.a).toBe(identicalObject); + expect(after.a.testAddingAProperty).toBe(true); + }); }); diff --git a/client/utils/aria.js b/client/utils/aria.js index 6118c86f5..6a9b97d8e 100644 --- a/client/utils/aria.js +++ b/client/utils/aria.js @@ -1,25 +1,25 @@ export const evaluateAtNameKey = atName => { - // Could probably add back support for AT keys from the database level - if (atName.toLowerCase().includes('voiceover')) return 'voiceover_macos'; - else return atName.toLowerCase(); + // Could probably add back support for AT keys from the database level + if (atName.toLowerCase().includes('voiceover')) return 'voiceover_macos'; + else return atName.toLowerCase(); }; export const buildTestPageUrl = (gitSha, directory, testReferencePath) => { - const BASE_PATH = '/aria-at'; - return `${BASE_PATH}/${gitSha}/build/tests/${directory}/${testReferencePath}`; + const BASE_PATH = '/aria-at'; + return `${BASE_PATH}/${gitSha}/build/tests/${directory}/${testReferencePath}`; }; export const derivePhaseName = name => { - switch (name) { - case 'RD': - return 'R&D'; - case 'DRAFT': - return 'Draft'; - case 'CANDIDATE': - return 'Candidate'; - case 'RECOMMENDED': - return 'Recommended'; - case 'DEPRECATED': - return 'Deprecated'; - } + switch (name) { + case 'RD': + return 'R&D'; + case 'DRAFT': + return 'Draft'; + case 'CANDIDATE': + return 'Candidate'; + case 'RECOMMENDED': + return 'Recommended'; + case 'DEPRECATED': + return 'Deprecated'; + } }; diff --git a/client/utils/automation.js b/client/utils/automation.js index 55f00b24a..070f89a92 100644 --- a/client/utils/automation.js +++ b/client/utils/automation.js @@ -1,15 +1,15 @@ export const isSupportedByResponseCollector = ctx => { - if (!ctx || !ctx.at || !ctx.browser) { - return false; - } - return ctx.at.name === 'NVDA' && ctx.browser.name === 'Chrome'; + if (!ctx || !ctx.at || !ctx.browser) { + return false; + } + return ctx.at.name === 'NVDA' && ctx.browser.name === 'Chrome'; }; export const isBot = user => user?.username?.toLowerCase().slice(-3) === 'bot'; // TODO: Stub, support for more bot users should be added export const getBotUsernameFromAtBrowser = (at, browser) => { - if (at?.name === 'NVDA' && browser?.name === 'Chrome') { - return 'NVDA Bot'; - } + if (at?.name === 'NVDA' && browser?.name === 'Chrome') { + return 'NVDA Bot'; + } }; diff --git a/client/utils/constants.js b/client/utils/constants.js index 8f496c7cf..95ac65805 100644 --- a/client/utils/constants.js +++ b/client/utils/constants.js @@ -1,6 +1,6 @@ export const TEST_PLAN_VERSION_PHASES = { - RD: 'RD', - DRAFT: 'DRAFT', - CANDIDATE: 'CANDIDATE', - RECOMMENDED: 'RECOMMENDED' + RD: 'RD', + DRAFT: 'DRAFT', + CANDIDATE: 'CANDIDATE', + RECOMMENDED: 'RECOMMENDED' }; diff --git a/client/utils/createIssueLink.js b/client/utils/createIssueLink.js index 253d17517..75df6fc7d 100644 --- a/client/utils/createIssueLink.js +++ b/client/utils/createIssueLink.js @@ -1,158 +1,158 @@ const GITHUB_ISSUES_URL = - process.env.ENVIRONMENT === 'production' - ? 'https://github.com/w3c/aria-at' - : 'https://github.com/bocoup/aria-at'; + process.env.ENVIRONMENT === 'production' + ? 'https://github.com/w3c/aria-at' + : 'https://github.com/bocoup/aria-at'; const atLabelMap = { - 'VoiceOver for macOS': 'vo', - JAWS: 'jaws', - NVDA: 'nvda' + 'VoiceOver for macOS': 'vo', + JAWS: 'jaws', + NVDA: 'nvda' }; const createIssueLink = ({ - isCandidateReview = false, - isCandidateReviewChangesRequested = false, - testPlanDirectory, - testPlanTitle, - versionString, - testTitle = null, - testRowNumber = null, - testRenderedUrl = null, - atName, - atVersionName = null, - browserName = null, - browserVersionName = null, - conflictMarkdown = null, - reportLink = null + isCandidateReview = false, + isCandidateReviewChangesRequested = false, + testPlanDirectory, + testPlanTitle, + versionString, + testTitle = null, + testRowNumber = null, + testRenderedUrl = null, + atName, + atVersionName = null, + browserName = null, + browserVersionName = null, + conflictMarkdown = null, + reportLink = null }) => { - if (!(testPlanDirectory || testPlanTitle || versionString || atName)) { - throw new Error('Cannot create issue link due to missing parameters'); - } - - const hasTest = !!(testTitle && testRowNumber && testRenderedUrl); - - let title; - if (hasTest) { - let titleStart; - if (isCandidateReview) { - titleStart = isCandidateReviewChangesRequested - ? `${atName} Changes Requested` - : `${atName} Feedback`; - } else { - titleStart = 'Feedback'; - } - - title = - `${titleStart}: "${testTitle}" (${testPlanTitle}, ` + - `Test ${testRowNumber}, ${versionString})`; + if (!(testPlanDirectory || testPlanTitle || versionString || atName)) { + throw new Error('Cannot create issue link due to missing parameters'); + } + + const hasTest = !!(testTitle && testRowNumber && testRenderedUrl); + + let title; + if (hasTest) { + let titleStart; + if (isCandidateReview) { + titleStart = isCandidateReviewChangesRequested + ? `${atName} Changes Requested` + : `${atName} Feedback`; } else { - title = `${atName} General Feedback: ${testPlanTitle} ${versionString}`; + titleStart = 'Feedback'; } - const labels = - (isCandidateReview ? 'candidate-review,' : '') + - `${atLabelMap[atName]},` + - (isCandidateReviewChangesRequested ? 'changes-requested' : 'feedback'); + title = + `${titleStart}: "${testTitle}" (${testPlanTitle}, ` + + `Test ${testRowNumber}, ${versionString})`; + } else { + title = `${atName} General Feedback: ${testPlanTitle} ${versionString}`; + } + + const labels = + (isCandidateReview ? 'candidate-review,' : '') + + `${atLabelMap[atName]},` + + (isCandidateReviewChangesRequested ? 'changes-requested' : 'feedback'); + + let reportLinkFormatted = ''; + if (reportLink) { + reportLinkFormatted = `- Report Page: [Link](${reportLink})\n`; + } + + let testSetupFormatted = ''; + if (hasTest) { + // TODO: fix renderedUrl + let modifiedRenderedUrl = testRenderedUrl.replace( + /.+(?=\/tests)/, + 'https://aria-at.netlify.app' + ); - let reportLinkFormatted = ''; - if (reportLink) { - reportLinkFormatted = `- Report Page: [Link](${reportLink})\n`; - } + const shortenedUrl = modifiedRenderedUrl?.match(/[^/]+$/)[0]; - let testSetupFormatted = ''; - if (hasTest) { - // TODO: fix renderedUrl - let modifiedRenderedUrl = testRenderedUrl.replace( - /.+(?=\/tests)/, - 'https://aria-at.netlify.app' - ); - - const shortenedUrl = modifiedRenderedUrl?.match(/[^/]+$/)[0]; - - let atFormatted; - if (atVersionName) { - atFormatted = `- AT: ${atName} (Version ${atVersionName})\n`; - } else { - atFormatted = `- AT: ${atName}\n`; - } - - let browserFormatted = ''; - if (browserName && browserVersionName) { - browserFormatted = `- Browser: ${browserName} (Version ${browserVersionName})\n`; - } else if (browserName) { - browserFormatted = `- Browser: ${browserName}\n`; - } - - testSetupFormatted = - `## Test Setup\n\n` + - `- Test File: ` + - `[${shortenedUrl}](${modifiedRenderedUrl})\n` + - reportLinkFormatted + - atFormatted + - browserFormatted + - '\n'; + let atFormatted; + if (atVersionName) { + atFormatted = `- AT: ${atName} (Version ${atVersionName})\n`; + } else { + atFormatted = `- AT: ${atName}\n`; } - const hiddenIssueMetadata = JSON.stringify({ - testPlanDirectory, - versionString, - atName, - browserName, - testRowNumber, - isCandidateReview, - isCandidateReviewChangesRequested - }); - - let body = - `## Description of Behavior\n\n` + - `\n\n` + - testSetupFormatted + - `\n` + - ``; - - if (conflictMarkdown) { - body += `\n${conflictMarkdown}`; + let browserFormatted = ''; + if (browserName && browserVersionName) { + browserFormatted = `- Browser: ${browserName} (Version ${browserVersionName})\n`; + } else if (browserName) { + browserFormatted = `- Browser: ${browserName}\n`; } - return ( - `${GITHUB_ISSUES_URL}/issues/new?title=${encodeURI(title)}&` + - `labels=${labels}&body=${encodeURIComponent(body)}` - ); + testSetupFormatted = + `## Test Setup\n\n` + + `- Test File: ` + + `[${shortenedUrl}](${modifiedRenderedUrl})\n` + + reportLinkFormatted + + atFormatted + + browserFormatted + + '\n'; + } + + const hiddenIssueMetadata = JSON.stringify({ + testPlanDirectory, + versionString, + atName, + browserName, + testRowNumber, + isCandidateReview, + isCandidateReviewChangesRequested + }); + + let body = + `## Description of Behavior\n\n` + + `\n\n` + + testSetupFormatted + + `\n` + + ``; + + if (conflictMarkdown) { + body += `\n${conflictMarkdown}`; + } + + return ( + `${GITHUB_ISSUES_URL}/issues/new?title=${encodeURI(title)}&` + + `labels=${labels}&body=${encodeURIComponent(body)}` + ); }; export const getIssueSearchLink = ({ - isCandidateReview = false, - isCandidateReviewChangesRequested = false, - username = null, - atName, - testPlanTitle, - versionString, - testRowNumber = null + isCandidateReview = false, + isCandidateReviewChangesRequested = false, + username = null, + atName, + testPlanTitle, + versionString, + testRowNumber = null }) => { - let atKey; - if (atName === 'JAWS' || atName === 'NVDA') { - atKey = atName.toLowerCase(); - } else { - atKey = 'vo'; - } - - const query = [ - isCandidateReview ? `label:candidate-review` : '', - isCandidateReviewChangesRequested - ? `label:changes-requested` - : 'label:feedback', - `label:${atLabelMap[atName]}`, - username ? `author:${username}` : '', - `label:${atKey}`, - `"${testPlanTitle}"`, - testRowNumber ? `Test ${testRowNumber}` : '', - versionString - ] - .filter(str => str) - .join(' '); - - return `${GITHUB_ISSUES_URL}/issues?q=${encodeURI(query)}`; + let atKey; + if (atName === 'JAWS' || atName === 'NVDA') { + atKey = atName.toLowerCase(); + } else { + atKey = 'vo'; + } + + const query = [ + isCandidateReview ? `label:candidate-review` : '', + isCandidateReviewChangesRequested + ? `label:changes-requested` + : 'label:feedback', + `label:${atLabelMap[atName]}`, + username ? `author:${username}` : '', + `label:${atKey}`, + `"${testPlanTitle}"`, + testRowNumber ? `Test ${testRowNumber}` : '', + versionString + ] + .filter(str => str) + .join(' '); + + return `${GITHUB_ISSUES_URL}/issues?q=${encodeURI(query)}`; }; export default createIssueLink; diff --git a/client/utils/evaluateAuth.js b/client/utils/evaluateAuth.js index 6c41f5c40..5811077dd 100644 --- a/client/utils/evaluateAuth.js +++ b/client/utils/evaluateAuth.js @@ -10,20 +10,20 @@ * @returns {Auth} - evaluated auth object */ export const evaluateAuth = (data = {}) => { - const roles = data.roles || []; + const roles = data.roles || []; - return { - // calculated booleans - isAdmin: roles.includes('ADMIN'), - isTester: roles.includes('TESTER'), - isVendor: roles.includes('VENDOR'), - isSignedIn: !!data.username, + return { + // calculated booleans + isAdmin: roles.includes('ADMIN'), + isTester: roles.includes('TESTER'), + isVendor: roles.includes('VENDOR'), + isSignedIn: !!data.username, - // user object values - id: data.id || null, - username: data.username || null, - roles - }; + // user object values + id: data.id || null, + username: data.username || null, + roles + }; }; /** diff --git a/client/utils/formSerialization.js b/client/utils/formSerialization.js index f2f7018a3..a8b0f1508 100644 --- a/client/utils/formSerialization.js +++ b/client/utils/formSerialization.js @@ -5,46 +5,46 @@ const selector = 'input, button, textarea, select, fieldset, optgroup, option'; // 'name', 'disabled', and 'selected' // state export function serialize(root) { - const nodes = root.querySelectorAll(selector); - // serialized element state is saved in an - // array since element traversal order will - // always be the same - let serialized = []; + const nodes = root.querySelectorAll(selector); + // serialized element state is saved in an + // array since element traversal order will + // always be the same + let serialized = []; - for (let node of nodes) { - let nodeState = {}; + for (let node of nodes) { + let nodeState = {}; - switch (node.tagName.toLowerCase()) { - case 'input': - if (node.type == 'checkbox' || node.type == 'radio') { - nodeState.checked = node.checked; - nodeState.indeterminate = node.indeterminate; - } - // falls through - case 'button': - case 'textarea': - nodeState.value = node.value; - // falls through - case 'select': - case 'fieldset': - nodeState.name = node.name; - // falls through - case 'optgroup': - nodeState.disabled = node.disabled; - break; - case 'option': - nodeState.value = node.value; - nodeState.disabled = node.disabled; - nodeState.selected = node.selected; - break; - default: - break; + switch (node.tagName.toLowerCase()) { + case 'input': + if (node.type == 'checkbox' || node.type == 'radio') { + nodeState.checked = node.checked; + nodeState.indeterminate = node.indeterminate; } - - serialized.push(nodeState); + // falls through + case 'button': + case 'textarea': + nodeState.value = node.value; + // falls through + case 'select': + case 'fieldset': + nodeState.name = node.name; + // falls through + case 'optgroup': + nodeState.disabled = node.disabled; + break; + case 'option': + nodeState.value = node.value; + nodeState.disabled = node.disabled; + nodeState.selected = node.selected; + break; + default: + break; } - return serialized; + serialized.push(nodeState); + } + + return serialized; } // hydrate form elements by restoring @@ -52,32 +52,32 @@ export function serialize(root) { // 'name', 'disabled', and 'selected' // state export function hydrate(serialized, root) { - const nodes = root.querySelectorAll(selector); + const nodes = root.querySelectorAll(selector); - if (nodes.length !== serialized.length) - throw new Error( - 'Form deserialization failed: serialized nodes are not the same shape as given nodes' - ); + if (nodes.length !== serialized.length) + throw new Error( + 'Form deserialization failed: serialized nodes are not the same shape as given nodes' + ); - for (let [i, node] of nodes.entries()) { - const nodeState = serialized[i]; - if (typeof nodeState.disabled !== 'undefined') { - node.disabled = nodeState.disabled; - } - if (typeof nodeState.name !== 'undefined') { - node.name = nodeState.name; - } - if (typeof nodeState.value !== 'undefined') { - node.value = nodeState.value; - } - if (typeof nodeState.selected !== 'undefined') { - node.selected = nodeState.selected; - } - if (typeof nodeState.indeterminate !== 'undefined') { - node.indeterminate = nodeState.indeterminate; - } - if (typeof nodeState.checked !== 'undefined') { - node.checked = nodeState.checked; - } + for (let [i, node] of nodes.entries()) { + const nodeState = serialized[i]; + if (typeof nodeState.disabled !== 'undefined') { + node.disabled = nodeState.disabled; + } + if (typeof nodeState.name !== 'undefined') { + node.name = nodeState.name; + } + if (typeof nodeState.value !== 'undefined') { + node.value = nodeState.value; + } + if (typeof nodeState.selected !== 'undefined') { + node.selected = nodeState.selected; + } + if (typeof nodeState.indeterminate !== 'undefined') { + node.indeterminate = nodeState.indeterminate; + } + if (typeof nodeState.checked !== 'undefined') { + node.checked = nodeState.checked; } + } } diff --git a/client/utils/formatter.js b/client/utils/formatter.js index 7951603bc..c5f4487e7 100644 --- a/client/utils/formatter.js +++ b/client/utils/formatter.js @@ -12,40 +12,40 @@ import moment from 'moment'; * @returns {string} - transformed string */ export const capitalizeEachWord = ( - sentence, - { splitChar = ' ', joinChar = ' ' } + sentence, + { splitChar = ' ', joinChar = ' ' } ) => { - const words = sentence.toLowerCase().split(splitChar); - for (let i = 0; i < words.length; i++) - words[i] = `${words[i][0].toUpperCase() + words[i].substr(1)}`; + const words = sentence.toLowerCase().split(splitChar); + for (let i = 0; i < words.length; i++) + words[i] = `${words[i][0].toUpperCase() + words[i].substr(1)}`; - return words.join(joinChar); + return words.join(joinChar); }; export const convertDateToString = (date, format = 'DD-MM-YYYY') => { - if (!date) return ''; - return moment(date).format(format); + if (!date) return ''; + return moment(date).format(format); }; export const convertStringToDate = (date, format = 'DD-MM-YYYY') => { - return moment(date, format).toDate(); + return moment(date, format).toDate(); }; export const convertStringFormatToAnotherFormat = ( - date, - fromFormat = 'DD-MM-YYYY', - toFormat = 'MM-DD-YYYY' + date, + fromFormat = 'DD-MM-YYYY', + toFormat = 'MM-DD-YYYY' ) => { - return moment(date, fromFormat).format(toFormat); + return moment(date, fromFormat).format(toFormat); }; export const isValidDate = (date, format = 'DD-MM-YYYY') => { - return moment(date, format).isValid(); + return moment(date, format).isValid(); }; export const checkDaysBetweenDates = (date, otherDate) => { - const _date = moment(date); - const _otherDate = moment(otherDate); - const hours = _date.diff(_otherDate, 'hours'); - return Math.ceil(hours / 24); + const _date = moment(date); + const _otherDate = moment(otherDate); + const hours = _date.diff(_otherDate, 'hours'); + return Math.ceil(hours / 24); }; diff --git a/client/utils/gitUtils.js b/client/utils/gitUtils.js index 4de5da85d..d3ad2cd04 100644 --- a/client/utils/gitUtils.js +++ b/client/utils/gitUtils.js @@ -3,15 +3,15 @@ const timeZone = 'UTC'; const options = { month: 'short' }; export const gitUpdatedDateToString = (dateString, locale = 'default') => { - const date = new Date(dateString); - const month = date.toLocaleString(locale, options); - const day = date.getDate(); - const year = date.getFullYear(); - const time = date - .toLocaleTimeString(locale, { timeZone: timeZone }) - .replace(/\s/g, ' '); + const date = new Date(dateString); + const month = date.toLocaleString(locale, options); + const day = date.getDate(); + const year = date.getFullYear(); + const time = date + .toLocaleTimeString(locale, { timeZone: timeZone }) + .replace(/\s/g, ' '); - const timeStamp = `${month} ${day}, ${year} at ${time} ${timeZone}`; + const timeStamp = `${month} ${day}, ${year} at ${time} ${timeZone}`; - return lc('PM', lc('AM', timeStamp)); + return lc('PM', lc('AM', timeStamp)); }; diff --git a/client/utils/gitUtils.test.js b/client/utils/gitUtils.test.js index e6d7d480d..793e255de 100644 --- a/client/utils/gitUtils.test.js +++ b/client/utils/gitUtils.test.js @@ -1,28 +1,28 @@ import { gitUpdatedDateToString } from './gitUtils'; describe('gitUpdatedDateToString', () => { - it('returns a formatted string AM', () => { - const date = '2021-11-30T09:51:28.000Z'; - const formattedDate = gitUpdatedDateToString(date, 'en-US'); - expect(formattedDate).toBe('Nov 30, 2021 at 9:51:28 am UTC'); - }); + it('returns a formatted string AM', () => { + const date = '2021-11-30T09:51:28.000Z'; + const formattedDate = gitUpdatedDateToString(date, 'en-US'); + expect(formattedDate).toBe('Nov 30, 2021 at 9:51:28 am UTC'); + }); - it('returns a formatted string PM', () => { - const date = '2021-11-30T14:51:28.000Z'; - const formattedDate = gitUpdatedDateToString(date, 'en-US'); - expect(formattedDate).toBe('Nov 30, 2021 at 2:51:28 pm UTC'); - }); + it('returns a formatted string PM', () => { + const date = '2021-11-30T14:51:28.000Z'; + const formattedDate = gitUpdatedDateToString(date, 'en-US'); + expect(formattedDate).toBe('Nov 30, 2021 at 2:51:28 pm UTC'); + }); - it('returns a formatted string when using 24-hour notation in a different locale (French)', () => { - const date = '2021-11-30T14:51:28.000Z'; - const formattedDate = gitUpdatedDateToString(date, 'fr-FR'); - // French time uses a lowercase month notation - expect(formattedDate).toBe('nov. 30, 2021 at 14:51:28 UTC'); - }); + it('returns a formatted string when using 24-hour notation in a different locale (French)', () => { + const date = '2021-11-30T14:51:28.000Z'; + const formattedDate = gitUpdatedDateToString(date, 'fr-FR'); + // French time uses a lowercase month notation + expect(formattedDate).toBe('nov. 30, 2021 at 14:51:28 UTC'); + }); - it('returns a formatted string when using a different locale (Korean)', () => { - const date = '2021-11-30T14:51:28.000Z'; - const formattedDate = gitUpdatedDateToString(date, 'ko-KR'); - expect(formattedDate).toBe('11월 30, 2021 at 오후 2:51:28 UTC'); - }); + it('returns a formatted string when using a different locale (Korean)', () => { + const date = '2021-11-30T14:51:28.000Z'; + const formattedDate = gitUpdatedDateToString(date, 'ko-KR'); + expect(formattedDate).toBe('11월 30, 2021 at 오후 2:51:28 UTC'); + }); }); diff --git a/client/utils/navigateTests.js b/client/utils/navigateTests.js index 8bc4ea6ba..7c8346f16 100644 --- a/client/utils/navigateTests.js +++ b/client/utils/navigateTests.js @@ -1,32 +1,31 @@ export const navigateTests = ( - previous = false, - currentTest, - tests = [], - setCurrentTestIndex = () => {}, - setIsFirstTest = () => {}, - setIsLastTest = () => {} + previous = false, + currentTest, + tests = [], + setCurrentTestIndex = () => {}, + setIsFirstTest = () => {}, + setIsLastTest = () => {} ) => { - // assume navigation forward if previous is false - let newTestIndex = currentTest.seq; - if (!previous) { - // next - const newTestIndexToEval = currentTest.seq + 1; - if (newTestIndexToEval <= tests.length) - newTestIndex = newTestIndexToEval; - } else { - // previous - const newTestIndexToEval = currentTest.seq - 1; - if (newTestIndexToEval >= 1 && newTestIndexToEval <= tests.length) - newTestIndex = newTestIndexToEval; - } + // assume navigation forward if previous is false + let newTestIndex = currentTest.seq; + if (!previous) { + // next + const newTestIndexToEval = currentTest.seq + 1; + if (newTestIndexToEval <= tests.length) newTestIndex = newTestIndexToEval; + } else { + // previous + const newTestIndexToEval = currentTest.seq - 1; + if (newTestIndexToEval >= 1 && newTestIndexToEval <= tests.length) + newTestIndex = newTestIndexToEval; + } - const currentIndex = tests.find(t => t.seq === newTestIndex).index; - const isFirstTest = newTestIndex - 1 === 0; - const isLastTest = newTestIndex === tests.length; + const currentIndex = tests.find(t => t.seq === newTestIndex).index; + const isFirstTest = newTestIndex - 1 === 0; + const isLastTest = newTestIndex === tests.length; - setCurrentTestIndex && setCurrentTestIndex(currentIndex); - setIsFirstTest && setIsFirstTest(isFirstTest); - setIsLastTest && setIsLastTest(isLastTest); + setCurrentTestIndex && setCurrentTestIndex(currentIndex); + setIsFirstTest && setIsFirstTest(isFirstTest); + setIsLastTest && setIsLastTest(isLastTest); - return { currentIndex, isFirstTest, isLastTest }; + return { currentIndex, isFirstTest, isLastTest }; }; diff --git a/client/webpack.config.js b/client/webpack.config.js index b74fa1861..a75d50806 100644 --- a/client/webpack.config.js +++ b/client/webpack.config.js @@ -4,92 +4,92 @@ const CopyWebpackPlugin = require('copy-webpack-plugin'); require('dotenv').config({ path: '../config/dev.env' }); module.exports = { - entry: ['babel-polyfill', './index.js'], - mode: 'development', - devtool: 'inline-source-map', - module: { - rules: [ - { - test: /\.(js|jsx)$/, - exclude: /(node_modules)/, - loader: 'babel-loader', - options: { - babelrcRoots: ['.', '../..'] - } - }, - { - test: /\.css$/, - use: ['style-loader', 'css-loader'] - }, - { - test: /\.s[ac]ss$/i, - use: [ - // Creates `style` nodes from JS strings - 'style-loader', - // Translates CSS into CommonJS - 'css-loader' - ] - }, - { - test: /\.(png|jpe?g|gif)$/i, - use: [ - { - loader: 'file-loader' - } - ] - } + entry: ['babel-polyfill', './index.js'], + mode: 'development', + devtool: 'inline-source-map', + module: { + rules: [ + { + test: /\.(js|jsx)$/, + exclude: /(node_modules)/, + loader: 'babel-loader', + options: { + babelrcRoots: ['.', '../..'] + } + }, + { + test: /\.css$/, + use: ['style-loader', 'css-loader'] + }, + { + test: /\.s[ac]ss$/i, + use: [ + // Creates `style` nodes from JS strings + 'style-loader', + // Translates CSS into CommonJS + 'css-loader' ] - }, - output: { - path: path.resolve(__dirname, './dist/'), - filename: 'bundle.js' - }, - resolve: { - alias: { - '@': path.resolve(__dirname, '..'), - '@client': __dirname, - '@components': path.resolve(__dirname, 'components'), - '@server': path.resolve(__dirname, '../server') - }, - extensions: ['*', '.js', '.jsx'] - }, - devServer: { - static: { - directory: path.join(__dirname, 'static') - }, - port: process.env.CLIENT_PORT || 3000, - // Allows access to the dev server over your local network. Note that - // you will need to use your computer's address, e.g. 192.168.0.20:3000, - // and that logging in will require you to manually change the URL from - // localhost:3000 to 192.168.0.20:3000 each time a redirect occurs. - host: '0.0.0.0', - devMiddleware: { - publicPath: '/' - }, - historyApiFallback: true, - hot: 'only', - proxy: [ - { - context: ['/aria-at', '/api', '/embed'], - target: `http://localhost:${process.env.PORT || 8000}` - } + }, + { + test: /\.(png|jpe?g|gif)$/i, + use: [ + { + loader: 'file-loader' + } ] + } + ] + }, + output: { + path: path.resolve(__dirname, './dist/'), + filename: 'bundle.js' + }, + resolve: { + alias: { + '@': path.resolve(__dirname, '..'), + '@client': __dirname, + '@components': path.resolve(__dirname, 'components'), + '@server': path.resolve(__dirname, '../server') + }, + extensions: ['*', '.js', '.jsx'] + }, + devServer: { + static: { + directory: path.join(__dirname, 'static') }, - watchOptions: { - aggregateTimeout: 300, - poll: 1000 + port: process.env.CLIENT_PORT || 3000, + // Allows access to the dev server over your local network. Note that + // you will need to use your computer's address, e.g. 192.168.0.20:3000, + // and that logging in will require you to manually change the URL from + // localhost:3000 to 192.168.0.20:3000 each time a redirect occurs. + host: '0.0.0.0', + devMiddleware: { + publicPath: '/' }, - plugins: [ - new CopyWebpackPlugin({ - patterns: [ - { - from: 'static' - } - ] - }), - new webpack.DefinePlugin({ - 'process.env.API_SERVER': JSON.stringify(process.env.API_SERVER), - 'process.env.ENVIRONMENT': JSON.stringify(process.env.ENVIRONMENT) - }) + historyApiFallback: true, + hot: 'only', + proxy: [ + { + context: ['/aria-at', '/api', '/embed'], + target: `http://localhost:${process.env.PORT || 8000}` + } ] + }, + watchOptions: { + aggregateTimeout: 300, + poll: 1000 + }, + plugins: [ + new CopyWebpackPlugin({ + patterns: [ + { + from: 'static' + } + ] + }), + new webpack.DefinePlugin({ + 'process.env.API_SERVER': JSON.stringify(process.env.API_SERVER), + 'process.env.ENVIRONMENT': JSON.stringify(process.env.ENVIRONMENT) + }) + ] }; diff --git a/client/webpack.prod.js b/client/webpack.prod.js index 61ebb6124..06d73b603 100644 --- a/client/webpack.prod.js +++ b/client/webpack.prod.js @@ -3,70 +3,70 @@ const webpack = require('webpack'); const CopyWebpackPlugin = require('copy-webpack-plugin'); module.exports = { - entry: ['babel-polyfill', './index.js'], - mode: 'production', - module: { - rules: [ - { - test: /\.(js|jsx)$/, - exclude: /(node_modules)/, - loader: 'babel-loader', - options: { - babelrcRoots: ['.', '../..'] - } - }, - { - test: /\.css$/, - use: ['style-loader', 'css-loader'] - }, - { - test: /\.s[ac]ss$/i, - use: [ - // Creates `style` nodes from JS strings - 'style-loader', - // Translates CSS into CommonJS - 'css-loader' - ] - }, - { - test: /\.(png|jpe?g|gif)$/i, - use: [ - { - loader: 'file-loader' - } - ] - } + entry: ['babel-polyfill', './index.js'], + mode: 'production', + module: { + rules: [ + { + test: /\.(js|jsx)$/, + exclude: /(node_modules)/, + loader: 'babel-loader', + options: { + babelrcRoots: ['.', '../..'] + } + }, + { + test: /\.css$/, + use: ['style-loader', 'css-loader'] + }, + { + test: /\.s[ac]ss$/i, + use: [ + // Creates `style` nodes from JS strings + 'style-loader', + // Translates CSS into CommonJS + 'css-loader' ] + }, + { + test: /\.(png|jpe?g|gif)$/i, + use: [ + { + loader: 'file-loader' + } + ] + } + ] + }, + output: { + path: path.resolve(__dirname, './dist/'), + filename: 'bundle.js' + }, + resolve: { + alias: { + '@': path.resolve(__dirname, '..'), + '@client': __dirname, + '@components': path.resolve(__dirname, 'components'), + '@server': path.resolve(__dirname, '../server') }, - output: { - path: path.resolve(__dirname, './dist/'), - filename: 'bundle.js' - }, - resolve: { - alias: { - '@': path.resolve(__dirname, '..'), - '@client': __dirname, - '@components': path.resolve(__dirname, 'components'), - '@server': path.resolve(__dirname, '../server') - }, - extensions: ['*', '.js', '.jsx'] - }, - plugins: [ - new CopyWebpackPlugin({ - patterns: [ - { - from: 'static' - } - ] - }), - new webpack.DefinePlugin({ - 'process.env.API_SERVER': JSON.stringify(process.env.API_SERVER), - 'process.env.ENVIRONMENT': JSON.stringify(process.env.ENVIRONMENT) - }) - ], - performance: { - hints: false, - maxEntrypointSize: 512000, - maxAssetSize: 512000 - } + extensions: ['*', '.js', '.jsx'] + }, + plugins: [ + new CopyWebpackPlugin({ + patterns: [ + { + from: 'static' + } + ] + }), + new webpack.DefinePlugin({ + 'process.env.API_SERVER': JSON.stringify(process.env.API_SERVER), + 'process.env.ENVIRONMENT': JSON.stringify(process.env.ENVIRONMENT) + }) + ], + performance: { + hints: false, + maxEntrypointSize: 512000, + maxAssetSize: 512000 + } }; diff --git a/server/app.js b/server/app.js index 2c14a07a8..b1d6305d9 100644 --- a/server/app.js +++ b/server/app.js @@ -22,7 +22,7 @@ app.use('/test', testRoutes); app.use('/jobs', automationSchedulerRoutes); apolloServer.start().then(() => { - apolloServer.applyMiddleware({ app }); + apolloServer.applyMiddleware({ app }); }); const listener = express(); @@ -32,35 +32,35 @@ const baseUrl = 'https://raw.githubusercontent.com'; const onlyStatus200 = (req, res) => res.statusCode === 200; listener.route('/aria-at/:branch*').get( - cacheMiddleware('7 days', onlyStatus200), - (req, res, next) => { - req.url = path.join('w3c', req.url); - next(); - }, - proxyMiddleware.fileRedirect(baseUrl), - proxyMiddleware.proxyPath(baseUrl) + cacheMiddleware('7 days', onlyStatus200), + (req, res, next) => { + req.url = path.join('w3c', req.url); + next(); + }, + proxyMiddleware.fileRedirect(baseUrl), + proxyMiddleware.proxyPath(baseUrl) ); // Conditionally initialize github workflow service, or mock automation scheduler if ( - process.env.ENVIRONMENT === 'production' || - process.env.ENVIRONMENT === 'staging' || - process.env.ENVIRONMENT === 'sandbox' || - process.env.AUTOMATION_CALLBACK_FQDN + process.env.ENVIRONMENT === 'production' || + process.env.ENVIRONMENT === 'staging' || + process.env.ENVIRONMENT === 'sandbox' || + process.env.AUTOMATION_CALLBACK_FQDN ) { - require('./services/GithubWorkflowService').setup(); + require('./services/GithubWorkflowService').setup(); } else { - setupMockAutomationSchedulerServer().catch(error => { - console.error('Failed to initialize mock automation server:', error); - }); + setupMockAutomationSchedulerServer().catch(error => { + console.error('Failed to initialize mock automation server:', error); + }); } app.use(transactionMiddleware.errorware); // Error handling must be the last middleware listener.use((error, req, res, next) => { - console.error(error); - next(error); + console.error(error); + next(error); }); module.exports = { app, listener }; diff --git a/server/apps/embed.js b/server/apps/embed.js index dda139e0d..b034a790d 100644 --- a/server/apps/embed.js +++ b/server/apps/embed.js @@ -12,10 +12,10 @@ const handlebarsPath = path.resolve(__dirname, '../handlebars/embed'); // handlebars const hbs = create({ - layoutsDir: path.resolve(handlebarsPath, 'views/layouts'), - extname: 'hbs', - defaultLayout: 'index', - helpers: require(path.resolve(handlebarsPath, 'helpers')) + layoutsDir: path.resolve(handlebarsPath, 'views/layouts'), + extname: 'hbs', + defaultLayout: 'index', + helpers: require(path.resolve(handlebarsPath, 'helpers')) }); app.engine('hbs', hbs.engine); @@ -31,252 +31,248 @@ app.set('views', path.resolve(handlebarsPath, 'views')); const millisecondsUntilStale = 5000; const queryReports = async () => { - const { data, errors } = await apolloServer.executeOperation({ - query: gql` - query { - ats { - id - name - browsers { - id - name - } - } - testPlanReports( - testPlanVersionPhases: [CANDIDATE, RECOMMENDED] - isFinal: true - ) { - id - metrics - at { - id - name - } - browser { - id - name - } - latestAtVersionReleasedAt { - id - name - releasedAt - } - testPlanVersion { - id - title - phase - updatedAt - testPlan { - id - } - tests { - ats { - id - name - } - } - } - } + const { data, errors } = await apolloServer.executeOperation({ + query: gql` + query { + ats { + id + name + browsers { + id + name + } + } + testPlanReports( + testPlanVersionPhases: [CANDIDATE, RECOMMENDED] + isFinal: true + ) { + id + metrics + at { + id + name + } + browser { + id + name + } + latestAtVersionReleasedAt { + id + name + releasedAt + } + testPlanVersion { + id + title + phase + updatedAt + testPlan { + id } - ` - }); + tests { + ats { + id + name + } + } + } + } + } + ` + }); - if (errors) { - throw new Error(errors); - } + if (errors) { + throw new Error(errors); + } - const reportsHashed = hash(data.testPlanReports); + const reportsHashed = hash(data.testPlanReports); - return { - allTestPlanReports: data.testPlanReports, - reportsHashed, - ats: data.ats - }; + return { + allTestPlanReports: data.testPlanReports, + reportsHashed, + ats: data.ats + }; }; // As of now, a full query for the complete list of reports is needed to build // the embed for a single pattern. This caching allows that query to be reused // between pattern embeds. const queryReportsCached = staleWhileRevalidate(queryReports, { - millisecondsUntilStale + millisecondsUntilStale }); const getLatestReportsForPattern = ({ allTestPlanReports, pattern }) => { - let title; + let title; - const testPlanReports = allTestPlanReports.filter(report => { - if (report.testPlanVersion.testPlan.id === pattern) { - title = report.testPlanVersion.title; - return true; - } - }); + const testPlanReports = allTestPlanReports.filter(report => { + if (report.testPlanVersion.testPlan.id === pattern) { + title = report.testPlanVersion.title; + return true; + } + }); - let allAts = new Set(); - let allBrowsers = new Set(); - let allAtVersionsByAt = {}; - let reportsByAt = {}; - let testPlanVersionIds = new Set(); - const uniqueReports = []; - let latestReports = []; + let allAts = new Set(); + let allBrowsers = new Set(); + let allAtVersionsByAt = {}; + let reportsByAt = {}; + let testPlanVersionIds = new Set(); + const uniqueReports = []; + let latestReports = []; - testPlanReports.forEach(report => { - allAts.add(report.at.name); - allBrowsers.add(report.browser.name); + testPlanReports.forEach(report => { + allAts.add(report.at.name); + allBrowsers.add(report.browser.name); - if (!allAtVersionsByAt[report.at.name]) - allAtVersionsByAt[report.at.name] = - report.latestAtVersionReleasedAt; - else if ( - new Date(report.latestAtVersionReleasedAt.releasedAt) > - new Date(allAtVersionsByAt[report.at.name].releasedAt) - ) { - allAtVersionsByAt[report.at.name] = - report.latestAtVersionReleasedAt; - } + if (!allAtVersionsByAt[report.at.name]) + allAtVersionsByAt[report.at.name] = report.latestAtVersionReleasedAt; + else if ( + new Date(report.latestAtVersionReleasedAt.releasedAt) > + new Date(allAtVersionsByAt[report.at.name].releasedAt) + ) { + allAtVersionsByAt[report.at.name] = report.latestAtVersionReleasedAt; + } - const sameAtAndBrowserReports = testPlanReports.filter( - r => - r.at.name === report.at.name && - r.browser.name === report.browser.name - ); + const sameAtAndBrowserReports = testPlanReports.filter( + r => + r.at.name === report.at.name && r.browser.name === report.browser.name + ); - // Only add a group of reports with same - // AT and browser once - if ( - !uniqueReports.find(group => - group.some( - g => - g.at.name === report.at.name && - g.browser.name === report.browser.name - ) - ) - ) { - uniqueReports.push(sameAtAndBrowserReports); - } + // Only add a group of reports with same + // AT and browser once + if ( + !uniqueReports.find(group => + group.some( + g => + g.at.name === report.at.name && + g.browser.name === report.browser.name + ) + ) + ) { + uniqueReports.push(sameAtAndBrowserReports); + } - testPlanVersionIds.add(report.testPlanVersion.id); - }); + testPlanVersionIds.add(report.testPlanVersion.id); + }); - uniqueReports.forEach(group => { - if (group.length <= 1) { - latestReports.push(group.pop()); - } else { - const latestReport = group - .sort( - (a, b) => - new Date(a.latestAtVersionReleasedAt.releasedAt) - - new Date(b.latestAtVersionReleasedAt.releasedAt) - ) - .pop(); + uniqueReports.forEach(group => { + if (group.length <= 1) { + latestReports.push(group.pop()); + } else { + const latestReport = group + .sort( + (a, b) => + new Date(a.latestAtVersionReleasedAt.releasedAt) - + new Date(b.latestAtVersionReleasedAt.releasedAt) + ) + .pop(); - latestReports.push(latestReport); - } - }); + latestReports.push(latestReport); + } + }); - allBrowsers = Array.from(allBrowsers).sort(); - testPlanVersionIds = Array.from(testPlanVersionIds); + allBrowsers = Array.from(allBrowsers).sort(); + testPlanVersionIds = Array.from(testPlanVersionIds); - const allAtsAlphabetical = Array.from(allAts).sort((a, b) => - a.localeCompare(b) - ); - allAtsAlphabetical.forEach(at => { - reportsByAt[at] = latestReports - .filter(report => report.at.name === at) - .sort((a, b) => a.browser.name.localeCompare(b.browser.name)); - }); + const allAtsAlphabetical = Array.from(allAts).sort((a, b) => + a.localeCompare(b) + ); + allAtsAlphabetical.forEach(at => { + reportsByAt[at] = latestReports + .filter(report => report.at.name === at) + .sort((a, b) => a.browser.name.localeCompare(b.browser.name)); + }); - const hasAnyCandidateReports = Object.values(reportsByAt).find(atReports => - atReports.some(report => report.testPlanVersion.phase === 'CANDIDATE') - ); - let phase = hasAnyCandidateReports ? 'CANDIDATE' : 'RECOMMENDED'; + const hasAnyCandidateReports = Object.values(reportsByAt).find(atReports => + atReports.some(report => report.testPlanVersion.phase === 'CANDIDATE') + ); + let phase = hasAnyCandidateReports ? 'CANDIDATE' : 'RECOMMENDED'; - return { - title, - allBrowsers, - allAtVersionsByAt, - testPlanVersionIds, - phase, - reportsByAt - }; + return { + title, + allBrowsers, + allAtVersionsByAt, + testPlanVersionIds, + phase, + reportsByAt + }; }; const renderEmbed = ({ - ats, - allTestPlanReports, - queryTitle, - pattern, - protocol, - host + ats, + allTestPlanReports, + queryTitle, + pattern, + protocol, + host }) => { - const { - title, - allBrowsers, - allAtVersionsByAt, - testPlanVersionIds, - phase, - reportsByAt - } = getLatestReportsForPattern({ pattern, allTestPlanReports }); - const allAtBrowserCombinations = Object.fromEntries( - ats.map(at => { - return [ - at.name, - at.browsers.map(browser => { - return browser.name; - }) - ]; + const { + title, + allBrowsers, + allAtVersionsByAt, + testPlanVersionIds, + phase, + reportsByAt + } = getLatestReportsForPattern({ pattern, allTestPlanReports }); + const allAtBrowserCombinations = Object.fromEntries( + ats.map(at => { + return [ + at.name, + at.browsers.map(browser => { + return browser.name; }) - ); + ]; + }) + ); - return hbs.renderView(path.resolve(handlebarsPath, 'views/main.hbs'), { - layout: 'index', - dataEmpty: Object.keys(reportsByAt).length === 0, - allAtBrowserCombinations, - title: queryTitle || title || 'Pattern Not Found', - pattern, - phase, - allBrowsers, - allAtVersionsByAt, - reportsByAt, - completeReportLink: `${protocol}${host}/report/${testPlanVersionIds.join( - ',' - )}`, - embedLink: `${protocol}${host}/embed/reports/${pattern}` - }); + return hbs.renderView(path.resolve(handlebarsPath, 'views/main.hbs'), { + layout: 'index', + dataEmpty: Object.keys(reportsByAt).length === 0, + allAtBrowserCombinations, + title: queryTitle || title || 'Pattern Not Found', + pattern, + phase, + allBrowsers, + allAtVersionsByAt, + reportsByAt, + completeReportLink: `${protocol}${host}/report/${testPlanVersionIds.join( + ',' + )}`, + embedLink: `${protocol}${host}/embed/reports/${pattern}` + }); }; // Limit the number of times the template is rendered const renderEmbedCached = staleWhileRevalidate(renderEmbed, { - getCacheKeyFromArguments: ({ reportsHashed, pattern }) => - reportsHashed + pattern, - millisecondsUntilStale + getCacheKeyFromArguments: ({ reportsHashed, pattern }) => + reportsHashed + pattern, + millisecondsUntilStale }); app.get('/reports/:pattern', async (req, res) => { - // In the instance where an editor doesn't want to display a certain title - // as it has defined when importing into the ARIA-AT database for being too - // verbose, etc. eg. `Link Example 1 (span element with text content)` - // Usage: https://aria-at.w3.org/embed/reports/command-button?title=Link+Example+(span+element+with+text+content) - const queryTitle = req.query.title; - const pattern = req.params.pattern; - const host = req.headers.host; - const protocol = /dev|vagrant/.test(process.env.ENVIRONMENT) - ? 'http://' - : 'https://'; - const { allTestPlanReports, reportsHashed, ats } = - await queryReportsCached(); - const embedRendered = await renderEmbedCached({ - ats, - allTestPlanReports, - reportsHashed, - queryTitle, - pattern, - protocol, - host - }); + // In the instance where an editor doesn't want to display a certain title + // as it has defined when importing into the ARIA-AT database for being too + // verbose, etc. eg. `Link Example 1 (span element with text content)` + // Usage: https://aria-at.w3.org/embed/reports/command-button?title=Link+Example+(span+element+with+text+content) + const queryTitle = req.query.title; + const pattern = req.params.pattern; + const host = req.headers.host; + const protocol = /dev|vagrant/.test(process.env.ENVIRONMENT) + ? 'http://' + : 'https://'; + const { allTestPlanReports, reportsHashed, ats } = await queryReportsCached(); + const embedRendered = await renderEmbedCached({ + ats, + allTestPlanReports, + reportsHashed, + queryTitle, + pattern, + protocol, + host + }); - // Disable browser-based caching which could potentially make the embed - // contents appear stale even after being refreshed - res.set('cache-control', 'must-revalidate').send(embedRendered); + // Disable browser-based caching which could potentially make the embed + // contents appear stale even after being refreshed + res.set('cache-control', 'must-revalidate').send(embedRendered); }); app.use(express.static(path.resolve(`${handlebarsPath}/public`))); diff --git a/server/controllers/AuthController.js b/server/controllers/AuthController.js index c1076ebb1..18f36508a 100644 --- a/server/controllers/AuthController.js +++ b/server/controllers/AuthController.js @@ -6,88 +6,88 @@ const getUsersFromFile = require('../util/getUsersFromFile'); const APP_SERVER = process.env.APP_SERVER; const oauthRedirectToGithubController = async (req, res) => { - const oauthUrl = GithubService.getOauthUrl(); - res.redirect(303, oauthUrl); - res.end(); + const oauthUrl = GithubService.getOauthUrl(); + res.redirect(303, oauthUrl); + res.end(); }; const oauthRedirectFromGithubController = async (req, res) => { - const loginSucceeded = () => { - res.redirect(303, `${APP_SERVER}/test-queue`); - }; - const loginFailedDueToRole = async () => { - if (req.session) { - await new Promise(resolve => req.session.destroy(resolve)); - } - res.redirect(303, `${APP_SERVER}/signup-instructions`); - }; - const loginFailedDueToGitHub = () => { - res.status(401).send( - ` + const loginSucceeded = () => { + res.redirect(303, `${APP_SERVER}/test-queue`); + }; + const loginFailedDueToRole = async () => { + if (req.session) { + await new Promise(resolve => req.session.destroy(resolve)); + } + res.redirect(303, `${APP_SERVER}/signup-instructions`); + }; + const loginFailedDueToGitHub = () => { + res.status(401).send( + ` ARIA-AT App failed to access GitHub. Return to home page. ` - ); - }; + ); + }; - const { code } = req.query; + const { code } = req.query; - const githubAccessToken = await GithubService.getGithubAccessToken(code); - if (!githubAccessToken) return loginFailedDueToGitHub(); + const githubAccessToken = await GithubService.getGithubAccessToken(code); + if (!githubAccessToken) return loginFailedDueToGitHub(); - const githubUsername = await GithubService.getGithubUsername( - githubAccessToken - ); + const githubUsername = await GithubService.getGithubUsername( + githubAccessToken + ); - if (!githubUsername) return loginFailedDueToGitHub(); + if (!githubUsername) return loginFailedDueToGitHub(); - const admins = await getUsersFromFile('admins.txt'); - const testers = await getUsersFromFile('testers.txt'); - const vendors = await getUsersFromFile('vendors.txt'); + const admins = await getUsersFromFile('admins.txt'); + const testers = await getUsersFromFile('testers.txt'); + const vendors = await getUsersFromFile('vendors.txt'); - const roles = []; - if (admins.includes(githubUsername)) { - roles.push({ name: User.ADMIN }); - } - if (admins.includes(githubUsername) || testers.includes(githubUsername)) { - roles.push({ name: User.TESTER }); // Admins are always testers - } + const roles = []; + if (admins.includes(githubUsername)) { + roles.push({ name: User.ADMIN }); + } + if (admins.includes(githubUsername) || testers.includes(githubUsername)) { + roles.push({ name: User.TESTER }); // Admins are always testers + } - if ( - admins.includes(githubUsername) || - vendors.some(vendor => vendor.split('|')[0] === githubUsername) - ) { - roles.push({ name: User.VENDOR }); - } + if ( + admins.includes(githubUsername) || + vendors.some(vendor => vendor.split('|')[0] === githubUsername) + ) { + roles.push({ name: User.VENDOR }); + } - if (roles.length === 0) return loginFailedDueToRole(); + if (roles.length === 0) return loginFailedDueToRole(); - let [user] = await getOrCreateUser({ - where: { username: githubUsername }, - values: { roles }, - atAttributes: [], - testPlanRunAttributes: [], - transaction: req.transaction - }); + let [user] = await getOrCreateUser({ + where: { username: githubUsername }, + values: { roles }, + atAttributes: [], + testPlanRunAttributes: [], + transaction: req.transaction + }); - req.session.user = user; + req.session.user = user; - return loginSucceeded(); + return loginSucceeded(); }; const signoutController = (req, res) => { - req.session.destroy(err => { - if (err) { - res.status(500); - } else { - res.status(200); - } - res.end(); - }); + req.session.destroy(err => { + if (err) { + res.status(500); + } else { + res.status(200); + } + res.end(); + }); }; module.exports = { - oauthRedirectToGithubController, - oauthRedirectFromGithubController, - signoutController + oauthRedirectToGithubController, + oauthRedirectFromGithubController, + signoutController }; diff --git a/server/controllers/AutomationController.js b/server/controllers/AutomationController.js index 5a2a0d909..7417378fe 100644 --- a/server/controllers/AutomationController.js +++ b/server/controllers/AutomationController.js @@ -1,26 +1,26 @@ const axios = require('axios'); const { - getCollectionJobById, - updateCollectionJobById + getCollectionJobById, + updateCollectionJobById } = require('../models/services/CollectionJobService'); const { - findOrCreateTestResult + findOrCreateTestResult } = require('../models/services/TestResultWriteService'); const convertTestResultToInput = require('../resolvers/TestPlanRunOperations/convertTestResultToInput'); const saveTestResultCommon = require('../resolvers/TestResultOperations/saveTestResultCommon'); const { - getAts, - findOrCreateAtVersion + getAts, + findOrCreateAtVersion } = require('../models/services/AtService'); const { - getBrowsers, - findOrCreateBrowserVersion + getBrowsers, + findOrCreateBrowserVersion } = require('../models/services/BrowserService'); const { HttpQueryError } = require('apollo-server-core'); const { COLLECTION_JOB_STATUS } = require('../util/enums'); const populateData = require('../services/PopulatedData/populateData'); const { - getFinalizedTestResults + getFinalizedTestResults } = require('../models/services/TestResultReadService'); const http = require('http'); const { NO_OUTPUT_STRING } = require('../util/constants'); @@ -28,287 +28,280 @@ const getTests = require('../models/services/TestsService'); const httpAgent = new http.Agent({ family: 4 }); const axiosConfig = { - headers: { - 'x-automation-secret': process.env.AUTOMATION_SCHEDULER_SECRET - }, - timeout: 1000, - httpAgent + headers: { + 'x-automation-secret': process.env.AUTOMATION_SCHEDULER_SECRET + }, + timeout: 1000, + httpAgent }; const throwNoJobFoundError = jobId => { - throw new HttpQueryError( - 404, - `Could not find job with jobId: ${jobId}`, - true - ); + throw new HttpQueryError( + 404, + `Could not find job with jobId: ${jobId}`, + true + ); }; const throwNoTestFoundError = rowNumber => { - throw new HttpQueryError( - 404, - `Could not find test at row number ${rowNumber}`, - true - ); + throw new HttpQueryError( + 404, + `Could not find test at row number ${rowNumber}`, + true + ); }; const throwSchedulerError = schedulerResponse => { - throw new HttpQueryError( - 502, - `Response scheduler did not give a correct response: ${schedulerResponse}`, - false - ); + throw new HttpQueryError( + 502, + `Response scheduler did not give a correct response: ${schedulerResponse}`, + false + ); }; const cancelJob = async (req, res) => { - const automationSchedulerResponse = await axios.post( - `${process.env.AUTOMATION_SCHEDULER_URL}/jobs/${req.params.jobID}/cancel`, - {}, - axiosConfig - ); - - if (!automationSchedulerResponse.data) { - throwSchedulerError(automationSchedulerResponse); - } - - if ( - automationSchedulerResponse.data.status === - COLLECTION_JOB_STATUS.CANCELLED - ) { - const graphqlRes = await updateCollectionJobById({ - id: req.params.jobID, - values: { status: COLLECTION_JOB_STATUS.CANCELLED }, - transaction: req.transaction - }); - if (!graphqlRes) { - throwNoJobFoundError(req.params.jobID); - } + const automationSchedulerResponse = await axios.post( + `${process.env.AUTOMATION_SCHEDULER_URL}/jobs/${req.params.jobID}/cancel`, + {}, + axiosConfig + ); + + if (!automationSchedulerResponse.data) { + throwSchedulerError(automationSchedulerResponse); + } + + if ( + automationSchedulerResponse.data.status === COLLECTION_JOB_STATUS.CANCELLED + ) { + const graphqlRes = await updateCollectionJobById({ + id: req.params.jobID, + values: { status: COLLECTION_JOB_STATUS.CANCELLED }, + transaction: req.transaction + }); + if (!graphqlRes) { + throwNoJobFoundError(req.params.jobID); } - res.json(automationSchedulerResponse.data); + } + res.json(automationSchedulerResponse.data); }; const updateJobStatus = async (req, res) => { - const { status, externalLogsUrl } = req.body; + const { status, externalLogsUrl } = req.body; - if (!Object.values(COLLECTION_JOB_STATUS).includes(status)) { - throw new HttpQueryError(400, `Invalid status: ${status}`, true); - } + if (!Object.values(COLLECTION_JOB_STATUS).includes(status)) { + throw new HttpQueryError(400, `Invalid status: ${status}`, true); + } - const updatePayload = { - status, - ...(externalLogsUrl != null && { externalLogsUrl }) - }; + const updatePayload = { + status, + ...(externalLogsUrl != null && { externalLogsUrl }) + }; - const graphqlResponse = await updateCollectionJobById({ - id: req.params.jobID, - values: updatePayload, - transaction: req.transaction - }); + const graphqlResponse = await updateCollectionJobById({ + id: req.params.jobID, + values: updatePayload, + transaction: req.transaction + }); - if (!graphqlResponse) { - throwNoJobFoundError(req.params.jobID); - } + if (!graphqlResponse) { + throwNoJobFoundError(req.params.jobID); + } - res.json(graphqlResponse); + res.json(graphqlResponse); }; const getApprovedFinalizedTestResults = async ( - testPlanRun, - { transaction } + testPlanRun, + { transaction } ) => { - const { - testPlanReport: { testPlanVersion } - } = testPlanRun; - - // To be considered "Approved", a test plan run must be associated with a test plan report - // that is associated with a test plan version that is in "CANDIDATE" or "RECOMMENDED" or - // "DRAFT" phase and the test plan report been marked as final. - const { phase } = testPlanVersion; - - if ( - phase === 'RD' || - (phase === 'DRAFT' && testPlanRun.testPlanReport.markedFinalAt === null) - ) { - return null; - } - - const { testPlanReport } = await populateData( - { testPlanReportId: testPlanRun.testPlanReport.id }, - { transaction } - ); + const { + testPlanReport: { testPlanVersion } + } = testPlanRun; + + // To be considered "Approved", a test plan run must be associated with a test plan report + // that is associated with a test plan version that is in "CANDIDATE" or "RECOMMENDED" or + // "DRAFT" phase and the test plan report been marked as final. + const { phase } = testPlanVersion; + + if ( + phase === 'RD' || + (phase === 'DRAFT' && testPlanRun.testPlanReport.markedFinalAt === null) + ) { + return null; + } + + const { testPlanReport } = await populateData( + { testPlanReportId: testPlanRun.testPlanReport.id }, + { transaction } + ); - return getFinalizedTestResults(testPlanReport, { transaction }); + return getFinalizedTestResults(testPlanReport, { transaction }); }; const updateOrCreateTestResultWithResponses = async ({ - testRowIdentifier, - testPlanRun, - responses, + testRowIdentifier, + testPlanRun, + responses, + atVersionId, + browserVersionId, + transaction +}) => { + const allTestsForTestPlanVersion = await getTests( + testPlanRun.testPlanReport.testPlanVersion + ); + + const isV2 = + testPlanRun.testPlanReport.testPlanVersion.metadata.testFormatVersion === 2; + + const testId = allTestsForTestPlanVersion.find( + test => + (!isV2 || test.at?.name === 'NVDA') && + parseInt(test.rowNumber, 10) === testRowIdentifier + )?.id; + + if (testId === undefined) { + throwNoTestFoundError(testRowIdentifier); + } + + const { testResult } = await findOrCreateTestResult({ + testId, + testPlanRunId: testPlanRun.id, atVersionId, browserVersionId, transaction -}) => { - const allTestsForTestPlanVersion = await getTests( - testPlanRun.testPlanReport.testPlanVersion - ); - - const isV2 = - testPlanRun.testPlanReport.testPlanVersion.metadata - .testFormatVersion === 2; - - const testId = allTestsForTestPlanVersion.find( - test => - (!isV2 || test.at?.name === 'NVDA') && - parseInt(test.rowNumber, 10) === testRowIdentifier - )?.id; - - if (testId === undefined) { - throwNoTestFoundError(testRowIdentifier); - } - - const { testResult } = await findOrCreateTestResult({ - testId, - testPlanRunId: testPlanRun.id, - atVersionId, - browserVersionId, - transaction - }); + }); - const historicalTestResults = await getApprovedFinalizedTestResults( - testPlanRun, - { transaction } + const historicalTestResults = await getApprovedFinalizedTestResults( + testPlanRun, + { transaction } + ); + + const historicalTestResult = historicalTestResults?.find(each => { + return each.testId === testId; + }); + + if ( + historicalTestResult && + historicalTestResult.scenarioResults?.length !== + testResult.scenarioResults.length + ) { + throw new Error( + 'Historical test result does not match current test result' ); + } - const historicalTestResult = historicalTestResults?.find(each => { - return each.testId === testId; - }); - - if ( + const getAutomatedResultFromOutput = ({ baseTestResult, outputs }) => ({ + ...baseTestResult, + atVersionId, + browserVersionId, + scenarioResults: baseTestResult.scenarioResults.map((scenarioResult, i) => { + // Check if output matches historical output + const outputMatches = historicalTestResult && - historicalTestResult.scenarioResults?.length !== - testResult.scenarioResults.length - ) { - throw new Error( - 'Historical test result does not match current test result' - ); - } - - const getAutomatedResultFromOutput = ({ baseTestResult, outputs }) => ({ - ...baseTestResult, - atVersionId, - browserVersionId, - scenarioResults: baseTestResult.scenarioResults.map( - (scenarioResult, i) => { - // Check if output matches historical output - const outputMatches = - historicalTestResult && - historicalTestResult.scenarioResults[i] && - historicalTestResult.scenarioResults[i].output === - outputs[i]; - - return { - ...scenarioResult, - output: outputs[i], - assertionResults: scenarioResult.assertionResults.map( - (assertionResult, j) => ({ - ...assertionResult, - passed: outputMatches - ? historicalTestResult.scenarioResults[i] - .assertionResults[j].passed - : false, - failedReason: outputMatches - ? historicalTestResult.scenarioResults[i] - .assertionResults[j].failedReason - : 'AUTOMATED_OUTPUT' - }) - ), - unexpectedBehaviors: null - }; - } - ) - }); - - return saveTestResultCommon({ - testResultId: testResult.id, - input: convertTestResultToInput( - getAutomatedResultFromOutput({ - baseTestResult: testResult, - outputs: responses - }) + historicalTestResult.scenarioResults[i] && + historicalTestResult.scenarioResults[i].output === outputs[i]; + + return { + ...scenarioResult, + output: outputs[i], + assertionResults: scenarioResult.assertionResults.map( + (assertionResult, j) => ({ + ...assertionResult, + passed: outputMatches + ? historicalTestResult.scenarioResults[i].assertionResults[j] + .passed + : false, + failedReason: outputMatches + ? historicalTestResult.scenarioResults[i].assertionResults[j] + .failedReason + : 'AUTOMATED_OUTPUT' + }) ), - isSubmit: false, - context: { transaction } - }); + unexpectedBehaviors: null + }; + }) + }); + + return saveTestResultCommon({ + testResultId: testResult.id, + input: convertTestResultToInput( + getAutomatedResultFromOutput({ + baseTestResult: testResult, + outputs: responses + }) + ), + isSubmit: false, + context: { transaction } + }); }; const updateJobResults = async (req, res) => { - const id = req.params.jobID; - const transaction = req.transaction; - const { - testCsvRow, - presentationNumber, - responses, - atVersionName, - browserVersionName - } = req.body; - const job = await getCollectionJobById({ id, transaction }); - if (!job) { - throwNoJobFoundError(id); - } + const id = req.params.jobID; + const transaction = req.transaction; + const { + testCsvRow, + presentationNumber, + responses, + atVersionName, + browserVersionName + } = req.body; + const job = await getCollectionJobById({ id, transaction }); + if (!job) { + throwNoJobFoundError(id); + } + + if (job.status !== COLLECTION_JOB_STATUS.RUNNING) { + throw new Error(`Job with id ${id} is not running, cannot update results`); + } + + /* TODO: Change this once we support more At + Browser Combos in Automation */ + const [at] = await getAts({ + where: { name: 'NVDA' }, + transaction + }); + const [browser] = await getBrowsers({ + where: { name: 'Chrome' }, + transaction + }); - if (job.status !== COLLECTION_JOB_STATUS.RUNNING) { - throw new Error( - `Job with id ${id} is not running, cannot update results` - ); - } + const [atVersion, browserVersion] = await Promise.all([ + findOrCreateAtVersion({ + where: { atId: at.id, name: atVersionName }, + transaction + }), + findOrCreateBrowserVersion({ + where: { browserId: browser.id, name: browserVersionName }, + transaction + }) + ]); - /* TODO: Change this once we support more At + Browser Combos in Automation */ - const [at] = await getAts({ - where: { name: 'NVDA' }, - transaction - }); - const [browser] = await getBrowsers({ - where: { name: 'Chrome' }, - transaction - }); + const processedResponses = convertEmptyStringsToNoOutputMessages(responses); - const [atVersion, browserVersion] = await Promise.all([ - findOrCreateAtVersion({ - where: { atId: at.id, name: atVersionName }, - transaction - }), - findOrCreateBrowserVersion({ - where: { browserId: browser.id, name: browserVersionName }, - transaction - }) - ]); - - const processedResponses = convertEmptyStringsToNoOutputMessages(responses); - - // v1 tests store testCsvRow in rowNumber, v2 tests store presentationNumber in rowNumber - const testRowIdentifier = presentationNumber ?? testCsvRow; - - await updateOrCreateTestResultWithResponses({ - testRowIdentifier, - responses: processedResponses, - testPlanRun: job.testPlanRun, - atVersionId: atVersion.id, - browserVersionId: browserVersion.id, - transaction - }); + // v1 tests store testCsvRow in rowNumber, v2 tests store presentationNumber in rowNumber + const testRowIdentifier = presentationNumber ?? testCsvRow; + + await updateOrCreateTestResultWithResponses({ + testRowIdentifier, + responses: processedResponses, + testPlanRun: job.testPlanRun, + atVersionId: atVersion.id, + browserVersionId: browserVersion.id, + transaction + }); - res.json({ success: true }); + res.json({ success: true }); }; // Human test runners are able to use a checkbox to indicate no output was detected. // This checkbox stores 'No output was detected.' as the output value for that scenarioResult. const convertEmptyStringsToNoOutputMessages = outputs => - outputs.map(output => - output === null || output.trim() === '' ? NO_OUTPUT_STRING : output - ); + outputs.map(output => + output === null || output.trim() === '' ? NO_OUTPUT_STRING : output + ); module.exports = { - cancelJob, - updateJobStatus, - updateJobResults, - axiosConfig + cancelJob, + updateJobStatus, + updateJobResults, + axiosConfig }; diff --git a/server/controllers/FakeUserController.js b/server/controllers/FakeUserController.js index e5a2d5297..ab870ff03 100644 --- a/server/controllers/FakeUserController.js +++ b/server/controllers/FakeUserController.js @@ -3,33 +3,31 @@ const { getOrCreateUser } = require('../models/services/UserService'); const ALLOW_FAKE_USER = process.env.ALLOW_FAKE_USER === 'true'; const setFakeUserController = async (req, res) => { - if (!ALLOW_FAKE_USER) { - return res - .status(400) - .send('Feature not supported in this environment'); - } + if (!ALLOW_FAKE_USER) { + return res.status(400).send('Feature not supported in this environment'); + } - const userToCreate = req.body; - if ( - !userToCreate || - !userToCreate.username || - !userToCreate?.roles.length || - userToCreate.roles.some( - role => !['TESTER', 'ADMIN', 'VENDOR'].includes(role.name) - ) - ) { - return res.status(400).send('Invalid user'); - } + const userToCreate = req.body; + if ( + !userToCreate || + !userToCreate.username || + !userToCreate?.roles.length || + userToCreate.roles.some( + role => !['TESTER', 'ADMIN', 'VENDOR'].includes(role.name) + ) + ) { + return res.status(400).send('Invalid user'); + } - let [user] = await getOrCreateUser({ - where: { username: userToCreate.username }, - values: { roles: userToCreate.roles }, - transaction: req.transaction - }); + let [user] = await getOrCreateUser({ + where: { username: userToCreate.username }, + values: { roles: userToCreate.roles }, + transaction: req.transaction + }); - req.session.user = user; + req.session.user = user; - res.status(200).send(''); + res.status(200).send(''); }; module.exports = setFakeUserController; diff --git a/server/controllers/TestController.js b/server/controllers/TestController.js index b40cec90c..f59d4bcf1 100644 --- a/server/controllers/TestController.js +++ b/server/controllers/TestController.js @@ -1,19 +1,19 @@ const TestService = require('../services/TestService'); async function importTests(req, res) { - const { git_hash } = req.body; - try { - await TestService.importTests(git_hash); - res.sendStatus(200); - } catch (error) { - // eslint-disable-next-line no-console - console.log(error.message); - // This is when the script fails because the git hash is invalid - // Sending semantic error. - res.sendStatus(422); - } + const { git_hash } = req.body; + try { + await TestService.importTests(git_hash); + res.sendStatus(200); + } catch (error) { + // eslint-disable-next-line no-console + console.log(error.message); + // This is when the script fails because the git hash is invalid + // Sending semantic error. + res.sendStatus(422); + } } module.exports = { - importTests + importTests }; diff --git a/server/graphql-context.js b/server/graphql-context.js index 04e9d31e8..acb6ff41c 100644 --- a/server/graphql-context.js +++ b/server/graphql-context.js @@ -1,16 +1,15 @@ const getGraphQLContext = ({ req }) => { - const user = - req && req.session && req.session.user ? req.session.user : null; + const user = req && req.session && req.session.user ? req.session.user : null; - let transaction; - if (req) { - transaction = req.transaction; - } else { - // Req will not be defined when queries are made with apolloServer.executeOperation() - transaction = false; - } + let transaction; + if (req) { + transaction = req.transaction; + } else { + // Req will not be defined when queries are made with apolloServer.executeOperation() + transaction = false; + } - return { user, transaction }; + return { user, transaction }; }; module.exports = getGraphQLContext; diff --git a/server/graphql-schema.js b/server/graphql-schema.js index 90f10dfa4..36d981592 100644 --- a/server/graphql-schema.js +++ b/server/graphql-schema.js @@ -1,1494 +1,1494 @@ const { gql } = require('apollo-server'); const graphqlSchema = gql` + """ + Freeform data. + """ + scalar Any + + """ + The field does not return a response (useful for some mutations). + """ + scalar NoResponse + + """ + ISO-8601-formatted timestamp. + """ + scalar Timestamp + + """ + The categories of actions a user can complete in the app. + """ + enum Role { """ - Freeform data. + Whether the user can perform testing. Testers are specified in + testers.txt. Note that all admins are testers. """ - scalar Any - + TESTER """ - The field does not return a response (useful for some mutations). + Whether the user can perform administrative actions. Admins are members + of a special GitHub team, which is different for each app environment. """ - scalar NoResponse - + ADMIN """ - ISO-8601-formatted timestamp. + Whether the user can perform vendor actions, such as reviewing + candidate test plans. Vendors are specified in vendors.txt. """ - scalar Timestamp + VENDOR + } + type User { + """ + Postgres-provided numeric ID. + """ + id: ID! + """ + The GitHub username of the person. + """ + username: String! + """ + List of types of actions the user can complete. + """ + roles: [Role]! + # TODO: Either use the recorded data somewhere or eliminate the field. + """ + The ATs the user has indicated they are able to test. """ - The categories of actions a user can complete in the app. - """ - enum Role { - """ - Whether the user can perform testing. Testers are specified in - testers.txt. Note that all admins are testers. - """ - TESTER - """ - Whether the user can perform administrative actions. Admins are members - of a special GitHub team, which is different for each app environment. - """ - ADMIN - """ - Whether the user can perform vendor actions, such as reviewing - candidate test plans. Vendors are specified in vendors.txt. - """ - VENDOR - } + ats: [At]! + } - type User { - """ - Postgres-provided numeric ID. - """ - id: ID! - """ - The GitHub username of the person. - """ - username: String! - """ - List of types of actions the user can complete. - """ - roles: [Role]! - # TODO: Either use the recorded data somewhere or eliminate the field. - """ - The ATs the user has indicated they are able to test. - """ - ats: [At]! - } + """ + The fields of the User type which can be updated after the User has been + created. It is a short list since most of the User fields originate outside + the app, i.e. the User roles are set by a GitHub team and txt file, and the + username is set in GitHub, etc. + """ + input UserInput { + """ + See User type for more information. + """ + atIds: [ID]! + } + """ + The possible statuses for a CollectionJob. + """ + enum CollectionJobStatus { + QUEUED + RUNNING + COMPLETED + ERROR + CANCELLED + } + """ + A job which was scheduled to collect automated test results using the Response Collection System. + """ + type CollectionJob { """ - The fields of the User type which can be updated after the User has been - created. It is a short list since most of the User fields originate outside - the app, i.e. the User roles are set by a GitHub team and txt file, and the - username is set in GitHub, etc. - """ - input UserInput { - """ - See User type for more information. - """ - atIds: [ID]! - } - + Job Scheduler server-provided ID. + """ + id: ID! + """ + The status of the job, which can be "QUEUED", "RUNNING", "COMPLETED", + "ERROR", or "CANCELLED". + """ + status: CollectionJobStatus! + """ + An ID for the Test Plan Run which was created as a result of the Collection Job. + This will store the test results. + """ + testPlanRun: TestPlanRun """ - The possible statuses for a CollectionJob. - """ - enum CollectionJobStatus { - QUEUED - RUNNING - COMPLETED - ERROR - CANCELLED - } - """ - A job which was scheduled to collect automated test results using the Response Collection System. - """ - type CollectionJob { - """ - Job Scheduler server-provided ID. - """ - id: ID! - """ - The status of the job, which can be "QUEUED", "RUNNING", "COMPLETED", - "ERROR", or "CANCELLED". - """ - status: CollectionJobStatus! - """ - An ID for the Test Plan Run which was created as a result of the Collection Job. - This will store the test results. - """ - testPlanRun: TestPlanRun - """ - The URL where the logs for the job can be found. - """ - externalLogsUrl: String - } + The URL where the logs for the job can be found. + """ + externalLogsUrl: String + } - type Browser { - """ - Postgres-provided numeric ID. - """ - id: ID! - """ - Browser name like "Chrome". - """ - name: String! - """ - A fully-qualified version like "99.0.4844.84" - """ - browserVersions: [BrowserVersion]! - """ - The Ats which can be run with the specific browser, for example, Jaws can be run with Chrome but not Safari, and Safari works with VoiceOver only. - """ - ats: [At]! - """ - The Ats which are required to move a TestPlanVersion to CANDIDATE phase. - """ - candidateAts: [At]! - """ - The Ats which are required to move a TestPlanVersion to RECOMMENDED phase. - """ - recommendedAts: [At]! - } + type Browser { + """ + Postgres-provided numeric ID. + """ + id: ID! + """ + Browser name like "Chrome". + """ + name: String! + """ + A fully-qualified version like "99.0.4844.84" + """ + browserVersions: [BrowserVersion]! + """ + The Ats which can be run with the specific browser, for example, Jaws can be run with Chrome but not Safari, and Safari works with VoiceOver only. + """ + ats: [At]! + """ + The Ats which are required to move a TestPlanVersion to CANDIDATE phase. + """ + candidateAts: [At]! + """ + The Ats which are required to move a TestPlanVersion to RECOMMENDED phase. + """ + recommendedAts: [At]! + } + """ + A version which has been used to collect test results. + """ + type BrowserVersion { + """ + Postgres-provided numeric ID + """ + id: ID! """ - A version which has been used to collect test results. - """ - type BrowserVersion { - """ - Postgres-provided numeric ID - """ - id: ID! - """ - Version string - """ - name: String! - } + Version string + """ + name: String! + } + """ + The fields on the BrowserVersion type which must be provided to create new + BrowserVersions. + """ + input BrowserVersionInput { """ - The fields on the BrowserVersion type which must be provided to create new - BrowserVersions. + See BrowserVersion type for more information. """ - input BrowserVersionInput { - """ - See BrowserVersion type for more information. - """ - name: String! - } + name: String! + } + """ + Some ATs like JAWS have modes - for example, normally pushing "h" would + navigate to the next header, but when you are interacting with a text input, + typing "h" would insert the letter "h" into that input. Our tests are aware + of these modes. + """ + enum AtMode { + """ + JAWS "browse" mode or NVDA "browse" mode. + """ + READING """ - Some ATs like JAWS have modes - for example, normally pushing "h" would - navigate to the next header, but when you are interacting with a text input, - typing "h" would insert the letter "h" into that input. Our tests are aware - of these modes. - """ - enum AtMode { - """ - JAWS "browse" mode or NVDA "browse" mode. - """ - READING - """ - JAWS "forms" mode, NVDA "focus" mode, or VoiceOver's one-and-only mode. - """ - INTERACTION - } + JAWS "forms" mode, NVDA "focus" mode, or VoiceOver's one-and-only mode. + """ + INTERACTION + } + """ + An assistive technology to be tested, such as NVDA or JAWS. + """ + type At { + """ + Postgres-provided numeric ID. + """ + id: ID! + """ + Human-readable name for the AT, such as "NVDA". + """ + name: String! + # TODO: reenable when this data is properly flowing into the system + # """ + # The categories of generalized AT modes the AT supports. + # """ + # modes: [AtMode]! + atVersions: [AtVersion]! + """ + The browsers which can run the At, for example, Safari can run VoiceOver but not Jaws because Jaws is Windows only. """ - An assistive technology to be tested, such as NVDA or JAWS. - """ - type At { - """ - Postgres-provided numeric ID. - """ - id: ID! - """ - Human-readable name for the AT, such as "NVDA". - """ - name: String! - # TODO: reenable when this data is properly flowing into the system - # """ - # The categories of generalized AT modes the AT supports. - # """ - # modes: [AtMode]! - atVersions: [AtVersion]! - """ - The browsers which can run the At, for example, Safari can run VoiceOver but not Jaws because Jaws is Windows only. - """ - browsers: [Browser]! - """ - The browsers which are required to move a TestPlanVersion to CANDIDATE phase. - """ - candidateBrowsers: [Browser]! - """ - The browsers which are required to move a TestPlanVersion to RECOMMENDED phase. - """ - recommendedBrowsers: [Browser]! - } + browsers: [Browser]! + """ + The browsers which are required to move a TestPlanVersion to CANDIDATE phase. + """ + candidateBrowsers: [Browser]! + """ + The browsers which are required to move a TestPlanVersion to RECOMMENDED phase. + """ + recommendedBrowsers: [Browser]! + } + """ + The version for a given assistive technology. + """ + type AtVersion { + """ + Postgres-provided numeric ID. + """ + id: ID! """ - The version for a given assistive technology. - """ - type AtVersion { - """ - Postgres-provided numeric ID. - """ - id: ID! - """ - Human-readable name for the version, such as "2020.1". - """ - name: String! - """ - Date for approximate availability of the version. - """ - releasedAt: Timestamp! - } + Human-readable name for the version, such as "2020.1". + """ + name: String! + """ + Date for approximate availability of the version. + """ + releasedAt: Timestamp! + } + """ + The fields on the AtVersion type which can be used to create or update the + AtVersion. + """ + input AtVersionInput { + """ + See AtVersion type for more information. + """ + name: String! + """ + See AtVersion type for more information. """ - The fields on the AtVersion type which can be used to create or update the - AtVersion. - """ - input AtVersionInput { - """ - See AtVersion type for more information. - """ - name: String! - """ - See AtVersion type for more information. - """ - releasedAt: Timestamp - } + releasedAt: Timestamp + } + """ + A suite of tests which keeps its identity as it evolves over time. + """ + type TestPlan { + """ + This is the same as the directory field. Sometimes you want to think of + that string as an ID and sometimes you want to explicitly refer to it + as a directory, and this allows you to do both. + """ + id: ID! + """ + The formal name of the test plan + """ + title: String! + """ + Corresponds to directory in the ARIA-AT repo which stores the test plan, + e.g. "checkbox-tri-state" or "disclosure-navigation" + """ + directory: String! + # TODO: determine what to do when a directory is removed from the + # ARIA-AT repo + # isObsolete: Boolean! """ - A suite of tests which keeps its identity as it evolves over time. - """ - type TestPlan { - """ - This is the same as the directory field. Sometimes you want to think of - that string as an ID and sometimes you want to explicitly refer to it - as a directory, and this allows you to do both. - """ - id: ID! - """ - The formal name of the test plan - """ - title: String! - """ - Corresponds to directory in the ARIA-AT repo which stores the test plan, - e.g. "checkbox-tri-state" or "disclosure-navigation" - """ - directory: String! - # TODO: determine what to do when a directory is removed from the - # ARIA-AT repo - # isObsolete: Boolean! - """ - Gets the most recent version imported from the test plan's directory. - """ - latestTestPlanVersion: TestPlanVersion - """ - Gets all historic versions of the test plan. - """ - testPlanVersions: [TestPlanVersion]! - """ - A list of all issues which have filed through "Raise an Issue" buttons - in the app. Note that results will be cached for at least ten seconds. - """ - issues: [Issue]! - } + Gets the most recent version imported from the test plan's directory. + """ + latestTestPlanVersion: TestPlanVersion + """ + Gets all historic versions of the test plan. + """ + testPlanVersions: [TestPlanVersion]! + """ + A list of all issues which have filed through "Raise an Issue" buttons + in the app. Note that results will be cached for at least ten seconds. + """ + issues: [Issue]! + } + """ + The life-cycle of a TestPlanVersion from the point it is imported automatically + or by an admin until it is saved an available to the public on the reports page. + """ + enum TestPlanVersionPhase { + """ + Accepting new TestPlanRuns from testers. + """ + RD + """ + Accepting new TestPlanRuns from testers. + """ + DRAFT + """ + Testing is complete and consistent, and ready to be displayed in the + Candidate Tests and Reports section of the app. + """ + CANDIDATE + """ + Testing is complete and consistent, and ready to be displayed in the + Reports section of the app as being recommended. """ - The life-cycle of a TestPlanVersion from the point it is imported automatically - or by an admin until it is saved an available to the public on the reports page. - """ - enum TestPlanVersionPhase { - """ - Accepting new TestPlanRuns from testers. - """ - RD - """ - Accepting new TestPlanRuns from testers. - """ - DRAFT - """ - Testing is complete and consistent, and ready to be displayed in the - Candidate Tests and Reports section of the app. - """ - CANDIDATE - """ - Testing is complete and consistent, and ready to be displayed in the - Reports section of the app as being recommended. - """ - RECOMMENDED - """ - The TestPlanVersion is now outdated and replaced by another version. - """ - DEPRECATED - } + RECOMMENDED + """ + The TestPlanVersion is now outdated and replaced by another version. + """ + DEPRECATED + } + """ + A snapshot of time for a test plan, containing all the test plan data, + including the actual executable tests. + """ + type TestPlanVersion { + """ + Postgres-provided numeric ID. + """ + id: ID! + # TODO: fix bug where the title is missing and make this field required + """ + The title of the TestPlan at this point in time. + """ + title: String + """ + See TestPlanVersionPhase type for more information. + """ + phase: TestPlanVersionPhase! + """ + Date of when the TestPlanVersion last updated to the 'Draft' + phase. + """ + draftPhaseReachedAt: Timestamp + """ + Date of when the TestPlanVersion was last updated to the 'Candidate' + phase. + """ + candidatePhaseReachedAt: Timestamp + """ + Date of when the TestPlanVersion was last updated to the 'Recommended' + phase. + """ + recommendedPhaseReachedAt: Timestamp + """ + The intended target date for the final TestPlanVersion phase promotion. + Based on the ARIA-AT Working Mode. + https://github.com/w3c/aria-at/wiki/Working-Mode + """ + recommendedPhaseTargetDate: Timestamp + """ + The date when the TestPlanVersion was deprecated. + """ + deprecatedAt: Timestamp + """ + The TestPlan this TestPlanVersion is a snapshot of. + """ + testPlan: TestPlan! + """ + A git sha corresponding to the current git commit at the time the + version was imported from the ARIA-AT repo. Used to version the test + plan over time. + """ + gitSha: String! # TODO: remove if using version labels + """ + Git commit message corresponding to the git sha's commit. """ - A snapshot of time for a test plan, containing all the test plan data, - including the actual executable tests. - """ - type TestPlanVersion { - """ - Postgres-provided numeric ID. - """ - id: ID! - # TODO: fix bug where the title is missing and make this field required - """ - The title of the TestPlan at this point in time. - """ - title: String - """ - See TestPlanVersionPhase type for more information. - """ - phase: TestPlanVersionPhase! - """ - Date of when the TestPlanVersion last updated to the 'Draft' - phase. - """ - draftPhaseReachedAt: Timestamp - """ - Date of when the TestPlanVersion was last updated to the 'Candidate' - phase. - """ - candidatePhaseReachedAt: Timestamp - """ - Date of when the TestPlanVersion was last updated to the 'Recommended' - phase. - """ - recommendedPhaseReachedAt: Timestamp - """ - The intended target date for the final TestPlanVersion phase promotion. - Based on the ARIA-AT Working Mode. - https://github.com/w3c/aria-at/wiki/Working-Mode - """ - recommendedPhaseTargetDate: Timestamp - """ - The date when the TestPlanVersion was deprecated. - """ - deprecatedAt: Timestamp - """ - The TestPlan this TestPlanVersion is a snapshot of. - """ - testPlan: TestPlan! - """ - A git sha corresponding to the current git commit at the time the - version was imported from the ARIA-AT repo. Used to version the test - plan over time. - """ - gitSha: String! # TODO: remove if using version labels - """ - Git commit message corresponding to the git sha's commit. - """ - gitMessage: String! # TODO: remove if using version labels - """ - The date (originating in Git) corresponding to the Git sha's commit. - This can also be considered as the time for when R & D was complete - """ - updatedAt: Timestamp! - """ - An easily readable representation of the date associated with the - version, formatted like V23.09.28 (or V23.09.28-1 in the case that - there are multiple versions on the same day). - """ - versionString: String! - # TODO: consider moving to the Scenario type if we support multiple - # test pages for one TestPlanVersion (i.e. testing that - # and + ); +}; + +ViewLogsButton.propTypes = { + externalLogsUrl: PropTypes.string +}; + +export default ViewLogsButton; diff --git a/client/components/ManageBotRunDialog/index.jsx b/client/components/ManageBotRunDialog/index.jsx index 40e4c9457..154a8db6b 100644 --- a/client/components/ManageBotRunDialog/index.jsx +++ b/client/components/ManageBotRunDialog/index.jsx @@ -15,6 +15,7 @@ import './ManageBotRunDialog.css'; import MarkBotRunFinishedButton from './MarkBotRunFinishedButton'; import RetryCanceledCollectionsButton from './RetryCanceledCollectionsButton'; import StopRunningCollectionButton from './StopRunningCollectionButton'; +import ViewLogsButton from './ViewLogsButton'; const ManageBotRunDialog = ({ testPlanReportId, @@ -78,6 +79,13 @@ const ManageBotRunDialog = ({ onChange } }, + { + component: ViewLogsButton, + props: { + externalLogsUrl: + collectionJobQuery?.collectionJobByTestPlanRunId?.externalLogsUrl + } + }, { component: StopRunningCollectionButton, props: { @@ -107,7 +115,14 @@ const ManageBotRunDialog = ({ } } ]; - }, [testPlanReportId, testPlanRun, possibleReassignees, onChange]); + }, [ + testPlanReportId, + testPlanRun, + possibleReassignees, + onChange, + collectionJobQuery + ]); + const deleteConfirmationContent = ( <>

    diff --git a/client/components/ManageBotRunDialog/queries.js b/client/components/ManageBotRunDialog/queries.js index 73cfffed8..dba46068e 100644 --- a/client/components/ManageBotRunDialog/queries.js +++ b/client/components/ManageBotRunDialog/queries.js @@ -5,6 +5,7 @@ export const COLLECTION_JOB_ID_BY_TEST_PLAN_RUN_ID_QUERY = gql` collectionJobByTestPlanRunId(testPlanRunId: $testPlanRunId) { id status + externalLogsUrl } } `; From c913504355a53adfef2bb807bc4629430c4bd044 Mon Sep 17 00:00:00 2001 From: Howard Edwards Date: Tue, 16 Jul 2024 21:10:57 -0400 Subject: [PATCH 12/15] fix: Reset TestPlanVersion `nextval` during import if IDs aren't used (#1153) * Reset TestPlanVersion nextval during import if ids go unused * Fix migration * Update id * Update testPlanVersion test id --- ...15150459-resetTestPlanVersionIdToLatest.js | 32 + server/scripts/import-tests/index.js | 25 +- server/tests/integration/graphql.test.js | 870 +++++++++--------- 3 files changed, 488 insertions(+), 439 deletions(-) create mode 100644 server/migrations/20240715150459-resetTestPlanVersionIdToLatest.js diff --git a/server/migrations/20240715150459-resetTestPlanVersionIdToLatest.js b/server/migrations/20240715150459-resetTestPlanVersionIdToLatest.js new file mode 100644 index 000000000..b0e59a0b3 --- /dev/null +++ b/server/migrations/20240715150459-resetTestPlanVersionIdToLatest.js @@ -0,0 +1,32 @@ +'use strict'; + +const { sequelize } = require('../models'); +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + return queryInterface.sequelize.transaction(async transaction => { + const [latestTestPlanVersion] = await queryInterface.sequelize.query( + `select id + from "TestPlanVersion" + order by id desc + limit 1`, + { + type: Sequelize.QueryTypes.SELECT, + transaction + } + ); + + if (latestTestPlanVersion) { + await sequelize.query( + `SELECT setval(pg_get_serial_sequence('"TestPlanVersion"', 'id'), :currentSequenceValue)`, + { + replacements: { currentSequenceValue: latestTestPlanVersion.id }, + transaction + } + ); + } + }); + }, + + async down() {} +}; diff --git a/server/scripts/import-tests/index.js b/server/scripts/import-tests/index.js index 661d1d935..b2420fe03 100644 --- a/server/scripts/import-tests/index.js +++ b/server/scripts/import-tests/index.js @@ -141,14 +141,21 @@ const buildTestsAndCreateTestPlanVersions = async (commit, { transaction }) => { // Gets the next ID and increments the ID counter in Postgres // Needed to create the testIds - see LocationOfDataId.js for more info const [testPlanVersionIdResult] = await sequelize.query( - `SELECT nextval( - pg_get_serial_sequence('"TestPlanVersion"', 'id') - )`, + `SELECT nextval(pg_get_serial_sequence('"TestPlanVersion"', 'id'))`, { transaction } ); const testPlanVersionIdResultRow = testPlanVersionIdResult[0]; const testPlanVersionId = testPlanVersionIdResultRow.nextval; + // Get the currently set value to rollback the 'correct' nextval for + // subsequent runs + const [currentTestPlanVersionIdResult] = await sequelize.query( + `SELECT currval(pg_get_serial_sequence('"TestPlanVersion"', 'id'))`, + { transaction } + ); + const currentTestPlanVersionId = + currentTestPlanVersionIdResult[0].currval - 1; + // Target the specific /tests/ directory to determine when a pattern's folder was // actually last changed const { @@ -180,7 +187,17 @@ const buildTestsAndCreateTestPlanVersions = async (commit, { transaction }) => { transaction }); - if (existing.length) continue; + if (existing.length) { + // Rollback the sequence to avoid unintentional id jumps (potentially 35+) + await sequelize.query( + `SELECT setval(pg_get_serial_sequence('"TestPlanVersion"', 'id'), :currentTestPlanVersionId)`, + { + replacements: { currentTestPlanVersionId }, + transaction + } + ); + continue; + } const { title, exampleUrl, designPatternUrl, testPageUrl } = readCsv({ sourceDirectoryPath, diff --git a/server/tests/integration/graphql.test.js b/server/tests/integration/graphql.test.js index 0db40d5b9..3a7195417 100644 --- a/server/tests/integration/graphql.test.js +++ b/server/tests/integration/graphql.test.js @@ -181,444 +181,444 @@ describe('graphql', () => { // eslint-disable-next-line no-unused-vars const queryResult = await typeAwareQuery( gql` - query { + query { + __typename + browsers { + __typename + id + key + name + ats { + __typename + id + name + } + candidateAts { + __typename + id + name + } + recommendedAts { + __typename + id + name + } + browserVersions { + __typename + id + name + } + } + ats { + __typename + id + key + name + browsers { + __typename + id + name + } + candidateBrowsers { + __typename + id + name + } + recommendedBrowsers { + __typename + id + name + } + atVersions { + __typename + id + name + releasedAt + } + } + users { + __typename + username + roles + isBot + } + me { + __typename + id + username + roles + ats { + id + name + } + } + collectionJob(id: 1) { + __typename + id + status + testPlanRun { + id + } + } + collectionJobs { + __typename + id + status + } + collectionJobByTestPlanRunId(testPlanRunId: 1) { + __typename + id + status + } + v2TestPlanVersion: testPlanVersion(id: 80) { + __typename + id + metadata + tests { + __typename + assertions { + __typename + phrase + } + } + } + testPlan(id: "checkbox") { + __typename + id + directory + title + latestTestPlanVersion { + __typename + id + title + updatedAt + gitSha + gitMessage + updatedAt + testPageUrl + metadata + tests { + __typename + id + rowNumber + title + ats { + id + } + scenarios { + __typename + id + at { + id + } + commands { __typename - browsers { - __typename - id - key - name - ats { - __typename - id - name - } - candidateAts { - __typename - id - name - } - recommendedAts { - __typename - id - name - } - browserVersions { - __typename - id - name - } - } - ats { - __typename - id - key - name - browsers { - __typename - id - name - } - candidateBrowsers { - __typename - id - name - } - recommendedBrowsers { - __typename - id - name - } - atVersions { - __typename - id - name - releasedAt - } - } - users { - __typename - username - roles - isBot - } - me { - __typename - id - username - roles - ats { - id - name - } - } - collectionJob(id: 1) { - __typename - id - status - testPlanRun { - id - } - } - collectionJobs { - __typename - id - status - } - collectionJobByTestPlanRunId(testPlanRunId: 1) { - __typename - id - status - } - v2TestPlanVersion: testPlanVersion(id: 133) { - __typename - id - metadata - tests { - __typename - assertions { - __typename - phrase - } - } - } - testPlan(id: "checkbox") { - __typename - id - directory - title - latestTestPlanVersion { - __typename - id - title - updatedAt - gitSha - gitMessage - updatedAt - testPageUrl - metadata - tests { - __typename - id - rowNumber - title - ats { - id - } - scenarios { - __typename - id - at { - id - } - commands { - __typename - id - text - atOperatingMode - } - } - assertions { - __typename - id - priority - text - } - testFormatVersion - } - } - testPlanVersions { - id - } - issues { - __typename - author - title - link - isCandidateReview - feedbackType - isOpen - testNumberFilteredByAt - createdAt - closedAt - at { - name - } - browser { - name - } - } - } - testPlans { - directory - title - } - testPlanRuns { - id - } - testPlanVersions { - __typename - id - phase - draftPhaseReachedAt - candidatePhaseReachedAt - recommendedPhaseTargetDate - recommendedPhaseReachedAt - deprecatedAt - versionString - } - testPlanVersion(id: 1) { - __typename - id - testPlanReports { - id - } - testPlan { - id - directory - } - } - recommendedTestPlanVersion: testPlanVersion(id: 69) { - __typename - id - testPlanReports { - __typename - id - recommendedAtVersion { - __typename - id - name - releasedAt - } - } - earliestAtVersion(atId: 1) { - id - name - releasedAt - } - testPlanReportStatuses { - __typename - isRequired - at { - id - } - exactAtVersion { - id - } - minimumAtVersion { - id - } - browser { - id - } - testPlanReport { - id - } - } - } - conflictTestPlanReport: testPlanReport(id: 2) { - __typename - id - isFinal - createdAt - vendorReviewStatus - testPlanVersion { - id - } - at { - __typename - id - } - browser { - __typename - id - } - runnableTests { - __typename - id - renderableContent - renderableContents { - __typename - at { - id - } - renderableContent - } - renderedUrl - renderedUrls { - __typename - at { - id - } - renderedUrl - } - } - runnableTestsLength - draftTestPlanRuns { - __typename - id - tester { - username - } - testResults { - __typename - id - test { - id - } - atVersion { - __typename - id - name - releasedAt - } - browserVersion { - __typename - id - name - } - scenarioResults { - __typename - id - scenario { - id - } - output - assertionResults { - __typename - id - assertion { - id - } - passed - } - unexpectedBehaviors { - __typename - id - text - impact - details - } - } - } - testResultsLength - } - conflicts { - __typename - source { - locationOfData - } - conflictingResults { - locationOfData - } - } - issues { - __typename - } - } - testPlanReport(id: 3) { - __typename - finalizedTestResults { - __typename - id - startedAt - completedAt - } - metrics - conflictsLength - atVersions { - id - name - releasedAt - } - latestAtVersionReleasedAt { - id - name - releasedAt - } - markedFinalAt - minimumAtVersion { - id - } - } - recommendedPhaseTestPlanReport: testPlanReport(id: 12) { - __typename - exactAtVersion { - id - } - } - testPlanReports { - id - atVersions { - id - name - releasedAt - } - latestAtVersionReleasedAt { - id - name - releasedAt - } - } - testPlanRun(id: 1) { - __typename - id - initiatedByAutomation - collectionJob { id } - testPlanReport { - id - } - } - populateData(locationOfData: { - assertionResultId: "${assertionResultId}" - }) { - __typename - locationOfData - testPlan { - id - } - testPlanVersion { - id - } - testPlanReport { - id - } - at { - id - } - browser { - id - } - testPlanRun { - id - } - test { - id - } - scenario { - id - } - assertion { - id - } - testResult { - id - } - atVersion { - id - } - browserVersion { - id - } - scenarioResult { - id - } - assertionResult { - id - } + id + text + atOperatingMode + } + } + assertions { + __typename + id + priority + text + } + testFormatVersion + } + } + testPlanVersions { + id + } + issues { + __typename + author + title + link + isCandidateReview + feedbackType + isOpen + testNumberFilteredByAt + createdAt + closedAt + at { + name + } + browser { + name + } + } + } + testPlans { + directory + title + } + testPlanRuns { + id + } + testPlanVersions { + __typename + id + phase + draftPhaseReachedAt + candidatePhaseReachedAt + recommendedPhaseTargetDate + recommendedPhaseReachedAt + deprecatedAt + versionString + } + testPlanVersion(id: 1) { + __typename + id + testPlanReports { + id + } + testPlan { + id + directory + } + } + recommendedTestPlanVersion: testPlanVersion(id: 67) { + __typename + id + testPlanReports { + __typename + id + recommendedAtVersion { + __typename + id + name + releasedAt + } + } + earliestAtVersion(atId: 1) { + id + name + releasedAt + } + testPlanReportStatuses { + __typename + isRequired + at { + id + } + exactAtVersion { + id + } + minimumAtVersion { + id + } + browser { + id + } + testPlanReport { + id + } + } + } + conflictTestPlanReport: testPlanReport(id: 2) { + __typename + id + isFinal + createdAt + vendorReviewStatus + testPlanVersion { + id + } + at { + __typename + id + } + browser { + __typename + id + } + runnableTests { + __typename + id + renderableContent + renderableContents { + __typename + at { + id + } + renderableContent + } + renderedUrl + renderedUrls { + __typename + at { + id + } + renderedUrl + } + } + runnableTestsLength + draftTestPlanRuns { + __typename + id + tester { + username + } + testResults { + __typename + id + test { + id + } + atVersion { + __typename + id + name + releasedAt + } + browserVersion { + __typename + id + name + } + scenarioResults { + __typename + id + scenario { + id + } + output + assertionResults { + __typename + id + assertion { + id } + passed + } + unexpectedBehaviors { + __typename + id + text + impact + details + } } - `, + } + testResultsLength + } + conflicts { + __typename + source { + locationOfData + } + conflictingResults { + locationOfData + } + } + issues { + __typename + } + } + testPlanReport(id: 3) { + __typename + finalizedTestResults { + __typename + id + startedAt + completedAt + } + metrics + conflictsLength + atVersions { + id + name + releasedAt + } + latestAtVersionReleasedAt { + id + name + releasedAt + } + markedFinalAt + minimumAtVersion { + id + } + } + recommendedPhaseTestPlanReport: testPlanReport(id: 12) { + __typename + exactAtVersion { + id + } + } + testPlanReports { + id + atVersions { + id + name + releasedAt + } + latestAtVersionReleasedAt { + id + name + releasedAt + } + } + testPlanRun(id: 1) { + __typename + id + initiatedByAutomation + collectionJob { id } + testPlanReport { + id + } + } + populateData(locationOfData: { + assertionResultId: "${assertionResultId}" + }) { + __typename + locationOfData + testPlan { + id + } + testPlanVersion { + id + } + testPlanReport { + id + } + at { + id + } + browser { + id + } + testPlanRun { + id + } + test { + id + } + scenario { + id + } + assertion { + id + } + testResult { + id + } + atVersion { + id + } + browserVersion { + id + } + scenarioResult { + id + } + assertionResult { + id + } + } + } + `, { transaction: false } ); From 52865e2192ebeb8ae6f41b23a8b05d4923bdb2a3 Mon Sep 17 00:00:00 2001 From: Stalgia Grigg Date: Wed, 17 Jul 2024 08:34:53 -0700 Subject: [PATCH 13/15] feat: Specify AtVersion for automation (#1144) * Virtual property for AtVersion.supportedByAutomation * Ensure that supportedByAutomation is testing in graphql query test * Do not provide option to run with automation when minimum/exact at version reqs not supported by automation * Support specifying required version to runner * Version reporting for mock automation * Support minimum version * Pass macos_version workflow input when scheduling VoiceOver jobs * Add test coverage * Ensure correct os number sent to VoiceOver runner * Remove errant log * Ref and comment update after aria-at-gh-actions-helper merge * Update server/util/getAtVersionWithRequirements.js Co-authored-by: Mx Corey Frang * Move query updates to new TestQueue * Update mock for DataManagePage and TestPlanReportStatusDialog, fix incorrect query after merge resolution * Update to handle merge conflicts * Correct dump test data with version recent enough for unit tests * Correct version in dump test data * JSDoc update for triggerWorkflow, fix missing arg in triggerWorkflow call, add issue link to comment, constants for at/browser combo check --------- Co-authored-by: Mx Corey Frang --- .../AddTestToQueueWithConfirmation/index.jsx | 25 +- client/components/DataManagement/queries.js | 1 + .../TestPlanReportStatusDialog/queries.js | 10 + client/components/TestQueue/AssignTesters.jsx | 23 +- client/components/TestQueue/queries.js | 10 + .../DataManagementPagePopulatedMock.js | 563 +++++++++++++++--- .../TestPlanReportStatusDialogMock.js | 98 ++- client/utils/automation.js | 81 ++- server/graphql-schema.js | 4 + server/models/AtVersion.js | 19 + server/models/TestPlanReport.js | 10 + .../models/services/CollectionJobService.js | 52 +- .../models/services/TestPlanReportService.js | 18 +- .../populate-test-data/pg_dump_test_data.sql | 4 + server/services/GithubWorkflowService.js | 9 +- .../integration/automation-scheduler.test.js | 3 + server/tests/integration/graphql.test.js | 1 + .../util/mock-automation-scheduler-server.js | 10 +- server/util/constants.js | 11 +- server/util/getAtVersionWithRequirements.js | 61 ++ 20 files changed, 890 insertions(+), 123 deletions(-) create mode 100644 server/util/getAtVersionWithRequirements.js diff --git a/client/components/AddTestToQueueWithConfirmation/index.jsx b/client/components/AddTestToQueueWithConfirmation/index.jsx index d249f29da..45c6931fb 100644 --- a/client/components/AddTestToQueueWithConfirmation/index.jsx +++ b/client/components/AddTestToQueueWithConfirmation/index.jsx @@ -102,7 +102,9 @@ function AddTestToQueueWithConfirmation({ const hasAutomationSupport = isSupportedByResponseCollector({ at, - browser + browser, + minimumAtVersion, + exactAtVersion }); const alreadyHasBotInTestPlanReport = useMemo( @@ -328,10 +330,25 @@ AddTestToQueueWithConfirmation.propTypes = { at: PropTypes.shape({ id: PropTypes.string.isRequired, key: PropTypes.string.isRequired, - name: PropTypes.string.isRequired + name: PropTypes.string.isRequired, + atVersions: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + supportedByAutomation: PropTypes.bool.isRequired + }) + ) + }), + exactAtVersion: PropTypes.shape({ + id: PropTypes.string, + name: PropTypes.string, + supportedByAutomation: PropTypes.bool + }), + minimumAtVersion: PropTypes.shape({ + id: PropTypes.string, + name: PropTypes.string, + supportedByAutomation: PropTypes.bool }), - exactAtVersion: PropTypes.object, - minimumAtVersion: PropTypes.object, buttonRef: PropTypes.object, onFocus: PropTypes.func, onBlur: PropTypes.func, diff --git a/client/components/DataManagement/queries.js b/client/components/DataManagement/queries.js index c677744ae..734b20f50 100644 --- a/client/components/DataManagement/queries.js +++ b/client/components/DataManagement/queries.js @@ -20,6 +20,7 @@ export const DATA_MANAGEMENT_PAGE_QUERY = gql` id name releasedAt + supportedByAutomation } candidateBrowsers { id diff --git a/client/components/TestPlanReportStatusDialog/queries.js b/client/components/TestPlanReportStatusDialog/queries.js index e32ed1ac0..75050f8dd 100644 --- a/client/components/TestPlanReportStatusDialog/queries.js +++ b/client/components/TestPlanReportStatusDialog/queries.js @@ -22,6 +22,12 @@ export const TEST_PLAN_REPORT_STATUS_DIALOG_QUERY = gql` id key name + atVersions { + id + name + supportedByAutomation + releasedAt + } } browser { id @@ -31,10 +37,14 @@ export const TEST_PLAN_REPORT_STATUS_DIALOG_QUERY = gql` minimumAtVersion { id name + supportedByAutomation + releasedAt } exactAtVersion { id name + supportedByAutomation + releasedAt } testPlanReport { id diff --git a/client/components/TestQueue/AssignTesters.jsx b/client/components/TestQueue/AssignTesters.jsx index 0fa43ada2..38f50c076 100644 --- a/client/components/TestQueue/AssignTesters.jsx +++ b/client/components/TestQueue/AssignTesters.jsx @@ -236,7 +236,9 @@ const AssignTesters = ({ me, testers, testPlanReport }) => { const supportedByResponseCollector = isSupportedByResponseCollector({ id: testPlanReport.id, at: testPlanReport.at, - browser: testPlanReport.browser + browser: testPlanReport.browser, + minimumAtVersion: testPlanReport.minimumAtVersion, + exactAtVersion: testPlanReport.exactAtVersion }); if (!foundAtForBot || !supportedByResponseCollector) return null; } @@ -353,13 +355,28 @@ AssignTesters.propTypes = { at: PropTypes.shape({ id: PropTypes.string.isRequired, name: PropTypes.string.isRequired, - key: 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 + }).isRequired, + minimumAtVersion: PropTypes.shape({ + id: PropTypes.string.isRequired, + name: PropTypes.string.isRequired + }), + exactAtVersion: PropTypes.shape({ + id: PropTypes.string.isRequired, + name: PropTypes.string.isRequired + }) }).isRequired }; diff --git a/client/components/TestQueue/queries.js b/client/components/TestQueue/queries.js index 7c201deff..6d83dff28 100644 --- a/client/components/TestQueue/queries.js +++ b/client/components/TestQueue/queries.js @@ -25,6 +25,7 @@ export const TEST_QUEUE_PAGE_QUERY = gql` id name releasedAt + supportedByAutomation } browsers { id @@ -49,6 +50,12 @@ export const TEST_QUEUE_PAGE_QUERY = gql` id key name + atVersions { + id + name + supportedByAutomation + releasedAt + } } browser { id @@ -58,10 +65,13 @@ export const TEST_QUEUE_PAGE_QUERY = gql` minimumAtVersion { id name + supportedByAutomation + releasedAt } exactAtVersion { id name + supportedByAutomation } runnableTestsLength conflictsLength diff --git a/client/tests/__mocks__/GraphQLMocks/DataManagementPagePopulatedMock.js b/client/tests/__mocks__/GraphQLMocks/DataManagementPagePopulatedMock.js index af6d23613..7053cf593 100644 --- a/client/tests/__mocks__/GraphQLMocks/DataManagementPagePopulatedMock.js +++ b/client/tests/__mocks__/GraphQLMocks/DataManagementPagePopulatedMock.js @@ -37,7 +37,8 @@ export default ( { id: '1', name: '2021.2111.13', - releasedAt: '2021-11-01T04:00:00.000Z' + releasedAt: '2021-11-01T04:00:00.000Z', + supportedByAutomation: false } ], browsers: [ @@ -63,7 +64,8 @@ export default ( { id: '2', name: '2020.4', - releasedAt: '2021-02-19T05:00:00.000Z' + releasedAt: '2021-02-19T05:00:00.000Z', + supportedByAutomation: false } ], browsers: [ @@ -89,7 +91,8 @@ export default ( { id: '3', name: '11.6 (20G165)', - releasedAt: '2019-09-01T04:00:00.000Z' + releasedAt: '2019-09-01T04:00:00.000Z', + supportedByAutomation: false } ], browsers: [ @@ -413,7 +416,15 @@ export default ( at: { id: '3', key: 'voiceover_macos', - name: 'VoiceOver for macOS' + name: 'VoiceOver for macOS', + atVersions: [ + { + id: '3', + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '1', @@ -1083,7 +1094,15 @@ export default ( at: { id: '2', key: 'nvda', - name: 'NVDA' + name: 'NVDA', + atVersions: [ + { + id: '2', + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' + } + ] }, browser: { id: '1', @@ -1638,7 +1657,15 @@ export default ( at: { id: '2', key: 'nvda', - name: 'NVDA' + name: 'NVDA', + atVersions: [ + { + id: '2', + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' + } + ] }, browser: { id: '2', @@ -1834,7 +1861,15 @@ export default ( at: { id: '2', key: 'nvda', - name: 'NVDA' + name: 'NVDA', + atVersions: [ + { + id: '2', + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' + } + ] }, browser: { id: '1', @@ -2126,7 +2161,15 @@ export default ( at: { id: '2', key: 'nvda', - name: 'NVDA' + name: 'NVDA', + atVersions: [ + { + id: '2', + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' + } + ] }, browser: { id: '2', @@ -2498,7 +2541,15 @@ export default ( at: { id: '1', key: 'jaws', - name: 'JAWS' + name: 'JAWS', + atVersions: [ + { + id: '1', + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '2', @@ -2507,7 +2558,9 @@ export default ( }, minimumAtVersion: { id: '1', - name: '2021.2111.13' + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: { @@ -2524,7 +2577,15 @@ export default ( at: { id: '1', key: 'jaws', - name: 'JAWS' + name: 'JAWS', + atVersions: [ + { + id: '1', + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '1', @@ -2533,7 +2594,9 @@ export default ( }, minimumAtVersion: { id: '1', - name: '2021.2111.13' + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null @@ -2543,7 +2606,15 @@ export default ( at: { id: '2', key: 'nvda', - name: 'NVDA' + name: 'NVDA', + atVersions: [ + { + id: '2', + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' + } + ] }, browser: { id: '2', @@ -2552,7 +2623,9 @@ export default ( }, minimumAtVersion: { id: '2', - name: '2020.4' + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null @@ -2562,7 +2635,15 @@ export default ( at: { id: '2', key: 'nvda', - name: 'NVDA' + name: 'NVDA', + atVersions: [ + { + id: '2', + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' + } + ] }, browser: { id: '1', @@ -2571,7 +2652,9 @@ export default ( }, minimumAtVersion: { id: '2', - name: '2020.4' + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null @@ -2581,7 +2664,15 @@ export default ( at: { id: '3', key: 'voiceover_macos', - name: 'VoiceOver for macOS' + name: 'VoiceOver for macOS', + atVersions: [ + { + id: '3', + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '3', @@ -2590,7 +2681,9 @@ export default ( }, minimumAtVersion: { id: '3', - name: '11.6 (20G165)' + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null @@ -2600,7 +2693,15 @@ export default ( at: { id: '3', key: 'voiceover_macos', - name: 'VoiceOver for macOS' + name: 'VoiceOver for macOS', + atVersions: [ + { + id: '3', + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '2', @@ -2609,7 +2710,9 @@ export default ( }, minimumAtVersion: { id: '3', - name: '11.6 (20G165)' + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null @@ -2619,7 +2722,15 @@ export default ( at: { id: '3', key: 'voiceover_macos', - name: 'VoiceOver for macOS' + name: 'VoiceOver for macOS', + atVersions: [ + { + id: '3', + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '1', @@ -2628,7 +2739,9 @@ export default ( }, minimumAtVersion: { id: '3', - name: '11.6 (20G165)' + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: { @@ -2672,7 +2785,15 @@ export default ( at: { id: '1', key: 'jaws', - name: 'JAWS' + name: 'JAWS', + atVersions: [ + { + id: '1', + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '2', @@ -2681,7 +2802,9 @@ export default ( }, minimumAtVersion: { id: '1', - name: '2021.2111.13' + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: { @@ -2933,7 +3056,15 @@ export default ( at: { id: '1', key: 'jaws', - name: 'JAWS' + name: 'JAWS', + atVersions: [ + { + id: '1', + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '1', @@ -2942,7 +3073,9 @@ export default ( }, minimumAtVersion: { id: '1', - name: '2021.2111.13' + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null @@ -2952,7 +3085,15 @@ export default ( at: { id: '2', key: 'nvda', - name: 'NVDA' + name: 'NVDA', + atVersions: [ + { + id: '2', + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' + } + ] }, browser: { id: '2', @@ -2961,7 +3102,9 @@ export default ( }, minimumAtVersion: { id: '2', - name: '2020.4' + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: { @@ -3213,7 +3356,15 @@ export default ( at: { id: '2', key: 'nvda', - name: 'NVDA' + name: 'NVDA', + atVersions: [ + { + id: '2', + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' + } + ] }, browser: { id: '1', @@ -3222,7 +3373,9 @@ export default ( }, minimumAtVersion: { id: '2', - name: '2020.4' + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null @@ -3232,7 +3385,15 @@ export default ( at: { id: '3', key: 'voiceover_macos', - name: 'VoiceOver for macOS' + name: 'VoiceOver for macOS', + atVersions: [ + { + id: '3', + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '2', @@ -3241,7 +3402,9 @@ export default ( }, minimumAtVersion: { id: '3', - name: '11.6 (20G165)' + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null @@ -3251,7 +3414,15 @@ export default ( at: { id: '3', key: 'voiceover_macos', - name: 'VoiceOver for macOS' + name: 'VoiceOver for macOS', + atVersions: [ + { + id: '3', + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '3', @@ -3260,7 +3431,9 @@ export default ( }, minimumAtVersion: { id: '3', - name: '11.6 (20G165)' + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: { @@ -3414,7 +3587,15 @@ export default ( at: { id: '3', key: 'voiceover_macos', - name: 'VoiceOver for macOS' + name: 'VoiceOver for macOS', + atVersions: [ + { + id: '3', + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '1', @@ -3423,7 +3604,9 @@ export default ( }, minimumAtVersion: { id: '3', - name: '11.6 (20G165)' + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null @@ -3461,7 +3644,15 @@ export default ( at: { id: '1', key: 'jaws', - name: 'JAWS' + name: 'JAWS', + atVersions: [ + { + id: '1', + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '2', @@ -3470,7 +3661,9 @@ export default ( }, minimumAtVersion: { id: '1', - name: '2021.2111.13' + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null @@ -3480,7 +3673,15 @@ export default ( at: { id: '1', key: 'jaws', - name: 'JAWS' + name: 'JAWS', + atVersions: [ + { + id: '1', + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '1', @@ -3489,7 +3690,9 @@ export default ( }, minimumAtVersion: { id: '1', - name: '2021.2111.13' + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null @@ -3499,7 +3702,15 @@ export default ( at: { id: '2', key: 'nvda', - name: 'NVDA' + name: 'NVDA', + atVersions: [ + { + id: '2', + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' + } + ] }, browser: { id: '2', @@ -3508,7 +3719,9 @@ export default ( }, minimumAtVersion: { id: '2', - name: '2020.4' + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null @@ -3518,7 +3731,15 @@ export default ( at: { id: '2', key: 'nvda', - name: 'NVDA' + name: 'NVDA', + atVersions: [ + { + id: '2', + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' + } + ] }, browser: { id: '1', @@ -3527,7 +3748,9 @@ export default ( }, minimumAtVersion: { id: '2', - name: '2020.4' + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: { @@ -4131,7 +4354,15 @@ export default ( at: { id: '3', key: 'voiceover_macos', - name: 'VoiceOver for macOS' + name: 'VoiceOver for macOS', + atVersions: [ + { + id: '3', + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '3', @@ -4140,7 +4371,9 @@ export default ( }, minimumAtVersion: { id: '3', - name: '11.6 (20G165)' + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null @@ -4150,7 +4383,15 @@ export default ( at: { id: '3', key: 'voiceover_macos', - name: 'VoiceOver for macOS' + name: 'VoiceOver for macOS', + atVersions: [ + { + id: '3', + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '2', @@ -4159,7 +4400,9 @@ export default ( }, minimumAtVersion: { id: '3', - name: '11.6 (20G165)' + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null @@ -4169,7 +4412,15 @@ export default ( at: { id: '3', key: 'voiceover_macos', - name: 'VoiceOver for macOS' + name: 'VoiceOver for macOS', + atVersions: [ + { + id: '3', + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '1', @@ -4178,7 +4429,9 @@ export default ( }, minimumAtVersion: { id: '3', - name: '11.6 (20G165)' + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null @@ -4215,7 +4468,15 @@ export default ( at: { id: '1', key: 'jaws', - name: 'JAWS' + name: 'JAWS', + atVersions: [ + { + id: '1', + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '2', @@ -4224,7 +4485,9 @@ export default ( }, minimumAtVersion: { id: '1', - name: '2021.2111.13' + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: { @@ -4532,7 +4795,15 @@ export default ( at: { id: '1', key: 'jaws', - name: 'JAWS' + name: 'JAWS', + atVersions: [ + { + id: '1', + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '2', @@ -4542,7 +4813,9 @@ export default ( minimumAtVersion: null, exactAtVersion: { id: '1', - name: '2021.2111.13' + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, testPlanReport: { id: '105', @@ -4558,7 +4831,15 @@ export default ( at: { id: '1', key: 'jaws', - name: 'JAWS' + name: 'JAWS', + atVersions: [ + { + id: '1', + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '1', @@ -4567,7 +4848,9 @@ export default ( }, minimumAtVersion: { id: '1', - name: '2021.2111.13' + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: { @@ -4875,7 +5158,15 @@ export default ( at: { id: '2', key: 'nvda', - name: 'NVDA' + name: 'NVDA', + atVersions: [ + { + id: '2', + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' + } + ] }, browser: { id: '2', @@ -4884,7 +5175,9 @@ export default ( }, minimumAtVersion: { id: '2', - name: '2020.4' + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: { @@ -5192,7 +5485,15 @@ export default ( at: { id: '2', key: 'nvda', - name: 'NVDA' + name: 'NVDA', + atVersions: [ + { + id: '2', + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' + } + ] }, browser: { id: '1', @@ -5201,7 +5502,9 @@ export default ( }, minimumAtVersion: { id: '2', - name: '2020.4' + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: { @@ -5509,7 +5812,15 @@ export default ( at: { id: '3', key: 'voiceover_macos', - name: 'VoiceOver for macOS' + name: 'VoiceOver for macOS', + atVersions: [ + { + id: '3', + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '3', @@ -5518,7 +5829,9 @@ export default ( }, minimumAtVersion: { id: '3', - name: '11.6 (20G165)' + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: { @@ -5728,7 +6041,15 @@ export default ( at: { id: '3', key: 'voiceover_macos', - name: 'VoiceOver for macOS' + name: 'VoiceOver for macOS', + atVersions: [ + { + id: '3', + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '2', @@ -5737,7 +6058,9 @@ export default ( }, minimumAtVersion: { id: '3', - name: '11.6 (20G165)' + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: { @@ -5947,7 +6270,15 @@ export default ( at: { id: '3', key: 'voiceover_macos', - name: 'VoiceOver for macOS' + name: 'VoiceOver for macOS', + atVersions: [ + { + id: '3', + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '1', @@ -5956,7 +6287,9 @@ export default ( }, minimumAtVersion: { id: '3', - name: '11.6 (20G165)' + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: { @@ -6194,7 +6527,15 @@ export default ( at: { id: '1', key: 'jaws', - name: 'JAWS' + name: 'JAWS', + atVersions: [ + { + id: '1', + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '2', @@ -6203,7 +6544,9 @@ export default ( }, minimumAtVersion: { id: '1', - name: '2021.2111.13' + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: { @@ -6469,7 +6812,15 @@ export default ( at: { id: '1', key: 'jaws', - name: 'JAWS' + name: 'JAWS', + atVersions: [ + { + id: '1', + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '1', @@ -6478,7 +6829,9 @@ export default ( }, minimumAtVersion: { id: '1', - name: '2021.2111.13' + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null @@ -6488,7 +6841,15 @@ export default ( at: { id: '2', key: 'nvda', - name: 'NVDA' + name: 'NVDA', + atVersions: [ + { + id: '2', + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' + } + ] }, browser: { id: '2', @@ -6497,7 +6858,9 @@ export default ( }, minimumAtVersion: { id: '2', - name: '2020.4' + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: { @@ -6777,7 +7140,15 @@ export default ( at: { id: '2', key: 'nvda', - name: 'NVDA' + name: 'NVDA', + atVersions: [ + { + id: '2', + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' + } + ] }, browser: { id: '1', @@ -6786,7 +7157,9 @@ export default ( }, minimumAtVersion: { id: '2', - name: '2020.4' + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null @@ -6796,7 +7169,15 @@ export default ( at: { id: '3', key: 'voiceover_macos', - name: 'VoiceOver for macOS' + name: 'VoiceOver for macOS', + atVersions: [ + { + id: '3', + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '3', @@ -6805,7 +7186,9 @@ export default ( }, minimumAtVersion: { id: '3', - name: '11.6 (20G165)' + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: { @@ -6973,7 +7356,15 @@ export default ( at: { id: '3', key: 'voiceover_macos', - name: 'VoiceOver for macOS' + name: 'VoiceOver for macOS', + atVersions: [ + { + id: '3', + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '2', @@ -6982,7 +7373,9 @@ export default ( }, minimumAtVersion: { id: '3', - name: '11.6 (20G165)' + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null @@ -6992,7 +7385,15 @@ export default ( at: { id: '3', key: 'voiceover_macos', - name: 'VoiceOver for macOS' + name: 'VoiceOver for macOS', + atVersions: [ + { + id: '3', + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '1', @@ -7001,7 +7402,9 @@ export default ( }, minimumAtVersion: { id: '3', - name: '11.6 (20G165)' + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null diff --git a/client/tests/__mocks__/GraphQLMocks/TestPlanReportStatusDialogMock.js b/client/tests/__mocks__/GraphQLMocks/TestPlanReportStatusDialogMock.js index 0d4b74b0d..84015446a 100644 --- a/client/tests/__mocks__/GraphQLMocks/TestPlanReportStatusDialogMock.js +++ b/client/tests/__mocks__/GraphQLMocks/TestPlanReportStatusDialogMock.js @@ -18,7 +18,15 @@ export const mockedTestPlanVersion = { at: { id: '1', key: 'jaws', - name: 'JAWS' + name: 'JAWS', + atVersions: [ + { + id: '1', + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '2', @@ -27,7 +35,9 @@ export const mockedTestPlanVersion = { }, minimumAtVersion: { id: '1', - name: '2021.2111.13' + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null @@ -37,7 +47,15 @@ export const mockedTestPlanVersion = { at: { id: '1', key: 'jaws', - name: 'JAWS' + name: 'JAWS', + atVersions: [ + { + id: '1', + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' + } + ] }, browser: { id: '1', @@ -46,7 +64,9 @@ export const mockedTestPlanVersion = { }, minimumAtVersion: { id: '1', - name: '2021.2111.13' + name: '2021.2111.13', + supportedByAutomation: false, + releasedAt: '2021-11-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null @@ -56,7 +76,15 @@ export const mockedTestPlanVersion = { at: { id: '2', key: 'nvda', - name: 'NVDA' + name: 'NVDA', + atVersions: [ + { + id: '2', + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' + } + ] }, browser: { id: '2', @@ -65,7 +93,9 @@ export const mockedTestPlanVersion = { }, minimumAtVersion: { id: '2', - name: '2020.4' + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null @@ -75,7 +105,15 @@ export const mockedTestPlanVersion = { at: { id: '2', key: 'nvda', - name: 'NVDA' + name: 'NVDA', + atVersions: [ + { + id: '2', + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' + } + ] }, browser: { id: '1', @@ -84,7 +122,9 @@ export const mockedTestPlanVersion = { }, minimumAtVersion: { id: '2', - name: '2020.4' + name: '2020.4', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: { @@ -688,7 +728,15 @@ export const mockedTestPlanVersion = { at: { id: '3', key: 'voiceover_macos', - name: 'VoiceOver for macOS' + name: 'VoiceOver for macOS', + atVersions: [ + { + id: '3', + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' + } + ] }, browser: { id: '3', @@ -697,7 +745,9 @@ export const mockedTestPlanVersion = { }, minimumAtVersion: { id: '3', - name: '11.6 (20G165)' + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null @@ -707,7 +757,15 @@ export const mockedTestPlanVersion = { at: { id: '3', key: 'voiceover_macos', - name: 'VoiceOver for macOS' + name: 'VoiceOver for macOS', + atVersions: [ + { + id: '3', + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' + } + ] }, browser: { id: '2', @@ -716,7 +774,9 @@ export const mockedTestPlanVersion = { }, minimumAtVersion: { id: '3', - name: '11.6 (20G165)' + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null @@ -726,7 +786,15 @@ export const mockedTestPlanVersion = { at: { id: '3', key: 'voiceover_macos', - name: 'VoiceOver for macOS' + name: 'VoiceOver for macOS', + atVersions: [ + { + id: '3', + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' + } + ] }, browser: { id: '1', @@ -735,7 +803,9 @@ export const mockedTestPlanVersion = { }, minimumAtVersion: { id: '3', - name: '11.6 (20G165)' + name: '11.6 (20G165)', + supportedByAutomation: false, + releasedAt: '2020-04-01T04:00:00.000Z' }, exactAtVersion: null, testPlanReport: null diff --git a/client/utils/automation.js b/client/utils/automation.js index 1e31e40e3..208091473 100644 --- a/client/utils/automation.js +++ b/client/utils/automation.js @@ -1,16 +1,79 @@ +/** + * Checks if the AT, browser, and AT version requirements are supported by the automation + * @param {object} ctx + * @param {object} ctx.at + * @param {object} ctx.browser + * @param {object} ctx.minimumAtVersion optional + * @param {object} ctx.exactAtVersion optional + * @returns {boolean} + */ export const isSupportedByResponseCollector = ctx => { if (!ctx || !ctx.at || !ctx.browser) { return false; } - const { - at: { key: atKey }, - browser: { key: browserKey } - } = ctx; - return ( - (atKey === 'nvda' && - (browserKey === 'chrome' || browserKey === 'firefox')) || - (atKey === 'voiceover_macos' && browserKey === 'safari_macos') - ); + + const { at, browser } = ctx; + const { key: atKey } = at; + const { key: browserKey } = browser; + + // Check if the AT and browser are supported by the automation + const isNvdaWithSupportedBrowser = + atKey === 'nvda' && (browserKey === 'chrome' || browserKey === 'firefox'); + const isVoiceOverMacWithSafari = + atKey === 'voiceover_macos' && browserKey === 'safari_macos'; + + if (!isNvdaWithSupportedBrowser && !isVoiceOverMacWithSafari) { + return false; + } + + // If there are version requirements, check if they are supported by automation + if (ctx.minimumAtVersion || ctx.exactAtVersion) { + return atVersionRequirementsSupportedByAutomation(ctx); + } + return true; +}; + +/** + * Checks if the version requirements are supported by automation + * @param {object} ctx + * @param {object} ctx.at + * @param {object} ctx.minimumAtVersion + * @param {object} ctx.exactAtVersion + * @returns {boolean} + */ +const atVersionRequirementsSupportedByAutomation = ({ + at, + minimumAtVersion, + exactAtVersion +}) => { + if (!at || !(exactAtVersion || minimumAtVersion)) { + return false; + } + + if (minimumAtVersion && exactAtVersion) { + console.warn( + 'Both minimumAtVersion and exactAtVersion are set. This is invalid. Using exactAtVersion' + ); + minimumAtVersion = null; + } + + const { atVersions } = at; + if (!atVersions) { + console.warn( + 'Version requirements check was done without atVersions in the supplied at object' + ); + return false; + } + + if (exactAtVersion) { + return exactAtVersion.supportedByAutomation; + } else { + return atVersions.some( + version => + version.supportedByAutomation && + new Date(version.releasedAt) >= new Date(minimumAtVersion.releasedAt) + ); + } }; /** diff --git a/server/graphql-schema.js b/server/graphql-schema.js index 831d9aeef..b6b50adfa 100644 --- a/server/graphql-schema.js +++ b/server/graphql-schema.js @@ -233,6 +233,10 @@ const graphqlSchema = gql` Date for approximate availability of the version. """ releasedAt: Timestamp! + """ + Whether this AT version is supported by automation. + """ + supportedByAutomation: Boolean! } """ diff --git a/server/models/AtVersion.js b/server/models/AtVersion.js index d04b2992b..5b7a30f00 100644 --- a/server/models/AtVersion.js +++ b/server/models/AtVersion.js @@ -1,3 +1,7 @@ +const { + AT_VERSIONS_SUPPORTED_BY_COLLECTION_JOBS +} = require('../util/constants'); + const MODEL_NAME = 'AtVersion'; module.exports = function (sequelize, DataTypes) { @@ -26,6 +30,12 @@ module.exports = function (sequelize, DataTypes) { type: DataTypes.DATE, allowNull: false, defaultValue: new Date() + }, + supportedByAutomation: { + type: DataTypes.VIRTUAL, + get() { + return Model.isSupportedByAutomation(this.atId, this.name); + } } }, { @@ -46,5 +56,14 @@ module.exports = function (sequelize, DataTypes) { }); }; + Model.isSupportedByAutomation = async function (atId, versionName) { + const At = sequelize.models.At; + const at = await At.findByPk(atId); + if (!at) return false; + const supportedVersions = + AT_VERSIONS_SUPPORTED_BY_COLLECTION_JOBS[at.name] || []; + return supportedVersions.includes(versionName); + }; + return Model; }; diff --git a/server/models/TestPlanReport.js b/server/models/TestPlanReport.js index 803ef73ae..223aa0860 100644 --- a/server/models/TestPlanReport.js +++ b/server/models/TestPlanReport.js @@ -83,6 +83,16 @@ module.exports = function (sequelize, DataTypes) { as: 'testPlan' }); + Model.belongsTo(sequelize.models.AtVersion, { + as: 'exactAtVersion', + foreignKey: 'exactAtVersionId' + }); + + Model.belongsTo(sequelize.models.AtVersion, { + as: 'minimumAtVersion', + foreignKey: 'minimumAtVersionId' + }); + Model.hasMany(models.TestPlanRun, { ...Model.TEST_PLAN_RUN_ASSOCIATION, foreignKey: 'testPlanReportId', diff --git a/server/models/services/CollectionJobService.js b/server/models/services/CollectionJobService.js index 251faee18..8d640dc40 100644 --- a/server/models/services/CollectionJobService.js +++ b/server/models/services/CollectionJobService.js @@ -32,6 +32,7 @@ const { const runnableTestsResolver = require('../../resolvers/TestPlanReport/runnableTestsResolver'); const getGraphQLContext = require('../../graphql-context'); const { getBotUserByAtId } = require('./UserService'); +const getAtVersionWithRequirements = require('../../util/getAtVersionWithRequirements'); // association helpers to be included with Models' results @@ -379,19 +380,20 @@ const getCollectionJobs = async ({ * Trigger a workflow, set job status to ERROR if workflow creation fails. * @param {object} job - CollectionJob to trigger workflow for. * @param {number[]} testIds - Array of testIds + * @param {object} atVersion - AtVersion to use for the workflow * @param {object} options * @param {*} options.transaction - Sequelize transaction * @returns Promise */ -const triggerWorkflow = async (job, testIds, { transaction }) => { +const triggerWorkflow = async (job, testIds, atVersion, { transaction }) => { const { testPlanVersion } = job.testPlanRun.testPlanReport; const { gitSha, directory } = testPlanVersion; try { if (isGithubWorkflowEnabled()) { // TODO: pass the reduced list of testIds along / deal with them somehow - await createGithubWorkflow({ job, directory, gitSha }); + await createGithubWorkflow({ job, directory, gitSha, atVersion }); } else { - await startCollectionJobSimulation(job, transaction); + await startCollectionJobSimulation(job, atVersion, transaction); } } catch (error) { console.error(error); @@ -483,6 +485,18 @@ const retryCanceledCollections = async ({ collectionJob }, { transaction }) => { !testResult?.scenarioResults?.every(scenario => scenario?.output !== null) ); + const testPlanReport = await getTestPlanReportById({ + id: job.testPlanRun.testPlanReportId, + transaction + }); + + const atVersion = await getAtVersionWithRequirements( + testPlanReport.at.id, + testPlanReport.exactAtVersion, + testPlanReport.minimumAtVersion, + transaction + ); + const testIds = cancelledTests.map(test => test.id); const job = await getCollectionJobById({ @@ -490,7 +504,7 @@ const retryCanceledCollections = async ({ collectionJob }, { transaction }) => { transaction }); - return triggerWorkflow(job, testIds, { transaction }); + return triggerWorkflow(job, testIds, atVersion, { transaction }); }; /** @@ -560,9 +574,21 @@ const scheduleCollectionJob = async ( transaction }); - return triggerWorkflow(job, testIds ?? tests.map(test => test.id), { + const atVersion = await getAtVersionWithRequirements( + report.at.id, + report.exactAtVersion, + report.minimumAtVersion, transaction - }); + ); + + return triggerWorkflow( + job, + testIds ?? tests.map(test => test.id), + atVersion, + { + transaction + } + ); }; /** @@ -631,7 +657,19 @@ const restartCollectionJob = async ({ id }, { transaction }) => { return null; } - return triggerWorkflow(job, [], { transaction }); + const testPlanReport = await getTestPlanReportById({ + id: job.testPlanRun.testPlanReportId, + transaction + }); + + const atVersion = await getAtVersionWithRequirements( + testPlanReport.at.id, + testPlanReport.exactAtVersion, + testPlanReport.minimumAtVersion, + transaction + ); + + return triggerWorkflow(job, [], atVersion, { transaction }); }; /** diff --git a/server/models/services/TestPlanReportService.js b/server/models/services/TestPlanReportService.js index c35f88c96..ff422459e 100644 --- a/server/models/services/TestPlanReportService.js +++ b/server/models/services/TestPlanReportService.js @@ -7,7 +7,8 @@ const { AT_ATTRIBUTES, BROWSER_ATTRIBUTES, USER_ATTRIBUTES, - TEST_PLAN_ATTRIBUTES + TEST_PLAN_ATTRIBUTES, + AT_VERSION_ATTRIBUTES } = require('./helpers'); const { TestPlanReport, TestPlanVersion } = require('../'); @@ -59,6 +60,16 @@ const testPlanRunAssociation = (testPlanRunAttributes, userAttributes) => ({ ] }); +/** + * @param {string} alias - alias for the association + * @param {string[]} atVersionAttributes - AtVersion attributes + * @returns {{association: string, attributes: string[]}} + */ +const atVersionAssociation = (alias, atVersionAttributes) => ({ + association: alias, + attributes: atVersionAttributes +}); + /** * @param {string[]} testPlanVersionAttributes - TestPlanVersion attributes * @returns {{association: string, attributes: string[]}} @@ -133,6 +144,7 @@ const getTestPlanReportById = async ({ atAttributes = AT_ATTRIBUTES, browserAttributes = BROWSER_ATTRIBUTES, userAttributes = USER_ATTRIBUTES, + atVersionAttributes = AT_VERSION_ATTRIBUTES, transaction }) => { return ModelService.getById(TestPlanReport, { @@ -142,7 +154,9 @@ const getTestPlanReportById = async ({ testPlanRunAssociation(testPlanRunAttributes, userAttributes), testPlanVersionAssociation(testPlanVersionAttributes, testPlanAttributes), atAssociation(atAttributes), - browserAssociation(browserAttributes) + browserAssociation(browserAttributes), + atVersionAssociation('exactAtVersion', atVersionAttributes), + atVersionAssociation('minimumAtVersion', atVersionAttributes) ], transaction }); diff --git a/server/scripts/populate-test-data/pg_dump_test_data.sql b/server/scripts/populate-test-data/pg_dump_test_data.sql index 6a1302143..7768e440f 100644 --- a/server/scripts/populate-test-data/pg_dump_test_data.sql +++ b/server/scripts/populate-test-data/pg_dump_test_data.sql @@ -31,6 +31,10 @@ $$; -- Data for Name: AtVersion; Type: TABLE DATA; Schema: public; Owner: atr -- +INSERT INTO "AtVersion" ("atId", "name", "releasedAt") VALUES (2, '2023.3.3', '2023-12-02'); +INSERT INTO "AtVersion" ("atId", "name", "releasedAt") VALUES (3, '14.0', '2024-09-23'); + + -- INSERT INTO "AtVersion" ("atId", "name", "releasedAt") VALUES (2, '2019.3', '2022-05-02'); -- INSERT INTO "AtVersion" ("atId", "name", "releasedAt") VALUES (2, '2020.1', '2022-05-02'); -- INSERT INTO "AtVersion" ("atId", "name", "releasedAt") VALUES (2, '2020.2', '2022-05-02'); diff --git a/server/services/GithubWorkflowService.js b/server/services/GithubWorkflowService.js index 3b196556b..c72d76561 100644 --- a/server/services/GithubWorkflowService.js +++ b/server/services/GithubWorkflowService.js @@ -114,7 +114,7 @@ const fetchInstallationAccessToken = async (jsonWebToken, installationID) => { return JSON.parse(response.data).token; }; -const createGithubWorkflow = async ({ job, directory, gitSha }) => { +const createGithubWorkflow = async ({ job, directory, gitSha, atVersion }) => { const payload = { iat: calculateIssuedAt(), exp: calculateExpiresAt(), @@ -147,6 +147,13 @@ const createGithubWorkflow = async ({ job, directory, gitSha }) => { if (atKey === 'nvda') { inputs.test_pattern = '{reference/**,test-*-nvda.*}'; inputs.browser = browser; + inputs.nvda_version = atVersion?.name; + } + if (atKey === 'voiceover_macos') { + // We just want the whole number of the macOS version + // due to limitations on Github workflow runners + // See https://github.com/w3c/aria-at-app/issues/1143 for more info + inputs.macos_version = atVersion?.name?.split('.')[0]; } const axiosConfig = { method: 'POST', diff --git a/server/tests/integration/automation-scheduler.test.js b/server/tests/integration/automation-scheduler.test.js index 9416eb324..4ec8e4be3 100644 --- a/server/tests/integration/automation-scheduler.test.js +++ b/server/tests/integration/automation-scheduler.test.js @@ -273,13 +273,16 @@ describe('Automation controller', () => { await dbCleaner(async transaction => { const { scheduleCollectionJob: job } = await scheduleCollectionJobByMutation({ transaction }); + const { restartCollectionJob: collectionJob } = await restartCollectionJobByMutation(job.id, { transaction }); + expect(collectionJob).not.toBe(undefined); expect(collectionJob).toEqual({ id: job.id, status: 'QUEUED' }); + const { collectionJob: storedCollectionJob } = await getTestCollectionJob( job.id, { transaction } diff --git a/server/tests/integration/graphql.test.js b/server/tests/integration/graphql.test.js index 3a7195417..2369ce033 100644 --- a/server/tests/integration/graphql.test.js +++ b/server/tests/integration/graphql.test.js @@ -234,6 +234,7 @@ describe('graphql', () => { id name releasedAt + supportedByAutomation } } users { diff --git a/server/tests/util/mock-automation-scheduler-server.js b/server/tests/util/mock-automation-scheduler-server.js index adab84a4d..b92b6890d 100644 --- a/server/tests/util/mock-automation-scheduler-server.js +++ b/server/tests/util/mock-automation-scheduler-server.js @@ -136,7 +136,7 @@ const simulateResultCompletion = async ( } }; -const startCollectionJobSimulation = async (job, transaction) => { +const startCollectionJobSimulation = async (job, atVersion, transaction) => { if (!mockSchedulerEnabled) throw new Error('mock scheduler is not enabled'); if (process.env.ENVIRONMENT === 'test') { // stub behavior in test suite @@ -195,7 +195,13 @@ const startCollectionJobSimulation = async (job, transaction) => { const browserVersionName = testPlanReport.browser.browserVersions[0].name; const atName = testPlanReport.at.name; - const atVersionName = testPlanReport.at.atVersions[0].name; + + if (!atVersion || !atVersion.name) { + throw new Error('Simulated job started without specified version'); + } + + const { name: atVersionName } = atVersion; + const { runnableTests } = testPlanReport; const isV2 = testPlanVersion.metadata?.testFormatVersion === 2; diff --git a/server/util/constants.js b/server/util/constants.js index cdd789f7a..d6c90d026 100644 --- a/server/util/constants.js +++ b/server/util/constants.js @@ -1,6 +1,15 @@ // Mirror of constant in /client/components/TestRenderer/OutputTextArea/constants.js const NO_OUTPUT_STRING = 'No output was detected.'; +const AT_VERSIONS_SUPPORTED_BY_COLLECTION_JOBS = { + // These are tracked with the available versions in the github workflow file + // https://github.com/bocoup/aria-at-gh-actions-helper/blob/main/.github/workflows/voiceover-test.yml#L39 + 'VoiceOver for macOS': ['13.0', '14.0'], + // These are tracked with the https://github.com/bocoup/aria-at-automation-nvda-builds/releases + NVDA: ['2024.1', '2023.3.3', '2023.3'] +}; + module.exports = { - NO_OUTPUT_STRING + NO_OUTPUT_STRING, + AT_VERSIONS_SUPPORTED_BY_COLLECTION_JOBS }; diff --git a/server/util/getAtVersionWithRequirements.js b/server/util/getAtVersionWithRequirements.js new file mode 100644 index 000000000..66c1494f2 --- /dev/null +++ b/server/util/getAtVersionWithRequirements.js @@ -0,0 +1,61 @@ +const { Op } = require('sequelize'); +const { getAtVersions } = require('../models/services/AtService'); + +const getAtVersionWithRequirements = async ( + atId, + exactAtVersion, + minimumAtVersion, + transaction +) => { + try { + if (exactAtVersion) { + return exactAtVersion; + } + + if (!minimumAtVersion) { + throw new Error( + 'Either exactAtVersion or minimumAtVersion must be provided' + ); + } + + const isMinimumVersionSupported = + await minimumAtVersion.supportedByAutomation; + if (isMinimumVersionSupported) { + return minimumAtVersion; + } + + const matchingAts = await getAtVersions({ + where: { + atId, + releasedAt: { [Op.gte]: minimumAtVersion.releasedAt } + }, + pagination: { + order: [['releasedAt', 'ASC']] + }, + transaction + }); + + const supportedAts = await Promise.all( + matchingAts.map(async version => { + const supportedByAutomation = await version.supportedByAutomation; + return supportedByAutomation ? version.toJSON() : null; + }) + ); + + const latestSupportedAt = supportedAts.find(Boolean); + + if (!latestSupportedAt) { + throw new Error( + `No suitable AT version found for automation for AT ${atId} ` + + `with minimumAtVersion ${minimumAtVersion?.name}` + ); + } + + return latestSupportedAt; + } catch (error) { + console.error('Error while determining AT version:', error); + throw error; + } +}; + +module.exports = getAtVersionWithRequirements; From 6b4aeddac40bc93599b1a215bcaa41bdc622d12a Mon Sep 17 00:00:00 2001 From: Howard Edwards Date: Wed, 17 Jul 2024 11:45:30 -0400 Subject: [PATCH 14/15] feat: Update Dependencies (#1148) * Update patch-package * Formatting and CI version updates * Search for latest packages from root to avoid dependabot PR dupes * Update eslint, jest and prettier related dependencies * Update @apollo/client * Update @babel related dependencies on client * Remove unused moxios * Update frontend styling related dependencies * Update bootstrap and other related client dependencies * Update additional client dependencies * Update react related dependencies * Consolidate react imports * Update puppeteer * Update webpack related dependencies * Additional updates * Update server testing dependencies * Update sequelize dependencies * Update pg, nodemon, minimist, moment on server * Update fs-extra, graphql, js-base64, pg-hstore on server * Update express, express-handlebars, express-session on server * Update dotenv, dotenv-cli dependencies on server * Update connect-pg-simple * Update apollo related dependencies on server * Limit dependabot PRs --- .eslintrc.json | 88 +- .github/dependabot.yml | 16 - .github/workflows/runtest.yml | 4 +- client/babel.config.json | 9 +- client/package.json | 104 +- client/tests/AssignTesterDropdown.test.jsx | 5 +- client/tests/BasicModal.test.jsx | 2 +- client/tests/BotRunTestStatusList.test.jsx | 2 +- client/tests/DataManagement.test.jsx | 6 +- client/tests/TestQueue.test.jsx | 2 +- .../TestRenderer/OutputTextArea.test.jsx | 2 +- config/config.js | 30 +- index.js | 2 +- package.json | 8 +- server/package.json | 64 +- yarn.lock | 5440 +++++++++++------ 16 files changed, 3599 insertions(+), 2185 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index f869dbd39..774709ebc 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,36 +1,62 @@ { - "env": { - "browser": true, - "es6": true, - "node": true, - "jest/globals": true + "env": { + "browser": true, + "es6": true, + "node": true, + "jest/globals": true + }, + "extends": [ + "eslint:recommended", + "plugin:react/recommended", + "prettier", + "plugin:prettier/recommended", + "plugin:jest/recommended" + ], + "parserOptions": { + "ecmaFeatures": { + "jsx": true }, - "extends": [ - "eslint:recommended", - "plugin:react/recommended", - "prettier", - "plugin:prettier/recommended", - "plugin:jest/recommended" + "ecmaVersion": 2020, + "sourceType": "module" + }, + "plugins": [ + "react", + "json", + "prettier", + "jest" + ], + "rules": { + "linebreak-style": [ + "error", + "unix" ], - "parserOptions": { - "ecmaFeatures": { - "jsx": true - }, - "ecmaVersion": 2020, - "sourceType": "module" - }, - "plugins": ["react", "json", "prettier", "jest"], - "rules": { - "linebreak-style": ["error", "unix"], - "semi": ["error", "always"], - "eol-last": ["error", "always"], - "no-console": ["error", { "allow": ["warn", "error"] }], - "no-use-before-define": ["off"], - "react/display-name": ["off"] - }, - "settings": { - "react": { - "version": "detect" - } + "semi": [ + "error", + "always" + ], + "eol-last": [ + "error", + "always" + ], + "no-console": [ + "error", + { + "allow": [ + "warn", + "error" + ] + } + ], + "no-use-before-define": [ + "off" + ], + "react/display-name": [ + "off" + ] + }, + "settings": { + "react": { + "version": "detect" } + } } diff --git a/.github/dependabot.yml b/.github/dependabot.yml index d4a4245f0..fb5e4c7fa 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,22 +6,6 @@ updates: schedule: interval: "monthly" - - package-ecosystem: "npm" - open-pull-requests-limit: 5 - directory: "/client" - schedule: - interval: "monthly" - commit-message: - prefix: "client" - - - package-ecosystem: "npm" - open-pull-requests-limit: 5 - directory: "/server" - schedule: - interval: "monthly" - commit-message: - prefix: "server" - - package-ecosystem: "github-actions" open-pull-requests-limit: 99 directory: "/" diff --git a/.github/workflows/runtest.yml b/.github/workflows/runtest.yml index 9e07ee492..d249e401a 100644 --- a/.github/workflows/runtest.yml +++ b/.github/workflows/runtest.yml @@ -7,9 +7,9 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Checkout the repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Install NodeJS 18 - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: '18' cache: 'npm' diff --git a/client/babel.config.json b/client/babel.config.json index 7d523fbe8..972938f03 100644 --- a/client/babel.config.json +++ b/client/babel.config.json @@ -1,4 +1,9 @@ { - "presets": ["@babel/env", "@babel/preset-react"], - "plugins": ["lodash"] + "presets": [ + "@babel/preset-env", + "@babel/preset-react" + ], + "plugins": [ + "lodash" + ] } diff --git a/client/package.json b/client/package.json index 233d87e81..1e167c527 100644 --- a/client/package.json +++ b/client/package.json @@ -23,43 +23,38 @@ }, "homepage": "https://github.com/bocoup/aria-at-app#readme", "dependencies": { - "@apollo/client": "^3.7.9", - "@emotion/core": "^11.0.0", - "@emotion/react": "^11.10.6", - "@emotion/styled": "^11.10.6", - "@fortawesome/fontawesome-svg-core": "^6.2.1", - "@fortawesome/free-solid-svg-icons": "^6.2.1", - "@fortawesome/react-fontawesome": "^0.2.0", - "bootstrap": "^5.2.3", - "core-js": "^3.8.0", - "graphql": "^16.6.0", + "@apollo/client": "^3.10.8", + "@emotion/react": "^11.11.4", + "@emotion/styled": "^11.11.5", + "@fortawesome/fontawesome-svg-core": "^6.5.2", + "@fortawesome/free-solid-svg-icons": "^6.5.2", + "@fortawesome/react-fontawesome": "^0.2.2", + "bootstrap": "^5.3.3", + "core-js": "^3.37.1", + "graphql": "^16.9.0", "lodash": "^4.17.21", - "moment": "^2.25.3", - "node-fetch": "^2.6.1", - "object-hash": "^3.0.0", - "octicons-react": "^1.0.4", - "prop-types": "^15.7.2", - "react": "^18.2.0", - "react-bootstrap": "^2.7.0", - "react-dom": "^18.2.0", - "react-helmet": "^6.0.0", + "moment": "^2.30.1", + "node-fetch": "^2.7.0", + "octicons-react": "^1.0.9", + "prop-types": "^15.8.1", + "react": "^18.3.1", + "react-bootstrap": "^2.10.4", + "react-dom": "^18.3.1", + "react-helmet": "^6.1.0", "react-html-parser": "^2.0.2", - "react-id-generator": "^3.0.0", - "react-responsive": "^9.0.0-beta.10", - "react-router-bootstrap": "^0.26.2", - "react-router-dom": "^6.8.1", + "react-id-generator": "^3.0.2", + "react-responsive": "^10.0.0", + "react-router-bootstrap": "^0.26.3", + "react-router-dom": "^6.24.1", "shared": "1.0.0", - "turndown": "^7.1.1", - "ua-parser-js": "1.0.33" + "turndown": "^7.2.0", + "ua-parser-js": "1.0.38" }, "devDependencies": { - "@babel/code-frame": "^7.8.3", - "@babel/core": "^7.21.4", - "@babel/plugin-proposal-class-properties": "^7.10.1", - "@babel/plugin-transform-runtime": "^7.21.0", - "@babel/preset-env": "^7.8.7", - "@babel/preset-react": "^7.8.3", - "@lhci/cli": "^0.11.0", + "@babel/core": "^7.24.7", + "@babel/preset-env": "^7.24.7", + "@babel/preset-react": "^7.24.7", + "@lhci/cli": "^0.11.1", "@storybook/addon-a11y": "^6.5.16", "@storybook/addon-actions": "^6.5.16", "@storybook/addon-controls": "^6.5.16", @@ -68,41 +63,38 @@ "@storybook/builder-webpack5": "^6.5.16", "@storybook/manager-webpack5": "^6.5.16", "@storybook/react": "^6.5.16", - "@testing-library/dom": "^9.0.0", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^14.0.0", - "@testing-library/user-event": "^14.4.3", - "babel-jest": "^29.4.3", - "babel-loader": "^9.1.2", + "@testing-library/jest-dom": "^6.4.6", + "@testing-library/react": "^16.0.0", + "babel-jest": "^29.7.0", + "babel-loader": "^9.1.3", "babel-plugin-lodash": "^3.3.4", "babel-polyfill": "^6.26.0", "copy-webpack-plugin": "^11.0.0", - "css-loader": "^6.7.3", - "dotenv-webpack": "^8.0.1", + "css-loader": "^6.11.0", + "dotenv-webpack": "^8.1.0", "enzyme": "^3.11.0", - "enzyme-adapter-react-16": "^1.15.2", - "eslint": "^8.31.0", - "eslint-config-prettier": "^8.6.0", - "eslint-plugin-jest": "^27.2.1", + "enzyme-adapter-react-16": "^1.15.8", + "eslint": "^8.57.0", + "eslint-config-prettier": "^8.10.0", + "eslint-plugin-jest": "^27.9.0", "eslint-plugin-json": "^3.1.0", "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-react": "^7.31.11", + "eslint-plugin-react": "^7.34.3", "file-loader": "^6.0.0", - "jest": "^29.4.1", - "jest-environment-jsdom": "^29.3.1", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", "jest-enzyme": "^7.1.2", - "moxios": "^0.4.0", - "prettier": "^2.8.4", - "puppeteer": "^21.7.0", - "storybook-addon-apollo-client": "^4.0.12", + "prettier": "^2.8.8", + "puppeteer": "^21.11.0", + "storybook-addon-apollo-client": "^4.1.4", "storybook-react-router": "^1.0.8", - "style-loader": "^3.3.1", + "style-loader": "^3.3.4", "tree-kill": "^1.2.2", - "webpack": "^5.75.0", - "webpack-cli": "^5.0.1", - "webpack-dev-server": "^4.11.1" + "webpack": "^5.92.1", + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^4.15.2" }, "resolutions": { - "jest-environment-jsdom": "^29.3.1" + "jest-environment-jsdom": "^29.7.0" } } diff --git a/client/tests/AssignTesterDropdown.test.jsx b/client/tests/AssignTesterDropdown.test.jsx index e29f46cc0..4fffe9257 100644 --- a/client/tests/AssignTesterDropdown.test.jsx +++ b/client/tests/AssignTesterDropdown.test.jsx @@ -1,7 +1,7 @@ /** * @jest-environment jsdom */ -import React from 'react'; +import React, { act } from 'react'; import { render, fireEvent, @@ -17,7 +17,7 @@ import { TEST_PLAN_REPORT_AT_BROWSER_QUERY } from '@components/common/AssignTesterDropdown/queries'; import { SCHEDULE_COLLECTION_JOB_MUTATION } from '@components/AddTestToQueueWithConfirmation/queries'; -import '@testing-library/jest-dom/extend-expect'; +import '@testing-library/jest-dom'; jest.mock('@apollo/client', () => { const original = jest.requireActual('@apollo/client'); @@ -55,7 +55,6 @@ const mockProps = { }; import { useMutation } from '@apollo/client'; -import { act } from 'react-dom/test-utils'; // Mock useMutation hook useMutation.mockImplementation(mutation => { diff --git a/client/tests/BasicModal.test.jsx b/client/tests/BasicModal.test.jsx index 370172efe..d67660136 100644 --- a/client/tests/BasicModal.test.jsx +++ b/client/tests/BasicModal.test.jsx @@ -3,7 +3,7 @@ */ import React from 'react'; import { render, fireEvent, screen } from '@testing-library/react'; -import '@testing-library/jest-dom/extend-expect'; +import '@testing-library/jest-dom'; import BasicModal from '../components/common/BasicModal'; const MockCustomComponent = ({ customProp }) => ; // eslint-disable-line react/prop-types diff --git a/client/tests/BotRunTestStatusList.test.jsx b/client/tests/BotRunTestStatusList.test.jsx index f7ba2e834..d6e5cc5a3 100644 --- a/client/tests/BotRunTestStatusList.test.jsx +++ b/client/tests/BotRunTestStatusList.test.jsx @@ -6,7 +6,7 @@ import { render, waitFor } from '@testing-library/react'; import { MockedProvider } from '@apollo/client/testing'; import BotRunTestStatusList from '../components/BotRunTestStatusList'; import { TEST_PLAN_RUNS_TEST_RESULTS_QUERY } from '../components/BotRunTestStatusList/queries'; -import '@testing-library/jest-dom/extend-expect'; +import '@testing-library/jest-dom'; import { COLLECTION_JOB_STATUS } from '../../server/util/enums'; const getMocks = testPlanRuns => { diff --git a/client/tests/DataManagement.test.jsx b/client/tests/DataManagement.test.jsx index 8a2f508ed..c379eea11 100644 --- a/client/tests/DataManagement.test.jsx +++ b/client/tests/DataManagement.test.jsx @@ -2,18 +2,16 @@ * @jest-environment jsdom */ -import React from 'react'; +import React, { act } from 'react'; import { render, renderHook, waitFor } from '@testing-library/react'; import { InMemoryCache } from '@apollo/client'; import { MockedProvider } from '@apollo/client/testing'; import { BrowserRouter } from 'react-router-dom'; -import '@testing-library/jest-dom/extend-expect'; - +import '@testing-library/jest-dom'; import DataManagement from '../components/DataManagement'; // eslint-disable-next-line jest/no-mocks-import import { DATA_MANAGEMENT_PAGE_POPULATED_MOCK_DATA } from './__mocks__/GraphQLMocks'; -import { act } from 'react-dom/test-utils'; import { useDataManagementTableFiltering, useDataManagementTableSorting, diff --git a/client/tests/TestQueue.test.jsx b/client/tests/TestQueue.test.jsx index dc425f701..d64af01f9 100644 --- a/client/tests/TestQueue.test.jsx +++ b/client/tests/TestQueue.test.jsx @@ -7,7 +7,7 @@ import { render, waitFor, fireEvent } from '@testing-library/react'; import { InMemoryCache } from '@apollo/client'; import { MockedProvider } from '@apollo/client/testing'; import { BrowserRouter } from 'react-router-dom'; -import '@testing-library/jest-dom/extend-expect'; +import '@testing-library/jest-dom'; import TestQueue from '../components/TestQueue'; diff --git a/client/tests/TestRenderer/OutputTextArea.test.jsx b/client/tests/TestRenderer/OutputTextArea.test.jsx index 4bf397603..20b9acabb 100644 --- a/client/tests/TestRenderer/OutputTextArea.test.jsx +++ b/client/tests/TestRenderer/OutputTextArea.test.jsx @@ -5,7 +5,7 @@ import React from 'react'; import { render, fireEvent, screen } from '@testing-library/react'; import OutputTextArea from '../../components/TestRenderer/OutputTextArea'; -import '@testing-library/jest-dom/extend-expect'; +import '@testing-library/jest-dom'; import { NO_OUTPUT_STRING } from '../../components/TestRenderer/OutputTextArea/constants'; describe('OutputTextArea', () => { diff --git a/config/config.js b/config/config.js index f32cfdff0..9f2f10954 100644 --- a/config/config.js +++ b/config/config.js @@ -1,17 +1,17 @@ module.exports = { - development: { - database: process.env.PGDATABASE, - username: process.env.PGUSER, - password: process.env.PGPASSWORD, - host: process.env.PGHOST, - port: process.env.PGPORT, - dialect: 'postgres', - dialectOption: { - ssl: true, - native: true, - multipleStatements: true - }, - seederStorage: 'sequelize', - logging: false // console.log // eslint-disable-line no-console - } + development: { + database: process.env.PGDATABASE, + username: process.env.PGUSER, + password: process.env.PGPASSWORD, + host: process.env.PGHOST, + port: process.env.PGPORT, + dialect: 'postgres', + dialectOption: { + ssl: true, + native: true, + multipleStatements: true + }, + seederStorage: 'sequelize', + logging: false // console.log // eslint-disable-line no-console + } }; diff --git a/index.js b/index.js index 4aeae28bf..afe12585d 100644 --- a/index.js +++ b/index.js @@ -8,5 +8,5 @@ const { listener } = require('./server/server'); listener.use(history()).use(express.static('./client/dist')); listener.get('*', (req, res) => { - res.sendFile(path.join(__dirname, './client/dist/index.html')); + res.sendFile(path.join(__dirname, './client/dist/index.html')); }); diff --git a/package.json b/package.json index 430f2a578..01312348a 100644 --- a/package.json +++ b/package.json @@ -33,15 +33,15 @@ "url": "https://github.com/w3c/aria-at-app/issues" }, "homepage": "https://github.com/w3c/aria-at-app#readme", - "dependencies": { - "patch-package": "^6.5.1", - "postinstall-postinstall": "^2.1.0" - }, "workspaces": [ "client", "server", "shared" ], + "dependencies": { + "patch-package": "^8.0.0", + "postinstall-postinstall": "^2.1.0" + }, "devDependencies": { "npm-run-all": "^4.1.5" } diff --git a/server/package.json b/server/package.json index 492afae16..111615838 100644 --- a/server/package.json +++ b/server/package.json @@ -26,55 +26,51 @@ "dependencies": { "@moebius/http-graceful-shutdown": "^1.1.0", "apicache": "^1.6.3", - "apollo-server": "^3.4.0", - "apollo-server-core": "^3.6.7", - "apollo-server-express": "^3.4.0", + "apollo-server": "^3.13.0", + "apollo-server-core": "^3.13.0", + "apollo-server-express": "^3.13.0", "axios": "^0.27.2", - "body-parser": "^1.20.0", + "body-parser": "^1.20.2", "connect-history-api-fallback": "^2.0.0", - "connect-pg-simple": "^8.0.0", - "cross-fetch": "^3.1.5", + "connect-pg-simple": "^9.0.1", "cross-spawn": "^7.0.3", - "dotenv": "^16.0.3", - "dotenv-cli": "^6.0.0", - "express": "^5.0.0-alpha.8", - "express-handlebars": "^6.0.6", - "express-session": "^1.17.2", - "fs-extra": "^11.1.0", - "graphql": "^16.6.0", - "js-base64": "^3.6.1", + "dotenv": "^16.4.5", + "dotenv-cli": "^7.4.2", + "express": "^5.0.0-beta.3", + "express-handlebars": "^7.1.3", + "express-session": "^1.18.0", + "fs-extra": "^11.2.0", + "graphql": "^16.9.0", + "js-base64": "^3.7.7", "jsonwebtoken": "^9.0.2", "lodash": "^4.17.21", - "minimist": "^1.2.7", - "moment": "^2.29.4", + "minimist": "^1.2.8", + "moment": "^2.30.1", "node-cache": "^5.1.2", - "nodemon": "^2.0.7", + "nodemon": "^2.0.22", "object-hash": "^3.0.0", - "pg": "^8.6.0", - "pg-hstore": "^2.3.3", + "pg": "^8.12.0", + "pg-hstore": "^2.3.4", "rawgit": "https://github.com/rgrove/rawgit.git#eaa9b36aa2143041894866ba9db72e51d05c2a52", - "sequelize": "^6.28.0", + "sequelize": "^6.37.3", "shared": "1.0.0", "supertest-session": "^4.1.0", - "uuid": "^10.0.0", - "vhost": "^3.0.2" + "uuid": "^10.0.0" }, "devDependencies": { - "@testing-library/dom": "^9.0.1", - "eslint": "^8.31.0", - "eslint-config-prettier": "^8.6.0", - "eslint-plugin-jest": "^27.2.1", + "@testing-library/dom": "^10.3.1", + "eslint": "^8.57.0", + "eslint-config-prettier": "^8.10.0", + "eslint-plugin-jest": "^27.9.0", "eslint-plugin-json": "^3.1.0", "eslint-plugin-prettier": "^4.2.1", - "eslint-plugin-react": "^7.31.11", - "jest": "^29.3.1", - "jsdom": "^21.1.1", + "jest": "^29.7.0", + "jsdom": "^24.1.0", "jsdom-global": "^3.0.2", - "moxios": "^0.4.0", - "node-mocks-http": "^1.8.1", - "prettier": "^2.8.4", - "sequelize-cli": "^6.5.2", + "node-mocks-http": "^1.15.0", + "prettier": "^2.8.8", + "sequelize-cli": "^6.6.2", "sequelize-test-helpers": "1.3.3", - "supertest": "^6.3.3" + "supertest": "^6.3.4" } } diff --git a/yarn.lock b/yarn.lock index 7a9ddb82b..ccf220f14 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@adobe/css-tools@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.0.1.tgz#b38b444ad3aa5fedbb15f2f746dcd934226a12dd" - integrity sha512-+u76oB43nOHrF4DDWRLWDCtci7f3QJoEBigemIdIeTi1ODqjx6Tad9NCVnPRwewWlKkVab5PlK8DCtPTyX7S8g== +"@adobe/css-tools@^4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.4.0.tgz#728c484f4e10df03d5a3acd0d8adcbbebff8ad63" + integrity sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ== "@ampproject/remapping@^2.2.0": version "2.2.0" @@ -15,19 +15,20 @@ "@jridgewell/gen-mapping" "^0.1.0" "@jridgewell/trace-mapping" "^0.3.9" -"@apollo/client@^3.7.9": - version "3.7.9" - resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.7.9.tgz#459454dc4a7c81adaa66e13e626ce41f633dc862" - integrity sha512-YnJvrJOVWrp4y/zdNvUaM8q4GuSHCEIecsRDTJhK/veT33P/B7lfqGJ24NeLdKMj8tDEuXYF7V0t+th4+rgC+Q== +"@apollo/client@^3.10.8": + version "3.10.8" + resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.10.8.tgz#96b1548818e45fac752ec2bd318e5466d9ca26b5" + integrity sha512-UaaFEitRrPRWV836wY2L7bd3HRCfbMie1jlYMcmazFAK23MVhz/Uq7VG1nwbotPb5xzFsw5RF4Wnp2G3dWPM3g== dependencies: "@graphql-typed-document-node/core" "^3.1.1" - "@wry/context" "^0.7.0" - "@wry/equality" "^0.5.0" - "@wry/trie" "^0.3.0" + "@wry/caches" "^1.0.0" + "@wry/equality" "^0.5.6" + "@wry/trie" "^0.5.0" graphql-tag "^2.12.6" hoist-non-react-statics "^3.3.2" - optimism "^0.16.1" + optimism "^0.18.0" prop-types "^15.7.2" + rehackt "^0.1.0" response-iterator "^0.2.6" symbol-observable "^4.0.0" ts-invariant "^0.10.3" @@ -157,6 +158,14 @@ "@babel/highlight" "^7.23.4" chalk "^2.4.2" +"@babel/code-frame@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" + integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== + dependencies: + "@babel/highlight" "^7.24.7" + picocolors "^1.0.0" + "@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.1", "@babel/compat-data@^7.20.5": version "7.20.10" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.10.tgz#9d92fa81b87542fff50e848ed585b4212c1d34ec" @@ -167,6 +176,11 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.21.4.tgz#457ffe647c480dff59c2be092fc3acf71195c87f" integrity sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g== +"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.7.tgz#d23bbea508c3883ba8251fb4164982c36ea577ed" + integrity sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw== + "@babel/compat-data@^7.23.5": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" @@ -215,7 +229,7 @@ json5 "^2.2.3" semver "^6.3.1" -"@babel/core@^7.11.6", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.21.4", "@babel/core@^7.7.5": +"@babel/core@^7.11.6", "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.7.5": version "7.21.4" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.21.4.tgz#c6dc73242507b8e2a27fd13a9c1814f9fa34a659" integrity sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA== @@ -236,6 +250,27 @@ json5 "^2.2.2" semver "^6.3.0" +"@babel/core@^7.23.9", "@babel/core@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.7.tgz#b676450141e0b52a3d43bc91da86aa608f950ac4" + integrity sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.24.7" + "@babel/helper-compilation-targets" "^7.24.7" + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helpers" "^7.24.7" + "@babel/parser" "^7.24.7" + "@babel/template" "^7.24.7" + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + "@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.21.4", "@babel/generator@^7.7.2": version "7.21.4" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.4.tgz#64a94b7448989f421f919d5239ef553b37bb26bc" @@ -256,6 +291,16 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" +"@babel/generator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.7.tgz#1654d01de20ad66b4b4d99c135471bc654c55e6d" + integrity sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA== + dependencies: + "@babel/types" "^7.24.7" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^2.5.1" + "@babel/helper-annotate-as-pure@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" @@ -263,6 +308,13 @@ dependencies: "@babel/types" "^7.18.6" +"@babel/helper-annotate-as-pure@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz#5373c7bc8366b12a033b4be1ac13a206c6656aab" + integrity sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg== + dependencies: + "@babel/types" "^7.24.7" + "@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz#acd4edfd7a566d1d51ea975dff38fd52906981bb" @@ -271,6 +323,14 @@ "@babel/helper-explode-assignable-expression" "^7.18.6" "@babel/types" "^7.18.9" +"@babel/helper-builder-binary-assignment-operator-visitor@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz#37d66feb012024f2422b762b9b2a7cfe27c7fba3" + integrity sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + "@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.20.0", "@babel/helper-compilation-targets@^7.20.7", "@babel/helper-compilation-targets@^7.21.4": version "7.21.4" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.4.tgz#770cd1ce0889097ceacb99418ee6934ef0572656" @@ -282,6 +342,17 @@ lru-cache "^5.1.1" semver "^6.3.0" +"@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz#4eb6c4a80d6ffeac25ab8cd9a21b5dfa48d503a9" + integrity sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg== + dependencies: + "@babel/compat-data" "^7.24.7" + "@babel/helper-validator-option" "^7.24.7" + browserslist "^4.22.2" + lru-cache "^5.1.1" + semver "^6.3.1" + "@babel/helper-compilation-targets@^7.23.6": version "7.23.6" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" @@ -307,6 +378,21 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" "@babel/helper-split-export-declaration" "^7.18.6" +"@babel/helper-create-class-features-plugin@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.7.tgz#2eaed36b3a1c11c53bdf80d53838b293c52f5b3b" + integrity sha512-kTkaDl7c9vO80zeX1rJxnuRpEsD5tA81yh11X1gQo+PhSti3JS+7qeZo9U4RHobKRiFPKaGK3svUAeb8D0Q7eg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-function-name" "^7.24.7" + "@babel/helper-member-expression-to-functions" "^7.24.7" + "@babel/helper-optimise-call-expression" "^7.24.7" + "@babel/helper-replace-supers" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" + semver "^6.3.1" + "@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.20.5": version "7.20.5" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.20.5.tgz#5ea79b59962a09ec2acf20a963a01ab4d076ccca" @@ -315,6 +401,15 @@ "@babel/helper-annotate-as-pure" "^7.18.6" regexpu-core "^5.2.1" +"@babel/helper-create-regexp-features-plugin@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz#be4f435a80dc2b053c76eeb4b7d16dd22cfc89da" + integrity sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + regexpu-core "^5.3.1" + semver "^6.3.1" + "@babel/helper-define-polyfill-provider@^0.1.5": version "0.1.5" resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.1.5.tgz#3c2f91b7971b9fc11fe779c945c014065dea340e" @@ -341,6 +436,17 @@ resolve "^1.14.2" semver "^6.1.2" +"@babel/helper-define-polyfill-provider@^0.6.1", "@babel/helper-define-polyfill-provider@^0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz#18594f789c3594acb24cfdb4a7f7b7d2e8bd912d" + integrity sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ== + dependencies: + "@babel/helper-compilation-targets" "^7.22.6" + "@babel/helper-plugin-utils" "^7.22.5" + debug "^4.1.1" + lodash.debounce "^4.0.8" + resolve "^1.14.2" + "@babel/helper-environment-visitor@^7.18.9": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" @@ -351,6 +457,13 @@ resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== +"@babel/helper-environment-visitor@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz#4b31ba9551d1f90781ba83491dd59cf9b269f7d9" + integrity sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ== + dependencies: + "@babel/types" "^7.24.7" + "@babel/helper-explode-assignable-expression@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096" @@ -382,6 +495,14 @@ "@babel/template" "^7.22.15" "@babel/types" "^7.23.0" +"@babel/helper-function-name@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz#75f1e1725742f39ac6584ee0b16d94513da38dd2" + integrity sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA== + dependencies: + "@babel/template" "^7.24.7" + "@babel/types" "^7.24.7" + "@babel/helper-hoist-variables@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" @@ -396,6 +517,13 @@ dependencies: "@babel/types" "^7.22.5" +"@babel/helper-hoist-variables@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz#b4ede1cde2fd89436397f30dc9376ee06b0f25ee" + integrity sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ== + dependencies: + "@babel/types" "^7.24.7" + "@babel/helper-member-expression-to-functions@^7.20.7": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.20.7.tgz#a6f26e919582275a93c3aa6594756d71b0bb7f05" @@ -403,6 +531,14 @@ dependencies: "@babel/types" "^7.20.7" +"@babel/helper-member-expression-to-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.7.tgz#67613d068615a70e4ed5101099affc7a41c5225f" + integrity sha512-LGeMaf5JN4hAT471eJdBs/GK1DoYIJ5GCtZN/EsL6KUiiDZOvO/eKE11AMZJa2zP4zk4qe9V2O/hxAmkRc8p6w== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + "@babel/helper-module-imports@^7.0.0-beta.49", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" @@ -417,6 +553,14 @@ dependencies: "@babel/types" "^7.22.15" +"@babel/helper-module-imports@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz#f2f980392de5b84c3328fc71d38bd81bbb83042b" + integrity sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + "@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.20.11", "@babel/helper-module-transforms@^7.21.2": version "7.21.2" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz#160caafa4978ac8c00ac66636cb0fa37b024e2d2" @@ -442,6 +586,17 @@ "@babel/helper-split-export-declaration" "^7.22.6" "@babel/helper-validator-identifier" "^7.22.20" +"@babel/helper-module-transforms@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz#31b6c9a2930679498db65b685b1698bfd6c7daf8" + integrity sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ== + dependencies: + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-simple-access" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" + "@babel/helper-validator-identifier" "^7.24.7" + "@babel/helper-optimise-call-expression@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" @@ -449,6 +604,13 @@ dependencies: "@babel/types" "^7.18.6" +"@babel/helper-optimise-call-expression@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz#8b0a0456c92f6b323d27cfd00d1d664e76692a0f" + integrity sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A== + dependencies: + "@babel/types" "^7.24.7" + "@babel/helper-plugin-utils@7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" @@ -459,6 +621,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== +"@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz#98c84fe6fe3d0d3ae7bfc3a5e166a46844feb2a0" + integrity sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg== + "@babel/helper-remap-async-to-generator@^7.18.9": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519" @@ -469,6 +636,15 @@ "@babel/helper-wrap-function" "^7.18.9" "@babel/types" "^7.18.9" +"@babel/helper-remap-async-to-generator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.7.tgz#b3f0f203628522713849d49403f1a414468be4c7" + integrity sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-wrap-function" "^7.24.7" + "@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.20.7": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz#243ecd2724d2071532b2c8ad2f0f9f083bcae331" @@ -481,6 +657,15 @@ "@babel/traverse" "^7.20.7" "@babel/types" "^7.20.7" +"@babel/helper-replace-supers@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz#f933b7eed81a1c0265740edc91491ce51250f765" + integrity sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg== + dependencies: + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-member-expression-to-functions" "^7.24.7" + "@babel/helper-optimise-call-expression" "^7.24.7" + "@babel/helper-simple-access@^7.20.2": version "7.20.2" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz#0ab452687fe0c2cfb1e2b9e0015de07fc2d62dd9" @@ -495,6 +680,14 @@ dependencies: "@babel/types" "^7.22.5" +"@babel/helper-simple-access@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz#bcade8da3aec8ed16b9c4953b74e506b51b5edb3" + integrity sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers@^7.20.0": version "7.20.0" resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz#fbe4c52f60518cab8140d77101f0e63a8a230684" @@ -502,6 +695,14 @@ dependencies: "@babel/types" "^7.20.0" +"@babel/helper-skip-transparent-expression-wrappers@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz#5f8fa83b69ed5c27adc56044f8be2b3ea96669d9" + integrity sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + "@babel/helper-split-export-declaration@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" @@ -516,6 +717,13 @@ dependencies: "@babel/types" "^7.22.5" +"@babel/helper-split-export-declaration@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz#83949436890e07fa3d6873c61a96e3bbf692d856" + integrity sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA== + dependencies: + "@babel/types" "^7.24.7" + "@babel/helper-string-parser@^7.19.4": version "7.19.4" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" @@ -526,6 +734,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== +"@babel/helper-string-parser@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz#4d2d0f14820ede3b9807ea5fc36dfc8cd7da07f2" + integrity sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg== + "@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": version "7.19.1" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" @@ -536,6 +749,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== +"@babel/helper-validator-identifier@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" + integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== + "@babel/helper-validator-option@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" @@ -551,6 +769,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== +"@babel/helper-validator-option@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz#24c3bb77c7a425d1742eec8fb433b5a1b38e62f6" + integrity sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw== + "@babel/helper-wrap-function@^7.18.9": version "7.20.5" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz#75e2d84d499a0ab3b31c33bcfe59d6b8a45f62e3" @@ -561,6 +784,16 @@ "@babel/traverse" "^7.20.5" "@babel/types" "^7.20.5" +"@babel/helper-wrap-function@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.24.7.tgz#52d893af7e42edca7c6d2c6764549826336aae1f" + integrity sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw== + dependencies: + "@babel/helper-function-name" "^7.24.7" + "@babel/template" "^7.24.7" + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + "@babel/helpers@^7.12.5", "@babel/helpers@^7.21.0": version "7.21.0" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.21.0.tgz#9dd184fb5599862037917cdc9eecb84577dc4e7e" @@ -579,6 +812,14 @@ "@babel/traverse" "^7.24.0" "@babel/types" "^7.24.0" +"@babel/helpers@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.7.tgz#aa2ccda29f62185acb5d42fb4a3a1b1082107416" + integrity sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg== + dependencies: + "@babel/template" "^7.24.7" + "@babel/types" "^7.24.7" + "@babel/highlight@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" @@ -597,16 +838,39 @@ chalk "^2.4.2" js-tokens "^4.0.0" +"@babel/highlight@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" + integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== + dependencies: + "@babel/helper-validator-identifier" "^7.24.7" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" + "@babel/parser@^7.1.0", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.21.4": version "7.21.4" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.4.tgz#94003fdfc520bbe2875d4ae557b43ddb6d880f17" integrity sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw== +"@babel/parser@^7.23.9", "@babel/parser@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.7.tgz#9a5226f92f0c5c8ead550b750f5608e766c8ce85" + integrity sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw== + "@babel/parser@^7.24.0", "@babel/parser@^7.4.3": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.0.tgz#26a3d1ff49031c53a97d03b604375f028746a9ac" integrity sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg== +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.7.tgz#fd059fd27b184ea2b4c7e646868a9a381bbc3055" + integrity sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ== + dependencies: + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2" @@ -614,6 +878,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.7.tgz#468096ca44bbcbe8fcc570574e12eb1950e18107" + integrity sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.9": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.20.7.tgz#d9c85589258539a22a901033853101a6198d4ef1" @@ -623,6 +894,23 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" "@babel/plugin-proposal-optional-chaining" "^7.20.7" +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz#e4eabdd5109acc399b38d7999b2ef66fc2022f89" + integrity sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/plugin-transform-optional-chaining" "^7.24.7" + +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.7.tgz#71b21bb0286d5810e63a1538aa901c58e87375ec" + integrity sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg== + dependencies: + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-proposal-async-generator-functions@^7.20.1": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz#bfb7276d2d573cb67ba379984a2334e262ba5326" @@ -633,7 +921,7 @@ "@babel/helper-remap-async-to-generator" "^7.18.9" "@babel/plugin-syntax-async-generators" "^7.8.4" -"@babel/plugin-proposal-class-properties@^7.10.1", "@babel/plugin-proposal-class-properties@^7.12.1", "@babel/plugin-proposal-class-properties@^7.18.6": +"@babel/plugin-proposal-class-properties@^7.12.1", "@babel/plugin-proposal-class-properties@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== @@ -762,6 +1050,11 @@ "@babel/helper-create-class-features-plugin" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": + version "7.21.0-placeholder-for-preset-env.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" + integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== + "@babel/plugin-proposal-private-property-in-object@^7.12.1", "@babel/plugin-proposal-private-property-in-object@^7.18.6": version "7.20.5" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.20.5.tgz#309c7668f2263f1c711aa399b5a9a6291eef6135" @@ -850,7 +1143,21 @@ dependencies: "@babel/helper-plugin-utils" "^7.19.0" -"@babel/plugin-syntax-import-meta@^7.8.3": +"@babel/plugin-syntax-import-assertions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz#2a0b406b5871a20a841240586b1300ce2088a778" + integrity sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-syntax-import-attributes@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz#b4f9ea95a79e6912480c4b626739f86a076624ca" + integrity sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-syntax-import-meta@^7.10.4", "@babel/plugin-syntax-import-meta@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== @@ -878,6 +1185,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-syntax-jsx@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz#39a1fa4a7e3d3d7f34e2acc6be585b718d30e02d" + integrity sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" @@ -941,6 +1255,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.19.0" +"@babel/plugin-syntax-unicode-sets-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz#d49a3b3e6b52e5be6740022317580234a6a47357" + integrity sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/plugin-transform-arrow-functions@^7.12.1", "@babel/plugin-transform-arrow-functions@^7.18.6": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz#bea332b0e8b2dab3dafe55a163d8227531ab0551" @@ -948,6 +1270,23 @@ dependencies: "@babel/helper-plugin-utils" "^7.20.2" +"@babel/plugin-transform-arrow-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz#4f6886c11e423bd69f3ce51dbf42424a5f275514" + integrity sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-async-generator-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz#7330a5c50e05181ca52351b8fd01642000c96cfd" + integrity sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g== + dependencies: + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-remap-async-to-generator" "^7.24.7" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-transform-async-to-generator@^7.18.6": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz#dfee18623c8cb31deb796aa3ca84dda9cea94354" @@ -957,6 +1296,15 @@ "@babel/helper-plugin-utils" "^7.20.2" "@babel/helper-remap-async-to-generator" "^7.18.9" +"@babel/plugin-transform-async-to-generator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz#72a3af6c451d575842a7e9b5a02863414355bdcc" + integrity sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA== + dependencies: + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-remap-async-to-generator" "^7.24.7" + "@babel/plugin-transform-block-scoped-functions@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8" @@ -964,6 +1312,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-transform-block-scoped-functions@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz#a4251d98ea0c0f399dafe1a35801eaba455bbf1f" + integrity sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-transform-block-scoping@^7.12.12", "@babel/plugin-transform-block-scoping@^7.20.2": version "7.20.11" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.11.tgz#9f5a3424bd112a3f32fe0cf9364fbb155cff262a" @@ -971,6 +1326,30 @@ dependencies: "@babel/helper-plugin-utils" "^7.20.2" +"@babel/plugin-transform-block-scoping@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz#42063e4deb850c7bd7c55e626bf4e7ab48e6ce02" + integrity sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-class-properties@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz#256879467b57b0b68c7ddfc5b76584f398cd6834" + integrity sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-class-static-block@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz#c82027ebb7010bc33c116d4b5044fbbf8c05484d" + integrity sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-transform-classes@^7.12.1", "@babel/plugin-transform-classes@^7.20.2": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.20.7.tgz#f438216f094f6bb31dc266ebfab8ff05aecad073" @@ -986,6 +1365,20 @@ "@babel/helper-split-export-declaration" "^7.18.6" globals "^11.1.0" +"@babel/plugin-transform-classes@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.7.tgz#4ae6ef43a12492134138c1e45913f7c46c41b4bf" + integrity sha512-CFbbBigp8ln4FU6Bpy6g7sE8B/WmCmzvivzUC6xDAdWVsjYTXijpuuGJmYkAaoWAzcItGKT3IOAbxRItZ5HTjw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-compilation-targets" "^7.24.7" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-function-name" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-replace-supers" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" + globals "^11.1.0" + "@babel/plugin-transform-computed-properties@^7.18.9": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.20.7.tgz#704cc2fd155d1c996551db8276d55b9d46e4d0aa" @@ -994,6 +1387,14 @@ "@babel/helper-plugin-utils" "^7.20.2" "@babel/template" "^7.20.7" +"@babel/plugin-transform-computed-properties@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz#4cab3214e80bc71fae3853238d13d097b004c707" + integrity sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/template" "^7.24.7" + "@babel/plugin-transform-destructuring@^7.12.1", "@babel/plugin-transform-destructuring@^7.20.2": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.7.tgz#8bda578f71620c7de7c93af590154ba331415454" @@ -1001,6 +1402,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.20.2" +"@babel/plugin-transform-destructuring@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.7.tgz#a097f25292defb6e6cc16d6333a4cfc1e3c72d9e" + integrity sha512-19eJO/8kdCQ9zISOf+SEUJM/bAUIsvY3YDnXZTupUCQ8LgrWnsG/gFB9dvXqdXnRXMAM8fvt7b0CBKQHNGy1mw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-transform-dotall-regex@^7.18.6", "@babel/plugin-transform-dotall-regex@^7.4.4": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz#b286b3e7aae6c7b861e45bed0a2fafd6b1a4fef8" @@ -1009,6 +1417,14 @@ "@babel/helper-create-regexp-features-plugin" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-transform-dotall-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz#5f8bf8a680f2116a7207e16288a5f974ad47a7a0" + integrity sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-transform-duplicate-keys@^7.18.9": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz#687f15ee3cdad6d85191eb2a372c4528eaa0ae0e" @@ -1016,6 +1432,21 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.9" +"@babel/plugin-transform-duplicate-keys@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz#dd20102897c9a2324e5adfffb67ff3610359a8ee" + integrity sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-dynamic-import@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz#4d8b95e3bae2b037673091aa09cd33fecd6419f4" + integrity sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-transform-exponentiation-operator@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz#421c705f4521888c65e91fdd1af951bfefd4dacd" @@ -1024,6 +1455,22 @@ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-transform-exponentiation-operator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz#b629ee22645f412024297d5245bce425c31f9b0d" + integrity sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-export-namespace-from@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz#176d52d8d8ed516aeae7013ee9556d540c53f197" + integrity sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-transform-flow-strip-types@^7.18.6": version "7.19.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.19.0.tgz#e9e8606633287488216028719638cbbb2f2dde8f" @@ -1039,6 +1486,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-transform-for-of@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz#f25b33f72df1d8be76399e1b8f3f9d366eb5bc70" + integrity sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/plugin-transform-function-name@^7.18.9": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz#cc354f8234e62968946c61a46d6365440fc764e0" @@ -1048,6 +1503,23 @@ "@babel/helper-function-name" "^7.18.9" "@babel/helper-plugin-utils" "^7.18.9" +"@babel/plugin-transform-function-name@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz#6d8601fbffe665c894440ab4470bc721dd9131d6" + integrity sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w== + dependencies: + "@babel/helper-compilation-targets" "^7.24.7" + "@babel/helper-function-name" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-json-strings@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz#f3e9c37c0a373fee86e36880d45b3664cedaf73a" + integrity sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-transform-literals@^7.18.9": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz#72796fdbef80e56fba3c6a699d54f0de557444bc" @@ -1055,6 +1527,21 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.9" +"@babel/plugin-transform-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz#36b505c1e655151a9d7607799a9988fc5467d06c" + integrity sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-logical-assignment-operators@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz#a58fb6eda16c9dc8f9ff1c7b1ba6deb7f4694cb0" + integrity sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-transform-member-expression-literals@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz#ac9fdc1a118620ac49b7e7a5d2dc177a1bfee88e" @@ -1062,6 +1549,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-transform-member-expression-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz#3b4454fb0e302e18ba4945ba3246acb1248315df" + integrity sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-transform-modules-amd@^7.19.6": version "7.20.11" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.20.11.tgz#3daccca8e4cc309f03c3a0c4b41dc4b26f55214a" @@ -1070,6 +1564,14 @@ "@babel/helper-module-transforms" "^7.20.11" "@babel/helper-plugin-utils" "^7.20.2" +"@babel/plugin-transform-modules-amd@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz#65090ed493c4a834976a3ca1cde776e6ccff32d7" + integrity sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg== + dependencies: + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-transform-modules-commonjs@^7.19.6": version "7.20.11" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.20.11.tgz#8cb23010869bf7669fd4b3098598b6b2be6dc607" @@ -1079,6 +1581,15 @@ "@babel/helper-plugin-utils" "^7.20.2" "@babel/helper-simple-access" "^7.20.2" +"@babel/plugin-transform-modules-commonjs@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.7.tgz#9fd5f7fdadee9085886b183f1ad13d1ab260f4ab" + integrity sha512-iFI8GDxtevHJ/Z22J5xQpVqFLlMNstcLXh994xifFwxxGslr2ZXXLWgtBeLctOD63UFDArdvN6Tg8RFw+aEmjQ== + dependencies: + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-simple-access" "^7.24.7" + "@babel/plugin-transform-modules-systemjs@^7.19.6": version "7.20.11" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.20.11.tgz#467ec6bba6b6a50634eea61c9c232654d8a4696e" @@ -1089,6 +1600,16 @@ "@babel/helper-plugin-utils" "^7.20.2" "@babel/helper-validator-identifier" "^7.19.1" +"@babel/plugin-transform-modules-systemjs@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz#f8012316c5098f6e8dee6ecd58e2bc6f003d0ce7" + integrity sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw== + dependencies: + "@babel/helper-hoist-variables" "^7.24.7" + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-validator-identifier" "^7.24.7" + "@babel/plugin-transform-modules-umd@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz#81d3832d6034b75b54e62821ba58f28ed0aab4b9" @@ -1097,6 +1618,14 @@ "@babel/helper-module-transforms" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-transform-modules-umd@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz#edd9f43ec549099620df7df24e7ba13b5c76efc8" + integrity sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A== + dependencies: + "@babel/helper-module-transforms" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-transform-named-capturing-groups-regex@^7.19.1": version "7.20.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz#626298dd62ea51d452c3be58b285d23195ba69a8" @@ -1105,6 +1634,14 @@ "@babel/helper-create-regexp-features-plugin" "^7.20.5" "@babel/helper-plugin-utils" "^7.20.2" +"@babel/plugin-transform-named-capturing-groups-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz#9042e9b856bc6b3688c0c2e4060e9e10b1460923" + integrity sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-transform-new-target@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz#d128f376ae200477f37c4ddfcc722a8a1b3246a8" @@ -1112,6 +1649,39 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-transform-new-target@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz#31ff54c4e0555cc549d5816e4ab39241dfb6ab00" + integrity sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-nullish-coalescing-operator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz#1de4534c590af9596f53d67f52a92f12db984120" + integrity sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + +"@babel/plugin-transform-numeric-separator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz#bea62b538c80605d8a0fac9b40f48e97efa7de63" + integrity sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-transform-object-rest-spread@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz#d13a2b93435aeb8a197e115221cab266ba6e55d6" + integrity sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q== + dependencies: + "@babel/helper-compilation-targets" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.24.7" + "@babel/plugin-transform-object-super@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c" @@ -1120,6 +1690,31 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/helper-replace-supers" "^7.18.6" +"@babel/plugin-transform-object-super@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz#66eeaff7830bba945dd8989b632a40c04ed625be" + integrity sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-replace-supers" "^7.24.7" + +"@babel/plugin-transform-optional-catch-binding@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz#00eabd883d0dd6a60c1c557548785919b6e717b4" + integrity sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + +"@babel/plugin-transform-optional-chaining@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.7.tgz#b8f6848a80cf2da98a8a204429bec04756c6d454" + integrity sha512-tK+0N9yd4j+x/4hxF3F0e0fu/VdcxU18y5SevtyM/PCFlQvXbR0Zmlo2eBrKtVipGNFzpq56o8WsIIKcJFUCRQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.20.1", "@babel/plugin-transform-parameters@^7.20.7": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.7.tgz#0ee349e9d1bc96e78e3b37a7af423a4078a7083f" @@ -1127,6 +1722,31 @@ dependencies: "@babel/helper-plugin-utils" "^7.20.2" +"@babel/plugin-transform-parameters@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz#5881f0ae21018400e320fc7eb817e529d1254b68" + integrity sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-private-methods@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz#e6318746b2ae70a59d023d5cc1344a2ba7a75f5e" + integrity sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-private-property-in-object@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz#4eec6bc701288c1fab5f72e6a4bbc9d67faca061" + integrity sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-create-class-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-transform-property-literals@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz#e22498903a483448e94e032e9bbb9c5ccbfc93a3" @@ -1134,6 +1754,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-transform-property-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz#f0d2ed8380dfbed949c42d4d790266525d63bbdc" + integrity sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-transform-react-display-name@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz#8b1125f919ef36ebdfff061d664e266c666b9415" @@ -1141,6 +1768,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-transform-react-display-name@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz#9caff79836803bc666bcfe210aeb6626230c293b" + integrity sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-transform-react-jsx-development@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz#dbe5c972811e49c7405b630e4d0d2e1380c0ddc5" @@ -1148,6 +1782,13 @@ dependencies: "@babel/plugin-transform-react-jsx" "^7.18.6" +"@babel/plugin-transform-react-jsx-development@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz#eaee12f15a93f6496d852509a850085e6361470b" + integrity sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ== + dependencies: + "@babel/plugin-transform-react-jsx" "^7.24.7" + "@babel/plugin-transform-react-jsx@^7.12.12", "@babel/plugin-transform-react-jsx@^7.18.6": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.20.7.tgz#025d85a1935fd7e19dfdcb1b1d4df34d4da484f7" @@ -1159,6 +1800,17 @@ "@babel/plugin-syntax-jsx" "^7.18.6" "@babel/types" "^7.20.7" +"@babel/plugin-transform-react-jsx@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.7.tgz#17cd06b75a9f0e2bd076503400e7c4b99beedac4" + integrity sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-syntax-jsx" "^7.24.7" + "@babel/types" "^7.24.7" + "@babel/plugin-transform-react-pure-annotations@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz#561af267f19f3e5d59291f9950fd7b9663d0d844" @@ -1167,6 +1819,14 @@ "@babel/helper-annotate-as-pure" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-transform-react-pure-annotations@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz#bdd9d140d1c318b4f28b29a00fb94f97ecab1595" + integrity sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-transform-regenerator@^7.18.6": version "7.20.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz#57cda588c7ffb7f4f8483cc83bdcea02a907f04d" @@ -1175,6 +1835,14 @@ "@babel/helper-plugin-utils" "^7.20.2" regenerator-transform "^0.15.1" +"@babel/plugin-transform-regenerator@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz#021562de4534d8b4b1851759fd7af4e05d2c47f8" + integrity sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + regenerator-transform "^0.15.2" + "@babel/plugin-transform-reserved-words@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz#b1abd8ebf8edaa5f7fe6bbb8d2133d23b6a6f76a" @@ -1182,17 +1850,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-runtime@^7.21.0": - version "7.21.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.21.0.tgz#2a884f29556d0a68cd3d152dcc9e6c71dfb6eee8" - integrity sha512-ReY6pxwSzEU0b3r2/T/VhqMKg/AkceBT19X0UptA3/tYi5Pe2eXgEUH+NNMC5nok6c6XQz5tyVTUpuezRfSMSg== +"@babel/plugin-transform-reserved-words@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz#80037fe4fbf031fc1125022178ff3938bb3743a4" + integrity sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ== dependencies: - "@babel/helper-module-imports" "^7.18.6" - "@babel/helper-plugin-utils" "^7.20.2" - babel-plugin-polyfill-corejs2 "^0.3.3" - babel-plugin-polyfill-corejs3 "^0.6.0" - babel-plugin-polyfill-regenerator "^0.4.1" - semver "^6.3.0" + "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-transform-shorthand-properties@^7.12.1", "@babel/plugin-transform-shorthand-properties@^7.18.6": version "7.18.6" @@ -1201,6 +1864,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-transform-shorthand-properties@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz#85448c6b996e122fa9e289746140aaa99da64e73" + integrity sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-transform-spread@^7.12.1", "@babel/plugin-transform-spread@^7.19.0": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.20.7.tgz#c2d83e0b99d3bf83e07b11995ee24bf7ca09401e" @@ -1209,6 +1879,14 @@ "@babel/helper-plugin-utils" "^7.20.2" "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" +"@babel/plugin-transform-spread@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz#e8a38c0fde7882e0fb8f160378f74bd885cc7bb3" + integrity sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers" "^7.24.7" + "@babel/plugin-transform-sticky-regex@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz#c6706eb2b1524028e317720339583ad0f444adcc" @@ -1216,6 +1894,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.6" +"@babel/plugin-transform-sticky-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz#96ae80d7a7e5251f657b5cf18f1ea6bf926f5feb" + integrity sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-transform-template-literals@^7.12.1", "@babel/plugin-transform-template-literals@^7.18.9": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz#04ec6f10acdaa81846689d63fae117dd9c243a5e" @@ -1223,6 +1908,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.9" +"@babel/plugin-transform-template-literals@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz#a05debb4a9072ae8f985bcf77f3f215434c8f8c8" + integrity sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-transform-typeof-symbol@^7.18.9": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz#c8cea68263e45addcd6afc9091429f80925762c0" @@ -1230,6 +1922,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.9" +"@babel/plugin-transform-typeof-symbol@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.7.tgz#f074be466580d47d6e6b27473a840c9f9ca08fb0" + integrity sha512-VtR8hDy7YLB7+Pet9IarXjg/zgCMSF+1mNS/EQEiEaUPoFXCVsHG64SIxcaaI2zJgRiv+YmgaQESUfWAdbjzgg== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-transform-typescript@^7.18.6": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.20.7.tgz#673f49499cd810ae32a1ea5f3f8fab370987e055" @@ -1246,6 +1945,21 @@ dependencies: "@babel/helper-plugin-utils" "^7.18.9" +"@babel/plugin-transform-unicode-escapes@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz#2023a82ced1fb4971630a2e079764502c4148e0e" + integrity sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-unicode-property-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz#9073a4cd13b86ea71c3264659590ac086605bbcd" + integrity sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-transform-unicode-regex@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz#194317225d8c201bbae103364ffe9e2cea36cdca" @@ -1254,7 +1968,23 @@ "@babel/helper-create-regexp-features-plugin" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" -"@babel/preset-env@^7.12.11", "@babel/preset-env@^7.8.7": +"@babel/plugin-transform-unicode-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz#dfc3d4a51127108099b19817c0963be6a2adf19f" + integrity sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-unicode-sets-regex@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz#d40705d67523803a576e29c63cef6e516b858ed9" + integrity sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/preset-env@^7.12.11": version "7.20.2" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.20.2.tgz#9b1642aa47bb9f43a86f9630011780dab7f86506" integrity sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg== @@ -1335,6 +2065,93 @@ core-js-compat "^3.25.1" semver "^6.3.0" +"@babel/preset-env@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.24.7.tgz#ff067b4e30ba4a72f225f12f123173e77b987f37" + integrity sha512-1YZNsc+y6cTvWlDHidMBsQZrZfEFjRIo/BZCT906PMdzOyXtSLTgqGdrpcuTDCXyd11Am5uQULtDIcCfnTc8fQ== + dependencies: + "@babel/compat-data" "^7.24.7" + "@babel/helper-compilation-targets" "^7.24.7" + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-validator-option" "^7.24.7" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.24.7" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.24.7" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.24.7" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.24.7" + "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-class-properties" "^7.12.13" + "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-import-assertions" "^7.24.7" + "@babel/plugin-syntax-import-attributes" "^7.24.7" + "@babel/plugin-syntax-import-meta" "^7.10.4" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/plugin-syntax-top-level-await" "^7.14.5" + "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" + "@babel/plugin-transform-arrow-functions" "^7.24.7" + "@babel/plugin-transform-async-generator-functions" "^7.24.7" + "@babel/plugin-transform-async-to-generator" "^7.24.7" + "@babel/plugin-transform-block-scoped-functions" "^7.24.7" + "@babel/plugin-transform-block-scoping" "^7.24.7" + "@babel/plugin-transform-class-properties" "^7.24.7" + "@babel/plugin-transform-class-static-block" "^7.24.7" + "@babel/plugin-transform-classes" "^7.24.7" + "@babel/plugin-transform-computed-properties" "^7.24.7" + "@babel/plugin-transform-destructuring" "^7.24.7" + "@babel/plugin-transform-dotall-regex" "^7.24.7" + "@babel/plugin-transform-duplicate-keys" "^7.24.7" + "@babel/plugin-transform-dynamic-import" "^7.24.7" + "@babel/plugin-transform-exponentiation-operator" "^7.24.7" + "@babel/plugin-transform-export-namespace-from" "^7.24.7" + "@babel/plugin-transform-for-of" "^7.24.7" + "@babel/plugin-transform-function-name" "^7.24.7" + "@babel/plugin-transform-json-strings" "^7.24.7" + "@babel/plugin-transform-literals" "^7.24.7" + "@babel/plugin-transform-logical-assignment-operators" "^7.24.7" + "@babel/plugin-transform-member-expression-literals" "^7.24.7" + "@babel/plugin-transform-modules-amd" "^7.24.7" + "@babel/plugin-transform-modules-commonjs" "^7.24.7" + "@babel/plugin-transform-modules-systemjs" "^7.24.7" + "@babel/plugin-transform-modules-umd" "^7.24.7" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.24.7" + "@babel/plugin-transform-new-target" "^7.24.7" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.24.7" + "@babel/plugin-transform-numeric-separator" "^7.24.7" + "@babel/plugin-transform-object-rest-spread" "^7.24.7" + "@babel/plugin-transform-object-super" "^7.24.7" + "@babel/plugin-transform-optional-catch-binding" "^7.24.7" + "@babel/plugin-transform-optional-chaining" "^7.24.7" + "@babel/plugin-transform-parameters" "^7.24.7" + "@babel/plugin-transform-private-methods" "^7.24.7" + "@babel/plugin-transform-private-property-in-object" "^7.24.7" + "@babel/plugin-transform-property-literals" "^7.24.7" + "@babel/plugin-transform-regenerator" "^7.24.7" + "@babel/plugin-transform-reserved-words" "^7.24.7" + "@babel/plugin-transform-shorthand-properties" "^7.24.7" + "@babel/plugin-transform-spread" "^7.24.7" + "@babel/plugin-transform-sticky-regex" "^7.24.7" + "@babel/plugin-transform-template-literals" "^7.24.7" + "@babel/plugin-transform-typeof-symbol" "^7.24.7" + "@babel/plugin-transform-unicode-escapes" "^7.24.7" + "@babel/plugin-transform-unicode-property-regex" "^7.24.7" + "@babel/plugin-transform-unicode-regex" "^7.24.7" + "@babel/plugin-transform-unicode-sets-regex" "^7.24.7" + "@babel/preset-modules" "0.1.6-no-external-plugins" + babel-plugin-polyfill-corejs2 "^0.4.10" + babel-plugin-polyfill-corejs3 "^0.10.4" + babel-plugin-polyfill-regenerator "^0.6.1" + core-js-compat "^3.31.0" + semver "^6.3.1" + "@babel/preset-flow@^7.12.1": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.18.6.tgz#83f7602ba566e72a9918beefafef8ef16d2810cb" @@ -1344,6 +2161,15 @@ "@babel/helper-validator-option" "^7.18.6" "@babel/plugin-transform-flow-strip-types" "^7.18.6" +"@babel/preset-modules@0.1.6-no-external-plugins": + version "0.1.6-no-external-plugins" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz#ccb88a2c49c817236861fee7826080573b8a923a" + integrity sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + "@babel/preset-modules@^0.1.5": version "0.1.5" resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" @@ -1355,7 +2181,7 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/preset-react@^7.12.10", "@babel/preset-react@^7.8.3": +"@babel/preset-react@^7.12.10": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.18.6.tgz#979f76d6277048dc19094c217b507f3ad517dd2d" integrity sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg== @@ -1367,6 +2193,18 @@ "@babel/plugin-transform-react-jsx-development" "^7.18.6" "@babel/plugin-transform-react-pure-annotations" "^7.18.6" +"@babel/preset-react@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.24.7.tgz#480aeb389b2a798880bf1f889199e3641cbb22dc" + integrity sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/helper-validator-option" "^7.24.7" + "@babel/plugin-transform-react-display-name" "^7.24.7" + "@babel/plugin-transform-react-jsx" "^7.24.7" + "@babel/plugin-transform-react-jsx-development" "^7.24.7" + "@babel/plugin-transform-react-pure-annotations" "^7.24.7" + "@babel/preset-typescript@^7.12.7": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz#ce64be3e63eddc44240c6358daefac17b3186399" @@ -1387,13 +2225,25 @@ pirates "^4.0.5" source-map-support "^0.5.16" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.2", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": +"@babel/regjsgen@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" + integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== + +"@babel/runtime@^7.0.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.7.tgz#fcb41a5a70550e04a7b708037c7c32f7f356d8fd" integrity sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ== dependencies: regenerator-runtime "^0.13.11" +"@babel/runtime@^7.21.0", "@babel/runtime@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.7.tgz#f4f0d5530e8dbdf59b3451b9b3e594b6ba082e12" + integrity sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/template@^7.12.7", "@babel/template@^7.18.10", "@babel/template@^7.20.7", "@babel/template@^7.3.3": version "7.20.7" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8" @@ -1412,7 +2262,16 @@ "@babel/parser" "^7.24.0" "@babel/types" "^7.24.0" -"@babel/traverse@^7.1.6", "@babel/traverse@^7.12.11", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.20.5", "@babel/traverse@^7.20.7", "@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2", "@babel/traverse@^7.21.4", "@babel/traverse@^7.7.2": +"@babel/template@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.7.tgz#02efcee317d0609d2c07117cb70ef8fb17ab7315" + integrity sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/parser" "^7.24.7" + "@babel/types" "^7.24.7" + +"@babel/traverse@^7.1.6", "@babel/traverse@^7.12.11", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.20.5", "@babel/traverse@^7.20.7", "@babel/traverse@^7.21.0", "@babel/traverse@^7.21.2", "@babel/traverse@^7.21.4": version "7.21.4" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.21.4.tgz#a836aca7b116634e97a6ed99976236b3282c9d36" integrity sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q== @@ -1444,6 +2303,22 @@ debug "^4.3.1" globals "^11.1.0" +"@babel/traverse@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.7.tgz#de2b900163fa741721ba382163fe46a936c40cf5" + integrity sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.24.7" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-function-name" "^7.24.7" + "@babel/helper-hoist-variables" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" + "@babel/parser" "^7.24.7" + "@babel/types" "^7.24.7" + debug "^4.3.1" + globals "^11.1.0" + "@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.12.11", "@babel/types@^7.12.7", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.2.0", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.20.5", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.21.2", "@babel/types@^7.21.4", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": version "7.21.4" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.4.tgz#2d5d6bb7908699b3b416409ffd3b5daa25b030d4" @@ -1462,6 +2337,15 @@ "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" +"@babel/types@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.7.tgz#6027fe12bc1aa724cd32ab113fb7f1988f1f66f2" + integrity sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q== + dependencies: + "@babel/helper-string-parser" "^7.24.7" + "@babel/helper-validator-identifier" "^7.24.7" + to-fast-properties "^2.0.0" + "@base2/pretty-print-object@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz#371ba8be66d556812dc7fb169ebc3c08378f69d4" @@ -1490,126 +2374,133 @@ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== -"@emotion/babel-plugin@^11.10.6": - version "11.10.6" - resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.10.6.tgz#a68ee4b019d661d6f37dec4b8903255766925ead" - integrity sha512-p2dAqtVrkhSa7xz1u/m9eHYdLi+en8NowrmXeF/dKtJpU8lCWli8RUAati7NcSl0afsBott48pdnANuD0wh9QQ== +"@emotion/babel-plugin@^11.11.0": + version "11.11.0" + resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz#c2d872b6a7767a9d176d007f5b31f7d504bb5d6c" + integrity sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ== dependencies: "@babel/helper-module-imports" "^7.16.7" "@babel/runtime" "^7.18.3" - "@emotion/hash" "^0.9.0" - "@emotion/memoize" "^0.8.0" - "@emotion/serialize" "^1.1.1" + "@emotion/hash" "^0.9.1" + "@emotion/memoize" "^0.8.1" + "@emotion/serialize" "^1.1.2" babel-plugin-macros "^3.1.0" convert-source-map "^1.5.0" escape-string-regexp "^4.0.0" find-root "^1.1.0" source-map "^0.5.7" - stylis "4.1.3" + stylis "4.2.0" -"@emotion/cache@^11.10.5": - version "11.10.5" - resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.10.5.tgz#c142da9351f94e47527ed458f7bbbbe40bb13c12" - integrity sha512-dGYHWyzTdmK+f2+EnIGBpkz1lKc4Zbj2KHd4cX3Wi8/OWr5pKslNjc3yABKH4adRGCvSX4VDC0i04mrrq0aiRA== +"@emotion/cache@^11.11.0": + version "11.11.0" + resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.11.0.tgz#809b33ee6b1cb1a625fef7a45bc568ccd9b8f3ff" + integrity sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ== dependencies: - "@emotion/memoize" "^0.8.0" - "@emotion/sheet" "^1.2.1" - "@emotion/utils" "^1.2.0" - "@emotion/weak-memoize" "^0.3.0" - stylis "4.1.3" - -"@emotion/core@^11.0.0": - version "11.0.0" - resolved "https://registry.yarnpkg.com/@emotion/core/-/core-11.0.0.tgz#d075867e07864119de7cfd5268c15012bd2d6290" - integrity sha512-w4sE3AmHmyG6RDKf6mIbtHpgJUSJ2uGvPQb8VXFL7hFjMPibE8IiehG8cMX3Ztm4svfCQV6KqusQbeIOkurBcA== + "@emotion/memoize" "^0.8.1" + "@emotion/sheet" "^1.2.2" + "@emotion/utils" "^1.2.1" + "@emotion/weak-memoize" "^0.3.1" + stylis "4.2.0" -"@emotion/hash@^0.9.0": - version "0.9.0" - resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.0.tgz#c5153d50401ee3c027a57a177bc269b16d889cb7" - integrity sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ== +"@emotion/hash@^0.9.1": + version "0.9.1" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.1.tgz#4ffb0055f7ef676ebc3a5a91fb621393294e2f43" + integrity sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ== -"@emotion/is-prop-valid@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz#7f2d35c97891669f7e276eb71c83376a5dc44c83" - integrity sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg== +"@emotion/is-prop-valid@^1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz#d4175076679c6a26faa92b03bb786f9e52612337" + integrity sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw== dependencies: - "@emotion/memoize" "^0.8.0" + "@emotion/memoize" "^0.8.1" -"@emotion/memoize@^0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.0.tgz#f580f9beb67176fa57aae70b08ed510e1b18980f" - integrity sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA== +"@emotion/memoize@^0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17" + integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA== -"@emotion/react@^11.10.6": - version "11.10.6" - resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.10.6.tgz#dbe5e650ab0f3b1d2e592e6ab1e006e75fd9ac11" - integrity sha512-6HT8jBmcSkfzO7mc+N1L9uwvOnlcGoix8Zn7srt+9ga0MjREo6lRpuVX0kzo6Jp6oTqDhREOFsygN6Ew4fEQbw== +"@emotion/react@^11.11.4": + version "11.11.4" + resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.11.4.tgz#3a829cac25c1f00e126408fab7f891f00ecc3c1d" + integrity sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw== dependencies: "@babel/runtime" "^7.18.3" - "@emotion/babel-plugin" "^11.10.6" - "@emotion/cache" "^11.10.5" - "@emotion/serialize" "^1.1.1" - "@emotion/use-insertion-effect-with-fallbacks" "^1.0.0" - "@emotion/utils" "^1.2.0" - "@emotion/weak-memoize" "^0.3.0" + "@emotion/babel-plugin" "^11.11.0" + "@emotion/cache" "^11.11.0" + "@emotion/serialize" "^1.1.3" + "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1" + "@emotion/utils" "^1.2.1" + "@emotion/weak-memoize" "^0.3.1" hoist-non-react-statics "^3.3.1" -"@emotion/serialize@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.1.1.tgz#0595701b1902feded8a96d293b26be3f5c1a5cf0" - integrity sha512-Zl/0LFggN7+L1liljxXdsVSVlg6E/Z/olVWpfxUTxOAmi8NU7YoeWeLfi1RmnB2TATHoaWwIBRoL+FvAJiTUQA== +"@emotion/serialize@^1.1.2", "@emotion/serialize@^1.1.3", "@emotion/serialize@^1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.1.4.tgz#fc8f6d80c492cfa08801d544a05331d1cc7cd451" + integrity sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ== dependencies: - "@emotion/hash" "^0.9.0" - "@emotion/memoize" "^0.8.0" - "@emotion/unitless" "^0.8.0" - "@emotion/utils" "^1.2.0" + "@emotion/hash" "^0.9.1" + "@emotion/memoize" "^0.8.1" + "@emotion/unitless" "^0.8.1" + "@emotion/utils" "^1.2.1" csstype "^3.0.2" -"@emotion/sheet@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.1.tgz#0767e0305230e894897cadb6c8df2c51e61a6c2c" - integrity sha512-zxRBwl93sHMsOj4zs+OslQKg/uhF38MB+OMKoCrVuS0nyTkqnau+BM3WGEoOptg9Oz45T/aIGs1qbVAsEFo3nA== +"@emotion/sheet@^1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.2.tgz#d58e788ee27267a14342303e1abb3d508b6d0fec" + integrity sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA== -"@emotion/styled@^11.10.6": - version "11.10.6" - resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.10.6.tgz#d886afdc51ef4d66c787ebde848f3cc8b117ebba" - integrity sha512-OXtBzOmDSJo5Q0AFemHCfl+bUueT8BIcPSxu0EGTpGk6DmI5dnhSzQANm1e1ze0YZL7TDyAyy6s/b/zmGOS3Og== +"@emotion/styled@^11.11.5": + version "11.11.5" + resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.11.5.tgz#0c5c8febef9d86e8a926e663b2e5488705545dfb" + integrity sha512-/ZjjnaNKvuMPxcIiUkf/9SHoG4Q196DRl1w82hQ3WCsjo1IUR8uaGWrC6a87CrYAW0Kb/pK7hk8BnLgLRi9KoQ== dependencies: "@babel/runtime" "^7.18.3" - "@emotion/babel-plugin" "^11.10.6" - "@emotion/is-prop-valid" "^1.2.0" - "@emotion/serialize" "^1.1.1" - "@emotion/use-insertion-effect-with-fallbacks" "^1.0.0" - "@emotion/utils" "^1.2.0" + "@emotion/babel-plugin" "^11.11.0" + "@emotion/is-prop-valid" "^1.2.2" + "@emotion/serialize" "^1.1.4" + "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1" + "@emotion/utils" "^1.2.1" -"@emotion/unitless@^0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.0.tgz#a4a36e9cbdc6903737cd20d38033241e1b8833db" - integrity sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw== +"@emotion/unitless@^0.8.1": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.1.tgz#182b5a4704ef8ad91bde93f7a860a88fd92c79a3" + integrity sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ== -"@emotion/use-insertion-effect-with-fallbacks@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz#ffadaec35dbb7885bd54de3fa267ab2f860294df" - integrity sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A== +"@emotion/use-insertion-effect-with-fallbacks@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz#08de79f54eb3406f9daaf77c76e35313da963963" + integrity sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw== -"@emotion/utils@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.0.tgz#9716eaccbc6b5ded2ea5a90d65562609aab0f561" - integrity sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw== +"@emotion/utils@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.1.tgz#bbab58465738d31ae4cb3dbb6fc00a5991f755e4" + integrity sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg== -"@emotion/weak-memoize@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz#ea89004119dc42db2e1dba0f97d553f7372f6fcb" - integrity sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg== +"@emotion/weak-memoize@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6" + integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww== -"@eslint/eslintrc@^1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.4.1.tgz#af58772019a2d271b7e2d4c23ff4ddcba3ccfb3e" - integrity sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA== +"@eslint-community/eslint-utils@^4.2.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.6.1": + version "4.11.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.11.0.tgz#b0ffd0312b4a3fd2d6f77237e7248a5ad3a680ae" + integrity sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A== + +"@eslint/eslintrc@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" + integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^9.4.0" + espree "^9.6.0" globals "^13.19.0" ignore "^5.2.0" import-fresh "^3.2.1" @@ -1617,29 +2508,34 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@fortawesome/fontawesome-common-types@6.2.1": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.2.1.tgz#411e02a820744d3f7e0d8d9df9d82b471beaa073" - integrity sha512-Sz07mnQrTekFWLz5BMjOzHl/+NooTdW8F8kDQxjWwbpOJcnoSg4vUDng8d/WR1wOxM0O+CY9Zw0nR054riNYtQ== +"@eslint/js@8.57.0": + version "8.57.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" + integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== -"@fortawesome/fontawesome-svg-core@^6.2.1": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.2.1.tgz#e87e905e444b5e7b715af09b64d27b53d4c8f9d9" - integrity sha512-HELwwbCz6C1XEcjzyT1Jugmz2NNklMrSPjZOWMlc+ZsHIVk+XOvOXLGGQtFBwSyqfJDNgRq4xBCwWOaZ/d9DEA== +"@fortawesome/fontawesome-common-types@6.5.2": + version "6.5.2" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.5.2.tgz#eaf2f5699f73cef198454ebc0c414e3688898179" + integrity sha512-gBxPg3aVO6J0kpfHNILc+NMhXnqHumFxOmjYCFfOiLZfwhnnfhtsdA2hfJlDnj+8PjAs6kKQPenOTKj3Rf7zHw== + +"@fortawesome/fontawesome-svg-core@^6.5.2": + version "6.5.2" + resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.5.2.tgz#4b42de71e196039b0d5ccf88559b8044e3296c21" + integrity sha512-5CdaCBGl8Rh9ohNdxeeTMxIj8oc3KNBgIeLMvJosBMdslK/UnEB8rzyDRrbKdL1kDweqBPo4GT9wvnakHWucZw== dependencies: - "@fortawesome/fontawesome-common-types" "6.2.1" + "@fortawesome/fontawesome-common-types" "6.5.2" -"@fortawesome/free-solid-svg-icons@^6.2.1": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.2.1.tgz#2290ea5adcf1537cbd0c43de6feb38af02141d27" - integrity sha512-oKuqrP5jbfEPJWTij4sM+/RvgX+RMFwx3QZCZcK9PrBDgxC35zuc7AOFsyMjMd/PIFPeB2JxyqDr5zs/DZFPPw== +"@fortawesome/free-solid-svg-icons@^6.5.2": + version "6.5.2" + resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.5.2.tgz#9b40b077b27400a5e9fcbf2d15b986c7be69e9ca" + integrity sha512-QWFZYXFE7O1Gr1dTIp+D6UcFUF0qElOnZptpi7PBUMylJh+vFmIedVe1Ir6RM1t2tEQLLSV1k7bR4o92M+uqlw== dependencies: - "@fortawesome/fontawesome-common-types" "6.2.1" + "@fortawesome/fontawesome-common-types" "6.5.2" -"@fortawesome/react-fontawesome@^0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz#d90dd8a9211830b4e3c08e94b63a0ba7291ddcf4" - integrity sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw== +"@fortawesome/react-fontawesome@^0.2.2": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.2.tgz#68b058f9132b46c8599875f6a636dad231af78d4" + integrity sha512-EnkrprPNqI6SXJl//m29hpaNzOp1bruISWaOiRtkMi/xSvHJlzc2j2JAYS7egxt/EbjSNV/k6Xy0AQI6vB2+1g== dependencies: prop-types "^15.8.1" @@ -1713,13 +2609,13 @@ resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.1.1.tgz#076d78ce99822258cf813ecc1e7fa460fa74d052" integrity sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg== -"@humanwhocodes/config-array@^0.11.8": - version "0.11.8" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz#03595ac2075a4dc0f191cc2131de14fbd7d410b9" - integrity sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g== +"@humanwhocodes/config-array@^0.11.14": + version "0.11.14" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" + integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== dependencies: - "@humanwhocodes/object-schema" "^1.2.1" - debug "^4.1.1" + "@humanwhocodes/object-schema" "^2.0.2" + debug "^4.3.1" minimatch "^3.0.5" "@humanwhocodes/module-importer@^1.0.1": @@ -1727,10 +2623,22 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== -"@humanwhocodes/object-schema@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" - integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@humanwhocodes/object-schema@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" + integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== + +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" @@ -1757,95 +2665,49 @@ chalk "^2.0.1" slash "^2.0.0" -"@jest/console@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.3.1.tgz#3e3f876e4e47616ea3b1464b9fbda981872e9583" - integrity sha512-IRE6GD47KwcqA09RIWrabKdHPiKDGgtAL31xDxbi/RjQMsr+lY+ppxmHwY0dUEV3qvvxZzoe5Hl0RXZJOjQNUg== - dependencies: - "@jest/types" "^29.3.1" - "@types/node" "*" - chalk "^4.0.0" - jest-message-util "^29.3.1" - jest-util "^29.3.1" - slash "^3.0.0" - -"@jest/console@^29.4.3": - version "29.4.3" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.4.3.tgz#1f25a99f7f860e4c46423b5b1038262466fadde1" - integrity sha512-W/o/34+wQuXlgqlPYTansOSiBnuxrTv61dEVkA6HNmpcgHLUjfaUbdqt6oVvOzaawwo9IdW9QOtMgQ1ScSZC4A== +"@jest/console@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" + integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== dependencies: - "@jest/types" "^29.4.3" + "@jest/types" "^29.6.3" "@types/node" "*" chalk "^4.0.0" - jest-message-util "^29.4.3" - jest-util "^29.4.3" + jest-message-util "^29.7.0" + jest-util "^29.7.0" slash "^3.0.0" -"@jest/core@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.3.1.tgz#bff00f413ff0128f4debec1099ba7dcd649774a1" - integrity sha512-0ohVjjRex985w5MmO5L3u5GR1O30DexhBSpuwx2P+9ftyqHdJXnk7IUWiP80oHMvt7ubHCJHxV0a0vlKVuZirw== +"@jest/core@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" + integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== dependencies: - "@jest/console" "^29.3.1" - "@jest/reporters" "^29.3.1" - "@jest/test-result" "^29.3.1" - "@jest/transform" "^29.3.1" - "@jest/types" "^29.3.1" + "@jest/console" "^29.7.0" + "@jest/reporters" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" ci-info "^3.2.0" exit "^0.1.2" graceful-fs "^4.2.9" - jest-changed-files "^29.2.0" - jest-config "^29.3.1" - jest-haste-map "^29.3.1" - jest-message-util "^29.3.1" - jest-regex-util "^29.2.0" - jest-resolve "^29.3.1" - jest-resolve-dependencies "^29.3.1" - jest-runner "^29.3.1" - jest-runtime "^29.3.1" - jest-snapshot "^29.3.1" - jest-util "^29.3.1" - jest-validate "^29.3.1" - jest-watcher "^29.3.1" + jest-changed-files "^29.7.0" + jest-config "^29.7.0" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-resolve-dependencies "^29.7.0" + jest-runner "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + jest-watcher "^29.7.0" micromatch "^4.0.4" - pretty-format "^29.3.1" - slash "^3.0.0" - strip-ansi "^6.0.0" - -"@jest/core@^29.4.3": - version "29.4.3" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.4.3.tgz#829dd65bffdb490de5b0f69e97de8e3b5eadd94b" - integrity sha512-56QvBq60fS4SPZCuM7T+7scNrkGIe7Mr6PVIXUpu48ouvRaWOFqRPV91eifvFM0ay2HmfswXiGf97NGUN5KofQ== - dependencies: - "@jest/console" "^29.4.3" - "@jest/reporters" "^29.4.3" - "@jest/test-result" "^29.4.3" - "@jest/transform" "^29.4.3" - "@jest/types" "^29.4.3" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - ci-info "^3.2.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-changed-files "^29.4.3" - jest-config "^29.4.3" - jest-haste-map "^29.4.3" - jest-message-util "^29.4.3" - jest-regex-util "^29.4.3" - jest-resolve "^29.4.3" - jest-resolve-dependencies "^29.4.3" - jest-runner "^29.4.3" - jest-runtime "^29.4.3" - jest-snapshot "^29.4.3" - jest-util "^29.4.3" - jest-validate "^29.4.3" - jest-watcher "^29.4.3" - micromatch "^4.0.4" - pretty-format "^29.4.3" + pretty-format "^29.7.0" slash "^3.0.0" strip-ansi "^6.0.0" @@ -1859,55 +2721,30 @@ "@jest/types" "^24.9.0" jest-mock "^24.9.0" -"@jest/environment@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.3.1.tgz#eb039f726d5fcd14698acd072ac6576d41cfcaa6" - integrity sha512-pMmvfOPmoa1c1QpfFW0nXYtNLpofqo4BrCIk6f2kW4JFeNlHV2t3vd+3iDLf31e2ot2Mec0uqZfmI+U0K2CFag== +"@jest/environment@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" + integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== dependencies: - "@jest/fake-timers" "^29.3.1" - "@jest/types" "^29.3.1" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" "@types/node" "*" - jest-mock "^29.3.1" - -"@jest/environment@^29.4.3": - version "29.4.3" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.4.3.tgz#9fe2f3169c3b33815dc4bd3960a064a83eba6548" - integrity sha512-dq5S6408IxIa+lr54zeqce+QgI+CJT4nmmA+1yzFgtcsGK8c/EyiUb9XQOgz3BMKrRDfKseeOaxj2eO8LlD3lA== - dependencies: - "@jest/fake-timers" "^29.4.3" - "@jest/types" "^29.4.3" - "@types/node" "*" - jest-mock "^29.4.3" - -"@jest/expect-utils@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.3.1.tgz#531f737039e9b9e27c42449798acb5bba01935b6" - integrity sha512-wlrznINZI5sMjwvUoLVk617ll/UYfGIZNxmbU+Pa7wmkL4vYzhV9R2pwVqUh4NWWuLQWkI8+8mOkxs//prKQ3g== - dependencies: - jest-get-type "^29.2.0" - -"@jest/expect-utils@^29.4.3": - version "29.4.3" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.4.3.tgz#95ce4df62952f071bcd618225ac7c47eaa81431e" - integrity sha512-/6JWbkxHOP8EoS8jeeTd9dTfc9Uawi+43oLKHfp6zzux3U2hqOOVnV3ai4RpDYHOccL6g+5nrxpoc8DmJxtXVQ== - dependencies: - jest-get-type "^29.4.3" + jest-mock "^29.7.0" -"@jest/expect@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.3.1.tgz#456385b62894349c1d196f2d183e3716d4c6a6cd" - integrity sha512-QivM7GlSHSsIAWzgfyP8dgeExPRZ9BIe2LsdPyEhCGkZkoyA+kGsoIzbKAfZCvvRzfZioKwPtCZIt5SaoxYCvg== +"@jest/expect-utils@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" + integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== dependencies: - expect "^29.3.1" - jest-snapshot "^29.3.1" + jest-get-type "^29.6.3" -"@jest/expect@^29.4.3": - version "29.4.3" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.4.3.tgz#d31a28492e45a6bcd0f204a81f783fe717045c6e" - integrity sha512-iktRU/YsxEtumI9zsPctYUk7ptpC+AVLLk1Ax3AsA4g1C+8OOnKDkIQBDHtD5hA/+VtgMd5AWI5gNlcAlt2vxQ== +"@jest/expect@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" + integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== dependencies: - expect "^29.4.3" - jest-snapshot "^29.4.3" + expect "^29.7.0" + jest-snapshot "^29.7.0" "@jest/fake-timers@^24.9.0": version "24.9.0" @@ -1918,91 +2755,39 @@ jest-message-util "^24.9.0" jest-mock "^24.9.0" -"@jest/fake-timers@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.3.1.tgz#b140625095b60a44de820876d4c14da1aa963f67" - integrity sha512-iHTL/XpnDlFki9Tq0Q1GGuVeQ8BHZGIYsvCO5eN/O/oJaRzofG9Xndd9HuSDBI/0ZS79pg0iwn07OMTQ7ngF2A== +"@jest/fake-timers@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" + integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== dependencies: - "@jest/types" "^29.3.1" - "@sinonjs/fake-timers" "^9.1.2" - "@types/node" "*" - jest-message-util "^29.3.1" - jest-mock "^29.3.1" - jest-util "^29.3.1" - -"@jest/fake-timers@^29.4.3": - version "29.4.3" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.4.3.tgz#31e982638c60fa657d310d4b9d24e023064027b0" - integrity sha512-4Hote2MGcCTWSD2gwl0dwbCpBRHhE6olYEuTj8FMowdg3oQWNKr2YuxenPQYZ7+PfqPY1k98wKDU4Z+Hvd4Tiw== - dependencies: - "@jest/types" "^29.4.3" + "@jest/types" "^29.6.3" "@sinonjs/fake-timers" "^10.0.2" "@types/node" "*" - jest-message-util "^29.4.3" - jest-mock "^29.4.3" - jest-util "^29.4.3" - -"@jest/globals@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.3.1.tgz#92be078228e82d629df40c3656d45328f134a0c6" - integrity sha512-cTicd134vOcwO59OPaB6AmdHQMCtWOe+/DitpTZVxWgMJ+YvXL1HNAmPyiGbSHmF/mXVBkvlm8YYtQhyHPnV6Q== - dependencies: - "@jest/environment" "^29.3.1" - "@jest/expect" "^29.3.1" - "@jest/types" "^29.3.1" - jest-mock "^29.3.1" - -"@jest/globals@^29.4.3": - version "29.4.3" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.4.3.tgz#63a2c4200d11bc6d46f12bbe25b07f771fce9279" - integrity sha512-8BQ/5EzfOLG7AaMcDh7yFCbfRLtsc+09E1RQmRBI4D6QQk4m6NSK/MXo+3bJrBN0yU8A2/VIcqhvsOLFmziioA== - dependencies: - "@jest/environment" "^29.4.3" - "@jest/expect" "^29.4.3" - "@jest/types" "^29.4.3" - jest-mock "^29.4.3" - -"@jest/reporters@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.3.1.tgz#9a6d78c109608e677c25ddb34f907b90e07b4310" - integrity sha512-GhBu3YFuDrcAYW/UESz1JphEAbvUjaY2vShRZRoRY1mxpCMB3yGSJ4j9n0GxVlEOdCf7qjvUfBCrTUUqhVfbRA== + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +"@jest/globals@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" + integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== dependencies: - "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^29.3.1" - "@jest/test-result" "^29.3.1" - "@jest/transform" "^29.3.1" - "@jest/types" "^29.3.1" - "@jridgewell/trace-mapping" "^0.3.15" - "@types/node" "*" - chalk "^4.0.0" - collect-v8-coverage "^1.0.0" - exit "^0.1.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^5.1.0" - istanbul-lib-report "^3.0.0" - istanbul-lib-source-maps "^4.0.0" - istanbul-reports "^3.1.3" - jest-message-util "^29.3.1" - jest-util "^29.3.1" - jest-worker "^29.3.1" - slash "^3.0.0" - string-length "^4.0.1" - strip-ansi "^6.0.0" - v8-to-istanbul "^9.0.1" + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/types" "^29.6.3" + jest-mock "^29.7.0" -"@jest/reporters@^29.4.3": - version "29.4.3" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.4.3.tgz#0a68a0c0f20554760cc2e5443177a0018969e353" - integrity sha512-sr2I7BmOjJhyqj9ANC6CTLsL4emMoka7HkQpcoMRlhCbQJjz2zsRzw0BDPiPyEFDXAbxKgGFYuQZiSJ1Y6YoTg== +"@jest/reporters@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" + integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== dependencies: "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^29.4.3" - "@jest/test-result" "^29.4.3" - "@jest/transform" "^29.4.3" - "@jest/types" "^29.4.3" - "@jridgewell/trace-mapping" "^0.3.15" + "@jest/console" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" "@types/node" "*" chalk "^4.0.0" collect-v8-coverage "^1.0.0" @@ -2010,31 +2795,24 @@ glob "^7.1.3" graceful-fs "^4.2.9" istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^5.1.0" + istanbul-lib-instrument "^6.0.0" istanbul-lib-report "^3.0.0" istanbul-lib-source-maps "^4.0.0" istanbul-reports "^3.1.3" - jest-message-util "^29.4.3" - jest-util "^29.4.3" - jest-worker "^29.4.3" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + jest-worker "^29.7.0" slash "^3.0.0" string-length "^4.0.1" strip-ansi "^6.0.0" v8-to-istanbul "^9.0.1" -"@jest/schemas@^29.0.0": - version "29.0.0" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.0.0.tgz#5f47f5994dd4ef067fb7b4188ceac45f77fe952a" - integrity sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA== +"@jest/schemas@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" + integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== dependencies: - "@sinclair/typebox" "^0.24.1" - -"@jest/schemas@^29.4.3": - version "29.4.3" - resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.4.3.tgz#39cf1b8469afc40b6f5a2baaa146e332c4151788" - integrity sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg== - dependencies: - "@sinclair/typebox" "^0.25.16" + "@sinclair/typebox" "^0.27.8" "@jest/source-map@^24.9.0": version "24.9.0" @@ -2045,21 +2823,12 @@ graceful-fs "^4.1.15" source-map "^0.6.0" -"@jest/source-map@^29.2.0": - version "29.2.0" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.2.0.tgz#ab3420c46d42508dcc3dc1c6deee0b613c235744" - integrity sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ== +"@jest/source-map@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" + integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== dependencies: - "@jridgewell/trace-mapping" "^0.3.15" - callsites "^3.0.0" - graceful-fs "^4.2.9" - -"@jest/source-map@^29.4.3": - version "29.4.3" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.4.3.tgz#ff8d05cbfff875d4a791ab679b4333df47951d20" - integrity sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w== - dependencies: - "@jridgewell/trace-mapping" "^0.3.15" + "@jridgewell/trace-mapping" "^0.3.18" callsites "^3.0.0" graceful-fs "^4.2.9" @@ -2072,44 +2841,24 @@ "@jest/types" "^24.9.0" "@types/istanbul-lib-coverage" "^2.0.0" -"@jest/test-result@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.3.1.tgz#92cd5099aa94be947560a24610aa76606de78f50" - integrity sha512-qeLa6qc0ddB0kuOZyZIhfN5q0e2htngokyTWsGriedsDhItisW7SDYZ7ceOe57Ii03sL988/03wAcBh3TChMGw== - dependencies: - "@jest/console" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/istanbul-lib-coverage" "^2.0.0" - collect-v8-coverage "^1.0.0" - -"@jest/test-result@^29.4.3": - version "29.4.3" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.4.3.tgz#e13d973d16c8c7cc0c597082d5f3b9e7f796ccb8" - integrity sha512-Oi4u9NfBolMq9MASPwuWTlC5WvmNRwI4S8YrQg5R5Gi47DYlBe3sh7ILTqi/LGrK1XUE4XY9KZcQJTH1WJCLLA== +"@jest/test-result@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" + integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== dependencies: - "@jest/console" "^29.4.3" - "@jest/types" "^29.4.3" + "@jest/console" "^29.7.0" + "@jest/types" "^29.6.3" "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-sequencer@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.3.1.tgz#fa24b3b050f7a59d48f7ef9e0b782ab65123090d" - integrity sha512-IqYvLbieTv20ArgKoAMyhLHNrVHJfzO6ARZAbQRlY4UGWfdDnLlZEF0BvKOMd77uIiIjSZRwq3Jb3Fa3I8+2UA== - dependencies: - "@jest/test-result" "^29.3.1" - graceful-fs "^4.2.9" - jest-haste-map "^29.3.1" - slash "^3.0.0" - -"@jest/test-sequencer@^29.4.3": - version "29.4.3" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.4.3.tgz#0862e876a22993385a0f3e7ea1cc126f208a2898" - integrity sha512-yi/t2nES4GB4G0mjLc0RInCq/cNr9dNwJxcGg8sslajua5Kb4kmozAc+qPLzplhBgfw1vLItbjyHzUN92UXicw== +"@jest/test-sequencer@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" + integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== dependencies: - "@jest/test-result" "^29.4.3" + "@jest/test-result" "^29.7.0" graceful-fs "^4.2.9" - jest-haste-map "^29.4.3" + jest-haste-map "^29.7.0" slash "^3.0.0" "@jest/transform@^24.9.0": @@ -2134,43 +2883,22 @@ source-map "^0.6.1" write-file-atomic "2.4.1" -"@jest/transform@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.3.1.tgz#1e6bd3da4af50b5c82a539b7b1f3770568d6e36d" - integrity sha512-8wmCFBTVGYqFNLWfcOWoVuMuKYPUBTnTMDkdvFtAYELwDOl9RGwOsvQWGPFxDJ8AWY9xM/8xCXdqmPK3+Q5Lug== +"@jest/transform@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" + integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== dependencies: "@babel/core" "^7.11.6" - "@jest/types" "^29.3.1" - "@jridgewell/trace-mapping" "^0.3.15" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" babel-plugin-istanbul "^6.1.1" chalk "^4.0.0" convert-source-map "^2.0.0" fast-json-stable-stringify "^2.1.0" graceful-fs "^4.2.9" - jest-haste-map "^29.3.1" - jest-regex-util "^29.2.0" - jest-util "^29.3.1" - micromatch "^4.0.4" - pirates "^4.0.4" - slash "^3.0.0" - write-file-atomic "^4.0.1" - -"@jest/transform@^29.4.3": - version "29.4.3" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.4.3.tgz#f7d17eac9cb5bb2e1222ea199c7c7e0835e0c037" - integrity sha512-8u0+fBGWolDshsFgPQJESkDa72da/EVwvL+II0trN2DR66wMwiQ9/CihaGfHdlLGFzbBZwMykFtxuwFdZqlKwg== - dependencies: - "@babel/core" "^7.11.6" - "@jest/types" "^29.4.3" - "@jridgewell/trace-mapping" "^0.3.15" - babel-plugin-istanbul "^6.1.1" - chalk "^4.0.0" - convert-source-map "^2.0.0" - fast-json-stable-stringify "^2.1.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.4.3" - jest-regex-util "^29.4.3" - jest-util "^29.4.3" + jest-haste-map "^29.7.0" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" micromatch "^4.0.4" pirates "^4.0.4" slash "^3.0.0" @@ -2185,24 +2913,12 @@ "@types/istanbul-reports" "^1.1.1" "@types/yargs" "^13.0.0" -"@jest/types@^29.3.1": - version "29.3.1" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.3.1.tgz#7c5a80777cb13e703aeec6788d044150341147e3" - integrity sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA== +"@jest/types@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" + integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== dependencies: - "@jest/schemas" "^29.0.0" - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^17.0.8" - chalk "^4.0.0" - -"@jest/types@^29.4.3": - version "29.4.3" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.4.3.tgz#9069145f4ef09adf10cec1b2901b2d390031431f" - integrity sha512-bPYfw8V65v17m2Od1cv44FH+SiKW7w2Xu7trhcdTLUmSv85rfKsP+qXSjO4KGJr4dtPSzl/gvslZBXctf1qGEA== - dependencies: - "@jest/schemas" "^29.4.3" + "@jest/schemas" "^29.6.3" "@types/istanbul-lib-coverage" "^2.0.0" "@types/istanbul-reports" "^3.0.0" "@types/node" "*" @@ -2231,16 +2947,35 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + "@jridgewell/resolve-uri@3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + "@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": version "1.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + "@jridgewell/source-map@^0.3.2": version "0.3.2" resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" @@ -2249,12 +2984,25 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" +"@jridgewell/source-map@^0.3.3": + version "0.3.6" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a" + integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + "@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": version "1.4.14" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.15", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": +"@jridgewell/sourcemap-codec@^1.4.14": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": version "0.3.17" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== @@ -2262,17 +3010,25 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" +"@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@leichtgewicht/ip-codec@^2.0.1": version "2.0.4" resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== -"@lhci/cli@^0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@lhci/cli/-/cli-0.11.0.tgz#dcc8970151b8a17e77abbb9568395a83adfdfed7" - integrity sha512-5P0yvctSuriCPvQbos8VThk2DsPG/9LHzI+c6DD1hSAXTdiQJB3GDbz6BO6J/5fCEofA5OGOgyAhGWCTaN7SnA== +"@lhci/cli@^0.11.1": + version "0.11.1" + resolved "https://registry.yarnpkg.com/@lhci/cli/-/cli-0.11.1.tgz#ebd00a49ffba8595f35739d7c3ce8189810b6323" + integrity sha512-NDq7Cd6cfINLuI88FSQt+hZ1RSRyOi4TFOO9MVip4BHtSm+BG83sYRGMllUoBt12N6F+5UQte58A9sJz65EI1g== dependencies: - "@lhci/utils" "0.11.0" + "@lhci/utils" "0.11.1" chrome-launcher "^0.13.4" compression "^1.7.4" debug "^4.3.1" @@ -2288,10 +3044,10 @@ yargs "^15.4.1" yargs-parser "^13.1.2" -"@lhci/utils@0.11.0": - version "0.11.0" - resolved "https://registry.yarnpkg.com/@lhci/utils/-/utils-0.11.0.tgz#9772862ec6a949f93db18e1a137284935aabbd5e" - integrity sha512-kG1a6X83GemLyU9UbxpcdQIikiT4SWJabpyB73C5Iz+6SwjcQXBY8+2VpLhFKtkU9o+FZyc826Ikj7tRHnd2cQ== +"@lhci/utils@0.11.1": + version "0.11.1" + resolved "https://registry.yarnpkg.com/@lhci/utils/-/utils-0.11.1.tgz#a2aa778b994f28400914298b892d6e636701a3b0" + integrity sha512-ABUp+AFLRdfQ3+nTDinGxZAz4afBMjEoC1g9GlL5b9Faa9eC90fcmv4uS5V+jcQWFMYjbYpsajHIJfI6r6OIjA== dependencies: debug "^4.3.1" isomorphic-fetch "^3.0.0" @@ -2329,6 +3085,11 @@ resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.22.tgz#219dfd89ae5b97a8801f015323ffa4b62f45718b" integrity sha512-H1rQc1ZOHANWBvPcW+JpGwr+juXSxM8Q8YCkm3GhZd8REu1fHR3z99CErO1p9pkcfcxZnMdIZdIsXkOHY0NilA== +"@mixmark-io/domino@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@mixmark-io/domino/-/domino-2.2.0.tgz#4e8ec69bf1afeb7a14f0628b7e2c0f35bdb336c3" + integrity sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw== + "@moebius/http-graceful-shutdown@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@moebius/http-graceful-shutdown/-/http-graceful-shutdown-1.1.0.tgz#b9d33e63358aa77b2103a577ea7ccdeae3e3c6d5" @@ -2399,6 +3160,11 @@ mkdirp "^1.0.4" rimraf "^3.0.2" +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + "@pmmmwh/react-refresh-webpack-plugin@^0.5.3": version "0.5.10" resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.10.tgz#2eba163b8e7dbabb4ce3609ab5e32ab63dda3ef8" @@ -2414,10 +3180,10 @@ schema-utils "^3.0.0" source-map "^0.7.3" -"@popperjs/core@^2.11.5": - version "2.11.6" - resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.6.tgz#cee20bd55e68a1720bdab363ecf0c821ded4cd45" - integrity sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw== +"@popperjs/core@^2.11.6": + version "2.11.8" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" + integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A== "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" @@ -2485,38 +3251,38 @@ unbzip2-stream "1.4.3" yargs "17.7.2" -"@react-aria/ssr@^3.2.0": - version "3.4.1" - resolved "https://registry.yarnpkg.com/@react-aria/ssr/-/ssr-3.4.1.tgz#79e8bb621487e8f52890c917d3c734f448ba95e7" - integrity sha512-NmhoilMDyIfQiOSdQgxpVH2tC2u85Y0mVijtBNbI9kcDYLEiW/r6vKYVKtkyU+C4qobXhGMPfZ70PTc0lysSVA== +"@react-aria/ssr@^3.5.0": + version "3.9.4" + resolved "https://registry.yarnpkg.com/@react-aria/ssr/-/ssr-3.9.4.tgz#9da8b10342c156e816dbfa4c9e713b21f274d7ab" + integrity sha512-4jmAigVq409qcJvQyuorsmBR4+9r3+JEC60wC+Y0MZV0HCtTmm8D9guYXlJMdx0SSkgj0hHAyFm/HvPNFofCoQ== dependencies: - "@swc/helpers" "^0.4.14" + "@swc/helpers" "^0.5.0" -"@remix-run/router@1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.3.2.tgz#58cd2bd25df2acc16c628e1b6f6150ea6c7455bc" - integrity sha512-t54ONhl/h75X94SWsHGQ4G/ZrCEguKSRQr7DrjTciJXW0YU1QhlwYeycvK5JgkzlxmvrK7wq1NB/PLtHxoiDcA== +"@remix-run/router@1.17.1": + version "1.17.1" + resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.17.1.tgz#bf93997beb81863fde042ebd05013a2618471362" + integrity sha512-mCOMec4BKd6BRGBZeSnGiIgwsbLGp3yhVqAD8H+PxiRNEHgDpZb8J1TnrSDlg97t0ySKMQJTHCWBCmBpSmkF6Q== -"@restart/hooks@^0.4.6", "@restart/hooks@^0.4.7": - version "0.4.7" - resolved "https://registry.yarnpkg.com/@restart/hooks/-/hooks-0.4.7.tgz#d79ca6472c01ce04389fc73d4a79af1b5e33cd39" - integrity sha512-ZbjlEHcG+FQtpDPHd7i4FzNNvJf2enAwZfJbpM8CW7BhmOAbsHpZe3tsHwfQUrBuyrxWqPYp2x5UMnilWcY22A== +"@restart/hooks@^0.4.9": + version "0.4.16" + resolved "https://registry.yarnpkg.com/@restart/hooks/-/hooks-0.4.16.tgz#95ae8ac1cc7e2bd4fed5e39800ff85604c6d59fb" + integrity sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w== dependencies: - dequal "^2.0.2" + dequal "^2.0.3" -"@restart/ui@^1.4.1": - version "1.4.1" - resolved "https://registry.yarnpkg.com/@restart/ui/-/ui-1.4.1.tgz#c9057915f0708c411824eeb16c03d0108c0208d2" - integrity sha512-J7wFOx2DcmkBqCqiZgDsggLO7faiNh4Nv1/v80FmbRgP+MYpwaVDKKXLC69DA4+ejgNIsBP5ORtC74EZqO1j8A== +"@restart/ui@^1.6.9": + version "1.6.9" + resolved "https://registry.yarnpkg.com/@restart/ui/-/ui-1.6.9.tgz#05ec905a56486fa39b62f29c09b3917e57acd62f" + integrity sha512-mUbygUsJcRurjZCt1f77gg4DpheD1D+Sc7J3JjAkysUj7t8m4EBJVOqWC9788Qtbc69cJ+HlJc6jBguKwS8Mcw== dependencies: - "@babel/runtime" "^7.18.3" - "@popperjs/core" "^2.11.5" - "@react-aria/ssr" "^3.2.0" - "@restart/hooks" "^0.4.7" + "@babel/runtime" "^7.21.0" + "@popperjs/core" "^2.11.6" + "@react-aria/ssr" "^3.5.0" + "@restart/hooks" "^0.4.9" "@types/warning" "^3.0.0" - dequal "^2.0.2" + dequal "^2.0.3" dom-helpers "^5.2.0" - uncontrollable "^7.2.1" + uncontrollable "^8.0.1" warning "^4.0.3" "@sentry/core@6.19.7": @@ -2575,22 +3341,10 @@ "@sentry/types" "6.19.7" tslib "^1.9.3" -"@sinclair/typebox@^0.24.1": - version "0.24.51" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.51.tgz#645f33fe4e02defe26f2f5c0410e1c094eac7f5f" - integrity sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA== - -"@sinclair/typebox@^0.25.16": - version "0.25.23" - resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.23.tgz#1c15b0d2b872d89cc0f47c7243eacb447df8b8bd" - integrity sha512-VEB8ygeP42CFLWyAJhN5OklpxUliqdNEUcXb4xZ/CINqtYGTjL5ukluKdKzQ0iWdUxyQ7B0539PAUhHKrCNWSQ== - -"@sinonjs/commons@^1.7.0": - version "1.8.6" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.6.tgz#80c516a4dc264c2a69115e7578d62581ff455ed9" - integrity sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ== - dependencies: - type-detect "4.0.8" +"@sinclair/typebox@^0.27.8": + version "0.27.8" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" + integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== "@sinonjs/commons@^2.0.0": version "2.0.0" @@ -2606,13 +3360,6 @@ dependencies: "@sinonjs/commons" "^2.0.0" -"@sinonjs/fake-timers@^9.1.2": - version "9.1.2" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz#4eaab737fab77332ab132d396a3c0d364bd0ea8c" - integrity sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw== - dependencies: - "@sinonjs/commons" "^1.7.0" - "@storybook/addon-a11y@^6.5.16": version "6.5.16" resolved "https://registry.yarnpkg.com/@storybook/addon-a11y/-/addon-a11y-6.5.16.tgz#9288a6c1d111fa4ec501d213100ffff91757d3fc" @@ -2696,24 +3443,7 @@ regenerator-runtime "^0.13.7" ts-dedent "^2.0.0" -"@storybook/addons@6.5.12": - version "6.5.12" - resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.5.12.tgz#891767b5f88ea99b956cf19e9e2893594068adc7" - integrity sha512-y3cgxZq41YGnuIlBJEuJjSFdMsm8wnvlNOGUP9Q+Er2dgfx8rJz4Q22o4hPjpvpaj4XdBtxCJXI2NeFpN59+Cw== - dependencies: - "@storybook/api" "6.5.12" - "@storybook/channels" "6.5.12" - "@storybook/client-logger" "6.5.12" - "@storybook/core-events" "6.5.12" - "@storybook/csf" "0.0.2--canary.4566f4d.1" - "@storybook/router" "6.5.12" - "@storybook/theming" "6.5.12" - "@types/webpack-env" "^1.16.0" - core-js "^3.8.2" - global "^4.4.0" - regenerator-runtime "^0.13.7" - -"@storybook/addons@6.5.16", "@storybook/addons@^6.5.16": +"@storybook/addons@6.5.16", "@storybook/addons@^6.5.16", "@storybook/addons@~6.5.12": version "6.5.16" resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.5.16.tgz#07e8f2205f86fa4c9dada719e3e096cb468e3cdd" integrity sha512-p3DqQi+8QRL5k7jXhXmJZLsE/GqHqyY6PcoA1oNTJr0try48uhTGUOYkgzmqtDaa/qPFO5LP+xCPzZXckGtquQ== @@ -2730,29 +3460,6 @@ global "^4.4.0" regenerator-runtime "^0.13.7" -"@storybook/api@6.5.12": - version "6.5.12" - resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.5.12.tgz#7cc82087fc9298be03f15bf4ab9c4aab294b3bac" - integrity sha512-DuUZmMlQxkFNU9Vgkp9aNfCkAongU76VVmygvCuSpMVDI9HQ2lG0ydL+ppL4XKoSMCCoXTY6+rg4hJANnH+1AQ== - dependencies: - "@storybook/channels" "6.5.12" - "@storybook/client-logger" "6.5.12" - "@storybook/core-events" "6.5.12" - "@storybook/csf" "0.0.2--canary.4566f4d.1" - "@storybook/router" "6.5.12" - "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.5.12" - core-js "^3.8.2" - fast-deep-equal "^3.1.3" - global "^4.4.0" - lodash "^4.17.21" - memoizerific "^1.11.3" - regenerator-runtime "^0.13.7" - store2 "^2.12.0" - telejson "^6.0.8" - ts-dedent "^2.0.0" - util-deprecate "^1.0.2" - "@storybook/api@6.5.16": version "6.5.16" resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.5.16.tgz#897915b76de05587fd702951d5d836f708043662" @@ -2897,15 +3604,6 @@ global "^4.4.0" telejson "^6.0.8" -"@storybook/channels@6.5.12": - version "6.5.12" - resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-6.5.12.tgz#98baf01691d263e2ac341853361ec69c1a6621bc" - integrity sha512-X5XaKbe4b7LXJ4sUakBo00x6pXnW78JkOonHoaKoWsccHLlEzwfBZpVVekhVZnqtCoLT23dB8wjKgA71RYWoiw== - dependencies: - core-js "^3.8.2" - ts-dedent "^2.0.0" - util-deprecate "^1.0.2" - "@storybook/channels@6.5.16": version "6.5.16" resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-6.5.16.tgz#3fb9a3b5666ecb951a2d0cf8b0699b084ef2d3c6" @@ -2941,14 +3639,6 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/client-logger@6.5.12": - version "6.5.12" - resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-6.5.12.tgz#d9809e13dc7939eb61452a5e94b1ccb61c4a022c" - integrity sha512-IrkMr5KZcudX935/C2balFbxLHhkvQnJ78rbVThHDVckQ7l3oIXTh66IMzldeOabVFDZEMiW8AWuGEYof+JtLw== - dependencies: - core-js "^3.8.2" - global "^4.4.0" - "@storybook/client-logger@6.5.16": version "6.5.16" resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-6.5.16.tgz#955cc46b389e7151c9eb1585a75e6a0605af61a1" @@ -2957,21 +3647,7 @@ core-js "^3.8.2" global "^4.4.0" -"@storybook/components@6.5.12": - version "6.5.12" - resolved "https://registry.yarnpkg.com/@storybook/components/-/components-6.5.12.tgz#e137f0683ea92e22de116bfa62cfd65ce4efe01d" - integrity sha512-NAAGl5PDXaHdVLd6hA+ttmLwH3zAVGXeUmEubzKZ9bJzb+duhFKxDa9blM4YEkI+palumvgAMm0UgS7ou680Ig== - dependencies: - "@storybook/client-logger" "6.5.12" - "@storybook/csf" "0.0.2--canary.4566f4d.1" - "@storybook/theming" "6.5.12" - core-js "^3.8.2" - memoizerific "^1.11.3" - qs "^6.10.0" - regenerator-runtime "^0.13.7" - util-deprecate "^1.0.2" - -"@storybook/components@6.5.16": +"@storybook/components@6.5.16", "@storybook/components@~6.5.12": version "6.5.16" resolved "https://registry.yarnpkg.com/@storybook/components/-/components-6.5.16.tgz#f8dc51213bc08fe32154be964e1e8b0e2f670ed6" integrity sha512-LzBOFJKITLtDcbW9jXl0/PaG+4xAz25PK8JxPZpIALbmOpYWOAPcO6V9C2heX6e6NgWFMUxjplkULEk9RCQMNA== @@ -3067,13 +3743,6 @@ util-deprecate "^1.0.2" webpack "4" -"@storybook/core-events@6.5.12": - version "6.5.12" - resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.5.12.tgz#28bd727cc4216012409bfac412fcb708346c56bc" - integrity sha512-0AMyMM19R/lHsYRfWqM8zZTXthasTAK2ExkSRzYi2GkIaVMxRKtM33YRwxKIpJ6KmIKIs8Ru3QCXu1mfCmGzNg== - dependencies: - core-js "^3.8.2" - "@storybook/core-events@6.5.16": version "6.5.16" resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.5.16.tgz#b1c265dac755007dae172d9d4b72656c9e5d7bb3" @@ -3363,17 +4032,6 @@ util-deprecate "^1.0.2" webpack ">=4.43.0 <6.0.0" -"@storybook/router@6.5.12": - version "6.5.12" - resolved "https://registry.yarnpkg.com/@storybook/router/-/router-6.5.12.tgz#58efbc1f2f301c8584802af1c710b2f6f03f948c" - integrity sha512-xHubde9YnBbpkDY5+zGO4Pr6VPxP8H9J2v4OTF3H82uaxCIKR0PKG0utS9pFKIsEiP3aM62Hb9qB8nU+v1nj3w== - dependencies: - "@storybook/client-logger" "6.5.12" - core-js "^3.8.2" - memoizerific "^1.11.3" - qs "^6.10.0" - regenerator-runtime "^0.13.7" - "@storybook/router@6.5.16": version "6.5.16" resolved "https://registry.yarnpkg.com/@storybook/router/-/router-6.5.16.tgz#28fb4d34e8219351a40bee1fc94dcacda6e1bd8b" @@ -3432,16 +4090,6 @@ read-pkg-up "^7.0.1" regenerator-runtime "^0.13.7" -"@storybook/theming@6.5.12": - version "6.5.12" - resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.5.12.tgz#7df1b52913d49c5e84fc1f2e837c02d9fa8cc639" - integrity sha512-uWOo84qMQ2R6c1C0faZ4Q0nY01uNaX7nXoJKieoiJ6ZqY9PSYxJl1kZLi3uPYnrxLZjzjVyXX8MgdxzbppYItA== - dependencies: - "@storybook/client-logger" "6.5.12" - core-js "^3.8.2" - memoizerific "^1.11.3" - regenerator-runtime "^0.13.7" - "@storybook/theming@6.5.16": version "6.5.16" resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.5.16.tgz#b999bdb98945b605b93b9dfdf7408535b701e2aa" @@ -3472,69 +4120,47 @@ regenerator-runtime "^0.13.7" resolve-from "^5.0.0" -"@swc/helpers@^0.4.14": - version "0.4.14" - resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.14.tgz#1352ac6d95e3617ccb7c1498ff019654f1e12a74" - integrity sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw== - dependencies: - tslib "^2.4.0" - -"@testing-library/dom@^9.0.0": - version "9.0.0" - resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-9.0.0.tgz#cc50e8df2a7dccff95555102beebbae60e95e95e" - integrity sha512-+/TLgKNFsYUshOY/zXsQOk+PlFQK+eyJ9T13IDVNJEi+M+Un7xlJK+FZKkbGSnf0+7E1G6PlDhkSYQ/GFiruBQ== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/runtime" "^7.12.5" - "@types/aria-query" "^5.0.1" - aria-query "^5.0.0" - chalk "^4.1.0" - dom-accessibility-api "^0.5.9" - lz-string "^1.4.4" - pretty-format "^27.0.2" +"@swc/helpers@^0.5.0": + version "0.5.11" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.11.tgz#5bab8c660a6e23c13b2d23fcd1ee44a2db1b0cb7" + integrity sha512-YNlnKRWF2sVojTpIyzwou9XoTNbzbzONwRhOoniEioF1AtaitTvVZblaQRrAzChWQ1bLYyYSWzM18y4WwgzJ+A== + dependencies: + tslib "^2.4.0" -"@testing-library/dom@^9.0.1": - version "9.0.1" - resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-9.0.1.tgz#fb9e3837fe2a662965df1536988f0863f01dbf51" - integrity sha512-fTOVsMY9QLFCCXRHG3Ese6cMH5qIWwSbgxZsgeF5TNsy81HKaZ4kgehnSF8FsR3OF+numlIV2YcU79MzbnhSig== +"@testing-library/dom@^10.3.1": + version "10.3.1" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-10.3.1.tgz#c960204cce7e969ac03ae5f3550e420226c61a21" + integrity sha512-q/WL+vlXMpC0uXDyfsMtc1rmotzLV8Y0gq6q1gfrrDjQeHoeLrqHbxdPvPNAh1i+xuJl7+BezywcXArz7vLqKQ== dependencies: "@babel/code-frame" "^7.10.4" "@babel/runtime" "^7.12.5" "@types/aria-query" "^5.0.1" - aria-query "^5.0.0" + aria-query "5.3.0" chalk "^4.1.0" dom-accessibility-api "^0.5.9" lz-string "^1.5.0" pretty-format "^27.0.2" -"@testing-library/jest-dom@^5.16.5": - version "5.16.5" - resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz#3912846af19a29b2dbf32a6ae9c31ef52580074e" - integrity sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA== +"@testing-library/jest-dom@^6.4.6": + version "6.4.6" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-6.4.6.tgz#ec1df8108651bed5475534955565bed88c6732ce" + integrity sha512-8qpnGVincVDLEcQXWaHOf6zmlbwTKc6Us6PPu4CRnPXCzo2OGBS5cwgMMOWdxDpEz1mkbvXHpEy99M5Yvt682w== dependencies: - "@adobe/css-tools" "^4.0.1" + "@adobe/css-tools" "^4.4.0" "@babel/runtime" "^7.9.2" - "@types/testing-library__jest-dom" "^5.9.1" aria-query "^5.0.0" chalk "^3.0.0" css.escape "^1.5.1" - dom-accessibility-api "^0.5.6" - lodash "^4.17.15" + dom-accessibility-api "^0.6.3" + lodash "^4.17.21" redent "^3.0.0" -"@testing-library/react@^14.0.0": - version "14.0.0" - resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-14.0.0.tgz#59030392a6792450b9ab8e67aea5f3cc18d6347c" - integrity sha512-S04gSNJbYE30TlIMLTzv6QCTzt9AqIF5y6s6SzVFILNcNvbV/jU96GeiTPillGQo+Ny64M/5PV7klNYYgv5Dfg== +"@testing-library/react@^16.0.0": + version "16.0.0" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-16.0.0.tgz#0a1e0c7a3de25841c3591b8cb7fb0cf0c0a27321" + integrity sha512-guuxUKRWQ+FgNX0h0NS0FIq3Q3uLtWVpBzcLOggmfMoUpgBnzBzvLLd4fbm6yS8ydJd94cIfY4yP9qUQjM2KwQ== dependencies: "@babel/runtime" "^7.12.5" - "@testing-library/dom" "^9.0.0" - "@types/react-dom" "^18.0.0" - -"@testing-library/user-event@^14.4.3": - version "14.4.3" - resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-14.4.3.tgz#af975e367743fa91989cd666666aec31a8f50591" - integrity sha512-kCUc5MEwaEMakkO5x7aoD+DLi02ehmEM2QCGWvNqAS1dV/fAvORWEjnjsEIvml59M7Y5kCkWN6fCCyPOe8OL6Q== "@tootallnate/once@2": version "2.0.0" @@ -3633,10 +4259,10 @@ resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080" integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw== -"@types/debug@^4.1.7": - version "4.1.7" - resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.7.tgz#7cc0ea761509124709b8b2d1090d8f6c17aadb82" - integrity sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg== +"@types/debug@^4.1.8": + version "4.1.12" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917" + integrity sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ== dependencies: "@types/ms" "*" @@ -3666,6 +4292,11 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== +"@types/estree@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" + integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== + "@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18", "@types/express-serve-static-core@^4.17.31": version "4.17.32" resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.32.tgz#93dda387f5516af616d8d3f05f2c4c79d81e1b82" @@ -3684,6 +4315,16 @@ "@types/qs" "*" "@types/range-parser" "*" +"@types/express-serve-static-core@^4.17.33": + version "4.19.5" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz#218064e321126fcf9048d1ca25dd2465da55d9c6" + integrity sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + "@types/send" "*" + "@types/express@*", "@types/express@^4.17.13": version "4.17.15" resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.15.tgz#9290e983ec8b054b65a5abccb610411953d417ff" @@ -3704,6 +4345,16 @@ "@types/qs" "*" "@types/serve-static" "*" +"@types/express@^4.17.21": + version "4.17.21" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" + integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.33" + "@types/qs" "*" + "@types/serve-static" "*" + "@types/glob@*": version "8.0.0" resolved "https://registry.yarnpkg.com/@types/glob/-/glob-8.0.0.tgz#321607e9cbaec54f687a0792b2d1d370739455d2" @@ -3783,14 +4434,6 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/jest@*": - version "29.2.5" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.2.5.tgz#c27f41a9d6253f288d1910d3c5f09484a56b73c0" - integrity sha512-H2cSxkKgVmqNHXP7TC2L/WUorrZu8ZigyRywfVzv6EyBlxj39n4C00hjXYQWsbwqgElaj/CiAeSRmk5GoaKTgw== - dependencies: - expect "^29.0.0" - pretty-format "^29.0.0" - "@types/jsdom@^20.0.0": version "20.0.1" resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-20.0.1.tgz#07c14bc19bd2f918c1929541cdaacae894744808" @@ -3827,6 +4470,11 @@ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== +"@types/mime@^1": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.5.tgz#1ef302e01cf7d2b5a0fa526790c9123bf1d06690" + integrity sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w== + "@types/minimatch@*": version "5.1.2" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" @@ -3860,6 +4508,13 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.11.tgz#cbb15c12ca7c16c85a72b6bdc4d4b01151bb3cae" integrity sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA== +"@types/node@^20.10.6": + version "20.14.10" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.10.tgz#a1a218290f1b6428682e3af044785e5874db469a" + integrity sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ== + dependencies: + undici-types "~5.26.4" + "@types/normalize-package-data@^2.4.0": version "2.4.1" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" @@ -3880,20 +4535,6 @@ resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109" integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== -"@types/pg@^8.6.5": - version "8.6.6" - resolved "https://registry.yarnpkg.com/@types/pg/-/pg-8.6.6.tgz#21cdf873a3e345a6e78f394677e3b3b1b543cb80" - integrity sha512-O2xNmXebtwVekJDD+02udOncjVcMZQuTEQEMpKJ0ZRf5E7/9JJX3izhKUcUifBkyKpljyUM6BTgy2trmviKlpw== - dependencies: - "@types/node" "*" - pg-protocol "*" - pg-types "^2.2.0" - -"@types/prettier@^2.1.5": - version "2.7.2" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.2.tgz#6c2324641cc4ba050a8c710b2b251b377581fbf0" - integrity sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg== - "@types/pretty-hrtime@^1.0.0": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/pretty-hrtime/-/pretty-hrtime-1.0.1.tgz#72a26101dc567b0d68fd956cf42314556e42d601" @@ -3914,17 +4555,10 @@ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== -"@types/react-dom@^18.0.0": - version "18.0.11" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.11.tgz#321351c1459bc9ca3d216aefc8a167beec334e33" - integrity sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw== - dependencies: - "@types/react" "*" - -"@types/react-transition-group@^4.4.4": - version "4.4.5" - resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.5.tgz#aae20dcf773c5aa275d5b9f7cdbca638abc5e416" - integrity sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA== +"@types/react-transition-group@^4.4.6": + version "4.4.10" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.10.tgz#6ee71127bdab1f18f11ad8fb3322c6da27c327ac" + integrity sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q== dependencies: "@types/react" "*" @@ -3952,6 +4586,14 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== +"@types/send@*": + version "0.17.4" + resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" + integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA== + dependencies: + "@types/mime" "^1" + "@types/node" "*" + "@types/serve-index@^1.9.1": version "1.9.1" resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" @@ -3994,13 +4636,6 @@ resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.8.tgz#b94a4391c85666c7b73299fd3ad79d4faa435310" integrity sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ== -"@types/testing-library__jest-dom@^5.9.1": - version "5.14.5" - resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.5.tgz#d113709c90b3c75fdb127ec338dad7d5f86c974f" - integrity sha512-SBwbxYoyPIvxHbeHxTZX2Pe/74F/tX2/D3mMvzabdeJ25bBojfW0TyB8BHrbq/9zaaKICJZjLP+8r6AeZMFCuQ== - dependencies: - "@types/jest" "*" - "@types/tough-cookie@*": version "4.0.2" resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.2.tgz#6286b4c7228d58ab7866d19716f3696e03a09397" @@ -4018,10 +4653,10 @@ resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== -"@types/validator@^13.7.1": - version "13.7.12" - resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.7.12.tgz#a285379b432cc8d103b69d223cbb159a253cf2f7" - integrity sha512-YVtyAPqpefU+Mm/qqnOANW6IkqKpCSrarcyV269C8MA8Ux0dbkEuQwM/4CjL47kVEM2LgBef/ETfkH+c6+moFA== +"@types/validator@^13.7.17": + version "13.12.0" + resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.12.0.tgz#1fe4c3ae9de5cf5193ce64717c99ef2fa7d8756f" + integrity sha512-nH45Lk7oPIJ1RVOF6JgFI6Dy0QpHEzq4QecZhvguxYPDwT8c93prCMqAtiIttm39voZ+DDR+qkNnMpJmMBRqag== "@types/warning@^3.0.0": version "3.0.0" @@ -4054,10 +4689,10 @@ anymatch "^3.0.0" source-map "^0.6.0" -"@types/ws@^8.5.1": - version "8.5.4" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.4.tgz#bb10e36116d6e570dd943735f86c933c1587b8a5" - integrity sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg== +"@types/ws@^8.5.5": + version "8.5.10" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.10.tgz#4acfb517970853fa6574a3a6886791d04a396787" + integrity sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A== dependencies: "@types/node" "*" @@ -4140,6 +4775,11 @@ resolved "https://registry.yarnpkg.com/@tyriar/fibonacci-heap/-/fibonacci-heap-2.0.9.tgz#df3dcbdb1b9182168601f6318366157ee16666e9" integrity sha512-bYuSNomfn4hu2tPiDN+JZtnzCpSpbJ/PNeulmocDy3xN2X5OkJL65zo6rPZp65cPPhLF9vfT/dgE+RtFRCSxOA== +"@ungap/structured-clone@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" + integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== + "@webassemblyjs/ast@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" @@ -4148,6 +4788,14 @@ "@webassemblyjs/helper-numbers" "1.11.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.1" +"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" + integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ast@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" @@ -4162,6 +4810,11 @@ resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== +"@webassemblyjs/floating-point-hex-parser@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" + integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== + "@webassemblyjs/floating-point-hex-parser@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4" @@ -4172,6 +4825,11 @@ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== +"@webassemblyjs/helper-api-error@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" + integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== + "@webassemblyjs/helper-api-error@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2" @@ -4182,6 +4840,11 @@ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== +"@webassemblyjs/helper-buffer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" + integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== + "@webassemblyjs/helper-buffer@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00" @@ -4215,11 +4878,25 @@ "@webassemblyjs/helper-api-error" "1.11.1" "@xtuc/long" "4.2.2" +"@webassemblyjs/helper-numbers@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" + integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.6" + "@webassemblyjs/helper-api-error" "1.11.6" + "@xtuc/long" "4.2.2" + "@webassemblyjs/helper-wasm-bytecode@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== +"@webassemblyjs/helper-wasm-bytecode@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" + integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== + "@webassemblyjs/helper-wasm-bytecode@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790" @@ -4235,6 +4912,16 @@ "@webassemblyjs/helper-wasm-bytecode" "1.11.1" "@webassemblyjs/wasm-gen" "1.11.1" +"@webassemblyjs/helper-wasm-section@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" + integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/helper-wasm-section@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346" @@ -4252,6 +4939,13 @@ dependencies: "@xtuc/ieee754" "^1.2.0" +"@webassemblyjs/ieee754@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" + integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== + dependencies: + "@xtuc/ieee754" "^1.2.0" + "@webassemblyjs/ieee754@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4" @@ -4266,6 +4960,13 @@ dependencies: "@xtuc/long" "4.2.2" +"@webassemblyjs/leb128@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" + integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== + dependencies: + "@xtuc/long" "4.2.2" + "@webassemblyjs/leb128@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95" @@ -4278,6 +4979,11 @@ resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== +"@webassemblyjs/utf8@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" + integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== + "@webassemblyjs/utf8@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab" @@ -4311,6 +5017,20 @@ "@webassemblyjs/wasm-parser" "1.9.0" "@webassemblyjs/wast-printer" "1.9.0" +"@webassemblyjs/wasm-edit@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" + integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/helper-wasm-section" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-opt" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + "@webassemblyjs/wast-printer" "1.12.1" + "@webassemblyjs/wasm-gen@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" @@ -4322,6 +5042,17 @@ "@webassemblyjs/leb128" "1.11.1" "@webassemblyjs/utf8" "1.11.1" +"@webassemblyjs/wasm-gen@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" + integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + "@webassemblyjs/wasm-gen@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c" @@ -4343,6 +5074,16 @@ "@webassemblyjs/wasm-gen" "1.11.1" "@webassemblyjs/wasm-parser" "1.11.1" +"@webassemblyjs/wasm-opt@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" + integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + "@webassemblyjs/wasm-opt@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61" @@ -4365,6 +5106,18 @@ "@webassemblyjs/leb128" "1.11.1" "@webassemblyjs/utf8" "1.11.1" +"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" + integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-api-error" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + "@webassemblyjs/wasm-parser@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e" @@ -4397,6 +5150,14 @@ "@webassemblyjs/ast" "1.11.1" "@xtuc/long" "4.2.2" +"@webassemblyjs/wast-printer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" + integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@xtuc/long" "4.2.2" + "@webassemblyjs/wast-printer@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899" @@ -4406,20 +5167,27 @@ "@webassemblyjs/wast-parser" "1.9.0" "@xtuc/long" "4.2.2" -"@webpack-cli/configtest@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.0.1.tgz#a69720f6c9bad6aef54a8fa6ba9c3533e7ef4c7f" - integrity sha512-njsdJXJSiS2iNbQVS0eT8A/KPnmyH4pv1APj2K0d1wrZcBLw+yppxOy4CGqa0OxDJkzfL/XELDhD8rocnIwB5A== +"@webpack-cli/configtest@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.1.1.tgz#3b2f852e91dac6e3b85fb2a314fb8bef46d94646" + integrity sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw== -"@webpack-cli/info@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.1.tgz#eed745799c910d20081e06e5177c2b2569f166c0" - integrity sha512-fE1UEWTwsAxRhrJNikE7v4EotYflkEhBL7EbajfkPlf6E37/2QshOy/D48Mw8G5XMFlQtS6YV42vtbG9zBpIQA== +"@webpack-cli/info@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.2.tgz#cc3fbf22efeb88ff62310cf885c5b09f44ae0fdd" + integrity sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A== -"@webpack-cli/serve@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.1.tgz#34bdc31727a1889198855913db2f270ace6d7bf8" - integrity sha512-0G7tNyS+yW8TdgHwZKlDWYXFA6OJQnoLCQvYKkQP0Q2X205PSQ6RNUj0M+1OB/9gRQaUZ/ccYfaxd0nhaWKfjw== +"@webpack-cli/serve@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e" + integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ== + +"@wry/caches@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@wry/caches/-/caches-1.0.1.tgz#8641fd3b6e09230b86ce8b93558d44cf1ece7e52" + integrity sha512-bXuaUNLVVkD20wcGBWRyo7j9N3TxePEWFZj2Y+r9OoUzfqmavM84+mFykRicNsBqatba5JLay1t48wxaXaWnlA== + dependencies: + tslib "^2.3.0" "@wry/context@^0.7.0": version "0.7.0" @@ -4428,17 +5196,24 @@ dependencies: tslib "^2.3.0" -"@wry/equality@^0.5.0": - version "0.5.3" - resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.5.3.tgz#fafebc69561aa2d40340da89fa7dc4b1f6fb7831" - integrity sha512-avR+UXdSrsF2v8vIqIgmeTY0UR91UT+IyablCyKe/uk22uOJ8fusKZnH9JH9e1/EtLeNJBtagNmL3eJdnOV53g== +"@wry/equality@^0.5.6": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@wry/equality/-/equality-0.5.7.tgz#72ec1a73760943d439d56b7b1e9985aec5d497bb" + integrity sha512-BRFORjsTuQv5gxcXsuDXx6oGRhuVsEGwZy6LOzRRfgu+eSfxbhUQ9L9YtSEIuIjY/o7g3iWFjrc5eSY1GXP2Dw== dependencies: tslib "^2.3.0" -"@wry/trie@^0.3.0": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@wry/trie/-/trie-0.3.2.tgz#a06f235dc184bd26396ba456711f69f8c35097e6" - integrity sha512-yRTyhWSls2OY/pYLfwff867r8ekooZ4UI+/gxot5Wj8EFwSf2rG+n+Mo/6LoLQm1TKA4GRj2+LCpbfS937dClQ== +"@wry/trie@^0.4.3": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@wry/trie/-/trie-0.4.3.tgz#077d52c22365871bf3ffcbab8e95cb8bc5689af4" + integrity sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w== + dependencies: + tslib "^2.3.0" + +"@wry/trie@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@wry/trie/-/trie-0.5.0.tgz#11e783f3a53f6e4cd1d42d2d1323f5bc3fa99c94" + integrity sha512-FNoYzHawTMk/6KMQoEG5O4PuioX19UbwdQKF44yw0nLfOypfQdjtfZzo/UIJWAJ23sNIFbD1Ug9lbaDGMwbqQA== dependencies: tslib "^2.3.0" @@ -4467,7 +5242,7 @@ abbrev@1, abbrev@^1.0.0: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -accepts@^1.3.5, accepts@^1.3.7, accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7, accepts@~1.3.8: +accepts@^1.3.5, accepts@^1.3.7, accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== @@ -4496,6 +5271,11 @@ acorn-import-assertions@^1.7.6: resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== +acorn-import-attributes@^1.9.5: + version "1.9.5" + resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" + integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== + acorn-jsx@^5.3.1, acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -4531,7 +5311,7 @@ acorn@^7.4.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.1.0, acorn@^8.5.0, acorn@^8.7.1, acorn@^8.8.0, acorn@^8.8.1: +acorn@^8.1.0, acorn@^8.5.0, acorn@^8.7.1, acorn@^8.8.1: version "8.8.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73" integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== @@ -4541,6 +5321,11 @@ acorn@^8.8.2: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== +acorn@^8.9.0: + version "8.12.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" + integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== + address@^1.0.1: version "1.2.2" resolved "https://registry.yarnpkg.com/address/-/address-1.2.2.tgz#2b5248dac5485a6390532c6a517fda2e3faac89e" @@ -4637,7 +5422,7 @@ ajv-keywords@^5.0.0: dependencies: fast-deep-equal "^3.1.3" -ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: +ajv@^6.1.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -4711,6 +5496,11 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -4730,6 +5520,11 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + ansi-to-html@^0.6.11: version "0.6.15" resolved "https://registry.yarnpkg.com/ansi-to-html/-/ansi-to-html-0.6.15.tgz#ac6ad4798a00f6aa045535d7f6a9cb9294eebea7" @@ -4766,17 +5561,17 @@ apollo-datasource@^3.3.2: "@apollo/utils.keyvaluecache" "^1.0.1" apollo-server-env "^4.2.1" -apollo-reporting-protobuf@^3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/apollo-reporting-protobuf/-/apollo-reporting-protobuf-3.3.3.tgz#df2b7ff73422cd682af3f1805d32301aefdd9e89" - integrity sha512-L3+DdClhLMaRZWVmMbBcwl4Ic77CnEBPXLW53F7hkYhkaZD88ivbCVB1w/x5gunO6ZHrdzhjq0FHmTsBvPo7aQ== +apollo-reporting-protobuf@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/apollo-reporting-protobuf/-/apollo-reporting-protobuf-3.4.0.tgz#6edd31f09d4a3704d9e808d1db30eca2229ded26" + integrity sha512-h0u3EbC/9RpihWOmcSsvTW2O6RXVaD/mPEjfrPkxRPTEPWqncsgOoRJw+wih4OqfH3PvTJvoEIf4LwKrUaqWog== dependencies: "@apollo/protobufjs" "1.2.6" -apollo-server-core@^3.11.1, apollo-server-core@^3.6.7: - version "3.11.1" - resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-3.11.1.tgz#89d83aeaa71a59f760ebfa35bb0cbd31e15474ca" - integrity sha512-t/eCKrRFK1lYZlc5pHD99iG7Np7CEm3SmbDiONA7fckR3EaB/pdsEdIkIwQ5QBBpT5JLp/nwvrZRVwhaWmaRvw== +apollo-server-core@^3.13.0: + version "3.13.0" + resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-3.13.0.tgz#ad6601fbb34cc97eedca27a9fb0b5738d11cd27d" + integrity sha512-v/g6DR6KuHn9DYSdtQijz8dLOkP78I5JSVJzPkARhDbhpH74QNwrQ2PP2URAPPEDJ2EeZNQDX8PvbYkAKqg+kg== dependencies: "@apollo/utils.keyvaluecache" "^1.0.1" "@apollo/utils.logger" "^1.0.0" @@ -4787,11 +5582,11 @@ apollo-server-core@^3.11.1, apollo-server-core@^3.6.7: "@graphql-tools/schema" "^8.0.0" "@josephg/resolvable" "^1.0.0" apollo-datasource "^3.3.2" - apollo-reporting-protobuf "^3.3.3" + apollo-reporting-protobuf "^3.4.0" apollo-server-env "^4.2.1" apollo-server-errors "^3.3.1" - apollo-server-plugin-base "^3.7.1" - apollo-server-types "^3.7.1" + apollo-server-plugin-base "^3.7.2" + apollo-server-types "^3.8.0" async-retry "^1.2.1" fast-json-stable-stringify "^2.1.0" graphql-tag "^2.11.0" @@ -4814,10 +5609,10 @@ apollo-server-errors@^3.3.1: resolved "https://registry.yarnpkg.com/apollo-server-errors/-/apollo-server-errors-3.3.1.tgz#ba5c00cdaa33d4cbd09779f8cb6f47475d1cd655" integrity sha512-xnZJ5QWs6FixHICXHxUfm+ZWqqxrNuPlQ+kj5m6RtEgIpekOPssH/SD9gf2B4HuWV0QozorrygwZnux8POvyPA== -apollo-server-express@^3.11.1, apollo-server-express@^3.4.0: - version "3.11.1" - resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-3.11.1.tgz#f46d2f2f8db3d99ede6c0c144fea02f24b73cb78" - integrity sha512-x9ngcpXbBlt4naCXTwNtBFb/mOd9OU0wtFXvJkObHF26NsRazu3DxDfEuekA6V1NFOocD+A9jmVMQeQWug5MgA== +apollo-server-express@^3.13.0: + version "3.13.0" + resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-3.13.0.tgz#0d8d9bbba3b8b8264912d215f63fd44e74d5f42a" + integrity sha512-iSxICNbDUyebOuM8EKb3xOrpIwOQgKxGbR2diSr4HP3IW8T3njKFOoMce50vr+moOCe1ev8BnLcw9SNbuUtf7g== dependencies: "@types/accepts" "^1.3.5" "@types/body-parser" "1.19.2" @@ -4825,37 +5620,37 @@ apollo-server-express@^3.11.1, apollo-server-express@^3.4.0: "@types/express" "4.17.14" "@types/express-serve-static-core" "4.17.31" accepts "^1.3.5" - apollo-server-core "^3.11.1" - apollo-server-types "^3.7.1" + apollo-server-core "^3.13.0" + apollo-server-types "^3.8.0" body-parser "^1.19.0" cors "^2.8.5" parseurl "^1.3.3" -apollo-server-plugin-base@^3.7.1: - version "3.7.1" - resolved "https://registry.yarnpkg.com/apollo-server-plugin-base/-/apollo-server-plugin-base-3.7.1.tgz#aa78ef49bd114e35906ca9cf7493fed2664cbde8" - integrity sha512-g3vJStmQtQvjGI289UkLMfThmOEOddpVgHLHT2bNj0sCD/bbisj4xKbBHETqaURokteqSWyyd4RDTUe0wAUDNQ== +apollo-server-plugin-base@^3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/apollo-server-plugin-base/-/apollo-server-plugin-base-3.7.2.tgz#c19cd137bc4c993ba2490ba2b571b0f3ce60a0cd" + integrity sha512-wE8dwGDvBOGehSsPTRZ8P/33Jan6/PmL0y0aN/1Z5a5GcbFhDaaJCjK5cav6npbbGL2DPKK0r6MPXi3k3N45aw== dependencies: - apollo-server-types "^3.7.1" + apollo-server-types "^3.8.0" -apollo-server-types@^3.7.1: - version "3.7.1" - resolved "https://registry.yarnpkg.com/apollo-server-types/-/apollo-server-types-3.7.1.tgz#87adfcb52ec0893999a9cfafd5474bfda7ab0798" - integrity sha512-aE9RDVplmkaOj/OduNmGa+0a1B5RIWI0o3zC1zLvBTVWMKTpo0ifVf11TyMkLCY+T7cnZqVqwyShziOyC3FyUw== +apollo-server-types@^3.8.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/apollo-server-types/-/apollo-server-types-3.8.0.tgz#d976b6967878681f715fe2b9e4dad9ba86b1346f" + integrity sha512-ZI/8rTE4ww8BHktsVpb91Sdq7Cb71rdSkXELSwdSR0eXu600/sY+1UXhTWdiJvk+Eq5ljqoHLwLbY2+Clq2b9A== dependencies: "@apollo/utils.keyvaluecache" "^1.0.1" "@apollo/utils.logger" "^1.0.0" - apollo-reporting-protobuf "^3.3.3" + apollo-reporting-protobuf "^3.4.0" apollo-server-env "^4.2.1" -apollo-server@^3.4.0: - version "3.11.1" - resolved "https://registry.yarnpkg.com/apollo-server/-/apollo-server-3.11.1.tgz#831646081323aadf2cb53cdc3401786e41d44d81" - integrity sha512-3RZ/veWGbi0zXy2YVaPkYIAavpbHyEVui91DNYvz6UFS0fZmhJwG7f1VmGheeRiqiV8nFa8GuBejI1niTeAYzA== +apollo-server@^3.13.0: + version "3.13.0" + resolved "https://registry.yarnpkg.com/apollo-server/-/apollo-server-3.13.0.tgz#38d355756717c0cb519e7ab95bce6dcc8ce35677" + integrity sha512-hgT/MswNB5G1r+oBhggVX4Fjw53CFLqG15yB5sN+OrYkCVWF5YwPbJWHfSWa7699JMEXJGaoVfFzcvLZK0UlDg== dependencies: "@types/express" "4.17.14" - apollo-server-core "^3.11.1" - apollo-server-express "^3.11.1" + apollo-server-core "^3.13.0" + apollo-server-express "^3.13.0" express "^4.17.1" app-root-dir@^1.0.2: @@ -4893,6 +5688,13 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +aria-query@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" + integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== + dependencies: + dequal "^2.0.3" + aria-query@^5.0.0: version "5.1.3" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.1.3.tgz#19db27cd101152773631396f7a95a3b58c22c35e" @@ -4948,7 +5750,7 @@ array-flatten@^2.1.2: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== -array-includes@^3.0.3, array-includes@^3.1.5, array-includes@^3.1.6: +array-includes@^3.0.3, array-includes@^3.1.5: version "3.1.6" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f" integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw== @@ -4959,6 +5761,18 @@ array-includes@^3.0.3, array-includes@^3.1.5, array-includes@^3.1.6: get-intrinsic "^1.1.3" is-string "^1.0.7" +array-includes@^3.1.8: + version "3.1.8" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.8.tgz#5e370cbe172fdd5dd6530c1d4aadda25281ba97d" + integrity sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.4" + is-string "^1.0.7" + array-union@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" @@ -5002,6 +5816,18 @@ array.prototype.find@^2.1.1: es-abstract "^1.20.4" es-shim-unscopables "^1.0.0" +array.prototype.findlast@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz#3e4fbcb30a15a7f5bf64cf2faae22d139c2e4904" + integrity sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-shim-unscopables "^1.0.2" + array.prototype.flat@^1.2.1, array.prototype.flat@^1.2.3: version "1.3.1" resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2" @@ -5012,7 +5838,7 @@ array.prototype.flat@^1.2.1, array.prototype.flat@^1.2.3: es-abstract "^1.20.4" es-shim-unscopables "^1.0.0" -array.prototype.flatmap@^1.2.1, array.prototype.flatmap@^1.3.1: +array.prototype.flatmap@^1.2.1: version "1.3.1" resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183" integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ== @@ -5022,6 +5848,16 @@ array.prototype.flatmap@^1.2.1, array.prototype.flatmap@^1.3.1: es-abstract "^1.20.4" es-shim-unscopables "^1.0.0" +array.prototype.flatmap@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" + integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + array.prototype.map@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/array.prototype.map/-/array.prototype.map-1.0.5.tgz#6e43c2fee6c0fb5e4806da2dc92eb00970809e55" @@ -5055,16 +5891,26 @@ array.prototype.reduce@^1.0.6: es-array-method-boxes-properly "^1.0.0" is-string "^1.0.7" -array.prototype.tosorted@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz#ccf44738aa2b5ac56578ffda97c03fd3e23dd532" - integrity sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ== +array.prototype.toreversed@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz#b989a6bf35c4c5051e1dc0325151bf8088954eba" + integrity sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA== dependencies: call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.0" + es-abstract "^1.22.1" es-shim-unscopables "^1.0.0" - get-intrinsic "^1.1.3" + +array.prototype.tosorted@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz#fe954678ff53034e717ea3352a03f0b0b86f7ffc" + integrity sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.3" + es-errors "^1.3.0" + es-shim-unscopables "^1.0.2" arraybuffer.prototype.slice@^1.0.3: version "1.0.3" @@ -5236,15 +6082,15 @@ b4a@^1.6.4: resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.6.4.tgz#ef1c1422cae5ce6535ec191baeed7567443f36c9" integrity sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw== -babel-jest@^29.3.1, babel-jest@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.4.3.tgz#478b84d430972b277ad67dd631be94abea676792" - integrity sha512-o45Wyn32svZE+LnMVWv/Z4x0SwtLbh4FyGcYtR20kIWd+rdrDZ9Fzq8Ml3MYLD+mZvEdzCjZsCnYZ2jpJyQ+Nw== +babel-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" + integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== dependencies: - "@jest/transform" "^29.4.3" + "@jest/transform" "^29.7.0" "@types/babel__core" "^7.1.14" babel-plugin-istanbul "^6.1.1" - babel-preset-jest "^29.4.3" + babel-preset-jest "^29.6.3" chalk "^4.0.0" graceful-fs "^4.2.9" slash "^3.0.0" @@ -5259,12 +6105,12 @@ babel-loader@^8.0.0: make-dir "^3.1.0" schema-utils "^2.6.5" -babel-loader@^9.1.2: - version "9.1.2" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-9.1.2.tgz#a16a080de52d08854ee14570469905a5fc00d39c" - integrity sha512-mN14niXW43tddohGl8HPu5yfQq70iUThvFL/4QzESA7GcZoC0eVOhvWdQ8+3UlSjaDE9MVtsW9mxDY07W7VpVA== +babel-loader@^9.1.3: + version "9.1.3" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-9.1.3.tgz#3d0e01b4e69760cc694ee306fe16d358aa1c6f9a" + integrity sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw== dependencies: - find-cache-dir "^3.3.2" + find-cache-dir "^4.0.0" schema-utils "^4.0.0" babel-plugin-add-react-displayname@^0.0.5: @@ -5308,10 +6154,10 @@ babel-plugin-istanbul@^6.1.1: istanbul-lib-instrument "^5.0.4" test-exclude "^6.0.0" -babel-plugin-jest-hoist@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.4.3.tgz#ad1dfb5d31940957e00410ef7d9b2aa94b216101" - integrity sha512-mB6q2q3oahKphy5V7CpnNqZOCkxxZ9aokf1eh82Dy3jQmg4xvM1tGrh5y6BQUJh4a3Pj9+eLfwvAZ7VNKg7H8Q== +babel-plugin-jest-hoist@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" + integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== dependencies: "@babel/template" "^7.3.3" "@babel/types" "^7.3.3" @@ -5352,6 +6198,15 @@ babel-plugin-polyfill-corejs2@^0.3.3: "@babel/helper-define-polyfill-provider" "^0.3.3" semver "^6.1.1" +babel-plugin-polyfill-corejs2@^0.4.10: + version "0.4.11" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz#30320dfe3ffe1a336c15afdcdafd6fd615b25e33" + integrity sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q== + dependencies: + "@babel/compat-data" "^7.22.6" + "@babel/helper-define-polyfill-provider" "^0.6.2" + semver "^6.3.1" + babel-plugin-polyfill-corejs3@^0.1.0: version "0.1.7" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.1.7.tgz#80449d9d6f2274912e05d9e182b54816904befd0" @@ -5360,6 +6215,14 @@ babel-plugin-polyfill-corejs3@^0.1.0: "@babel/helper-define-polyfill-provider" "^0.1.5" core-js-compat "^3.8.1" +babel-plugin-polyfill-corejs3@^0.10.4: + version "0.10.4" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz#789ac82405ad664c20476d0233b485281deb9c77" + integrity sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.6.1" + core-js-compat "^3.36.1" + babel-plugin-polyfill-corejs3@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz#56ad88237137eade485a71b52f72dbed57c6230a" @@ -5375,6 +6238,13 @@ babel-plugin-polyfill-regenerator@^0.4.1: dependencies: "@babel/helper-define-polyfill-provider" "^0.3.3" +babel-plugin-polyfill-regenerator@^0.6.1: + version "0.6.2" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz#addc47e240edd1da1058ebda03021f382bba785e" + integrity sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.6.2" + babel-plugin-react-docgen@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/babel-plugin-react-docgen/-/babel-plugin-react-docgen-4.2.1.tgz#7cc8e2f94e8dc057a06e953162f0810e4e72257b" @@ -5411,12 +6281,12 @@ babel-preset-current-node-syntax@^1.0.0: "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-top-level-await" "^7.8.3" -babel-preset-jest@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.4.3.tgz#bb926b66ae253b69c6e3ef87511b8bb5c53c5b52" - integrity sha512-gWx6COtSuma6n9bw+8/F+2PCXrIgxV/D1TJFnp6OyBK2cxPWg0K9p/sriNYeifKjpUkMViWQ09DSWtzJQRETsw== +babel-preset-jest@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" + integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== dependencies: - babel-plugin-jest-hoist "^29.4.3" + babel-plugin-jest-hoist "^29.6.3" babel-preset-current-node-syntax "^1.0.0" babel-runtime@^6.26.0: @@ -5551,7 +6421,7 @@ body-parser@1.18.2: raw-body "2.3.2" type-is "~1.6.15" -body-parser@1.20.1, body-parser@^1.19.0, body-parser@^1.20.0: +body-parser@1.20.1, body-parser@^1.19.0: version "1.20.1" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== @@ -5569,21 +6439,40 @@ body-parser@1.20.1, body-parser@^1.19.0, body-parser@^1.20.0: type-is "~1.6.18" unpipe "1.0.0" -body-parser@2.0.0-beta.1: - version "2.0.0-beta.1" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-2.0.0-beta.1.tgz#d4ed97d6ed51f6040b967db0db2252a0b235a661" - integrity sha512-I1v2bt2OdYqtmk8nEFZuEf+9Opb30DphYwTPDbgg/OorSAoJOuTpWyDrZaSWQw7FdoevbBRCP2+9z/halXSWcA== +body-parser@2.0.0-beta.2: + version "2.0.0-beta.2" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-2.0.0-beta.2.tgz#46081eb83ab83e436c2bce8fa71464b2385d61fb" + integrity sha512-oxdqeGYQcO5ovwwkC1A89R0Mf0v3+7smTVh0chGfzDeiK37bg5bYNtXDy3Nmzn6CShoIYk5+nHTyBoSZIWwnCA== dependencies: - bytes "3.1.1" - content-type "~1.0.4" + bytes "3.1.2" + content-type "~1.0.5" + debug "3.1.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.5.2" + on-finished "2.4.1" + qs "6.11.0" + raw-body "3.0.0-beta.1" + type-is "~1.6.18" + unpipe "1.0.0" + +body-parser@^1.20.2: + version "1.20.2" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" + integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== + dependencies: + bytes "3.1.2" + content-type "~1.0.5" debug "2.6.9" - depd "~1.1.2" - http-errors "1.8.1" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.9.6" - raw-body "2.4.2" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.2" type-is "~1.6.18" + unpipe "1.0.0" bonjour-service@^1.0.11: version "1.0.14" @@ -5600,10 +6489,10 @@ boolbase@^1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== -bootstrap@^5.2.3: - version "5.2.3" - resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.2.3.tgz#54739f4414de121b9785c5da3c87b37ff008322b" - integrity sha512-cEKPM+fwb3cT8NzQZYEu4HilJ3anCrWqh3CHAok1p9jXqMPsPTBhU25fBckEJHJ/p+tTxTFTsFQGM+gaHpi3QQ== +bootstrap@^5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.3.3.tgz#de35e1a765c897ac940021900fcbb831602bac38" + integrity sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg== boxen@^5.1.2: version "5.1.2" @@ -5750,6 +6639,16 @@ browserslist@^4.12.0, browserslist@^4.14.5, browserslist@^4.21.3, browserslist@^ node-releases "^2.0.6" update-browserslist-db "^1.0.9" +browserslist@^4.21.10, browserslist@^4.23.0: + version "4.23.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.2.tgz#244fe803641f1c19c28c48c4b6ec9736eb3d32ed" + integrity sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA== + dependencies: + caniuse-lite "^1.0.30001640" + electron-to-chromium "^1.4.820" + node-releases "^2.0.14" + update-browserslist-db "^1.1.0" + browserslist@^4.22.2: version "4.23.0" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" @@ -5819,11 +6718,6 @@ bytes@3.0.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== -bytes@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.1.tgz#3f018291cb4cbad9accb6e6970bca9c8889e879a" - integrity sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg== - bytes@3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" @@ -5982,6 +6876,11 @@ caniuse-lite@^1.0.30001587: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001596.tgz#da06b79c3d9c3d9958eb307aa832ac68ead79bee" integrity sha512-zpkZ+kEr6We7w63ORkoJ2pOfBwBkY/bJrG/UZ90qNb45Isblu8wzDgevEOrRL1r9dWayHjYiiyCMEXPn4DweGQ== +caniuse-lite@^1.0.30001640: + version "1.0.30001641" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001641.tgz#3572862cd18befae3f637f2a1101cc033c6782ac" + integrity sha512-Phv5thgl67bHYo1TtMY/MurjkHhV4EDaCosezRXgZ8jzA/Ub+wjxAvbGvjoFENStinwi5kCyOYV3mi5tOGykwA== + capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -6150,13 +7049,13 @@ chrome-trace-event@^1.0.2: resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== -chromium-bidi@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/chromium-bidi/-/chromium-bidi-0.5.2.tgz#358b03bb7c53e0f8d0fd77d596ea67ee30f7ff06" - integrity sha512-PbVOSddxgKyj+JByqavWMNqWPCoCaT6XK5Z1EFe168sxnB/BM51LnZEPXSbFcFAJv/+u2B4XNTs9uXxy4GW3cQ== +chromium-bidi@0.5.8: + version "0.5.8" + resolved "https://registry.yarnpkg.com/chromium-bidi/-/chromium-bidi-0.5.8.tgz#5053038425c062ed34b9bc973e84e79de0a5cef0" + integrity sha512-blqh+1cEQbHBKmok3rVJkBlBxt9beKBgOsxbFgs7UJcoVbbeZ+K7+6liAsjgpc8l1Xd55cQUy14fXZdGSb4zIw== dependencies: mitt "3.0.1" - urlpattern-polyfill "9.0.0" + urlpattern-polyfill "10.0.0" ci-info@^2.0.0: version "2.0.0" @@ -6168,6 +7067,11 @@ ci-info@^3.2.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.7.1.tgz#708a6cdae38915d597afdf3b145f2f8e1ff55f3f" integrity sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w== +ci-info@^3.7.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" + integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== + cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" @@ -6196,10 +7100,10 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -classnames@^2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" - integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== +classnames@^2.3.2: + version "2.5.1" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b" + integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow== clean-css@^4.2.3: version "4.2.4" @@ -6372,6 +7276,11 @@ comma-separated-tokens@^1.0.0: resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== +commander@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + commander@^2.19.0, commander@^2.20.0, commander@^2.20.3: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -6392,11 +7301,6 @@ commander@^8.3.0: resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== -commander@^9.4.1: - version "9.4.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-9.4.1.tgz#d1dd8f2ce6faf93147295c0df13c7c21141cfbdd" - integrity sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw== - common-path-prefix@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0" @@ -6472,12 +7376,11 @@ connect-history-api-fallback@^2.0.0: resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8" integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA== -connect-pg-simple@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/connect-pg-simple/-/connect-pg-simple-8.0.0.tgz#f005051ef693b1e8fb8c3d5eb5e16e10ab3972b2" - integrity sha512-pBDa23RA1LCkwvRrPOh5xevB+Nknh1UDuhFOKsUrkUDodYqfiQT18P2qXc4lk/TqCMB6hI06B8KNncHh91bZMQ== +connect-pg-simple@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/connect-pg-simple/-/connect-pg-simple-9.0.1.tgz#98637ff17a5bfeaeef638093fcf484bc96fcbbf6" + integrity sha512-BuwWJH3K3aLpONkO9s12WhZ9ceMjIBxIJAh0JD9x4z1Y9nShmWqZvge5PG/+4j2cIOcguUoa2PSQ4HO/oTsrVg== dependencies: - "@types/pg" "^8.6.5" pg "^8.8.0" console-browserify@^1.1.0: @@ -6512,6 +7415,11 @@ content-type@~1.0.4: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== +content-type@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.9.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" @@ -6527,31 +7435,41 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== +cookie-signature@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.7.tgz#ab5dd7ab757c54e60f37ef6550f481c426d10454" + integrity sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA== + cookie@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" integrity sha512-+IJOX0OqlHCszo2mBUq+SrEbCj6w7Kpffqx60zYbPTFaO4+yYgRjHwcZNpWvaTylDHaV7PPmBHzSecZiMhtPgw== -cookie@0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" - integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== - -cookie@0.4.2, cookie@^0.4.1: - version "0.4.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" - integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== - cookie@0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== -cookiejar@^2.1.2, cookiejar@^2.1.3: +cookie@0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" + integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== + +cookie@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + +cookiejar@^2.1.2: version "2.1.3" resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.3.tgz#fc7a6216e408e74414b90230050842dacda75acc" integrity sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ== +cookiejar@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.4.tgz#ee669c1fea2cf42dc31585469d193fef0d65771b" + integrity sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw== + copy-concurrently@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" @@ -6588,6 +7506,13 @@ core-js-compat@^3.25.1, core-js-compat@^3.8.1: dependencies: browserslist "^4.21.4" +core-js-compat@^3.31.0, core-js-compat@^3.36.1: + version "3.37.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.37.1.tgz#c844310c7852f4bdf49b8d339730b97e17ff09ee" + integrity sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg== + dependencies: + browserslist "^4.23.0" + core-js-pure@^3.23.3: version "3.27.1" resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.27.1.tgz#ede4a6b8440585c7190062757069c01d37a19dca" @@ -6598,11 +7523,16 @@ core-js@^2.4.0, core-js@^2.5.0: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== -core-js@^3.0.4, core-js@^3.6.5, core-js@^3.8.0, core-js@^3.8.2: +core-js@^3.0.4, core-js@^3.6.5, core-js@^3.8.2: version "3.27.1" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.27.1.tgz#23cc909b315a6bb4e418bf40a52758af2103ba46" integrity sha512-GutwJLBChfGCpwwhbYoqfv03LAfmiz7e7D/BNxzeMxwQf10GRSzqiOjx7AmtEk+heiD/JWmBuyBPgFtx0Sg1ww== +core-js@^3.37.1: + version "3.37.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.37.1.tgz#d21751ddb756518ac5a00e4d66499df981a62db9" + integrity sha512-Xn6qmxrQZyB0FFY8E3bgRXei3lWDJHhvI+u0q9TKIYM49G8pAr0FgnnrFRAmsbptZL1yxRADVXn+x5AGsbBfyw== + core-util-is@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -6621,15 +7551,15 @@ cors@^2.8.5: object-assign "^4" vary "^1" -cosmiconfig@8.3.6: - version "8.3.6" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" - integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA== +cosmiconfig@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-9.0.0.tgz#34c3fc58287b915f3ae905ab6dc3de258b55ad9d" + integrity sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg== dependencies: + env-paths "^2.2.1" import-fresh "^3.3.0" js-yaml "^4.1.0" parse-json "^5.2.0" - path-type "^4.0.0" cosmiconfig@^6.0.0: version "6.0.0" @@ -6709,7 +7639,20 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: safe-buffer "^5.0.1" sha.js "^2.4.8" -cross-fetch@3.1.5, cross-fetch@^3.1.5: +create-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" + integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-config "^29.7.0" + jest-util "^29.7.0" + prompts "^2.0.1" + +cross-fetch@3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== @@ -6805,19 +7748,19 @@ css-loader@^5.0.1: schema-utils "^3.0.0" semver "^7.3.5" -css-loader@^6.7.3: - version "6.7.3" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.7.3.tgz#1e8799f3ccc5874fdd55461af51137fcc5befbcd" - integrity sha512-qhOH1KlBMnZP8FzRO6YCH9UHXQhVMcEGLyNdb7Hv2cpcmJbW0YrddO+tG1ab5nT41KpHIYGsbeHqxB9xPu1pKQ== +css-loader@^6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.11.0.tgz#33bae3bf6363d0a7c2cf9031c96c744ff54d85ba" + integrity sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g== dependencies: icss-utils "^5.1.0" - postcss "^8.4.19" - postcss-modules-extract-imports "^3.0.0" - postcss-modules-local-by-default "^4.0.0" - postcss-modules-scope "^3.0.0" + postcss "^8.4.33" + postcss-modules-extract-imports "^3.1.0" + postcss-modules-local-by-default "^4.0.5" + postcss-modules-scope "^3.2.0" postcss-modules-values "^4.0.0" postcss-value-parser "^4.2.0" - semver "^7.3.8" + semver "^7.5.4" css-mediaquery@^0.1.2: version "0.1.2" @@ -6897,10 +7840,10 @@ cssstyle@^2.3.0: dependencies: cssom "~0.3.6" -cssstyle@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-3.0.0.tgz#17ca9c87d26eac764bb8cfd00583cff21ce0277a" - integrity sha512-N4u2ABATi3Qplzf0hWbVCdjenim8F3ojEXpBDF5hBpjzW182MjNGLqfmQ0SkSPeQ+V86ZXgeH8aXj6kayd4jgg== +cssstyle@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-4.0.1.tgz#ef29c598a1e90125c870525490ea4f354db0660a" + integrity sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ== dependencies: rrweb-cssom "^0.6.0" @@ -6959,14 +7902,40 @@ data-urls@^3.0.2: whatwg-mimetype "^3.0.0" whatwg-url "^11.0.0" -data-urls@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-4.0.0.tgz#333a454eca6f9a5b7b0f1013ff89074c3f522dd4" - integrity sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g== +data-urls@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-5.0.0.tgz#2f76906bce1824429ffecb6920f45a0b30f00dde" + integrity sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg== dependencies: - abab "^2.0.6" - whatwg-mimetype "^3.0.0" - whatwg-url "^12.0.0" + whatwg-mimetype "^4.0.0" + whatwg-url "^14.0.0" + +data-view-buffer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2" + integrity sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +data-view-byte-length@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz#90721ca95ff280677eb793749fce1011347669e2" + integrity sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +data-view-byte-offset@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz#5e0bbfb4828ed2d1b9b400cd8a7d119bca0ff18a" + integrity sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + is-data-view "^1.0.1" debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" @@ -6982,7 +7951,7 @@ debug@3.1.0: dependencies: ms "2.0.0" -debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: +debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -7016,6 +7985,11 @@ dedent@^0.7.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== +dedent@^1.0.0: + version "1.5.3" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.3.tgz#99aee19eb9bae55a67327717b6e848d0bf777e5a" + integrity sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ== + deep-equal-ident@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/deep-equal-ident/-/deep-equal-ident-1.1.1.tgz#06f4b89e53710cd6cea4a7781c7a956642de8dc9" @@ -7157,7 +8131,7 @@ depd@^1.1.0, depd@~1.1.1, depd@~1.1.2: resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== -dequal@^2.0.2: +dequal@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== @@ -7212,10 +8186,10 @@ detect-port@^1.3.0: address "^1.0.1" debug "4" -devtools-protocol@0.0.1203626: - version "0.0.1203626" - resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1203626.tgz#4366a4c81a7e0d4fd6924e9182c67f1e5941e820" - integrity sha512-nEzHZteIUZfGCZtTiS1fRpC8UZmsfD1SiyPvaUNvS13dvKf666OAm8YTi0+Ca3n1nLEyu49Cy4+dPWpaHFJk9g== +devtools-protocol@0.0.1232444: + version "0.0.1232444" + resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1232444.tgz#406345a90a871ba852c530d73482275234936eed" + integrity sha512-pM27vqEfxSxRkTMnF+XCmxSEb6duO5R+t8A9DEEJgy4Wz2RVanje2mmj99B6A3zv2r/qGfYlOvYznUhuokizmg== devtools-protocol@0.0.981744: version "0.0.981744" @@ -7230,15 +8204,10 @@ dezalgo@^1.0.4: asap "^2.0.0" wrappy "1" -diff-sequences@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.3.1.tgz#104b5b95fe725932421a9c6e5b4bef84c3f2249e" - integrity sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ== - -diff-sequences@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.4.3.tgz#9314bc1fabe09267ffeca9cbafc457d8499a13f2" - integrity sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA== +diff-sequences@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" + integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== diffie-hellman@^5.0.0: version "5.0.3" @@ -7294,11 +8263,16 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -dom-accessibility-api@^0.5.6, dom-accessibility-api@^0.5.9: +dom-accessibility-api@^0.5.9: version "0.5.15" resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.15.tgz#357e74338704f36fada8b2e01a4bfc11ef436ac9" integrity sha512-8o+oVqLQZoruQPYy3uAAQtc6YbtSiRq5aPJBhJ82YTJRHvI6ofhYAkC81WmjFTnfUbqg6T3aCglIpU9p/5e7Cw== +dom-accessibility-api@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz#993e925cc1d73f2c662e7d75dd5a5445259a8fd8" + integrity sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w== + dom-converter@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" @@ -7395,11 +8369,6 @@ domhandler@^5.0.1, domhandler@^5.0.2, domhandler@^5.0.3: dependencies: domelementtype "^2.3.0" -domino@^2.1.6: - version "2.1.6" - resolved "https://registry.yarnpkg.com/domino/-/domino-2.1.6.tgz#fe4ace4310526e5e7b9d12c7de01b7f485a57ffe" - integrity sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ== - domutils@^1.5.1: version "1.7.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" @@ -7441,15 +8410,15 @@ dot-prop@^5.2.0: dependencies: is-obj "^2.0.0" -dotenv-cli@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/dotenv-cli/-/dotenv-cli-6.0.0.tgz#8a30cbc59d0a8aaa166b2fee0a9a55e23a1223ab" - integrity sha512-qXlCOi3UMDhCWFKe0yq5sg3X+pJAz+RQDiFN38AMSbUrnY3uZshSfDJUAge951OS7J9gwLZGfsBlWRSOYz/TRg== +dotenv-cli@^7.4.2: + version "7.4.2" + resolved "https://registry.yarnpkg.com/dotenv-cli/-/dotenv-cli-7.4.2.tgz#c158a818de08e1fbc51d310f628cbace9075b734" + integrity sha512-SbUj8l61zIbzyhIbg0FwPJq6+wjbzdn9oEtozQpZ6kW2ihCcapKVZj49oCT3oPM+mgQm+itgvUQcG5szxVrZTA== dependencies: cross-spawn "^7.0.3" - dotenv "^16.0.0" - dotenv-expand "^8.0.1" - minimist "^1.2.5" + dotenv "^16.3.0" + dotenv-expand "^10.0.0" + minimist "^1.2.6" dotenv-defaults@^2.0.2: version "2.0.2" @@ -7458,37 +8427,37 @@ dotenv-defaults@^2.0.2: dependencies: dotenv "^8.2.0" +dotenv-expand@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-10.0.0.tgz#12605d00fb0af6d0a592e6558585784032e4ef37" + integrity sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A== + dotenv-expand@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0" integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA== -dotenv-expand@^8.0.1: - version "8.0.3" - resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-8.0.3.tgz#29016757455bcc748469c83a19b36aaf2b83dd6e" - integrity sha512-SErOMvge0ZUyWd5B0NXMQlDkN+8r+HhVUsxgOO7IoPDOdDRD2JjExpN6y3KnFR66jsJMwSn1pqIivhU5rcJiNg== - -dotenv-webpack@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/dotenv-webpack/-/dotenv-webpack-8.0.1.tgz#6656550460a8076fab20e5ac2eac867e72478645" - integrity sha512-CdrgfhZOnx4uB18SgaoP9XHRN2v48BbjuXQsZY5ixs5A8579NxQkmMxRtI7aTwSiSQcM2ao12Fdu+L3ZS3bG4w== +dotenv-webpack@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/dotenv-webpack/-/dotenv-webpack-8.1.0.tgz#4d66abc4a30395b46a030ebcd125320232b54873" + integrity sha512-owK1JcsPkIobeqjVrk6h7jPED/W6ZpdFsMPR+5ursB7/SdgDyO+VzAU+szK8C8u3qUhtENyYnj8eyXMR5kkGag== dependencies: dotenv-defaults "^2.0.2" -dotenv@^16.0.0, dotenv@^16.0.3: - version "16.0.3" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" - integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== +dotenv@^16.3.0, dotenv@^16.4.5: + version "16.4.5" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" + integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== dotenv@^8.0.0, dotenv@^8.2.0: version "8.6.0" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b" integrity sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g== -dottie@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/dottie/-/dottie-2.0.3.tgz#797a4f4c92a9a65499806be4051b9d9dcd5a5d77" - integrity sha512-4liA0PuRkZWQFQjwBypdxPfZaRWiv5tkhMXY2hzsa2pNf5s7U3m9cwUchfNKe8wZQxdGPQQzO6Rm2uGe0rvohQ== +dottie@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/dottie/-/dottie-2.0.6.tgz#34564ebfc6ec5e5772272d466424ad5b696484d4" + integrity sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA== duplexify@^3.4.2, duplexify@^3.6.0: version "3.7.1" @@ -7500,6 +8469,11 @@ duplexify@^3.4.2, duplexify@^3.6.0: readable-stream "^2.0.0" stream-shift "^1.0.0" +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -7540,6 +8514,11 @@ electron-to-chromium@^1.4.668: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.696.tgz#77532a00908897e4c331fe0044d98105ced4bcb5" integrity sha512-SOr0bHP52OvYg2chCsz/0+FUSMGFm8L8HKwPpx3cbwRY24EOemVJtbgTm+IFO8LzhcnPy+hXmTq7ZcZ8uUuaYg== +electron-to-chromium@^1.4.820: + version "1.4.823" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.823.tgz#38587f7aa55bed14930f04091dfc65c39a3d8bd7" + integrity sha512-4h+oPeAiGQOHFyUJOqpoEcPj/xxlicxBzOErVeYVMMmAiXUXsGpsFd0QXBMaUUbnD8hhSfLf9uw+MlsoIA7j5w== + element-resize-detector@^1.2.2: version "1.2.4" resolved "https://registry.yarnpkg.com/element-resize-detector/-/element-resize-detector-1.2.4.tgz#3e6c5982dd77508b5fa7e6d5c02170e26325c9b1" @@ -7570,6 +8549,11 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + emojis-list@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" @@ -7613,6 +8597,14 @@ enhanced-resolve@^5.10.0: graceful-fs "^4.2.4" tapable "^2.2.0" +enhanced-resolve@^5.17.0: + version "5.17.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz#d037603789dd9555b89aaec7eb78845c49089bc5" + integrity sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + enquirer@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" @@ -7635,38 +8627,43 @@ entities@^4.2.0, entities@^4.3.0, entities@^4.4.0: resolved "https://registry.yarnpkg.com/entities/-/entities-4.4.0.tgz#97bdaba170339446495e653cfd2db78962900174" integrity sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA== +env-paths@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" + integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== + envinfo@^7.7.3: version "7.8.1" resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== -enzyme-adapter-react-16@^1.15.2: - version "1.15.7" - resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.7.tgz#a737e6d8e2c147e9da5acf957755be7634f76201" - integrity sha512-LtjKgvlTc/H7adyQcj+aq0P0H07LDL480WQl1gU512IUyaDo/sbOaNDdZsJXYW2XaoPqrLLE9KbZS+X2z6BASw== +enzyme-adapter-react-16@^1.15.8: + version "1.15.8" + resolved "https://registry.yarnpkg.com/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.8.tgz#1aecb5daadaae33d32c5b8b78566d7cf45dc49d8" + integrity sha512-uYGC31eGZBp5nGsr4nKhZKvxGQjyHGjS06BJsUlWgE29/hvnpgCsT1BJvnnyny7N3GIIVyxZ4O9GChr6hy2WQA== dependencies: - enzyme-adapter-utils "^1.14.1" - enzyme-shallow-equal "^1.0.5" - has "^1.0.3" - object.assign "^4.1.4" - object.values "^1.1.5" + enzyme-adapter-utils "^1.14.2" + enzyme-shallow-equal "^1.0.7" + hasown "^2.0.0" + object.assign "^4.1.5" + object.values "^1.1.7" prop-types "^15.8.1" react-is "^16.13.1" react-test-renderer "^16.0.0-0" - semver "^5.7.0" + semver "^5.7.2" -enzyme-adapter-utils@^1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.14.1.tgz#f30db15dafc22e0ccd44f5acc8d93be29218cdcf" - integrity sha512-JZgMPF1QOI7IzBj24EZoDpaeG/p8Os7WeBZWTJydpsH7JRStc7jYbHE4CmNQaLqazaGFyLM8ALWA3IIZvxW3PQ== +enzyme-adapter-utils@^1.14.2: + version "1.14.2" + resolved "https://registry.yarnpkg.com/enzyme-adapter-utils/-/enzyme-adapter-utils-1.14.2.tgz#1d012e6261accbe7d406db098bb4d8dfdce8c003" + integrity sha512-1ZC++RlsYRaiOWE5NRaF5OgsMt7F5rn/VuaJIgc7eW/fmgg8eS1/Ut7EugSPPi7VMdWMLcymRnMF+mJUJ4B8KA== dependencies: airbnb-prop-types "^2.16.0" - function.prototype.name "^1.1.5" - has "^1.0.3" - object.assign "^4.1.4" - object.fromentries "^2.0.5" + function.prototype.name "^1.1.6" + hasown "^2.0.0" + object.assign "^4.1.5" + object.fromentries "^2.0.7" prop-types "^15.8.1" - semver "^5.7.1" + semver "^6.3.1" enzyme-matchers@^7.1.2: version "7.1.2" @@ -7676,7 +8673,7 @@ enzyme-matchers@^7.1.2: circular-json-es6 "^2.0.1" deep-equal-ident "^1.1.1" -enzyme-shallow-equal@^1.0.1, enzyme-shallow-equal@^1.0.5: +enzyme-shallow-equal@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.5.tgz#5528a897a6ad2bdc417c7221a7db682cd01711ba" integrity sha512-i6cwm7hN630JXenxxJFBKzgLC3hMTafFQXflvzHgPmDhOBhxUWDe8AeRv1qp2/uWJ2Y8z5yLWMzmAfkTOiOCZg== @@ -7684,6 +8681,14 @@ enzyme-shallow-equal@^1.0.1, enzyme-shallow-equal@^1.0.5: has "^1.0.3" object-is "^1.1.5" +enzyme-shallow-equal@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.7.tgz#4e3aa678022387a68e6c47aff200587851885b5e" + integrity sha512-/um0GFqUXnpM9SvKtje+9Tjoz3f1fpBC3eXRFrNs8kpYn69JljciYP7KZTqM/YQbUY9KUjvKB4jo/q+L6WGGvg== + dependencies: + hasown "^2.0.0" + object-is "^1.1.5" + enzyme-to-json@^3.3.0: version "3.6.2" resolved "https://registry.yarnpkg.com/enzyme-to-json/-/enzyme-to-json-3.6.2.tgz#94f85c413bcae8ab67be53b0a94b69a560e27823" @@ -7827,6 +8832,58 @@ es-abstract@^1.22.1, es-abstract@^1.22.3: unbox-primitive "^1.0.2" which-typed-array "^1.1.14" +es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2, es-abstract@^1.23.3: + version "1.23.3" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" + integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== + dependencies: + array-buffer-byte-length "^1.0.1" + arraybuffer.prototype.slice "^1.0.3" + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + data-view-buffer "^1.0.1" + data-view-byte-length "^1.0.1" + data-view-byte-offset "^1.0.0" + es-define-property "^1.0.0" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-set-tostringtag "^2.0.3" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.6" + get-intrinsic "^1.2.4" + get-symbol-description "^1.0.2" + globalthis "^1.0.3" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + has-proto "^1.0.3" + has-symbols "^1.0.3" + hasown "^2.0.2" + internal-slot "^1.0.7" + is-array-buffer "^3.0.4" + is-callable "^1.2.7" + is-data-view "^1.0.1" + is-negative-zero "^2.0.3" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.3" + is-string "^1.0.7" + is-typed-array "^1.1.13" + is-weakref "^1.0.2" + object-inspect "^1.13.1" + object-keys "^1.1.1" + object.assign "^4.1.5" + regexp.prototype.flags "^1.5.2" + safe-array-concat "^1.1.2" + safe-regex-test "^1.0.3" + string.prototype.trim "^1.2.9" + string.prototype.trimend "^1.0.8" + string.prototype.trimstart "^1.0.8" + typed-array-buffer "^1.0.2" + typed-array-byte-length "^1.0.1" + typed-array-byte-offset "^1.0.2" + typed-array-length "^1.0.6" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.15" + es-array-method-boxes-properly@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" @@ -7858,11 +8915,43 @@ es-get-iterator@^1.0.2, es-get-iterator@^1.1.2: is-string "^1.0.5" isarray "^2.0.5" +es-iterator-helpers@^1.0.19: + version "1.0.19" + resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz#117003d0e5fec237b4b5c08aded722e0c6d50ca8" + integrity sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.3" + es-errors "^1.3.0" + es-set-tostringtag "^2.0.3" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + globalthis "^1.0.3" + has-property-descriptors "^1.0.2" + has-proto "^1.0.3" + has-symbols "^1.0.3" + internal-slot "^1.0.7" + iterator.prototype "^1.1.2" + safe-array-concat "^1.1.2" + es-module-lexer@^0.9.0: version "0.9.3" resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== +es-module-lexer@^1.2.1: + version "1.5.4" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.4.tgz#a8efec3a3da991e60efa6b633a7cad6ab8d26b78" + integrity sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw== + +es-object-atoms@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" + integrity sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw== + dependencies: + es-errors "^1.3.0" + es-set-tostringtag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.0.tgz#b33fdef554fb35a264fe022c1f095f1f2022fa85" @@ -7887,6 +8976,13 @@ es-shim-unscopables@^1.0.0: dependencies: has "^1.0.3" +es-shim-unscopables@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" + integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== + dependencies: + hasown "^2.0.0" + es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -7959,6 +9055,11 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== +escalade@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== + escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -8014,15 +9115,15 @@ escodegen@^2.1.0: optionalDependencies: source-map "~0.6.1" -eslint-config-prettier@^8.6.0: - version "8.6.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.6.0.tgz#dec1d29ab728f4fa63061774e1672ac4e363d207" - integrity sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA== +eslint-config-prettier@^8.10.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz#3a06a662130807e2502fc3ff8b4143d8a0658e11" + integrity sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg== -eslint-plugin-jest@^27.2.1: - version "27.2.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.2.1.tgz#b85b4adf41c682ea29f1f01c8b11ccc39b5c672c" - integrity sha512-l067Uxx7ZT8cO9NJuf+eJHvt6bqJyz2Z29wykyEdz/OtmcELQl2MQGQLX8J94O1cSJWAwUSEvCjwjA7KEK3Hmg== +eslint-plugin-jest@^27.9.0: + version "27.9.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz#7c98a33605e1d8b8442ace092b60e9919730000b" + integrity sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug== dependencies: "@typescript-eslint/utils" "^5.10.0" @@ -8041,26 +9142,29 @@ eslint-plugin-prettier@^4.2.1: dependencies: prettier-linter-helpers "^1.0.0" -eslint-plugin-react@^7.31.11: - version "7.31.11" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.31.11.tgz#011521d2b16dcf95795df688a4770b4eaab364c8" - integrity sha512-TTvq5JsT5v56wPa9OYHzsrOlHzKZKjV+aLgS+55NJP/cuzdiQPC7PfYoUjMoxlffKtvijpk7vA/jmuqRb9nohw== +eslint-plugin-react@^7.34.3: + version "7.34.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.34.3.tgz#9965f27bd1250a787b5d4cfcc765e5a5d58dcb7b" + integrity sha512-aoW4MV891jkUulwDApQbPYTVZmeuSyFrudpbTAQuj5Fv8VL+o6df2xIGpw8B0hPjAaih1/Fb0om9grCdyFYemA== dependencies: - array-includes "^3.1.6" - array.prototype.flatmap "^1.3.1" - array.prototype.tosorted "^1.1.1" + array-includes "^3.1.8" + array.prototype.findlast "^1.2.5" + array.prototype.flatmap "^1.3.2" + array.prototype.toreversed "^1.1.2" + array.prototype.tosorted "^1.1.4" doctrine "^2.1.0" + es-iterator-helpers "^1.0.19" estraverse "^5.3.0" jsx-ast-utils "^2.4.1 || ^3.0.0" minimatch "^3.1.2" - object.entries "^1.1.6" - object.fromentries "^2.0.6" - object.hasown "^1.1.2" - object.values "^1.1.6" + object.entries "^1.1.8" + object.fromentries "^2.0.8" + object.hasown "^1.1.4" + object.values "^1.2.0" prop-types "^15.8.1" - resolve "^2.0.0-next.3" - semver "^6.3.0" - string.prototype.matchall "^4.0.8" + resolve "^2.0.0-next.5" + semver "^6.3.1" + string.prototype.matchall "^4.0.11" eslint-scope@5.1.1, eslint-scope@^5.1.1: version "5.1.1" @@ -8078,10 +9182,10 @@ eslint-scope@^4.0.3: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-scope@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" - integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== +eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" @@ -8103,69 +9207,73 @@ eslint-visitor-keys@^3.3.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== -eslint@^8.31.0: - version "8.31.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.31.0.tgz#75028e77cbcff102a9feae1d718135931532d524" - integrity sha512-0tQQEVdmPZ1UtUKXjX7EMm9BlgJ08G90IhWh0PKDCb3ZLsgAOHI8fYSIzYVZej92zsgq+ft0FGsxhJ3xo2tbuA== - dependencies: - "@eslint/eslintrc" "^1.4.1" - "@humanwhocodes/config-array" "^0.11.8" +eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint@^8.57.0: + version "8.57.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" + integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^2.1.4" + "@eslint/js" "8.57.0" + "@humanwhocodes/config-array" "^0.11.14" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" - ajv "^6.10.0" + "@ungap/structured-clone" "^1.2.0" + ajv "^6.12.4" chalk "^4.0.0" cross-spawn "^7.0.2" debug "^4.3.2" doctrine "^3.0.0" escape-string-regexp "^4.0.0" - eslint-scope "^7.1.1" - eslint-utils "^3.0.0" - eslint-visitor-keys "^3.3.0" - espree "^9.4.0" - esquery "^1.4.0" + eslint-scope "^7.2.2" + eslint-visitor-keys "^3.4.3" + espree "^9.6.1" + esquery "^1.4.2" esutils "^2.0.2" fast-deep-equal "^3.1.3" file-entry-cache "^6.0.1" find-up "^5.0.0" glob-parent "^6.0.2" globals "^13.19.0" - grapheme-splitter "^1.0.4" + graphemer "^1.4.0" ignore "^5.2.0" - import-fresh "^3.0.0" imurmurhash "^0.1.4" is-glob "^4.0.0" is-path-inside "^3.0.3" - js-sdsl "^4.1.4" js-yaml "^4.1.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" lodash.merge "^4.6.2" minimatch "^3.1.2" natural-compare "^1.4.0" - optionator "^0.9.1" - regexpp "^3.2.0" + optionator "^0.9.3" strip-ansi "^6.0.1" - strip-json-comments "^3.1.0" text-table "^0.2.0" -espree@^9.4.0: - version "9.4.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.1.tgz#51d6092615567a2c2cff7833445e37c28c0065bd" - integrity sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg== +espree@^9.6.0, espree@^9.6.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== dependencies: - acorn "^8.8.0" + acorn "^8.9.0" acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.3.0" + eslint-visitor-keys "^3.4.1" esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" - integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== +esquery@^1.4.2: + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== dependencies: estraverse "^5.1.0" @@ -8282,27 +9390,16 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expect@^29.0.0, expect@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/expect/-/expect-29.3.1.tgz#92877aad3f7deefc2e3f6430dd195b92295554a6" - integrity sha512-gGb1yTgU30Q0O/tQq+z30KBWv24ApkMgFUpvKBkyLUBL68Wv8dHdJxTBZFl/iT8K/bqDHvUYRH6IIN3rToopPA== - dependencies: - "@jest/expect-utils" "^29.3.1" - jest-get-type "^29.2.0" - jest-matcher-utils "^29.3.1" - jest-message-util "^29.3.1" - jest-util "^29.3.1" - -expect@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/expect/-/expect-29.4.3.tgz#5e47757316df744fe3b8926c3ae8a3ebdafff7fe" - integrity sha512-uC05+Q7eXECFpgDrHdXA4k2rpMyStAYPItEDLyQDo5Ta7fVkJnNA/4zh/OIVkVVNZ1oOK1PipQoyNjuZ6sz6Dg== +expect@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" + integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== dependencies: - "@jest/expect-utils" "^29.4.3" - jest-get-type "^29.4.3" - jest-matcher-utils "^29.4.3" - jest-message-util "^29.4.3" - jest-util "^29.4.3" + "@jest/expect-utils" "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" express-handlebars@3.0.0: version "3.0.0" @@ -8315,22 +9412,22 @@ express-handlebars@3.0.0: object.assign "^4.0.3" promise "^7.0.0" -express-handlebars@^6.0.6: - version "6.0.6" - resolved "https://registry.yarnpkg.com/express-handlebars/-/express-handlebars-6.0.6.tgz#2589bcc4cf9545918047c767e66fa625f5ace85b" - integrity sha512-E4QHYCh+9fyfdBEb8uKJ8p6HD4qq/sUSHBq83lRNlLJp2TQKEg2nFJYbVdC+M3QzaV19dODe43lgjQWVaIpbyQ== +express-handlebars@^7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/express-handlebars/-/express-handlebars-7.1.3.tgz#48de4fff6617af9574a6d63031f34fe95e255dd2" + integrity sha512-O0W4n14iQ8+iFIDdiMh9HRI2nbVQJ/h1qndlD1TXWxxcfbKjKoqJh+ti2tROkyx4C4VQrt0y3bANBQ5auQAiew== dependencies: - glob "^8.0.2" - graceful-fs "^4.2.10" - handlebars "^4.7.7" + glob "^10.4.2" + graceful-fs "^4.2.11" + handlebars "^4.7.8" -express-session@^1.17.2: - version "1.17.3" - resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.17.3.tgz#14b997a15ed43e5949cb1d073725675dd2777f36" - integrity sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw== +express-session@^1.18.0: + version "1.18.0" + resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.18.0.tgz#a6ae39d9091f2efba5f20fc5c65a3ce7c9ce16a3" + integrity sha512-m93QLWr0ju+rOwApSsyso838LQwgfs44QtOP/WBiwtAgPIo/SAh1a5c6nn2BR6mFNZehTpqKDESzP+fRHVbxwQ== dependencies: - cookie "0.4.2" - cookie-signature "1.0.6" + cookie "0.6.0" + cookie-signature "1.0.7" debug "2.6.9" depd "~2.0.0" on-headers "~1.0.2" @@ -8411,40 +9508,41 @@ express@^4.17.1, express@^4.17.3: utils-merge "1.0.1" vary "~1.1.2" -express@^5.0.0-alpha.8: - version "5.0.0-beta.1" - resolved "https://registry.yarnpkg.com/express/-/express-5.0.0-beta.1.tgz#efbfd372e4650a48e417b1adbaf43599092ddc8f" - integrity sha512-KPtBrlZoQu2Ps0Ce/Imqtq73AB0KBJ8Gx59yZQ3pmDJU2/LhcoZETo03oSgtTQufbcLXt/WBITk/jMjl/WMyrQ== +express@^5.0.0-beta.3: + version "5.0.0-beta.3" + resolved "https://registry.yarnpkg.com/express/-/express-5.0.0-beta.3.tgz#be38300eaafadee3de6ce756aaa34f52c0472da6" + integrity sha512-e7Qizw4gMBVe1Ky2oNi5C1h6oS8aWDcY2yYxvRMy5aMc6t2aqobuHpQRfR3LRC9NAW/c6081SeGWMGBorLXePg== dependencies: - accepts "~1.3.7" + accepts "~1.3.8" array-flatten "3.0.0" - body-parser "2.0.0-beta.1" + body-parser "2.0.0-beta.2" content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.4.1" + cookie "0.6.0" cookie-signature "1.0.6" debug "3.1.0" - depd "~1.1.2" + depd "2.0.0" encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" - finalhandler "~1.1.2" + finalhandler "1.2.0" fresh "0.5.2" + http-errors "2.0.0" merge-descriptors "1.0.1" methods "~1.1.2" mime-types "~2.1.34" - on-finished "~2.3.0" + on-finished "2.4.1" parseurl "~1.3.3" path-is-absolute "1.0.1" proxy-addr "~2.0.7" - qs "6.9.6" + qs "6.11.0" range-parser "~1.2.1" - router "2.0.0-beta.1" + router "2.0.0-beta.2" safe-buffer "5.2.1" - send "1.0.0-beta.1" - serve-static "2.0.0-beta.1" + send "1.0.0-beta.2" + serve-static "2.0.0-beta.2" setprototypeof "1.2.0" - statuses "~1.5.0" + statuses "2.0.1" type-is "~1.6.18" utils-merge "1.0.1" vary "~1.1.2" @@ -8699,19 +9797,6 @@ finalhandler@1.2.0: statuses "2.0.1" unpipe "~1.0.0" -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.3" - statuses "~1.5.0" - unpipe "~1.0.0" - find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" @@ -8721,7 +9806,7 @@ find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: make-dir "^2.0.0" pkg-dir "^3.0.0" -find-cache-dir@^3.3.1, find-cache-dir@^3.3.2: +find-cache-dir@^3.3.1: version "3.3.2" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== @@ -8730,6 +9815,14 @@ find-cache-dir@^3.3.1, find-cache-dir@^3.3.2: make-dir "^3.0.2" pkg-dir "^4.1.0" +find-cache-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-4.0.0.tgz#a30ee0448f81a3990708f6453633c733e2f6eec2" + integrity sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg== + dependencies: + common-path-prefix "^3.0.0" + pkg-dir "^7.0.0" + find-root@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" @@ -8766,6 +9859,14 @@ find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" +find-up@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-6.3.0.tgz#2abab3d3280b2dc7ac10199ef324c4e002c8c790" + integrity sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw== + dependencies: + locate-path "^7.1.0" + path-exists "^5.0.0" + find-yarn-workspace-root@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz#f47fb8d239c900eb78179aa81b66673eac88f7bd" @@ -8819,6 +9920,14 @@ foreground-child@^2.0.0: cross-spawn "^7.0.0" signal-exit "^3.0.2" +foreground-child@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.2.1.tgz#767004ccf3a5b30df39bed90718bab43fe0a59f7" + integrity sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^4.0.1" + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -8883,10 +9992,10 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -formidable@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/formidable/-/formidable-2.1.1.tgz#81269cbea1a613240049f5f61a9d97731517414f" - integrity sha512-0EcS9wCFEzLvfiks7omJ+SiYJAiD+TzK4Pcw1UlUoGnhUxDcMKjt0P7x8wEb0u6OHu8Nb98WG3nxtlF5C7bvUQ== +formidable@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/formidable/-/formidable-2.1.2.tgz#fa973a2bec150e4ce7cac15589d7a25fc30ebd89" + integrity sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g== dependencies: dezalgo "^1.0.4" hexoid "^1.0.0" @@ -8932,10 +10041,10 @@ fs-extra@^10.1.0: jsonfile "^6.0.1" universalify "^2.0.0" -fs-extra@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.0.tgz#5784b102104433bb0e090f48bfc4a30742c357ed" - integrity sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw== +fs-extra@^11.2.0: + version "11.2.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" + integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== dependencies: graceful-fs "^4.2.0" jsonfile "^6.0.1" @@ -9187,6 +10296,18 @@ glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== +glob@^10.4.2: + version "10.4.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + glob@^6.0.4: version "6.0.4" resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" @@ -9210,7 +10331,7 @@ glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^8.0.2, glob@^8.0.3: +glob@^8.0.3: version "8.0.3" resolved "https://registry.yarnpkg.com/glob/-/glob-8.0.3.tgz#415c6eb2deed9e502c68fa44a272e6da6eeca42e" integrity sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ== @@ -9292,15 +10413,20 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== -grapheme-splitter@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" - integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== +graceful-fs@^4.2.11: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== graphql-tag@^2.11.0, graphql-tag@^2.12.6: version "2.12.6" @@ -9309,10 +10435,10 @@ graphql-tag@^2.11.0, graphql-tag@^2.12.6: dependencies: tslib "^2.1.0" -graphql@^16.6.0: - version "16.6.0" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.6.0.tgz#c2dcffa4649db149f6282af726c8c83f1c7c5fdb" - integrity sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw== +graphql@^16.9.0: + version "16.9.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.9.0.tgz#1c310e63f16a49ce1fbb230bd0a000e99f6f115f" + integrity sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw== handle-thing@^2.0.0: version "2.0.1" @@ -9331,6 +10457,18 @@ handlebars@^4.0.5, handlebars@^4.7.7: optionalDependencies: uglify-js "^3.1.4" +handlebars@^4.7.8: + version "4.7.8" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" + integrity sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ== + dependencies: + minimist "^1.2.5" + neo-async "^2.6.2" + source-map "^0.6.1" + wordwrap "^1.0.0" + optionalDependencies: + uglify-js "^3.1.4" + har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" @@ -9476,6 +10614,13 @@ hasown@^2.0.0, hasown@^2.0.1: dependencies: function-bind "^1.1.2" +hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + hast-to-hyperscript@^9.0.0: version "9.0.1" resolved "https://registry.yarnpkg.com/hast-to-hyperscript/-/hast-to-hyperscript-9.0.1.tgz#9b67fd188e4c81e8ad66f803855334173920218d" @@ -9607,6 +10752,13 @@ html-encoding-sniffer@^3.0.0: dependencies: whatwg-encoding "^2.0.0" +html-encoding-sniffer@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz#696df529a7cfd82446369dc5193e590a3735b448" + integrity sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ== + dependencies: + whatwg-encoding "^3.1.1" + html-entities@^2.1.0, html-entities@^2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46" @@ -9726,17 +10878,6 @@ http-errors@1.6.2: setprototypeof "1.0.3" statuses ">= 1.3.1 < 2" -http-errors@1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c" - integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.1" - http-errors@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" @@ -9785,6 +10926,14 @@ http-proxy-agent@^7.0.0: agent-base "^7.1.0" debug "^4.3.4" +http-proxy-agent@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" + integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== + dependencies: + agent-base "^7.1.0" + debug "^4.3.4" + http-proxy-middleware@^2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" @@ -9843,6 +10992,14 @@ https-proxy-agent@^7.0.2: agent-base "^7.0.2" debug "4" +https-proxy-agent@^7.0.4: + version "7.0.5" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz#9e8b5013873299e11fab6fd548405da2d6c602b2" + integrity sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw== + dependencies: + agent-base "^7.0.2" + debug "4" + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -9865,6 +11022,13 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" +iconv-lite@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.5.2.tgz#af6d628dccfb463b7364d97f715e4b74b8c8c2b8" + integrity sha512-kERHXvpSaB4aU3eANwidg79K8FlrN77m8G9V+0vOR3HYaRifrlwMEpT7ZBJqLSEIHnEgJTHcWK82wwLwwKwtag== + dependencies: + safer-buffer ">= 2.1.2 < 3" + iconv-lite@0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" @@ -9914,7 +11078,7 @@ image-ssim@^0.2.0: resolved "https://registry.yarnpkg.com/image-ssim/-/image-ssim-0.2.0.tgz#83b42c7a2e6e4b85505477fe6917f5dbc56420e5" integrity sha512-W7+sO6/yhxy83L0G7xR8YAc5Z5QFtYEXXRV6EaE8tuYBZJnA3gVgp3q7X7muhLZVodeb9UfvjSbwt9VJwjIYAg== -import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.3.0: +import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -9952,7 +11116,7 @@ infer-owner@^1.0.3, infer-owner@^1.0.4: resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== -inflection@^1.13.2: +inflection@^1.13.4: version "1.13.4" resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.13.4.tgz#65aa696c4e2da6225b148d7a154c449366633a32" integrity sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw== @@ -10132,6 +11296,13 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== +is-async-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.0.0.tgz#8e4418efd3e5d3a6ebb0164c05ef5afb69aa9646" + integrity sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA== + dependencies: + has-tostringtag "^1.0.0" + is-bigint@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" @@ -10183,6 +11354,13 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" +is-core-module@^2.13.0: + version "2.14.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.14.0.tgz#43b8ef9f46a6a08888db67b1ffd4ec9e3dfd59d1" + integrity sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A== + dependencies: + hasown "^2.0.2" + is-core-module@^2.9.0: version "2.11.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" @@ -10204,6 +11382,13 @@ is-data-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-data-view@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.1.tgz#4b4d3a511b70f3dc26d42c03ca9ca515d847759f" + integrity sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w== + dependencies: + is-typed-array "^1.1.13" + is-date-object@^1.0.1, is-date-object@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" @@ -10264,6 +11449,13 @@ is-extglob@^2.1.0, is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== +is-finalizationregistry@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz#c8749b65f17c133313e661b1289b95ad3dbd62e6" + integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw== + dependencies: + call-bind "^1.0.2" + is-finite@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" @@ -10289,6 +11481,13 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== +is-generator-function@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" + integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + dependencies: + has-tostringtag "^1.0.0" + is-glob@^3.0.0, is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" @@ -10384,6 +11583,11 @@ is-potential-custom-element-name@^1.0.1: resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== +is-promise@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-4.0.0.tgz#42ff9f84206c1991d26debf520dd5c01042dd2f3" + integrity sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ== + is-promise@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" @@ -10601,7 +11805,7 @@ istanbul-lib-instrument@^3.3.0: istanbul-lib-coverage "^2.0.5" semver "^6.0.0" -istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: +istanbul-lib-instrument@^5.0.4: version "5.2.1" resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== @@ -10612,6 +11816,17 @@ istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: istanbul-lib-coverage "^3.2.0" semver "^6.3.0" +istanbul-lib-instrument@^6.0.0: + version "6.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765" + integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q== + dependencies: + "@babel/core" "^7.23.9" + "@babel/parser" "^7.23.9" + "@istanbuljs/schema" "^0.1.3" + istanbul-lib-coverage "^3.2.0" + semver "^7.5.4" + istanbul-lib-report@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" @@ -10651,219 +11866,133 @@ iterate-value@^1.0.2: es-get-iterator "^1.0.2" iterate-iterator "^1.0.1" -jest-changed-files@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.2.0.tgz#b6598daa9803ea6a4dce7968e20ab380ddbee289" - integrity sha512-qPVmLLyBmvF5HJrY7krDisx6Voi8DmlV3GZYX0aFNbaQsZeoz1hfxcCMbqDGuQCxU1dJy9eYc2xscE8QrCCYaA== +iterator.prototype@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0" + integrity sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w== dependencies: - execa "^5.0.0" - p-limit "^3.1.0" + define-properties "^1.2.1" + get-intrinsic "^1.2.1" + has-symbols "^1.0.3" + reflect.getprototypeof "^1.0.4" + set-function-name "^2.0.1" -jest-changed-files@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.4.3.tgz#7961fe32536b9b6d5c28dfa0abcfab31abcf50a7" - integrity sha512-Vn5cLuWuwmi2GNNbokPOEcvrXGSGrqVnPEZV7rC6P7ck07Dyw9RFnvWglnupSh+hGys0ajGtw/bc2ZgweljQoQ== +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== dependencies: - execa "^5.0.0" - p-limit "^3.1.0" + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" -jest-circus@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.3.1.tgz#177d07c5c0beae8ef2937a67de68f1e17bbf1b4a" - integrity sha512-wpr26sEvwb3qQQbdlmei+gzp6yoSSoSL6GsLPxnuayZSMrSd5Ka7IjAvatpIernBvT2+Ic6RLTg+jSebScmasg== +jest-changed-files@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" + integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== dependencies: - "@jest/environment" "^29.3.1" - "@jest/expect" "^29.3.1" - "@jest/test-result" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - chalk "^4.0.0" - co "^4.6.0" - dedent "^0.7.0" - is-generator-fn "^2.0.0" - jest-each "^29.3.1" - jest-matcher-utils "^29.3.1" - jest-message-util "^29.3.1" - jest-runtime "^29.3.1" - jest-snapshot "^29.3.1" - jest-util "^29.3.1" + execa "^5.0.0" + jest-util "^29.7.0" p-limit "^3.1.0" - pretty-format "^29.3.1" - slash "^3.0.0" - stack-utils "^2.0.3" -jest-circus@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.4.3.tgz#fff7be1cf5f06224dd36a857d52a9efeb005ba04" - integrity sha512-Vw/bVvcexmdJ7MLmgdT3ZjkJ3LKu8IlpefYokxiqoZy6OCQ2VAm6Vk3t/qHiAGUXbdbJKJWnc8gH3ypTbB/OBw== +jest-circus@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" + integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== dependencies: - "@jest/environment" "^29.4.3" - "@jest/expect" "^29.4.3" - "@jest/test-result" "^29.4.3" - "@jest/types" "^29.4.3" + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" "@types/node" "*" chalk "^4.0.0" co "^4.6.0" - dedent "^0.7.0" + dedent "^1.0.0" is-generator-fn "^2.0.0" - jest-each "^29.4.3" - jest-matcher-utils "^29.4.3" - jest-message-util "^29.4.3" - jest-runtime "^29.4.3" - jest-snapshot "^29.4.3" - jest-util "^29.4.3" + jest-each "^29.7.0" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" p-limit "^3.1.0" - pretty-format "^29.4.3" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-cli@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.3.1.tgz#e89dff427db3b1df50cea9a393ebd8640790416d" - integrity sha512-TO/ewvwyvPOiBBuWZ0gm04z3WWP8TIK8acgPzE4IxgsLKQgb377NYGrQLc3Wl/7ndWzIH2CDNNsUjGxwLL43VQ== - dependencies: - "@jest/core" "^29.3.1" - "@jest/test-result" "^29.3.1" - "@jest/types" "^29.3.1" - chalk "^4.0.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - import-local "^3.0.2" - jest-config "^29.3.1" - jest-util "^29.3.1" - jest-validate "^29.3.1" - prompts "^2.0.1" - yargs "^17.3.1" - -jest-cli@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.4.3.tgz#fe31fdd0c90c765f392b8b7c97e4845071cd2163" - integrity sha512-PiiAPuFNfWWolCE6t3ZrDXQc6OsAuM3/tVW0u27UWc1KE+n/HSn5dSE6B2juqN7WP+PP0jAcnKtGmI4u8GMYCg== - dependencies: - "@jest/core" "^29.4.3" - "@jest/test-result" "^29.4.3" - "@jest/types" "^29.4.3" - chalk "^4.0.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - import-local "^3.0.2" - jest-config "^29.4.3" - jest-util "^29.4.3" - jest-validate "^29.4.3" - prompts "^2.0.1" - yargs "^17.3.1" - -jest-config@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.3.1.tgz#0bc3dcb0959ff8662957f1259947aedaefb7f3c6" - integrity sha512-y0tFHdj2WnTEhxmGUK1T7fgLen7YK4RtfvpLFBXfQkh2eMJAQq24Vx9472lvn5wg0MAO6B+iPfJfzdR9hJYalg== - dependencies: - "@babel/core" "^7.11.6" - "@jest/test-sequencer" "^29.3.1" - "@jest/types" "^29.3.1" - babel-jest "^29.3.1" - chalk "^4.0.0" - ci-info "^3.2.0" - deepmerge "^4.2.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-circus "^29.3.1" - jest-environment-node "^29.3.1" - jest-get-type "^29.2.0" - jest-regex-util "^29.2.0" - jest-resolve "^29.3.1" - jest-runner "^29.3.1" - jest-util "^29.3.1" - jest-validate "^29.3.1" - micromatch "^4.0.4" - parse-json "^5.2.0" - pretty-format "^29.3.1" + pretty-format "^29.7.0" + pure-rand "^6.0.0" slash "^3.0.0" - strip-json-comments "^3.1.1" + stack-utils "^2.0.3" + +jest-cli@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" + integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== + dependencies: + "@jest/core" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + chalk "^4.0.0" + create-jest "^29.7.0" + exit "^0.1.2" + import-local "^3.0.2" + jest-config "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + yargs "^17.3.1" -jest-config@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.4.3.tgz#fca9cdfe6298ae6d04beef1624064d455347c978" - integrity sha512-eCIpqhGnIjdUCXGtLhz4gdDoxKSWXKjzNcc5r+0S1GKOp2fwOipx5mRcwa9GB/ArsxJ1jlj2lmlD9bZAsBxaWQ== +jest-config@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" + integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== dependencies: "@babel/core" "^7.11.6" - "@jest/test-sequencer" "^29.4.3" - "@jest/types" "^29.4.3" - babel-jest "^29.4.3" + "@jest/test-sequencer" "^29.7.0" + "@jest/types" "^29.6.3" + babel-jest "^29.7.0" chalk "^4.0.0" ci-info "^3.2.0" deepmerge "^4.2.2" glob "^7.1.3" graceful-fs "^4.2.9" - jest-circus "^29.4.3" - jest-environment-node "^29.4.3" - jest-get-type "^29.4.3" - jest-regex-util "^29.4.3" - jest-resolve "^29.4.3" - jest-runner "^29.4.3" - jest-util "^29.4.3" - jest-validate "^29.4.3" + jest-circus "^29.7.0" + jest-environment-node "^29.7.0" + jest-get-type "^29.6.3" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-runner "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" micromatch "^4.0.4" parse-json "^5.2.0" - pretty-format "^29.4.3" + pretty-format "^29.7.0" slash "^3.0.0" strip-json-comments "^3.1.1" -jest-diff@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.3.1.tgz#d8215b72fed8f1e647aed2cae6c752a89e757527" - integrity sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw== - dependencies: - chalk "^4.0.0" - diff-sequences "^29.3.1" - jest-get-type "^29.2.0" - pretty-format "^29.3.1" - -jest-diff@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.4.3.tgz#42f4eb34d0bf8c0fb08b0501069b87e8e84df347" - integrity sha512-YB+ocenx7FZ3T5O9lMVMeLYV4265socJKtkwgk/6YUz/VsEzYDkiMuMhWzZmxm3wDRQvayJu/PjkjjSkjoHsCA== +jest-diff@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" + integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== dependencies: chalk "^4.0.0" - diff-sequences "^29.4.3" - jest-get-type "^29.4.3" - pretty-format "^29.4.3" - -jest-docblock@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.2.0.tgz#307203e20b637d97cee04809efc1d43afc641e82" - integrity sha512-bkxUsxTgWQGbXV5IENmfiIuqZhJcyvF7tU4zJ/7ioTutdz4ToB5Yx6JOFBpgI+TphRY4lhOyCWGNH/QFQh5T6A== - dependencies: - detect-newline "^3.0.0" + diff-sequences "^29.6.3" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" -jest-docblock@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.4.3.tgz#90505aa89514a1c7dceeac1123df79e414636ea8" - integrity sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg== +jest-docblock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" + integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== dependencies: detect-newline "^3.0.0" -jest-each@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.3.1.tgz#bc375c8734f1bb96625d83d1ca03ef508379e132" - integrity sha512-qrZH7PmFB9rEzCSl00BWjZYuS1BSOH8lLuC0azQE9lQrAx3PWGKHTDudQiOSwIy5dGAJh7KA0ScYlCP7JxvFYA== - dependencies: - "@jest/types" "^29.3.1" - chalk "^4.0.0" - jest-get-type "^29.2.0" - jest-util "^29.3.1" - pretty-format "^29.3.1" - -jest-each@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.4.3.tgz#a434c199a2f6151c5e3dc80b2d54586bdaa72819" - integrity sha512-1ElHNAnKcbJb/b+L+7j0/w7bDvljw4gTv1wL9fYOczeJrbTbkMGQ5iQPFJ3eFQH19VPTx1IyfePdqSpePKss7Q== +jest-each@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" + integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== dependencies: - "@jest/types" "^29.4.3" + "@jest/types" "^29.6.3" chalk "^4.0.0" - jest-get-type "^29.4.3" - jest-util "^29.4.3" - pretty-format "^29.4.3" + jest-get-type "^29.6.3" + jest-util "^29.7.0" + pretty-format "^29.7.0" jest-environment-enzyme@^7.1.2: version "7.1.2" @@ -10884,43 +12013,31 @@ jest-environment-jsdom@^24.0.0: jest-util "^24.9.0" jsdom "^11.5.1" -jest-environment-jsdom@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-29.3.1.tgz#14ca63c3e0ef5c63c5bcb46033e50bc649e3b639" - integrity sha512-G46nKgiez2Gy4zvYNhayfMEAFlVHhWfncqvqS6yCd0i+a4NsSUD2WtrKSaYQrYiLQaupHXxCRi8xxVL2M9PbhA== +jest-environment-jsdom@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz#d206fa3551933c3fd519e5dfdb58a0f5139a837f" + integrity sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA== dependencies: - "@jest/environment" "^29.3.1" - "@jest/fake-timers" "^29.3.1" - "@jest/types" "^29.3.1" + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" "@types/jsdom" "^20.0.0" "@types/node" "*" - jest-mock "^29.3.1" - jest-util "^29.3.1" + jest-mock "^29.7.0" + jest-util "^29.7.0" jsdom "^20.0.0" -jest-environment-node@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.3.1.tgz#5023b32472b3fba91db5c799a0d5624ad4803e74" - integrity sha512-xm2THL18Xf5sIHoU7OThBPtuH6Lerd+Y1NLYiZJlkE3hbE+7N7r8uvHIl/FkZ5ymKXJe/11SQuf3fv4v6rUMag== +jest-environment-node@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" + integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== dependencies: - "@jest/environment" "^29.3.1" - "@jest/fake-timers" "^29.3.1" - "@jest/types" "^29.3.1" + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" "@types/node" "*" - jest-mock "^29.3.1" - jest-util "^29.3.1" - -jest-environment-node@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.4.3.tgz#579c4132af478befc1889ddc43c2413a9cdbe014" - integrity sha512-gAiEnSKF104fsGDXNkwk49jD/0N0Bqu2K9+aMQXA6avzsA9H3Fiv1PW2D+gzbOSR705bWd2wJZRFEFpV0tXISg== - dependencies: - "@jest/environment" "^29.4.3" - "@jest/fake-timers" "^29.4.3" - "@jest/types" "^29.4.3" - "@types/node" "*" - jest-mock "^29.4.3" - jest-util "^29.4.3" + jest-mock "^29.7.0" + jest-util "^29.7.0" jest-enzyme@^7.1.2: version "7.1.2" @@ -10931,15 +12048,10 @@ jest-enzyme@^7.1.2: enzyme-to-json "^3.3.0" jest-environment-enzyme "^7.1.2" -jest-get-type@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.2.0.tgz#726646f927ef61d583a3b3adb1ab13f3a5036408" - integrity sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA== - -jest-get-type@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.4.3.tgz#1ab7a5207c995161100b5187159ca82dd48b3dd5" - integrity sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg== +jest-get-type@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" + integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== jest-haste-map@^24.9.0: version "24.9.0" @@ -10960,79 +12072,42 @@ jest-haste-map@^24.9.0: optionalDependencies: fsevents "^1.2.7" -jest-haste-map@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.3.1.tgz#af83b4347f1dae5ee8c2fb57368dc0bb3e5af843" - integrity sha512-/FFtvoG1xjbbPXQLFef+WSU4yrc0fc0Dds6aRPBojUid7qlPqZvxdUBA03HW0fnVHXVCnCdkuoghYItKNzc/0A== - dependencies: - "@jest/types" "^29.3.1" - "@types/graceful-fs" "^4.1.3" - "@types/node" "*" - anymatch "^3.0.3" - fb-watchman "^2.0.0" - graceful-fs "^4.2.9" - jest-regex-util "^29.2.0" - jest-util "^29.3.1" - jest-worker "^29.3.1" - micromatch "^4.0.4" - walker "^1.0.8" - optionalDependencies: - fsevents "^2.3.2" - -jest-haste-map@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.4.3.tgz#085a44283269e7ace0645c63a57af0d2af6942e2" - integrity sha512-eZIgAS8tvm5IZMtKlR8Y+feEOMfo2pSQkmNbufdbMzMSn9nitgGxF1waM/+LbryO3OkMcKS98SUb+j/cQxp/vQ== +jest-haste-map@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" + integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== dependencies: - "@jest/types" "^29.4.3" + "@jest/types" "^29.6.3" "@types/graceful-fs" "^4.1.3" "@types/node" "*" anymatch "^3.0.3" fb-watchman "^2.0.0" graceful-fs "^4.2.9" - jest-regex-util "^29.4.3" - jest-util "^29.4.3" - jest-worker "^29.4.3" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + jest-worker "^29.7.0" micromatch "^4.0.4" walker "^1.0.8" optionalDependencies: fsevents "^2.3.2" -jest-leak-detector@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.3.1.tgz#95336d020170671db0ee166b75cd8ef647265518" - integrity sha512-3DA/VVXj4zFOPagGkuqHnSQf1GZBmmlagpguxEERO6Pla2g84Q1MaVIB3YMxgUaFIaYag8ZnTyQgiZ35YEqAQA== - dependencies: - jest-get-type "^29.2.0" - pretty-format "^29.3.1" - -jest-leak-detector@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.4.3.tgz#2b35191d6b35aa0256e63a9b79b0f949249cf23a" - integrity sha512-9yw4VC1v2NspMMeV3daQ1yXPNxMgCzwq9BocCwYrRgXe4uaEJPAN0ZK37nFBhcy3cUwEVstFecFLaTHpF7NiGA== - dependencies: - jest-get-type "^29.4.3" - pretty-format "^29.4.3" - -jest-matcher-utils@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.3.1.tgz#6e7f53512f80e817dfa148672bd2d5d04914a572" - integrity sha512-fkRMZUAScup3txIKfMe3AIZZmPEjWEdsPJFK3AIy5qRohWqQFg1qrmKfYXR9qEkNc7OdAu2N4KPHibEmy4HPeQ== +jest-leak-detector@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" + integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== dependencies: - chalk "^4.0.0" - jest-diff "^29.3.1" - jest-get-type "^29.2.0" - pretty-format "^29.3.1" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" -jest-matcher-utils@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.4.3.tgz#ea68ebc0568aebea4c4213b99f169ff786df96a0" - integrity sha512-TTciiXEONycZ03h6R6pYiZlSkvYgT0l8aa49z/DLSGYjex4orMUcafuLXYyyEDWB1RKglq00jzwY00Ei7yFNVg== +jest-matcher-utils@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" + integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== dependencies: chalk "^4.0.0" - jest-diff "^29.4.3" - jest-get-type "^29.4.3" - pretty-format "^29.4.3" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" jest-message-util@^24.9.0: version "24.9.0" @@ -11048,33 +12123,18 @@ jest-message-util@^24.9.0: slash "^2.0.0" stack-utils "^1.0.1" -jest-message-util@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.3.1.tgz#37bc5c468dfe5120712053dd03faf0f053bd6adb" - integrity sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA== - dependencies: - "@babel/code-frame" "^7.12.13" - "@jest/types" "^29.3.1" - "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^29.3.1" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-message-util@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.4.3.tgz#65b5280c0fdc9419503b49d4f48d4999d481cb5b" - integrity sha512-1Y8Zd4ZCN7o/QnWdMmT76If8LuDv23Z1DRovBj/vcSFNlGCJGoO8D1nJDw1AdyAGUk0myDLFGN5RbNeJyCRGCw== +jest-message-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" + integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== dependencies: "@babel/code-frame" "^7.12.13" - "@jest/types" "^29.4.3" + "@jest/types" "^29.6.3" "@types/stack-utils" "^2.0.0" chalk "^4.0.0" graceful-fs "^4.2.9" micromatch "^4.0.4" - pretty-format "^29.4.3" + pretty-format "^29.7.0" slash "^3.0.0" stack-utils "^2.0.3" @@ -11085,23 +12145,14 @@ jest-mock@^24.9.0: dependencies: "@jest/types" "^24.9.0" -jest-mock@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.3.1.tgz#60287d92e5010979d01f218c6b215b688e0f313e" - integrity sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA== - dependencies: - "@jest/types" "^29.3.1" - "@types/node" "*" - jest-util "^29.3.1" - -jest-mock@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.4.3.tgz#23d84a20a74cdfff0510fdbeefb841ed57b0fe7e" - integrity sha512-LjFgMg+xed9BdkPMyIJh+r3KeHt1klXPJYBULXVVAkbTaaKjPX1o1uVCAZADMEp/kOxGTwy/Ot8XbvgItOrHEg== +jest-mock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" + integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== dependencies: - "@jest/types" "^29.4.3" + "@jest/types" "^29.6.3" "@types/node" "*" - jest-util "^29.4.3" + jest-util "^29.7.0" jest-pnp-resolver@^1.2.2: version "1.2.3" @@ -11113,169 +12164,86 @@ jest-regex-util@^24.9.0: resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.9.0.tgz#c13fb3380bde22bf6575432c493ea8fe37965636" integrity sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA== -jest-regex-util@^29.2.0: - version "29.2.0" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.2.0.tgz#82ef3b587e8c303357728d0322d48bbfd2971f7b" - integrity sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA== +jest-regex-util@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" + integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== -jest-regex-util@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.4.3.tgz#a42616141e0cae052cfa32c169945d00c0aa0bb8" - integrity sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg== - -jest-resolve-dependencies@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.3.1.tgz#a6a329708a128e68d67c49f38678a4a4a914c3bf" - integrity sha512-Vk0cYq0byRw2WluNmNWGqPeRnZ3p3hHmjJMp2dyyZeYIfiBskwq4rpiuGFR6QGAdbj58WC7HN4hQHjf2mpvrLA== - dependencies: - jest-regex-util "^29.2.0" - jest-snapshot "^29.3.1" - -jest-resolve-dependencies@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.4.3.tgz#9ad7f23839a6d88cef91416bda9393a6e9fd1da5" - integrity sha512-uvKMZAQ3nmXLH7O8WAOhS5l0iWyT3WmnJBdmIHiV5tBbdaDZ1wqtNX04FONGoaFvSOSHBJxnwAVnSn1WHdGVaw== - dependencies: - jest-regex-util "^29.4.3" - jest-snapshot "^29.4.3" - -jest-resolve@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.3.1.tgz#9a4b6b65387a3141e4a40815535c7f196f1a68a7" - integrity sha512-amXJgH/Ng712w3Uz5gqzFBBjxV8WFLSmNjoreBGMqxgCz5cH7swmBZzgBaCIOsvb0NbpJ0vgaSFdJqMdT+rADw== +jest-resolve-dependencies@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" + integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== dependencies: - chalk "^4.0.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.3.1" - jest-pnp-resolver "^1.2.2" - jest-util "^29.3.1" - jest-validate "^29.3.1" - resolve "^1.20.0" - resolve.exports "^1.1.0" - slash "^3.0.0" + jest-regex-util "^29.6.3" + jest-snapshot "^29.7.0" -jest-resolve@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.4.3.tgz#3c5b5c984fa8a763edf9b3639700e1c7900538e2" - integrity sha512-GPokE1tzguRyT7dkxBim4wSx6E45S3bOQ7ZdKEG+Qj0Oac9+6AwJPCk0TZh5Vu0xzeX4afpb+eDmgbmZFFwpOw== +jest-resolve@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" + integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== dependencies: chalk "^4.0.0" graceful-fs "^4.2.9" - jest-haste-map "^29.4.3" + jest-haste-map "^29.7.0" jest-pnp-resolver "^1.2.2" - jest-util "^29.4.3" - jest-validate "^29.4.3" + jest-util "^29.7.0" + jest-validate "^29.7.0" resolve "^1.20.0" resolve.exports "^2.0.0" slash "^3.0.0" -jest-runner@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.3.1.tgz#a92a879a47dd096fea46bb1517b0a99418ee9e2d" - integrity sha512-oFvcwRNrKMtE6u9+AQPMATxFcTySyKfLhvso7Sdk/rNpbhg4g2GAGCopiInk1OP4q6gz3n6MajW4+fnHWlU3bA== - dependencies: - "@jest/console" "^29.3.1" - "@jest/environment" "^29.3.1" - "@jest/test-result" "^29.3.1" - "@jest/transform" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - chalk "^4.0.0" - emittery "^0.13.1" - graceful-fs "^4.2.9" - jest-docblock "^29.2.0" - jest-environment-node "^29.3.1" - jest-haste-map "^29.3.1" - jest-leak-detector "^29.3.1" - jest-message-util "^29.3.1" - jest-resolve "^29.3.1" - jest-runtime "^29.3.1" - jest-util "^29.3.1" - jest-watcher "^29.3.1" - jest-worker "^29.3.1" - p-limit "^3.1.0" - source-map-support "0.5.13" - -jest-runner@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.4.3.tgz#68dc82c68645eda12bea42b5beece6527d7c1e5e" - integrity sha512-GWPTEiGmtHZv1KKeWlTX9SIFuK19uLXlRQU43ceOQ2hIfA5yPEJC7AMkvFKpdCHx6pNEdOD+2+8zbniEi3v3gA== +jest-runner@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" + integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== dependencies: - "@jest/console" "^29.4.3" - "@jest/environment" "^29.4.3" - "@jest/test-result" "^29.4.3" - "@jest/transform" "^29.4.3" - "@jest/types" "^29.4.3" + "@jest/console" "^29.7.0" + "@jest/environment" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" "@types/node" "*" chalk "^4.0.0" emittery "^0.13.1" graceful-fs "^4.2.9" - jest-docblock "^29.4.3" - jest-environment-node "^29.4.3" - jest-haste-map "^29.4.3" - jest-leak-detector "^29.4.3" - jest-message-util "^29.4.3" - jest-resolve "^29.4.3" - jest-runtime "^29.4.3" - jest-util "^29.4.3" - jest-watcher "^29.4.3" - jest-worker "^29.4.3" + jest-docblock "^29.7.0" + jest-environment-node "^29.7.0" + jest-haste-map "^29.7.0" + jest-leak-detector "^29.7.0" + jest-message-util "^29.7.0" + jest-resolve "^29.7.0" + jest-runtime "^29.7.0" + jest-util "^29.7.0" + jest-watcher "^29.7.0" + jest-worker "^29.7.0" p-limit "^3.1.0" source-map-support "0.5.13" -jest-runtime@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.3.1.tgz#21efccb1a66911d6d8591276a6182f520b86737a" - integrity sha512-jLzkIxIqXwBEOZx7wx9OO9sxoZmgT2NhmQKzHQm1xwR1kNW/dn0OjxR424VwHHf1SPN6Qwlb5pp1oGCeFTQ62A== - dependencies: - "@jest/environment" "^29.3.1" - "@jest/fake-timers" "^29.3.1" - "@jest/globals" "^29.3.1" - "@jest/source-map" "^29.2.0" - "@jest/test-result" "^29.3.1" - "@jest/transform" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - chalk "^4.0.0" - cjs-module-lexer "^1.0.0" - collect-v8-coverage "^1.0.0" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-haste-map "^29.3.1" - jest-message-util "^29.3.1" - jest-mock "^29.3.1" - jest-regex-util "^29.2.0" - jest-resolve "^29.3.1" - jest-snapshot "^29.3.1" - jest-util "^29.3.1" - slash "^3.0.0" - strip-bom "^4.0.0" - -jest-runtime@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.4.3.tgz#f25db9874dcf35a3ab27fdaabca426666cc745bf" - integrity sha512-F5bHvxSH+LvLV24vVB3L8K467dt3y3dio6V3W89dUz9nzvTpqd/HcT9zfYKL2aZPvD63vQFgLvaUX/UpUhrP6Q== - dependencies: - "@jest/environment" "^29.4.3" - "@jest/fake-timers" "^29.4.3" - "@jest/globals" "^29.4.3" - "@jest/source-map" "^29.4.3" - "@jest/test-result" "^29.4.3" - "@jest/transform" "^29.4.3" - "@jest/types" "^29.4.3" +jest-runtime@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" + integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/globals" "^29.7.0" + "@jest/source-map" "^29.6.3" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" "@types/node" "*" chalk "^4.0.0" cjs-module-lexer "^1.0.0" collect-v8-coverage "^1.0.0" glob "^7.1.3" graceful-fs "^4.2.9" - jest-haste-map "^29.4.3" - jest-message-util "^29.4.3" - jest-mock "^29.4.3" - jest-regex-util "^29.4.3" - jest-resolve "^29.4.3" - jest-snapshot "^29.4.3" - jest-util "^29.4.3" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" slash "^3.0.0" strip-bom "^4.0.0" @@ -11284,65 +12252,31 @@ jest-serializer@^24.9.0: resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.9.0.tgz#e6d7d7ef96d31e8b9079a714754c5d5c58288e73" integrity sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ== -jest-snapshot@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.3.1.tgz#17bcef71a453adc059a18a32ccbd594b8cc4e45e" - integrity sha512-+3JOc+s28upYLI2OJM4PWRGK9AgpsMs/ekNryUV0yMBClT9B1DF2u2qay8YxcQd338PPYSFNb0lsar1B49sLDA== - dependencies: - "@babel/core" "^7.11.6" - "@babel/generator" "^7.7.2" - "@babel/plugin-syntax-jsx" "^7.7.2" - "@babel/plugin-syntax-typescript" "^7.7.2" - "@babel/traverse" "^7.7.2" - "@babel/types" "^7.3.3" - "@jest/expect-utils" "^29.3.1" - "@jest/transform" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/babel__traverse" "^7.0.6" - "@types/prettier" "^2.1.5" - babel-preset-current-node-syntax "^1.0.0" - chalk "^4.0.0" - expect "^29.3.1" - graceful-fs "^4.2.9" - jest-diff "^29.3.1" - jest-get-type "^29.2.0" - jest-haste-map "^29.3.1" - jest-matcher-utils "^29.3.1" - jest-message-util "^29.3.1" - jest-util "^29.3.1" - natural-compare "^1.4.0" - pretty-format "^29.3.1" - semver "^7.3.5" - -jest-snapshot@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.4.3.tgz#183d309371450d9c4a3de7567ed2151eb0e91145" - integrity sha512-NGlsqL0jLPDW91dz304QTM/SNO99lpcSYYAjNiX0Ou+sSGgkanKBcSjCfp/pqmiiO1nQaOyLp6XQddAzRcx3Xw== +jest-snapshot@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" + integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== dependencies: "@babel/core" "^7.11.6" "@babel/generator" "^7.7.2" "@babel/plugin-syntax-jsx" "^7.7.2" "@babel/plugin-syntax-typescript" "^7.7.2" - "@babel/traverse" "^7.7.2" "@babel/types" "^7.3.3" - "@jest/expect-utils" "^29.4.3" - "@jest/transform" "^29.4.3" - "@jest/types" "^29.4.3" - "@types/babel__traverse" "^7.0.6" - "@types/prettier" "^2.1.5" + "@jest/expect-utils" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" babel-preset-current-node-syntax "^1.0.0" chalk "^4.0.0" - expect "^29.4.3" + expect "^29.7.0" graceful-fs "^4.2.9" - jest-diff "^29.4.3" - jest-get-type "^29.4.3" - jest-haste-map "^29.4.3" - jest-matcher-utils "^29.4.3" - jest-message-util "^29.4.3" - jest-util "^29.4.3" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" natural-compare "^1.4.0" - pretty-format "^29.4.3" - semver "^7.3.5" + pretty-format "^29.7.0" + semver "^7.5.3" jest-util@^24.9.0: version "24.9.0" @@ -11362,80 +12296,42 @@ jest-util@^24.9.0: slash "^2.0.0" source-map "^0.6.0" -jest-util@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.3.1.tgz#1dda51e378bbcb7e3bc9d8ab651445591ed373e1" - integrity sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ== - dependencies: - "@jest/types" "^29.3.1" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" - -jest-util@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.4.3.tgz#851a148e23fc2b633c55f6dad2e45d7f4579f496" - integrity sha512-ToSGORAz4SSSoqxDSylWX8JzkOQR7zoBtNRsA7e+1WUX5F8jrOwaNpuh1YfJHJKDHXLHmObv5eOjejUd+/Ws+Q== +jest-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" + integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== dependencies: - "@jest/types" "^29.4.3" + "@jest/types" "^29.6.3" "@types/node" "*" chalk "^4.0.0" ci-info "^3.2.0" graceful-fs "^4.2.9" picomatch "^2.2.3" -jest-validate@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.3.1.tgz#d56fefaa2e7d1fde3ecdc973c7f7f8f25eea704a" - integrity sha512-N9Lr3oYR2Mpzuelp1F8negJR3YE+L1ebk1rYA5qYo9TTY3f9OWdptLoNSPP9itOCBIRBqjt/S5XHlzYglLN67g== - dependencies: - "@jest/types" "^29.3.1" - camelcase "^6.2.0" - chalk "^4.0.0" - jest-get-type "^29.2.0" - leven "^3.1.0" - pretty-format "^29.3.1" - -jest-validate@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.4.3.tgz#a13849dec4f9e95446a7080ad5758f58fa88642f" - integrity sha512-J3u5v7aPQoXPzaar6GndAVhdQcZr/3osWSgTeKg5v574I9ybX/dTyH0AJFb5XgXIB7faVhf+rS7t4p3lL9qFaw== +jest-validate@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" + integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== dependencies: - "@jest/types" "^29.4.3" + "@jest/types" "^29.6.3" camelcase "^6.2.0" chalk "^4.0.0" - jest-get-type "^29.4.3" + jest-get-type "^29.6.3" leven "^3.1.0" - pretty-format "^29.4.3" - -jest-watcher@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.3.1.tgz#3341547e14fe3c0f79f9c3a4c62dbc3fc977fd4a" - integrity sha512-RspXG2BQFDsZSRKGCT/NiNa8RkQ1iKAjrO0//soTMWx/QUt+OcxMqMSBxz23PYGqUuWm2+m2mNNsmj0eIoOaFg== - dependencies: - "@jest/test-result" "^29.3.1" - "@jest/types" "^29.3.1" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - emittery "^0.13.1" - jest-util "^29.3.1" - string-length "^4.0.1" + pretty-format "^29.7.0" -jest-watcher@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.4.3.tgz#e503baa774f0c2f8f3c8db98a22ebf885f19c384" - integrity sha512-zwlXH3DN3iksoIZNk73etl1HzKyi5FuQdYLnkQKm5BW4n8HpoG59xSwpVdFrnh60iRRaRBGw0gcymIxjJENPcA== +jest-watcher@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" + integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== dependencies: - "@jest/test-result" "^29.4.3" - "@jest/types" "^29.4.3" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" emittery "^0.13.1" - jest-util "^29.4.3" + jest-util "^29.7.0" string-length "^4.0.1" jest-worker@^24.9.0: @@ -11464,55 +12360,35 @@ jest-worker@^27.4.5: merge-stream "^2.0.0" supports-color "^8.0.0" -jest-worker@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.3.1.tgz#e9462161017a9bb176380d721cab022661da3d6b" - integrity sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw== - dependencies: - "@types/node" "*" - jest-util "^29.3.1" - merge-stream "^2.0.0" - supports-color "^8.0.0" - -jest-worker@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.4.3.tgz#9a4023e1ea1d306034237c7133d7da4240e8934e" - integrity sha512-GLHN/GTAAMEy5BFdvpUfzr9Dr80zQqBrh0fz1mtRMe05hqP45+HfQltu7oTBfduD0UeZs09d+maFtFYAXFWvAA== +jest-worker@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" + integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== dependencies: "@types/node" "*" - jest-util "^29.4.3" + jest-util "^29.7.0" merge-stream "^2.0.0" supports-color "^8.0.0" -jest@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/jest/-/jest-29.3.1.tgz#c130c0d551ae6b5459b8963747fed392ddbde122" - integrity sha512-6iWfL5DTT0Np6UYs/y5Niu7WIfNv/wRTtN5RSXt2DIEft3dx3zPuw/3WJQBCJfmEzvDiEKwoqMbGD9n49+qLSA== - dependencies: - "@jest/core" "^29.3.1" - "@jest/types" "^29.3.1" - import-local "^3.0.2" - jest-cli "^29.3.1" - -jest@^29.4.1: - version "29.4.3" - resolved "https://registry.yarnpkg.com/jest/-/jest-29.4.3.tgz#1b8be541666c6feb99990fd98adac4737e6e6386" - integrity sha512-XvK65feuEFGZT8OO0fB/QAQS+LGHvQpaadkH5p47/j3Ocqq3xf2pK9R+G0GzgfuhXVxEv76qCOOcMb5efLk6PA== +jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" + integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== dependencies: - "@jest/core" "^29.4.3" - "@jest/types" "^29.4.3" + "@jest/core" "^29.7.0" + "@jest/types" "^29.6.3" import-local "^3.0.2" - jest-cli "^29.4.3" + jest-cli "^29.7.0" jpeg-js@^0.4.1, jpeg-js@^0.4.3: version "0.4.4" resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.4.tgz#a9f1c6f1f9f0fa80cdb3484ed9635054d28936aa" integrity sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg== -js-base64@^3.6.1: - version "3.7.3" - resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.3.tgz#2e784bb0851636bf1e99ef12e4f3a8a8c9b7639f" - integrity sha512-PAr6Xg2jvd7MCR6Ld9Jg3BmTcjYsHEBx1VlwEwULb/qowPf5VD9kEMagj23Gm7JRnSvE/Da/57nChZjnvL8v6A== +js-base64@^3.7.7: + version "3.7.7" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-3.7.7.tgz#e51b84bf78fbf5702b9541e2cb7bfcb893b43e79" + integrity sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw== js-beautify@^1.14.5: version "1.14.7" @@ -11529,11 +12405,6 @@ js-library-detector@^6.5.0: resolved "https://registry.yarnpkg.com/js-library-detector/-/js-library-detector-6.6.0.tgz#b531a4784f8242d87f68f6f3eafc771a0650fb9d" integrity sha512-z8OkDmXALZ22bIzBtIW8cpJ39MV93/Zu1rWrFdhsNw+sity2rOLaGT2kfWWQ6mnRTWs4ddONY5kiroA8e98Gvg== -js-sdsl@^4.1.4: - version "4.2.0" - resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.2.0.tgz#278e98b7bea589b8baaf048c20aeb19eb7ad09d0" - integrity sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ== - js-string-escape@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" @@ -11633,37 +12504,32 @@ jsdom@^20.0.0: ws "^8.11.0" xml-name-validator "^4.0.0" -jsdom@^21.1.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-21.1.1.tgz#ab796361e3f6c01bcfaeda1fea3c06197ac9d8ae" - integrity sha512-Jjgdmw48RKcdAIQyUD1UdBh2ecH7VqwaXPN3ehoZN6MqgVbMn+lRm1aAT1AsdJRAJpwfa4IpwgzySn61h2qu3w== +jsdom@^24.1.0: + version "24.1.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-24.1.0.tgz#0cffdabd42c506788bfecd160e8ac22d4387f971" + integrity sha512-6gpM7pRXCwIOKxX47cgOyvyQDN/Eh0f1MeKySBV2xGdKtqJBLj8P25eY3EVCWo2mglDDzozR2r2MW4T+JiNUZA== dependencies: - abab "^2.0.6" - acorn "^8.8.2" - acorn-globals "^7.0.0" - cssstyle "^3.0.0" - data-urls "^4.0.0" + cssstyle "^4.0.1" + data-urls "^5.0.0" decimal.js "^10.4.3" - domexception "^4.0.0" - escodegen "^2.0.0" form-data "^4.0.0" - html-encoding-sniffer "^3.0.0" - http-proxy-agent "^5.0.0" - https-proxy-agent "^5.0.1" + html-encoding-sniffer "^4.0.0" + http-proxy-agent "^7.0.2" + https-proxy-agent "^7.0.4" is-potential-custom-element-name "^1.0.1" - nwsapi "^2.2.2" + nwsapi "^2.2.10" parse5 "^7.1.2" - rrweb-cssom "^0.6.0" + rrweb-cssom "^0.7.0" saxes "^6.0.0" symbol-tree "^3.2.4" - tough-cookie "^4.1.2" - w3c-xmlserializer "^4.0.0" + tough-cookie "^4.1.4" + w3c-xmlserializer "^5.0.0" webidl-conversions "^7.0.0" - whatwg-encoding "^2.0.0" - whatwg-mimetype "^3.0.0" - whatwg-url "^12.0.1" - ws "^8.13.0" - xml-name-validator "^4.0.0" + whatwg-encoding "^3.1.1" + whatwg-mimetype "^4.0.0" + whatwg-url "^14.0.0" + ws "^8.17.0" + xml-name-validator "^5.0.0" jsesc@^2.5.1: version "2.5.2" @@ -11705,6 +12571,16 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== +json-stable-stringify@^1.0.2: + version "1.1.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.1.1.tgz#52d4361b47d49168bcc4e564189a42e5a7439454" + integrity sha512-SU/971Kt5qVQfJpyDveVhQ/vya+5hvrjClFOcr8c0Fq5aODJjMwutrOfCU+eCnVD5gpx1Q3fEqkyom77zH1iIg== + dependencies: + call-bind "^1.0.5" + isarray "^2.0.5" + jsonify "^0.0.1" + object-keys "^1.1.1" + json-stringify-safe@^5.0.0, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -11743,6 +12619,11 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" +jsonify@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" + integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== + jsonwebtoken@^9.0.2: version "9.0.2" resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz#65ff91f4abef1784697d40952bb1998c504caaf3" @@ -11840,6 +12721,14 @@ klona@^2.0.4: resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== +launch-editor@^2.6.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.8.0.tgz#7255d90bdba414448e2138faa770a74f28451305" + integrity sha512-vJranOAJrI/llyWGRQqiDM+adrw+k83fvmmx3+nV47g3+36xM15jE+zyZ6Ffel02+xSvuM0b2GDRosXZkbb6wA== + dependencies: + picocolors "^1.0.0" + shell-quote "^1.8.1" + lazy-universal-dotenv@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/lazy-universal-dotenv/-/lazy-universal-dotenv-3.0.1.tgz#a6c8938414bca426ab8c9463940da451a911db38" @@ -12007,6 +12896,13 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +locate-path@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-7.2.0.tgz#69cb1779bd90b35ab1e771e1f2f89a202c2a8a8a" + integrity sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA== + dependencies: + p-locate "^6.0.0" + lodash._baseisequal@^3.0.0: version "3.0.7" resolved "https://registry.yarnpkg.com/lodash._baseisequal/-/lodash._baseisequal-3.0.7.tgz#d8025f76339d29342767dcc887ce5cb95a5b51f1" @@ -12175,6 +13071,11 @@ lower-case@^2.0.2: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.13.1.tgz#267a81fbd0881327c46a81c5922606a2cfe336c4" integrity sha512-CHqbAq7NFlW3RSnoWXLJBxCWaZVBrfa9UEHId2M3AW8iEBurbqduNexEUCGc3SHc6iCYXNJCDi903LajSVAEPQ== +lru-cache@^10.2.0: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + lru-cache@^4.1.5: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" @@ -12214,11 +13115,6 @@ lru_map@^0.3.3: resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== -lz-string@^1.4.4: - version "1.4.4" - resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26" - integrity sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ== - lz-string@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" @@ -12285,10 +13181,10 @@ marky@^1.2.0, marky@^1.2.2: resolved "https://registry.yarnpkg.com/marky/-/marky-1.2.5.tgz#55796b688cbd72390d2d399eaaf1832c9413e3c0" integrity sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q== -matchmediaquery@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/matchmediaquery/-/matchmediaquery-0.3.1.tgz#8247edc47e499ebb7c58f62a9ff9ccf5b815c6d7" - integrity sha512-Hlk20WQHRIm9EE9luN1kjRjYXAQToHOIAHPJn9buxBwuhfTHoKUcX+lXBbxc85DVQfXYbEQ4HcwQdd128E3qHQ== +matchmediaquery@^0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/matchmediaquery/-/matchmediaquery-0.4.2.tgz#22582bd4ae63ad9f54c53001bba80cbed0f7eafa" + integrity sha512-wrZpoT50ehYOudhDjt/YvUJc6eUzcdFPdmbizfgvswCKNHD1/OBOHYJpHie+HXpu6bSkEGieFMYk6VuutaiRfA== dependencies: css-mediaquery "^0.1.2" @@ -12567,12 +13463,19 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" -minimist@^1.1.1: +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.1.1, minimist@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== -minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.7: +minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: version "1.2.7" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== @@ -12612,6 +13515,11 @@ minipass@^4.0.0: dependencies: yallist "^4.0.0" +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + minizlib@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" @@ -12666,18 +13574,23 @@ mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -moment-timezone@^0.5.34: - version "0.5.40" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.40.tgz#c148f5149fd91dd3e29bf481abc8830ecba16b89" - integrity sha512-tWfmNkRYmBkPJz5mr9GVDn9vRlVZOTe6yqY92rFxiOdWXbjaR0+9LwQnZGGuNR63X456NqmEkbskte8tWL5ePg== +moment-timezone@^0.5.43: + version "0.5.45" + resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.45.tgz#cb685acd56bac10e69d93c536366eb65aa6bcf5c" + integrity sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ== dependencies: - moment ">= 2.9.0" + moment "^2.29.4" -"moment@>= 2.9.0", moment@^2.25.3, moment@^2.29.1, moment@^2.29.4: +moment@^2.29.4: version "2.29.4" resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== +moment@^2.30.1: + version "2.30.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== + moo@^0.5.0: version "0.5.2" resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.2.tgz#f9fe82473bc7c184b0d32e2215d3f6e67278733c" @@ -12695,11 +13608,6 @@ move-concurrently@^1.0.1: rimraf "^2.5.4" run-queue "^1.0.3" -moxios@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/moxios/-/moxios-0.4.0.tgz#fc0da2c65477d725ca6b9679d58370ed0c52f53b" - integrity sha512-r+7DOsTcoTAwY6TGIDtjeTEBXMW8aGgk74MfASOC1tgYXD8Kq+cnqQHUdMnvfjf/CK7Pg/Wo52ohqy5zlyv9XQ== - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -12743,6 +13651,11 @@ nanoid@^3.3.1, nanoid@^3.3.4: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== +nanoid@^3.3.7: + version "3.3.7" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -12855,7 +13768,7 @@ node-fetch@2.6.7, node-fetch@^2.6.1, node-fetch@^2.6.7: dependencies: whatwg-url "^5.0.0" -node-fetch@^2.6.12: +node-fetch@^2.6.12, node-fetch@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== @@ -12901,11 +13814,13 @@ node-libs-browser@^2.2.1: util "^0.11.0" vm-browserify "^1.0.1" -node-mocks-http@^1.8.1: - version "1.12.1" - resolved "https://registry.yarnpkg.com/node-mocks-http/-/node-mocks-http-1.12.1.tgz#838e176019daf177caff6bb8534e3a32646e7531" - integrity sha512-jrA7Sn3qI6GsHgWtUW3gMj0vO6Yz0nJjzg3jRZYjcfj4tzi8oWPauDK1qHVJoAxTbwuDHF1JiM9GISZ/ocI/ig== +node-mocks-http@^1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/node-mocks-http/-/node-mocks-http-1.15.0.tgz#fe7bb1efa4ab395739f4097b44f745440326a1b3" + integrity sha512-3orGBAxXrnwz3ixU8AZpa0x8srAvVSHvbWanAqd5F0zVCVA2QstxaVcTSarFcjz4+pFSnR1zm28MsV83s/BtmA== dependencies: + "@types/express" "^4.17.21" + "@types/node" "^20.10.6" accepts "^1.3.7" content-disposition "^0.5.3" depd "^1.1.0" @@ -12927,10 +13842,10 @@ node-releases@^2.0.6: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.8.tgz#0f349cdc8fcfa39a92ac0be9bc48b7706292b9ae" integrity sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A== -nodemon@^2.0.7: - version "2.0.20" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.20.tgz#e3537de768a492e8d74da5c5813cb0c7486fc701" - integrity sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw== +nodemon@^2.0.22: + version "2.0.22" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.22.tgz#182c45c3a78da486f673d6c1702e00728daf5258" + integrity sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ== dependencies: chokidar "^3.5.2" debug "^3.2.7" @@ -13040,6 +13955,11 @@ nwsapi@^2.0.7: resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.7.tgz#738e0707d3128cb750dddcfe90e4610482df0f30" integrity sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ== +nwsapi@^2.2.10: + version "2.2.12" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.12.tgz#fb6af5c0ec35b27b4581eb3bbad34ec9e5c696f8" + integrity sha512-qXDmcVlZV4XRtKFzddidpfVP4oMSGhga+xdMc25mv8kaLUHtgzCDhUxkrN8exkGdTlLNaXj7CV3GtON7zuGZ+w== + nwsapi@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.2.tgz#e5418863e7905df67d51ec95938d67bf801f0bb0" @@ -13119,7 +14039,7 @@ object.assign@^4.1.5: has-symbols "^1.0.3" object-keys "^1.1.1" -object.entries@^1.1.0, object.entries@^1.1.1, object.entries@^1.1.2, object.entries@^1.1.6: +object.entries@^1.1.0, object.entries@^1.1.1, object.entries@^1.1.2: version "1.1.6" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.6.tgz#9737d0e5b8291edd340a3e3264bb8a3b00d5fa23" integrity sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w== @@ -13128,7 +14048,16 @@ object.entries@^1.1.0, object.entries@^1.1.1, object.entries@^1.1.2, object.entr define-properties "^1.1.4" es-abstract "^1.20.4" -"object.fromentries@^2.0.0 || ^1.0.0", object.fromentries@^2.0.5, object.fromentries@^2.0.6: +object.entries@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.8.tgz#bffe6f282e01f4d17807204a24f8edd823599c41" + integrity sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +"object.fromentries@^2.0.0 || ^1.0.0": version "2.0.6" resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.6.tgz#cdb04da08c539cffa912dcd368b886e0904bfa73" integrity sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg== @@ -13137,6 +14066,16 @@ object.entries@^1.1.0, object.entries@^1.1.1, object.entries@^1.1.2, object.entr define-properties "^1.1.4" es-abstract "^1.20.4" +object.fromentries@^2.0.7, object.fromentries@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65" + integrity sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" + object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.2: version "2.1.5" resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.5.tgz#db5a9002489b64eef903df81d6623c07e5b4b4d3" @@ -13158,13 +14097,14 @@ object.getownpropertydescriptors@^2.1.6: es-abstract "^1.22.1" safe-array-concat "^1.0.0" -object.hasown@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.2.tgz#f919e21fad4eb38a57bc6345b3afd496515c3f92" - integrity sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw== +object.hasown@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.4.tgz#e270ae377e4c120cdcb7656ce66884a6218283dc" + integrity sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg== dependencies: - define-properties "^1.1.4" - es-abstract "^1.20.4" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" object.pick@^1.3.0: version "1.3.0" @@ -13173,7 +14113,7 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" -object.values@^1.1.0, object.values@^1.1.1, object.values@^1.1.5, object.values@^1.1.6: +object.values@^1.1.0, object.values@^1.1.1: version "1.1.6" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw== @@ -13182,6 +14122,15 @@ object.values@^1.1.0, object.values@^1.1.1, object.values@^1.1.5, object.values@ define-properties "^1.1.4" es-abstract "^1.20.4" +object.values@^1.1.7, object.values@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.0.tgz#65405a9d92cee68ac2d303002e0b8470a4d9ab1b" + integrity sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + objectorarray@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/objectorarray/-/objectorarray-1.0.5.tgz#2c05248bbefabd8f43ad13b41085951aac5e68a5" @@ -13197,7 +14146,7 @@ octicons-modular@^1.0.7: resolved "https://registry.yarnpkg.com/octicons-modular/-/octicons-modular-1.0.7.tgz#022a964306cf3991f50370d3669c04b4c80bf6d6" integrity sha512-90ZEWv3cVNT0CjApsKrGIbynu+BG8Ou0RrG3Q3ntHzvzCs9fasxH1EikN37Ff1b80+nyCuD02g1I0gIHCfVBUQ== -octicons-react@^1.0.4: +octicons-react@^1.0.9: version "1.0.9" resolved "https://registry.yarnpkg.com/octicons-react/-/octicons-react-1.0.9.tgz#9937966b527521c1eb8d15998eaf700ee2b96a1f" integrity sha512-oAORK1SBacavXa9SmME9Z4lZxgAGI9QVIVUS4fRUG46kapuBLdQwg+oCobI5qH/4G8OywCH8+iW/UzC5a9MvYw== @@ -13261,13 +14210,15 @@ open@^8.0.9, open@^8.4.0: is-docker "^2.1.1" is-wsl "^2.2.0" -optimism@^0.16.1: - version "0.16.2" - resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.16.2.tgz#519b0c78b3b30954baed0defe5143de7776bf081" - integrity sha512-zWNbgWj+3vLEjZNIh/okkY2EUfX+vB9TJopzIZwT1xxaMqC5hRLLraePod4c5n4He08xuXNH+zhKFFCu390wiQ== +optimism@^0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.18.0.tgz#e7bb38b24715f3fdad8a9a7fc18e999144bbfa63" + integrity sha512-tGn8+REwLRNFnb9WmcY5IfpOqeX2kpaYJ1s6Ae3mn12AeydLkR3j+jSCmVQFoXqU8D41PAJ1RG1rCRNWmNZVmQ== dependencies: + "@wry/caches" "^1.0.0" "@wry/context" "^0.7.0" - "@wry/trie" "^0.3.0" + "@wry/trie" "^0.4.3" + tslib "^2.3.0" optionator@^0.8.1: version "0.8.3" @@ -13281,17 +14232,17 @@ optionator@^0.8.1: type-check "~0.3.2" word-wrap "~1.2.3" -optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" - integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== +optionator@^0.9.3: + version "0.9.4" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== dependencies: deep-is "^0.1.3" fast-levenshtein "^2.0.6" levn "^0.4.1" prelude-ls "^1.2.1" type-check "^0.4.0" - word-wrap "^1.2.3" + word-wrap "^1.2.5" os-browserify@^0.3.0: version "0.3.0" @@ -13353,6 +14304,13 @@ p-limit@^3.0.2, p-limit@^3.1.0: dependencies: yocto-queue "^0.1.0" +p-limit@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-4.0.0.tgz#914af6544ed32bfa54670b061cafcbd04984b644" + integrity sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ== + dependencies: + yocto-queue "^1.0.0" + p-locate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" @@ -13374,6 +14332,13 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" +p-locate@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-6.0.0.tgz#3da9a49d4934b901089dca3302fa65dc5a05c04f" + integrity sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw== + dependencies: + p-limit "^4.0.0" + p-map@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" @@ -13436,6 +14401,11 @@ pac-resolver@^7.0.0: ip "^1.1.8" netmask "^2.0.2" +package-json-from-dist@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz#e501cd3094b278495eb4258d4c9f6d5ac3019f00" + integrity sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw== + packet-reader@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74" @@ -13566,25 +14536,26 @@ pascalcase@^0.1.1: resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw== -patch-package@^6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.5.1.tgz#3e5d00c16997e6160291fee06a521c42ac99b621" - integrity sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA== +patch-package@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-8.0.0.tgz#d191e2f1b6e06a4624a0116bcb88edd6714ede61" + integrity sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA== dependencies: "@yarnpkg/lockfile" "^1.1.0" chalk "^4.1.2" - cross-spawn "^6.0.5" + ci-info "^3.7.0" + cross-spawn "^7.0.3" find-yarn-workspace-root "^2.0.0" fs-extra "^9.0.0" - is-ci "^2.0.0" + json-stable-stringify "^1.0.2" klaw-sync "^6.0.0" minimist "^1.2.6" open "^7.4.2" rimraf "^2.6.3" - semver "^5.6.0" + semver "^7.5.3" slash "^2.0.0" tmp "^0.0.33" - yaml "^1.10.2" + yaml "^2.2.2" path-browserify@0.0.1: version "0.0.1" @@ -13618,6 +14589,11 @@ path-exists@^4.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== +path-exists@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-5.0.0.tgz#a6aad9489200b21fab31e49cf09277e5116fb9e7" + integrity sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ== + path-is-absolute@1.0.1, path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -13638,6 +14614,14 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -13690,12 +14674,22 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== +pg-cloudflare@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz#e6d5833015b170e23ae819e8c5d7eaedb472ca98" + integrity sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q== + pg-connection-string@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.5.0.tgz#538cadd0f7e603fc09a12590f3b8a452c2c0cf34" integrity sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ== -pg-hstore@^2.3.3: +pg-connection-string@^2.6.1, pg-connection-string@^2.6.4: + version "2.6.4" + resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.6.4.tgz#f543862adfa49fa4e14bc8a8892d2a84d754246d" + integrity sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA== + +pg-hstore@^2.3.4: version "2.3.4" resolved "https://registry.yarnpkg.com/pg-hstore/-/pg-hstore-2.3.4.tgz#4425e3e2a3e15d2a334c35581186c27cf2e9b8dd" integrity sha512-N3SGs/Rf+xA1M2/n0JBiXFDVMzdekwLZLAO0g7mpDY9ouX+fDI7jS6kTq3JujmYbtNSJ53TJ0q4G98KVZSM4EA== @@ -13712,12 +14706,22 @@ pg-pool@^3.5.2: resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.5.2.tgz#ed1bed1fb8d79f1c6fd5fb1c99e990fbf9ddf178" integrity sha512-His3Fh17Z4eg7oANLob6ZvH8xIVen3phEZh2QuyrIl4dQSDVEabNducv6ysROKpDNPSD+12tONZVWfSgMvDD9w== -pg-protocol@*, pg-protocol@^1.5.0: +pg-pool@^3.6.2: + version "3.6.2" + resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.6.2.tgz#3a592370b8ae3f02a7c8130d245bc02fa2c5f3f2" + integrity sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg== + +pg-protocol@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.5.0.tgz#b5dd452257314565e2d54ab3c132adc46565a6a0" integrity sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ== -pg-types@^2.1.0, pg-types@^2.2.0: +pg-protocol@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.6.1.tgz#21333e6d83b01faaebfe7a33a7ad6bfd9ed38cb3" + integrity sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg== + +pg-types@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== @@ -13728,7 +14732,20 @@ pg-types@^2.1.0, pg-types@^2.2.0: postgres-date "~1.0.4" postgres-interval "^1.1.0" -pg@^8.6.0, pg@^8.8.0: +pg@^8.12.0: + version "8.12.0" + resolved "https://registry.yarnpkg.com/pg/-/pg-8.12.0.tgz#9341724db571022490b657908f65aee8db91df79" + integrity sha512-A+LHUSnwnxrnL/tZ+OLfqR1SxLN3c/pgDztZ47Rpbsd4jUytsTtwQo/TLPRzPJMp/1pbhYVhH9cuSZLAajNfjQ== + dependencies: + pg-connection-string "^2.6.4" + pg-pool "^3.6.2" + pg-protocol "^1.6.1" + pg-types "^2.1.0" + pgpass "1.x" + optionalDependencies: + pg-cloudflare "^1.1.1" + +pg@^8.8.0: version "8.8.0" resolved "https://registry.yarnpkg.com/pg/-/pg-8.8.0.tgz#a77f41f9d9ede7009abfca54667c775a240da686" integrity sha512-UXYN0ziKj+AeNNP7VDMwrehpACThH7LUl/p8TDFpEUuSejCUIwGSfxpHsPvtM6/WXFy6SU4E5RG4IJV/TZAGjw== @@ -13758,6 +14775,11 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== +picocolors@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" + integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== + picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.0, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" @@ -13826,6 +14848,13 @@ pkg-dir@^5.0.0: dependencies: find-up "^5.0.0" +pkg-dir@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-7.0.0.tgz#8f0c08d6df4476756c5ff29b3282d0bab7517d11" + integrity sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA== + dependencies: + find-up "^6.3.0" + pn@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" @@ -13885,6 +14914,11 @@ postcss-modules-extract-imports@^3.0.0: resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d" integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw== +postcss-modules-extract-imports@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz#b4497cb85a9c0c4b5aabeb759bb25e8d89f15002" + integrity sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q== + postcss-modules-local-by-default@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz#bb14e0cc78279d504dbdcbfd7e0ca28993ffbbb0" @@ -13904,6 +14938,15 @@ postcss-modules-local-by-default@^4.0.0: postcss-selector-parser "^6.0.2" postcss-value-parser "^4.1.0" +postcss-modules-local-by-default@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz#f1b9bd757a8edf4d8556e8d0f4f894260e3df78f" + integrity sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw== + dependencies: + icss-utils "^5.0.0" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.1.0" + postcss-modules-scope@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee" @@ -13919,6 +14962,13 @@ postcss-modules-scope@^3.0.0: dependencies: postcss-selector-parser "^6.0.4" +postcss-modules-scope@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz#a43d28289a169ce2c15c00c4e64c0858e43457d5" + integrity sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ== + dependencies: + postcss-selector-parser "^6.0.4" + postcss-modules-values@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" @@ -13964,14 +15014,14 @@ postcss@^8.2.15: picocolors "^1.0.0" source-map-js "^1.0.2" -postcss@^8.4.19: - version "8.4.20" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.20.tgz#64c52f509644cecad8567e949f4081d98349dc56" - integrity sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g== +postcss@^8.4.33: + version "8.4.39" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.39.tgz#aa3c94998b61d3a9c259efa51db4b392e1bde0e3" + integrity sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw== dependencies: - nanoid "^3.3.4" - picocolors "^1.0.0" - source-map-js "^1.0.2" + nanoid "^3.3.7" + picocolors "^1.0.1" + source-map-js "^1.2.0" postgres-array@~2.0.0: version "2.0.0" @@ -14022,10 +15072,10 @@ prettier-linter-helpers@^1.0.0: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.0.tgz#b6a5bf1284026ae640f17f7ff5658a7567fc0d18" integrity sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w== -prettier@^2.8.4: - version "2.8.4" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.4.tgz#34dd2595629bfbb79d344ac4a91ff948694463c3" - integrity sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw== +prettier@^2.8.8: + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== pretty-error@^2.1.1: version "2.1.2" @@ -14052,21 +15102,12 @@ pretty-format@^27.0.2: ansi-styles "^5.0.0" react-is "^17.0.1" -pretty-format@^29.0.0, pretty-format@^29.3.1: - version "29.3.1" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.3.1.tgz#1841cac822b02b4da8971dacb03e8a871b4722da" - integrity sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg== - dependencies: - "@jest/schemas" "^29.0.0" - ansi-styles "^5.0.0" - react-is "^18.0.0" - -pretty-format@^29.4.3: - version "29.4.3" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.4.3.tgz#25500ada21a53c9e8423205cf0337056b201244c" - integrity sha512-cvpcHTc42lcsvOOAzd3XuNWTcvk1Jmnzqeu+WsOuiPmxUJTnkbAcFNsRKvEpBEUFVUgy/GTZLulZDcDEi+CIlA== +pretty-format@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" + integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== dependencies: - "@jest/schemas" "^29.4.3" + "@jest/schemas" "^29.6.3" ansi-styles "^5.0.0" react-is "^18.0.0" @@ -14273,21 +15314,21 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -punycode@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" - integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== +punycode@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== -puppeteer-core@21.7.0: - version "21.7.0" - resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-21.7.0.tgz#c0abb98cbd17dbd7ee317b4257958337fa25d2c7" - integrity sha512-elPYPozrgiM3phSy7VDUJCVWQ07SPnOm78fpSaaSNFoQx5sur/MqhTSro9Wz8lOEjqCykGC6WRkwxDgmqcy1dQ== +puppeteer-core@21.11.0: + version "21.11.0" + resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-21.11.0.tgz#6c60ec350f1a3a2152179c68166da6edfce18a23" + integrity sha512-ArbnyA3U5SGHokEvkfWjW+O8hOxV1RSJxOgriX/3A4xZRqixt9ZFHD0yPgZQF05Qj0oAqi8H/7stDorjoHY90Q== dependencies: "@puppeteer/browsers" "1.9.1" - chromium-bidi "0.5.2" + chromium-bidi "0.5.8" cross-fetch "4.0.0" debug "4.3.4" - devtools-protocol "0.0.1203626" + devtools-protocol "0.0.1232444" ws "8.16.0" puppeteer-core@^13.7.0: @@ -14308,14 +15349,19 @@ puppeteer-core@^13.7.0: unbzip2-stream "1.4.3" ws "8.5.0" -puppeteer@^21.7.0: - version "21.7.0" - resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-21.7.0.tgz#c4b46ef28a2986f9c536eb086ab47c8dea80e4f9" - integrity sha512-Yy+UUy0b9siJezbhHO/heYUoZQUwyqDK1yOQgblTt0l97tspvDVFkcW9toBlnSvSfkDmMI3Dx9cZL6R8bDArHA== +puppeteer@^21.11.0: + version "21.11.0" + resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-21.11.0.tgz#46e64067b742b0e17a3b8dc668bc437f45cdd9f1" + integrity sha512-9jTHuYe22TD3sNxy0nEIzC7ZrlRnDgeX3xPkbS7PnbdwYjl2o/z/YuCrRBwezdKpbTDTJ4VqIggzNyeRcKq3cg== dependencies: "@puppeteer/browsers" "1.9.1" - cosmiconfig "8.3.6" - puppeteer-core "21.7.0" + cosmiconfig "9.0.0" + puppeteer-core "21.11.0" + +pure-rand@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.1.0.tgz#d173cf23258231976ccbdb05247c9787957604f2" + integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA== qs@6.11.0, qs@^6.10.0, qs@^6.11.0: version "6.11.0" @@ -14329,11 +15375,6 @@ qs@6.5.1: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" integrity sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A== -qs@6.9.6: - version "6.9.6" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee" - integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ== - qs@~6.5.2: version "6.5.3" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" @@ -14424,16 +15465,6 @@ raw-body@2.3.2: iconv-lite "0.4.19" unpipe "1.0.0" -raw-body@2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.2.tgz#baf3e9c21eebced59dd6533ac872b71f7b61cb32" - integrity sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ== - dependencies: - bytes "3.1.1" - http-errors "1.8.1" - iconv-lite "0.4.24" - unpipe "1.0.0" - raw-body@2.5.1: version "2.5.1" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" @@ -14444,6 +15475,26 @@ raw-body@2.5.1: iconv-lite "0.4.24" unpipe "1.0.0" +raw-body@2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +raw-body@3.0.0-beta.1: + version "3.0.0-beta.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-3.0.0-beta.1.tgz#b202356e7adb97dd5f35604aac992a6ccce3bbfd" + integrity sha512-XlSTHr67bCjSo5aOfAnN3x507zGvi3unF65BW57limYkc2ws/XB0mLUtJvvP7JGFeSPsYrlCv1ZrPGh0cwDxPQ== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.5.2" + unpipe "1.0.0" + raw-loader@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-4.0.2.tgz#1aac6b7d1ad1501e66efdac1522c73e59a584eb6" @@ -14462,21 +15513,21 @@ raw-loader@^4.0.2: newrelic "4.6.0" on-finished "2.3.0" -react-bootstrap@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/react-bootstrap/-/react-bootstrap-2.7.0.tgz#4a8f0311bccac477dc925366763c536f46e4393b" - integrity sha512-Jcrn6aUuRVBeSB6dzKODKZU1TONOdhAxu0IDm4Sv74SJUm98dMdhSotF2SNvFEADANoR+stV+7TK6SNX1wWu5w== - dependencies: - "@babel/runtime" "^7.17.2" - "@restart/hooks" "^0.4.6" - "@restart/ui" "^1.4.1" - "@types/react-transition-group" "^4.4.4" - classnames "^2.3.1" +react-bootstrap@^2.10.4: + version "2.10.4" + resolved "https://registry.yarnpkg.com/react-bootstrap/-/react-bootstrap-2.10.4.tgz#ed92f5f8225a44919a7707829bac879558b71b70" + integrity sha512-W3398nBM2CBfmGP2evneEO3ZZwEMPtHs72q++eNw60uDGDAdiGn0f9yNys91eo7/y8CTF5Ke1C0QO8JFVPU40Q== + dependencies: + "@babel/runtime" "^7.24.7" + "@restart/hooks" "^0.4.9" + "@restart/ui" "^1.6.9" + "@types/react-transition-group" "^4.4.6" + classnames "^2.3.2" dom-helpers "^5.2.1" invariant "^2.2.4" prop-types "^15.8.1" prop-types-extra "^1.1.0" - react-transition-group "^4.4.2" + react-transition-group "^4.4.5" uncontrollable "^7.2.1" warning "^4.0.3" @@ -14501,13 +15552,13 @@ react-docgen@^5.0.0: node-dir "^0.1.10" strip-indent "^3.0.0" -react-dom@^18.2.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" - integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== +react-dom@^18.3.1: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" + integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== dependencies: loose-envify "^1.1.0" - scheduler "^0.23.0" + scheduler "^0.23.2" react-element-to-jsx-string@^14.3.4: version "14.3.4" @@ -14523,7 +15574,7 @@ react-fast-compare@^3.1.1: resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== -react-helmet@^6.0.0: +react-helmet@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/react-helmet/-/react-helmet-6.1.0.tgz#a750d5165cb13cf213e44747502652e794468726" integrity sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw== @@ -14540,7 +15591,7 @@ react-html-parser@^2.0.2: dependencies: htmlparser2 "^3.9.0" -react-id-generator@^3.0.0: +react-id-generator@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/react-id-generator/-/react-id-generator-3.0.2.tgz#e5bc5bae463907755e809beb625fafd67ded5d56" integrity sha512-d0rqWzZ6g0P9agHtA7wX/ErQ4iV/657/0Oz+SX3kid7nR4d0YwaWjjOTIrgYHv2lICZKrxIH4BaKppKrM8fRfw== @@ -14579,37 +15630,37 @@ react-refresh@^0.11.0: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046" integrity sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A== -react-responsive@^9.0.0-beta.10: - version "9.0.2" - resolved "https://registry.yarnpkg.com/react-responsive/-/react-responsive-9.0.2.tgz#34531ca77a61e7a8775714016d21241df7e4205c" - integrity sha512-+4CCab7z8G8glgJoRjAwocsgsv6VA2w7JPxFWHRc7kvz8mec1/K5LutNC2MG28Mn8mu6+bu04XZxHv5gyfT7xQ== +react-responsive@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/react-responsive/-/react-responsive-10.0.0.tgz#657c7a90823cd565f43aa5918bd8eb0cd2c91c91" + integrity sha512-N6/UiRLGQyGUqrarhBZmrSmHi2FXSD++N5VbSKsBBvWfG0ZV7asvUBluSv5lSzdMyEVjzZ6Y8DL4OHABiztDOg== dependencies: hyphenate-style-name "^1.0.0" - matchmediaquery "^0.3.0" + matchmediaquery "^0.4.2" prop-types "^15.6.1" - shallow-equal "^1.2.1" + shallow-equal "^3.1.0" -react-router-bootstrap@^0.26.2: - version "0.26.2" - resolved "https://registry.yarnpkg.com/react-router-bootstrap/-/react-router-bootstrap-0.26.2.tgz#255ffb662b77141624d89d97105ba4f93863e664" - integrity sha512-YlpI9Xi+Uqp6zFAUO8D/wu6P8mr1ujqq+0V5MhJG1kx9dr/95fAMoGk4J+/CsysOkwtR3tYSac4DDWmHwXvC8w== +react-router-bootstrap@^0.26.3: + version "0.26.3" + resolved "https://registry.yarnpkg.com/react-router-bootstrap/-/react-router-bootstrap-0.26.3.tgz#4bad61ed1e9ce4a325ca1af329a86bd0ba55789c" + integrity sha512-cBgcWekti6lFRl/vXP8ZfKuA/0Qe7L5xBjQ6OwbGI30+NSAAH/YZGbO6whSeBWFILn6uTVOX939HDGhs+5WzOw== dependencies: prop-types "^15.7.2" -react-router-dom@^6.8.1: - version "6.8.1" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.8.1.tgz#7e136b67d9866f55999e9a8482c7008e3c575ac9" - integrity sha512-67EXNfkQgf34P7+PSb6VlBuaacGhkKn3kpE51+P6zYSG2kiRoumXEL6e27zTa9+PGF2MNXbgIUHTVlleLbIcHQ== +react-router-dom@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.24.1.tgz#b1a22f7d6c5a1bfce30732bd370713f991ab4de4" + integrity sha512-U19KtXqooqw967Vw0Qcn5cOvrX5Ejo9ORmOtJMzYWtCT4/WOfFLIZGGsVLxcd9UkBO0mSTZtXqhZBsWlHr7+Sg== dependencies: - "@remix-run/router" "1.3.2" - react-router "6.8.1" + "@remix-run/router" "1.17.1" + react-router "6.24.1" -react-router@6.8.1: - version "6.8.1" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.8.1.tgz#e362caf93958a747c649be1b47cd505cf28ca63e" - integrity sha512-Jgi8BzAJQ8MkPt8ipXnR73rnD7EmZ0HFFb7jdQU24TynGW1Ooqin2KVDN9voSC+7xhqbbCd2cjGUepb6RObnyg== +react-router@6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.24.1.tgz#5a3bbba0000afba68d42915456ca4c806f37a7de" + integrity sha512-PTXFXGK2pyXpHzVo3rR9H7ip4lSPZZc0bHG5CARmj65fTT6qG7sTngmb6lcYu1gf3y/8KxORoy9yn59pGpCnpg== dependencies: - "@remix-run/router" "1.3.2" + "@remix-run/router" "1.17.1" react-side-effect@^2.1.0: version "2.1.2" @@ -14636,7 +15687,7 @@ react-test-renderer@^16.0.0-0: react-is "^16.8.6" scheduler "^0.19.1" -react-transition-group@^4.4.2: +react-transition-group@^4.4.5: version "4.4.5" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1" integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g== @@ -14646,10 +15697,10 @@ react-transition-group@^4.4.2: loose-envify "^1.4.0" prop-types "^15.6.2" -react@^18.2.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" - integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== +react@^18.3.1: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" + integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== dependencies: loose-envify "^1.1.0" @@ -14774,6 +15825,19 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" +reflect.getprototypeof@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz#3ab04c32a8390b770712b7a8633972702d278859" + integrity sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.1" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + globalthis "^1.0.3" + which-builtin-type "^1.1.3" + reflect.ownkeys@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz#749aceec7f3fdf8b63f927a04809e90c5c0b3460" @@ -14806,6 +15870,11 @@ regenerator-runtime@^0.13.11, regenerator-runtime@^0.13.7: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== +regenerator-runtime@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== + regenerator-transform@^0.15.1: version "0.15.1" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.1.tgz#f6c4e99fc1b4591f780db2586328e4d9a9d8dc56" @@ -14813,6 +15882,13 @@ regenerator-transform@^0.15.1: dependencies: "@babel/runtime" "^7.8.4" +regenerator-transform@^0.15.2: + version "0.15.2" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.2.tgz#5bbae58b522098ebdf09bca2f83838929001c7a4" + integrity sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg== + dependencies: + "@babel/runtime" "^7.8.4" + regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" @@ -14840,11 +15916,6 @@ regexp.prototype.flags@^1.5.2: es-errors "^1.3.0" set-function-name "^2.0.1" -regexpp@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" - integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== - regexpu-core@^5.2.1: version "5.2.2" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.2.2.tgz#3e4e5d12103b64748711c3aad69934d7718e75fc" @@ -14857,6 +15928,18 @@ regexpu-core@^5.2.1: unicode-match-property-ecmascript "^2.0.0" unicode-match-property-value-ecmascript "^2.1.0" +regexpu-core@^5.3.1: + version "5.3.2" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b" + integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ== + dependencies: + "@babel/regjsgen" "^0.8.0" + regenerate "^1.4.2" + regenerate-unicode-properties "^10.1.0" + regjsparser "^0.9.1" + unicode-match-property-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.1.0" + regjsgen@^0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.7.1.tgz#ee5ef30e18d3f09b7c369b76e7c2373ed25546f6" @@ -14869,6 +15952,11 @@ regjsparser@^0.9.1: dependencies: jsesc "~0.5.0" +rehackt@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/rehackt/-/rehackt-0.1.0.tgz#a7c5e289c87345f70da8728a7eb878e5d03c696b" + integrity sha512-7kRDOuLHB87D/JESKxQoRwv4DzbIdwkAGQ7p6QKGdVlY1IZheUnVhlk/4UZlNUVxdAXpyxikE3URsG067ybVzw== + relateurl@^0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" @@ -15055,11 +16143,6 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== -resolve.exports@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" - integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== - resolve.exports@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.0.tgz#c1a0028c2d166ec2fbf7d0644584927e76e7400e" @@ -15074,12 +16157,12 @@ resolve@^1.10.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.2 path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -resolve@^2.0.0-next.3: - version "2.0.0-next.4" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.4.tgz#3d37a113d6429f496ec4752d2a2e58efb1fd4660" - integrity sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ== +resolve@^2.0.0-next.5: + version "2.0.0-next.5" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" + integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== dependencies: - is-core-module "^2.9.0" + is-core-module "^2.13.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -15101,7 +16184,7 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== -retry-as-promised@^7.0.3: +retry-as-promised@^7.0.4: version "7.0.4" resolved "https://registry.yarnpkg.com/retry-as-promised/-/retry-as-promised-7.0.4.tgz#9df73adaeea08cb2948b9d34990549dc13d800a2" integrity sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA== @@ -15143,12 +16226,13 @@ robots-parser@^3.0.0: resolved "https://registry.yarnpkg.com/robots-parser/-/robots-parser-3.0.1.tgz#3d8a3cdfa8ac240cbb062a4bd16fcc0e0fb9ed23" integrity sha512-s+pyvQeIKIZ0dx5iJiQk1tPLJAWln39+MI5jtM8wnyws+G5azk+dMnMX0qfbqNetKKNgcWWOdi0sfm+FbQbgdQ== -router@2.0.0-beta.1: - version "2.0.0-beta.1" - resolved "https://registry.yarnpkg.com/router/-/router-2.0.0-beta.1.tgz#86fb03143cee259497d8b658c7f13b1d20049331" - integrity sha512-GLoYgkhAGAiwVda5nt6Qd4+5RAPuQ4WIYLlZ+mxfYICI+22gnIB3eCfmhgV8+uJNPS1/39DOYi/vdrrz0/ouKA== +router@2.0.0-beta.2: + version "2.0.0-beta.2" + resolved "https://registry.yarnpkg.com/router/-/router-2.0.0-beta.2.tgz#c8da30dea93ecb628d28116b63ad83f5021b07af" + integrity sha512-ascmzrv4IAB64SpWzFwYOA+jz6PaUbrzHLPsQrPjQ3uQTL2qlhwY9S2sRvvBMgUISQptQG457jcWWcWqtwrbag== dependencies: array-flatten "3.0.0" + is-promise "4.0.0" methods "~1.1.2" parseurl "~1.3.3" path-to-regexp "3.2.0" @@ -15160,6 +16244,11 @@ rrweb-cssom@^0.6.0: resolved "https://registry.yarnpkg.com/rrweb-cssom/-/rrweb-cssom-0.6.0.tgz#ed298055b97cbddcdeb278f904857629dec5e0e1" integrity sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw== +rrweb-cssom@^0.7.0: + version "0.7.1" + resolved "https://registry.yarnpkg.com/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz#c73451a484b86dd7cfb1e0b2898df4b703183e4b" + integrity sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg== + rst-selector-parser@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz#81b230ea2fcc6066c89e3472de794285d9b03d91" @@ -15209,6 +16298,16 @@ safe-array-concat@^1.0.0, safe-array-concat@^1.1.0: has-symbols "^1.0.3" isarray "^2.0.5" +safe-array-concat@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" + integrity sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q== + dependencies: + call-bind "^1.0.7" + get-intrinsic "^1.2.4" + has-symbols "^1.0.3" + isarray "^2.0.5" + safe-buffer@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" @@ -15289,10 +16388,10 @@ scheduler@^0.19.1: loose-envify "^1.1.0" object-assign "^4.1.1" -scheduler@^0.23.0: - version "0.23.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" - integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== +scheduler@^0.23.2: + version "0.23.2" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" + integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ== dependencies: loose-envify "^1.1.0" @@ -15332,6 +16431,15 @@ schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: ajv "^6.12.5" ajv-keywords "^3.5.2" +schema-utils@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" + integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + schema-utils@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" @@ -15354,11 +16462,16 @@ selfsigned@^2.1.1: dependencies: node-forge "^1" -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== +semver@^5.7.2: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" @@ -15376,6 +16489,11 @@ semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8: dependencies: lru-cache "^6.0.0" +semver@^7.5.3: + version "7.6.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" + integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== + semver@^7.5.4: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" @@ -15426,28 +16544,28 @@ send@0.18.0: range-parser "~1.2.1" statuses "2.0.1" -send@1.0.0-beta.1: - version "1.0.0-beta.1" - resolved "https://registry.yarnpkg.com/send/-/send-1.0.0-beta.1.tgz#9db741443b0b25771cfd38adc833376ae2d606fe" - integrity sha512-OKTRokcl/oo34O8+6aUpj8Jf2Bjw2D0tZzmX0/RvyfVC9ZOZW+HPAWAlhS817IsRaCnzYX1z++h2kHFr2/KNRg== +send@1.0.0-beta.2, send@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/send/-/send-1.0.0-beta.2.tgz#1b6d727648acd1564d4095cd7f618b7b9474ce3e" + integrity sha512-k1yHu/FNK745PULKdsGpQ+bVSXYNwSk+bWnYzbxGZbt5obZc0JKDVANsCRuJD1X/EG15JtP9eZpwxkhUxIYEcg== dependencies: debug "3.1.0" - destroy "~1.0.4" + destroy "1.2.0" encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" fresh "0.5.2" - http-errors "1.8.1" + http-errors "2.0.0" mime-types "~2.1.34" ms "2.1.3" - on-finished "~2.3.0" + on-finished "2.4.1" range-parser "~1.2.1" - statuses "~1.5.0" + statuses "2.0.1" -sequelize-cli@^6.5.2: - version "6.6.0" - resolved "https://registry.yarnpkg.com/sequelize-cli/-/sequelize-cli-6.6.0.tgz#f11588c93b53321637f8aedd5b10ed57d6d06482" - integrity sha512-FwTClhGRvXKanFRHMZbgfXOBV8UC2B3VkE0WOdW1n39/36PF4lWyurF95f246une/V4eaO3a7/Ywvy++3r+Jmg== +sequelize-cli@^6.6.2: + version "6.6.2" + resolved "https://registry.yarnpkg.com/sequelize-cli/-/sequelize-cli-6.6.2.tgz#8d838b25c988cf136914cdc3843e19d88c3dcb67" + integrity sha512-V8Oh+XMz2+uquLZltZES6MVAD+yEnmMfwfn+gpXcDiwE3jyQygLt4xoI0zG8gKt6cRcs84hsKnXAKDQjG/JAgg== dependencies: cli-color "^2.0.3" fs-extra "^9.1.0" @@ -15467,26 +16585,26 @@ sequelize-test-helpers@1.3.3: resolved "https://registry.yarnpkg.com/sequelize-test-helpers/-/sequelize-test-helpers-1.3.3.tgz#99ed213d21c0a794a67b89886bf227dec460fb47" integrity sha512-np07UQY+hbgn6fJvfTU5CdKxjUk7MDme8okDx/4i5hCcDGB4BMXUQpt5N/MwpsLumR82bqGTHGdh4hGIpojGEQ== -sequelize@^6.28.0: - version "6.28.0" - resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-6.28.0.tgz#d6bc4e36647e8501635467c0777c45a33f5d5ba8" - integrity sha512-+WHqvUQgTp19GLkt+gyQ+F6qg+FIEO2O5F9C0TOYV/PjZ2a/XwWvVkL1NCkS4VSIjVVvAUutiW6Wv9ofveGaVw== +sequelize@^6.37.3: + version "6.37.3" + resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-6.37.3.tgz#ed6212029a52c59a18638d2a703da84bc2f81311" + integrity sha512-V2FTqYpdZjPy3VQrZvjTPnOoLm0KudCRXfGWp48QwhyPPp2yW8z0p0sCYZd/em847Tl2dVxJJ1DR+hF+O77T7A== dependencies: - "@types/debug" "^4.1.7" - "@types/validator" "^13.7.1" - debug "^4.3.3" - dottie "^2.0.2" - inflection "^1.13.2" + "@types/debug" "^4.1.8" + "@types/validator" "^13.7.17" + debug "^4.3.4" + dottie "^2.0.6" + inflection "^1.13.4" lodash "^4.17.21" - moment "^2.29.1" - moment-timezone "^0.5.34" - pg-connection-string "^2.5.0" - retry-as-promised "^7.0.3" - semver "^7.3.5" + moment "^2.29.4" + moment-timezone "^0.5.43" + pg-connection-string "^2.6.1" + retry-as-promised "^7.0.4" + semver "^7.5.4" sequelize-pool "^7.1.0" toposort-class "^1.0.1" uuid "^8.3.2" - validator "^13.7.0" + validator "^13.9.0" wkx "^0.5.0" serialize-javascript@^4.0.0: @@ -15510,6 +16628,13 @@ serialize-javascript@^6.0.0: dependencies: randombytes "^2.1.0" +serialize-javascript@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== + dependencies: + randombytes "^2.1.0" + serve-favicon@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/serve-favicon/-/serve-favicon-2.5.0.tgz#935d240cdfe0f5805307fdfe967d88942a2cbcf0" @@ -15554,15 +16679,15 @@ serve-static@1.15.0: parseurl "~1.3.3" send "0.18.0" -serve-static@2.0.0-beta.1: - version "2.0.0-beta.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-2.0.0-beta.1.tgz#003bc35db8b37905e1f6d380a4ccc0a34f30ec1d" - integrity sha512-DEJ9on/tQeFO2Omj7ovT02lCp1YgP4Kb8W2lv2o/4keTFAbgc8HtH3yPd47++2wv9lvQeqiA7FHFDe5+8c4XpA== +serve-static@2.0.0-beta.2: + version "2.0.0-beta.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-2.0.0-beta.2.tgz#9c0ca60e21a6332d18ade72db7cf7a96b27db474" + integrity sha512-Ge718g4UJjzYoXFEGLY/VLSuTHp0kQcUV65QA98J8d3XREsVIHu53GBh9NWjDy4u2xwsSwRzu9nu7Q+b4o6Xyw== dependencies: encodeurl "~1.0.2" escape-html "~1.0.3" parseurl "~1.3.3" - send "1.0.0-beta.1" + send "^1.0.0-beta.2" set-blocking@^2.0.0: version "2.0.0" @@ -15581,7 +16706,7 @@ set-function-length@^1.2.1: gopd "^1.0.1" has-property-descriptors "^1.0.1" -set-function-name@^2.0.1: +set-function-name@^2.0.1, set-function-name@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== @@ -15636,10 +16761,10 @@ shallow-clone@^3.0.0: dependencies: kind-of "^6.0.2" -shallow-equal@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/shallow-equal/-/shallow-equal-1.2.1.tgz#4c16abfa56043aa20d050324efa68940b0da79da" - integrity sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA== +shallow-equal@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/shallow-equal/-/shallow-equal-3.1.0.tgz#e7a54bac629c7f248eff6c2f5b63122ba4320bec" + integrity sha512-pfVOw8QZIXpMbhBWvzBISicvToTiM5WBF1EeAUZDDSb5Dt29yl4AYbyywbJFSEsRUMr7gJaxqCdr4L3tQf9wVg== shallowequal@^1.1.0: version "1.1.0" @@ -15675,6 +16800,11 @@ shell-quote@^1.6.1: resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.4.tgz#33fe15dee71ab2a81fcbd3a52106c5cfb9fb75d8" integrity sha512-8o/QEhSSRb1a5i7TFR0iM4G16Z0vYB2OQVs4G3aAFXjn3T6yEx8AZxy1PgDF7I00LZHYA3WxaSYIf5e5sAX8Rw== +shell-quote@^1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" + integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== + side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" @@ -15684,6 +16814,16 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" +side-channel@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" + sigmund@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" @@ -15694,6 +16834,11 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +signal-exit@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + simple-update-notifier@^1.0.7: version "1.1.0" resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz#67694c121de354af592b347cdba798463ed49c82" @@ -15792,6 +16937,11 @@ source-map-js@^1.0.2: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== +source-map-js@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" + integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== + source-map-resolve@^0.5.0: version "0.5.3" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" @@ -15990,7 +17140,7 @@ statuses@2.0.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== -"statuses@>= 1.3.1 < 2", "statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: +"statuses@>= 1.3.1 < 2", "statuses@>= 1.4.0 < 2": version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== @@ -16010,13 +17160,13 @@ store2@^2.12.0: resolved "https://registry.yarnpkg.com/store2/-/store2-2.14.2.tgz#56138d200f9fe5f582ad63bc2704dbc0e4a45068" integrity sha512-siT1RiqlfQnGqgT/YzXVUNsom9S0H1OX+dpdGN1xkyYATo4I6sep5NmsRD/40s3IIOvlCq6akxkqG82urIZW1w== -storybook-addon-apollo-client@^4.0.12: - version "4.0.13" - resolved "https://registry.yarnpkg.com/storybook-addon-apollo-client/-/storybook-addon-apollo-client-4.0.13.tgz#49d360ab2cdabfe47f120fedadb17f9504e8d396" - integrity sha512-j4oH2t1WXuIBAcdl4mTUYPnCjSChwlLY9Z7dT7Pur6o+eLsuAcG5MGhQpLGO6hH5s7ZBohaaD2IYq1I18As+hA== +storybook-addon-apollo-client@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/storybook-addon-apollo-client/-/storybook-addon-apollo-client-4.1.4.tgz#3f16d3845b878bfe4dfdc571c8d70352a8312d90" + integrity sha512-i+zhyqCpL5qE6K2bjRrA5064Qf1Y7h9WihEhrD3kMS9y5WfRijqhOQjMCsYdKviXoIsTE+woEZPspD7Pq1JgUw== dependencies: - "@storybook/addons" "6.5.12" - "@storybook/components" "6.5.12" + "@storybook/addons" "~6.5.12" + "@storybook/components" "~6.5.12" tslib "^2.4.0" storybook-react-router@^1.0.8: @@ -16074,6 +17224,15 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -16091,7 +17250,16 @@ string-width@^2.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -"string.prototype.matchall@^4.0.0 || ^3.0.1", string.prototype.matchall@^4.0.8: +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +"string.prototype.matchall@^4.0.0 || ^3.0.1": version "4.0.8" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz#3bf85722021816dcd1bf38bb714915887ca79fd3" integrity sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg== @@ -16105,6 +17273,24 @@ string-width@^2.1.0: regexp.prototype.flags "^1.4.3" side-channel "^1.0.4" +string.prototype.matchall@^4.0.11: + version "4.0.11" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz#1092a72c59268d2abaad76582dccc687c0297e0a" + integrity sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.4" + gopd "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.7" + regexp.prototype.flags "^1.5.2" + set-function-name "^2.0.2" + side-channel "^1.0.6" + string.prototype.padend@^3.0.0: version "3.1.4" resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.1.4.tgz#2c43bb3a89eb54b6750de5942c123d6c98dd65b6" @@ -16141,6 +17327,16 @@ string.prototype.trim@^1.2.8: define-properties "^1.2.0" es-abstract "^1.22.1" +string.prototype.trim@^1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" + integrity sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.0" + es-object-atoms "^1.0.0" + string.prototype.trimend@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" @@ -16159,6 +17355,15 @@ string.prototype.trimend@^1.0.7: define-properties "^1.2.0" es-abstract "^1.22.1" +string.prototype.trimend@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz#3651b8513719e8a9f48de7f2f77640b26652b229" + integrity sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + string.prototype.trimstart@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" @@ -16177,6 +17382,15 @@ string.prototype.trimstart@^1.0.7: define-properties "^1.2.0" es-abstract "^1.22.1" +string.prototype.trimstart@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde" + integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -16191,6 +17405,13 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" @@ -16219,6 +17440,13 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" @@ -16260,7 +17488,7 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: +strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -16281,10 +17509,10 @@ style-loader@^2.0.0: loader-utils "^2.0.0" schema-utils "^3.0.0" -style-loader@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.1.tgz#057dfa6b3d4d7c7064462830f9113ed417d38575" - integrity sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ== +style-loader@^3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.4.tgz#f30f786c36db03a45cbd55b6a70d930c479090e7" + integrity sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w== style-to-object@0.3.0, style-to-object@^0.3.0: version "0.3.0" @@ -16293,22 +17521,22 @@ style-to-object@0.3.0, style-to-object@^0.3.0: dependencies: inline-style-parser "0.1.1" -stylis@4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.1.3.tgz#fd2fbe79f5fed17c55269e16ed8da14c84d069f7" - integrity sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA== +stylis@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51" + integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw== -superagent@^8.0.5: - version "8.0.6" - resolved "https://registry.yarnpkg.com/superagent/-/superagent-8.0.6.tgz#e3fb0b3112b79b12acd605c08846253197765bf6" - integrity sha512-HqSe6DSIh3hEn6cJvCkaM1BLi466f1LHi4yubR0tpewlMpk4RUFFy35bKz8SsPBwYfIIJy5eclp+3tCYAuX0bw== +superagent@^8.1.2: + version "8.1.2" + resolved "https://registry.yarnpkg.com/superagent/-/superagent-8.1.2.tgz#03cb7da3ec8b32472c9d20f6c2a57c7f3765f30b" + integrity sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA== dependencies: component-emitter "^1.3.0" - cookiejar "^2.1.3" + cookiejar "^2.1.4" debug "^4.3.4" fast-safe-stringify "^2.1.1" form-data "^4.0.0" - formidable "^2.1.1" + formidable "^2.1.2" methods "^1.1.2" mime "2.6.0" qs "^6.11.0" @@ -16323,13 +17551,13 @@ supertest-session@^4.1.0: methods "^1.1.2" object-assign "^4.0.1" -supertest@^6.3.3: - version "6.3.3" - resolved "https://registry.yarnpkg.com/supertest/-/supertest-6.3.3.tgz#42f4da199fee656106fd422c094cf6c9578141db" - integrity sha512-EMCG6G8gDu5qEqRQ3JjjPs6+FYT1a7Hv5ApHvtSghmOFJYtsU5S+pSb6Y2EUeCEY3CmEL3mmQ8YWlPOzQomabA== +supertest@^6.3.4: + version "6.3.4" + resolved "https://registry.yarnpkg.com/supertest/-/supertest-6.3.4.tgz#2145c250570c2ea5d337db3552dbfb78a2286218" + integrity sha512-erY3HFDG0dPnhw4U+udPfrzXa4xhSG+n4rxfRuZWCUvjFWwKl+OxWf/7zk50s84/fAAs7vf5QAb9uRa0cCykxw== dependencies: methods "^1.1.2" - superagent "^8.0.5" + superagent "^8.1.2" supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" @@ -16505,6 +17733,17 @@ terser-webpack-plugin@^5.0.3, terser-webpack-plugin@^5.1.3: serialize-javascript "^6.0.0" terser "^5.14.1" +terser-webpack-plugin@^5.3.10: + version "5.3.10" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" + integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== + dependencies: + "@jridgewell/trace-mapping" "^0.3.20" + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.1" + terser "^5.26.0" + terser@^4.1.2, terser@^4.6.3: version "4.8.1" resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.1.tgz#a00e5634562de2239fd404c649051bf6fc21144f" @@ -16534,6 +17773,16 @@ terser@^5.14.1, terser@^5.3.4: commander "^2.20.0" source-map-support "~0.5.20" +terser@^5.26.0: + version "5.31.2" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.31.2.tgz#b5ca188107b706084dca82f988089fa6102eba11" + integrity sha512-LGyRZVFm/QElZHy/CPr/O4eNZOZIzsrQ92y4v9UJe/pFJjypje2yI3C2FmPtvUEnhadlSbmG2nXtdcjHOjCfxw== + dependencies: + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" + commander "^2.20.0" + source-map-support "~0.5.20" + test-exclude@^5.2.3: version "5.2.3" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.2.3.tgz#c3d3e1e311eb7ee405e092dac10aefd09091eac0" @@ -16697,6 +17946,16 @@ tough-cookie@^4.1.2: universalify "^0.2.0" url-parse "^1.5.3" +tough-cookie@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36" + integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.2.0" + url-parse "^1.5.3" + tr46@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" @@ -16711,12 +17970,12 @@ tr46@^3.0.0: dependencies: punycode "^2.1.1" -tr46@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-4.1.1.tgz#281a758dcc82aeb4fe38c7dfe4d11a395aac8469" - integrity sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw== +tr46@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-5.0.0.tgz#3b46d583613ec7283020d79019f1335723801cec" + integrity sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g== dependencies: - punycode "^2.3.0" + punycode "^2.3.1" tr46@~0.0.3: version "0.0.3" @@ -16794,12 +18053,12 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" -turndown@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/turndown/-/turndown-7.1.1.tgz#96992f2d9b40a1a03d3ea61ad31b5a5c751ef77f" - integrity sha512-BEkXaWH7Wh7e9bd2QumhfAXk5g34+6QUmmWx+0q6ThaVOLuLUqsnkq35HQ5SBHSaxjSfSM7US5o4lhJNH7B9MA== +turndown@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/turndown/-/turndown-7.2.0.tgz#67d614fe8371fb511079a93345abfd156c0ffcf4" + integrity sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A== dependencies: - domino "^2.1.6" + "@mixmark-io/domino" "^2.2.0" tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" @@ -16916,6 +18175,18 @@ typed-array-length@^1.0.5: is-typed-array "^1.1.13" possible-typed-array-names "^1.0.0" +typed-array-length@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.6.tgz#57155207c76e64a3457482dfdc1c9d1d3c4c73a3" + integrity sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g== + dependencies: + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" + possible-typed-array-names "^1.0.0" + typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -16928,10 +18199,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== -ua-parser-js@1.0.33: - version "1.0.33" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.33.tgz#f21f01233e90e7ed0f059ceab46eb190ff17f8f4" - integrity sha512-RqshF7TPTE0XLYAqmjlu5cLLuGdKrNu9O1KLA/qp39QtbZwuzwv1dT46DZSopoUMsYgXpB3Cv8a03FI8b74oFQ== +ua-parser-js@1.0.38: + version "1.0.38" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.38.tgz#66bb0c4c0e322fe48edfe6d446df6042e62f25e2" + integrity sha512-Aq5ppTOfvrCMgAPneW1HfWj66Xi7XL+/mIy996R1/CLS/rcyJQm6QZdsKrUeivDFQ+Oc9Wyuwor8Ze8peEoUoQ== uglify-js@^3.1.4: version "3.17.4" @@ -16980,6 +18251,11 @@ uncontrollable@^7.2.1: invariant "^2.2.4" react-lifecycles-compat "^3.0.4" +uncontrollable@^8.0.1: + version "8.0.4" + resolved "https://registry.yarnpkg.com/uncontrollable/-/uncontrollable-8.0.4.tgz#a0a8307f638795162fafd0550f4a1efa0f8c5eb6" + integrity sha512-ulRWYWHvscPFc0QQXvyJjY6LIXU56f0h8pQFvhxiKk5V1fcI8gp9Ht9leVAhrVjzqMw0BgjspBINx9r6oyJUvQ== + undefsafe@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" @@ -16990,6 +18266,11 @@ underscore@^1.13.1: resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.6.tgz#04786a1f589dc6c09f761fc5f45b89e935136441" integrity sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A== +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + unfetch@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-4.2.0.tgz#7e21b0ef7d363d8d9af0fb929a5555f6ef97a3be" @@ -17183,6 +18464,14 @@ update-browserslist-db@^1.0.9: escalade "^3.1.1" picocolors "^1.0.0" +update-browserslist-db@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz#7ca61c0d8650766090728046e416a8cde682859e" + integrity sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ== + dependencies: + escalade "^3.1.2" + picocolors "^1.0.1" + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -17220,10 +18509,10 @@ url@^0.11.0: punycode "1.3.2" querystring "0.2.0" -urlpattern-polyfill@9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/urlpattern-polyfill/-/urlpattern-polyfill-9.0.0.tgz#bc7e386bb12fd7898b58d1509df21d3c29ab3460" - integrity sha512-WHN8KDQblxd32odxeIgo83rdVDE2bvdkb86it7bMhYZwWKJz0+O0RK/eZiHYnM+zgt/U7hAHOlCQGfjjvSkw2g== +urlpattern-polyfill@10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz#f0a03a97bfb03cdf33553e5e79a2aadd22cac8ec" + integrity sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg== use@^3.1.0: version "3.1.1" @@ -17322,10 +18611,10 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -validator@^13.7.0: - version "13.9.0" - resolved "https://registry.yarnpkg.com/validator/-/validator-13.9.0.tgz#33e7b85b604f3bbce9bb1a05d5c3e22e1c2ff855" - integrity sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA== +validator@^13.9.0: + version "13.12.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-13.12.0.tgz#7d78e76ba85504da3fee4fd1922b385914d4b35f" + integrity sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg== value-or-promise@1.0.11: version "1.0.11" @@ -17369,11 +18658,6 @@ vfile@^4.0.0: unist-util-stringify-position "^2.0.0" vfile-message "^2.0.0" -vhost@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/vhost/-/vhost-3.0.2.tgz#2fb1decd4c466aa88b0f9341af33dc1aff2478d5" - integrity sha512-S3pJdWrpFWrKMboRU4dLYgMrTgoPALsmYwOvyebK2M6X95b9kQrjZy5rwl3uzzpfpENe/XrNYu/2U+e7/bmT5g== - vm-browserify@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" @@ -17424,6 +18708,13 @@ w3c-xmlserializer@^4.0.0: dependencies: xml-name-validator "^4.0.0" +w3c-xmlserializer@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz#f925ba26855158594d907313cedd1476c5967f6c" + integrity sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA== + dependencies: + xml-name-validator "^5.0.0" + walker@^1.0.7, walker@^1.0.8, walker@~1.0.5: version "1.0.8" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" @@ -17464,6 +18755,14 @@ watchpack@^2.2.0, watchpack@^2.4.0: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" +watchpack@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.1.tgz#29308f2cac150fa8e4c92f90e0ec954a9fed7fff" + integrity sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + wbuf@^1.1.0, wbuf@^1.7.3: version "1.7.3" resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" @@ -17491,17 +18790,17 @@ webidl-conversions@^7.0.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== -webpack-cli@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.0.1.tgz#95fc0495ac4065e9423a722dec9175560b6f2d9a" - integrity sha512-S3KVAyfwUqr0Mo/ur3NzIp6jnerNpo7GUO6so51mxLi1spqsA17YcMXy0WOIJtBSnj748lthxC6XLbNKh/ZC+A== +webpack-cli@^5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.4.tgz#c8e046ba7eaae4911d7e71e2b25b776fcc35759b" + integrity sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg== dependencies: "@discoveryjs/json-ext" "^0.5.0" - "@webpack-cli/configtest" "^2.0.1" - "@webpack-cli/info" "^2.0.1" - "@webpack-cli/serve" "^2.0.1" + "@webpack-cli/configtest" "^2.1.1" + "@webpack-cli/info" "^2.0.2" + "@webpack-cli/serve" "^2.0.5" colorette "^2.0.14" - commander "^9.4.1" + commander "^10.0.1" cross-spawn "^7.0.3" envinfo "^7.7.3" fastest-levenshtein "^1.0.12" @@ -17533,10 +18832,10 @@ webpack-dev-middleware@^4.1.0: range-parser "^1.2.1" schema-utils "^3.0.0" -webpack-dev-middleware@^5.3.1: - version "5.3.3" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz#efae67c2793908e7311f1d9b06f2a08dcc97e51f" - integrity sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA== +webpack-dev-middleware@^5.3.4: + version "5.3.4" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz#eb7b39281cbce10e104eb2b8bf2b63fce49a3517" + integrity sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q== dependencies: colorette "^2.0.10" memfs "^3.4.3" @@ -17544,10 +18843,10 @@ webpack-dev-middleware@^5.3.1: range-parser "^1.2.1" schema-utils "^4.0.0" -webpack-dev-server@^4.11.1: - version "4.11.1" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.11.1.tgz#ae07f0d71ca0438cf88446f09029b92ce81380b5" - integrity sha512-lILVz9tAUy1zGFwieuaQtYiadImb5M3d+H+L1zDYalYoDl0cksAB1UNyuE5MMWJrG6zR1tXkCP2fitl7yoUJiw== +webpack-dev-server@^4.15.2: + version "4.15.2" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz#9e0c70a42a012560860adb186986da1248333173" + integrity sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g== dependencies: "@types/bonjour" "^3.5.9" "@types/connect-history-api-fallback" "^1.3.5" @@ -17555,7 +18854,7 @@ webpack-dev-server@^4.11.1: "@types/serve-index" "^1.9.1" "@types/serve-static" "^1.13.10" "@types/sockjs" "^0.3.33" - "@types/ws" "^8.5.1" + "@types/ws" "^8.5.5" ansi-html-community "^0.0.8" bonjour-service "^1.0.11" chokidar "^3.5.3" @@ -17568,6 +18867,7 @@ webpack-dev-server@^4.11.1: html-entities "^2.3.2" http-proxy-middleware "^2.0.3" ipaddr.js "^2.0.1" + launch-editor "^2.6.0" open "^8.0.9" p-retry "^4.5.0" rimraf "^3.0.2" @@ -17576,8 +18876,8 @@ webpack-dev-server@^4.11.1: serve-index "^1.9.1" sockjs "^0.3.24" spdy "^4.0.2" - webpack-dev-middleware "^5.3.1" - ws "^8.4.2" + webpack-dev-middleware "^5.3.4" + ws "^8.13.0" webpack-filter-warnings-plugin@^1.2.1: version "1.2.1" @@ -17663,7 +18963,7 @@ webpack@4: watchpack "^1.7.4" webpack-sources "^1.4.1" -"webpack@>=4.43.0 <6.0.0", webpack@^5.75.0, webpack@^5.9.0: +"webpack@>=4.43.0 <6.0.0", webpack@^5.9.0: version "5.75.0" resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.75.0.tgz#1e440468647b2505860e94c9ff3e44d5b582c152" integrity sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ== @@ -17693,6 +18993,36 @@ webpack@4: watchpack "^2.4.0" webpack-sources "^3.2.3" +webpack@^5.92.1: + version "5.92.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.92.1.tgz#eca5c1725b9e189cffbd86e8b6c3c7400efc5788" + integrity sha512-JECQ7IwJb+7fgUFBlrJzbyu3GEuNBcdqr1LD7IbSzwkSmIevTm8PF+wej3Oxuz/JFBUZ6O1o43zsPkwm1C4TmA== + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^1.0.5" + "@webassemblyjs/ast" "^1.12.1" + "@webassemblyjs/wasm-edit" "^1.12.1" + "@webassemblyjs/wasm-parser" "^1.12.1" + acorn "^8.7.1" + acorn-import-attributes "^1.9.5" + browserslist "^4.21.10" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.17.0" + es-module-lexer "^1.2.1" + eslint-scope "5.1.1" + events "^3.2.0" + glob-to-regexp "^0.4.1" + graceful-fs "^4.2.11" + json-parse-even-better-errors "^2.3.1" + loader-runner "^4.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.2.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.3.10" + watchpack "^2.4.1" + webpack-sources "^3.2.3" + websocket-driver@>=0.5.1, websocket-driver@^0.7.4: version "0.7.4" resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" @@ -17721,6 +19051,13 @@ whatwg-encoding@^2.0.0: dependencies: iconv-lite "0.6.3" +whatwg-encoding@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz#d0f4ef769905d426e1688f3e34381a99b60b76e5" + integrity sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ== + dependencies: + iconv-lite "0.6.3" + whatwg-fetch@^3.4.1: version "3.6.2" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" @@ -17736,6 +19073,11 @@ whatwg-mimetype@^3.0.0: resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7" integrity sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q== +whatwg-mimetype@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz#bc1bf94a985dc50388d54a9258ac405c3ca2fc0a" + integrity sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg== + whatwg-url@^11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-11.0.0.tgz#0a849eebb5faf2119b901bb76fd795c2848d4018" @@ -17744,12 +19086,12 @@ whatwg-url@^11.0.0: tr46 "^3.0.0" webidl-conversions "^7.0.0" -whatwg-url@^12.0.0, whatwg-url@^12.0.1: - version "12.0.1" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-12.0.1.tgz#fd7bcc71192e7c3a2a97b9a8d6b094853ed8773c" - integrity sha512-Ed/LrqB8EPlGxjS+TrsXcpUond1mhccS3pchLhzSgPCnTimUCKj3IZE75pAs5m6heB2U2TMerKFUXheyHY+VDQ== +whatwg-url@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-14.0.0.tgz#00baaa7fd198744910c4b1ef68378f2200e4ceb6" + integrity sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw== dependencies: - tr46 "^4.1.1" + tr46 "^5.0.0" webidl-conversions "^7.0.0" whatwg-url@^5.0.0: @@ -17789,6 +19131,24 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" +which-builtin-type@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.1.3.tgz#b1b8443707cc58b6e9bf98d32110ff0c2cbd029b" + integrity sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw== + dependencies: + function.prototype.name "^1.1.5" + has-tostringtag "^1.0.0" + is-async-function "^2.0.0" + is-date-object "^1.0.5" + is-finalizationregistry "^1.0.2" + is-generator-function "^1.0.10" + is-regex "^1.1.4" + is-weakref "^1.0.2" + isarray "^2.0.5" + which-boxed-primitive "^1.0.2" + which-collection "^1.0.1" + which-typed-array "^1.1.9" + which-collection@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906" @@ -17815,6 +19175,17 @@ which-typed-array@^1.1.14: gopd "^1.0.1" has-tostringtag "^1.0.1" +which-typed-array@^1.1.15: + version "1.1.15" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" + integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.2" + which-typed-array@^1.1.8, which-typed-array@^1.1.9: version "1.1.9" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" @@ -17867,7 +19238,12 @@ wkx@^0.5.0: dependencies: "@types/node" "*" -word-wrap@^1.2.3, word-wrap@~1.2.3: +word-wrap@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + +word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== @@ -17891,6 +19267,15 @@ worker-rpc@^0.1.0: dependencies: microevent.ts "~0.1.1" +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" @@ -17909,6 +19294,15 @@ wrap-ansi@^7.0.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -17933,7 +19327,7 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" -write-file-atomic@^4.0.1, write-file-atomic@^4.0.2: +write-file-atomic@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== @@ -17973,7 +19367,12 @@ ws@^8.13.0: resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== -ws@^8.2.3, ws@^8.4.2: +ws@^8.17.0: + version "8.18.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== + +ws@^8.2.3: version "8.11.0" resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== @@ -18000,6 +19399,11 @@ xml-name-validator@^4.0.0: resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835" integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw== +xml-name-validator@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-5.0.0.tgz#82be9b957f7afdacf961e5980f1bf227c0bf7673" + integrity sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg== + xmlchars@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" @@ -18043,11 +19447,16 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2: +yaml@^1.10.0, yaml@^1.7.2: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== +yaml@^2.2.2: + version "2.4.5" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.5.tgz#60630b206dd6d84df97003d33fc1ddf6296cca5e" + integrity sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg== + yargs-parser@^13.1.2: version "13.1.2" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" @@ -18143,6 +19552,11 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +yocto-queue@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.1.1.tgz#fef65ce3ac9f8a32ceac5a634f74e17e5b232110" + integrity sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g== + zen-observable-ts@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-1.2.5.tgz#6c6d9ea3d3a842812c6e9519209365a122ba8b58" From d118b35418d4e8f9b43dbd2a4ec53f84575150c6 Mon Sep 17 00:00:00 2001 From: Howard Edwards Date: Wed, 17 Jul 2024 16:22:25 -0400 Subject: [PATCH 15/15] fix: onHide error thrown on ESC press when is open --- client/components/common/BasicModal/index.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/components/common/BasicModal/index.jsx b/client/components/common/BasicModal/index.jsx index 76a786d8f..11d487264 100644 --- a/client/components/common/BasicModal/index.jsx +++ b/client/components/common/BasicModal/index.jsx @@ -79,8 +79,8 @@ const BasicModal = ({ id={`focus-trapped-${id}`} centered={centered} animation={animation} - onHide={useOnHide ? handleHide || handleClose : null} - onExit={!useOnHide ? handleHide || handleClose : null} + onHide={useOnHide ? handleHide || handleClose : () => {}} + onExit={!useOnHide ? handleHide || handleClose : () => {}} /* Disabled due to buggy implementation which jumps the page */ autoFocus={false} aria-labelledby={`title-${id}`}