diff --git a/client/src/templates/Challenges/generic/show.tsx b/client/src/templates/Challenges/generic/show.tsx index 99b230e67b9..fe8bb31c673 100644 --- a/client/src/templates/Challenges/generic/show.tsx +++ b/client/src/templates/Challenges/generic/show.tsx @@ -7,6 +7,7 @@ import { Container, Col, Row, Button, Spacer } from '@freecodecamp/ui'; import { isEqual } from 'lodash'; import store from 'store'; import { YouTubeEvent } from 'react-youtube'; +import { ObserveKeys } from 'react-hotkeys'; // Local Utilities import LearnLayout from '../../../components/layouts/learn'; @@ -259,21 +260,25 @@ const ShowGeneric = ({ )} {assignments.length > 0 && ( - + + + )} {questions.length > 0 && ( - + + + )} {explanation ? ( diff --git a/e2e/hotkeys.spec.ts b/e2e/hotkeys.spec.ts index 7d59999ce13..606e9e72d7a 100644 --- a/e2e/hotkeys.spec.ts +++ b/e2e/hotkeys.spec.ts @@ -21,7 +21,11 @@ const links = { video1: '/learn/python-for-everybody/python-for-everybody/introduction-why-program', video2: - '/learn/python-for-everybody/python-for-everybody/introduction-hardware-architecture' + '/learn/python-for-everybody/python-for-everybody/introduction-hardware-architecture', + multipleChoiceQuestion: + '/learn/a2-english-for-developers/learn-greetings-in-your-first-day-at-the-office/task-7', + assignment: + '/learn/full-stack-developer/review-semantic-html/review-semantic-html' }; const titles = { @@ -143,3 +147,71 @@ test('User can use shortcuts to navigate between video-based challenges', async await page.keyboard.press('p'); await page.waitForURL(links.video1); }); + +test('User can use Ctrl+Enter to submit their answer in a multiple-choice question challenge', async ({ + page +}) => { + await page.goto(links.multipleChoiceQuestion); + + // Wait for page load + await expect(page.getByRole('heading', { name: 'Task 7' })).toBeVisible(); + + await page.keyboard.press('Control+Enter'); + + await expect( + page.getByText('You have unanswered questions and/or incorrect answers.') + ).toBeVisible(); +}); + +test('User can use Cmd+Enter to submit their answer in a multiple-choice question challenge', async ({ + page +}) => { + await page.goto(links.multipleChoiceQuestion); + + // Wait for page load + await expect(page.getByRole('heading', { name: 'Task 7' })).toBeVisible(); + + await page.keyboard.press('Meta+Enter'); + + await expect( + page.getByText('You have unanswered questions and/or incorrect answers.') + ).toBeVisible(); +}); + +test('User can use Ctrl+Enter to submit their answer in an assignment-type challenge', async ({ + page +}) => { + await page.goto(links.assignment); + + // Wait for page load + await expect( + page.getByRole('heading', { name: 'Semantic HTML Review' }) + ).toBeVisible(); + + // Check the assignment checkbox + await page.getByRole('checkbox').check(); + + await page.keyboard.press('Control+Enter'); + + // Completion modal shows up + await expect(page.getByRole('dialog')).toBeVisible(); +}); + +test('User can use Cmd+Enter to submit their answer in an assignment-type challenge', async ({ + page +}) => { + await page.goto(links.assignment); + + // Wait for page load + await expect( + page.getByRole('heading', { name: 'Semantic HTML Review' }) + ).toBeVisible(); + + // Check the assignment checkbox + await page.getByRole('checkbox').check(); + + await page.keyboard.press('Meta+Enter'); + + // Completion modal shows up + await expect(page.getByRole('dialog')).toBeVisible(); +});