diff --git a/client/components/TestRun/TestNavigator.jsx b/client/components/TestRun/TestNavigator.jsx index 65b891e3d..956304baa 100644 --- a/client/components/TestRun/TestNavigator.jsx +++ b/client/components/TestRun/TestNavigator.jsx @@ -5,14 +5,15 @@ import { faArrowLeft, faArrowRight } from '@fortawesome/free-solid-svg-icons'; -import { Col } from 'react-bootstrap'; -import React from 'react'; +import { Col, Overlay, Tooltip } from 'react-bootstrap'; +import React, { useRef, useState } from 'react'; const TestNavigator = ({ show = true, isSignedIn = false, tests = [], currentTestIndex = 0, + testPlanRunId = 0, toggleShowClick = () => {}, handleTestClick = () => {} }) => { @@ -69,27 +70,48 @@ const TestNavigator = ({ } } + const [show, setShow] = useState(false); + const target = useRef(null); + return (
  • await handleTestClick(test.index) } + onBlur={() => setShow(false)} + onFocus={() => setShow(true)} + onMouseLeave={() => setShow(false)} + onMouseEnter={() => setShow(true)} className="test-name" aria-current={ test.index === currentTestIndex } + aria-label={`${test.title} (${resultStatus})`} > {test.title}
  • ); })} @@ -107,6 +129,7 @@ TestNavigator.propTypes = { testResult: PropTypes.object, conflicts: PropTypes.object, currentTestIndex: PropTypes.number, + testPlanRunId: PropTypes.number, toggleShowClick: PropTypes.func, handleTestClick: PropTypes.func }; diff --git a/client/components/TestRun/index.jsx b/client/components/TestRun/index.jsx index f41de2e88..06c0a4fac 100644 --- a/client/components/TestRun/index.jsx +++ b/client/components/TestRun/index.jsx @@ -1,6 +1,6 @@ import React, { useState, useEffect, useRef } from 'react'; import { Helmet } from 'react-helmet'; -import { Link, useParams, useHistory } from 'react-router-dom'; +import { Link, useParams, useHistory, Redirect } from 'react-router-dom'; import useRouterQuery from '../../hooks/useRouterQuery'; import { useQuery, useMutation } from '@apollo/client'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; @@ -79,7 +79,11 @@ const TestRun = () => { const testRendererSubmitButtonRef = useRef(); const conflictMarkdownRef = useRef(); - const { runId: testPlanRunId, testPlanReportId } = params; + const { + runId: testPlanRunId, + taskId: testPlanTaskId, + testPlanReportId + } = params; const { loading, data, error, refetch } = useQuery( testPlanRunId ? TEST_RUN_PAGE_QUERY : TEST_RUN_PAGE_ANON_QUERY, @@ -197,7 +201,24 @@ const TestRun = () => { testResult: testResults.find(t => t.test.id === test.id), hasConflicts: !!conflicts.find(c => c.source.test.id === test.id) })); - const currentTest = tests[currentTestIndex]; + + // Validate any /task/\d+ route parameter + if ( + testPlanTaskId !== undefined && + testPlanTaskId > 0 && + tests.length < testPlanTaskId + ) { + return ; + } + + if ( + testPlanTaskId !== undefined && + testPlanTaskId - 1 !== currentTestIndex + ) { + setCurrentTestIndex(testPlanTaskId - 1); + } + + const currentTest = tests[testPlanTaskId - 1 || currentTestIndex]; const hasTestsToRun = tests.length; if (!currentTest.testResult && !pageReadyRef.current && isSignedIn) @@ -814,6 +835,7 @@ const TestRun = () => { { + return ( + + + + ); + } + }, { path: '/run/:runId(\\d+)', component: () => {