fix (client): prevent completion modal in multi-file labs (#66552)

Co-authored-by: Venkat <venkat@Venkats-MacBook-Pro.local>
Co-authored-by: sembauke <semboot699@gmail.com>
This commit is contained in:
Venkataramana Devathoti
2026-05-21 16:44:14 +05:30
committed by GitHub
parent 9372acecf7
commit 5f60026666
6 changed files with 80 additions and 12 deletions
@@ -633,6 +633,7 @@ const Editor = (props: EditorProps): JSX.Element => {
monaco.KeyMod.WinCtrl | monaco.KeyCode.Enter
],
run: () => {
const shouldShowCompletionModal = !props.showIndependentLowerJaw;
if (props.usesMultifileEditor && !isProjectBased(props.challengeType)) {
if (challengeIsComplete()) {
tryToSubmitChallenge();
@@ -640,7 +641,9 @@ const Editor = (props: EditorProps): JSX.Element => {
tryToExecuteChallenge();
}
} else {
props.executeChallenge({ showCompletionModal: true });
props.executeChallenge({
showCompletionModal: shouldShowCompletionModal
});
}
}
});
@@ -445,6 +445,7 @@ function ShowClassic({
instructionsPanelRef={instructionsPanelRef}
usesMultifileEditor={usesMultifileEditor}
editorRef={editorRef}
showIndependentLowerJaw={showIndependentLowerJaw}
>
<LearnLayout>
<Helmet title={windowTitle} />
@@ -97,6 +97,7 @@ export type HotkeysProps = Pick<
openShortcutsModal: () => void;
playScene?: () => void;
keyboardShortcuts: boolean;
showIndependentLowerJaw?: boolean;
};
function Hotkeys({
@@ -119,7 +120,8 @@ function Hotkeys({
isHelpModalOpen,
isResetModalOpen,
isShortcutsModalOpen,
isProjectPreviewModalOpen
isProjectPreviewModalOpen,
showIndependentLowerJaw
}: HotkeysProps): JSX.Element {
const submitChallenge = useSubmit();
@@ -167,7 +169,7 @@ function Hotkeys({
executeChallenge();
}
} else {
executeChallenge({ showCompletionModal: true });
executeChallenge({ showCompletionModal: !showIndependentLowerJaw });
}
},
...(keyboardShortcuts
+60 -2
View File
@@ -2,7 +2,7 @@ import { test, expect, type Page } from '@playwright/test';
import translations from '../client/i18n/locales/english/translations.json';
import { authedRequest } from './utils/request';
import { getEditors } from './utils/editor';
import { clearEditor, getEditors } from './utils/editor';
import { alertToBeVisible } from './utils/alerts';
const links = {
@@ -25,7 +25,9 @@ const links = {
multipleChoiceQuestion:
'/learn/a2-english-for-developers/learn-greetings-in-your-first-day-at-the-office/task-7',
assignment:
'/learn/responsive-web-design-v9/review-semantic-html/review-semantic-html'
'/learn/responsive-web-design-v9/review-semantic-html/review-semantic-html',
multifileLab:
'/learn/responsive-web-design-v9/lab-debug-camperbots-profile-page/lab-debug-camperbots-profile-page'
};
const titles = {
@@ -37,6 +39,15 @@ const titles = {
};
type PageId = keyof typeof titles;
const multifileLabSolution = `<h1>Hello from Camperbot!</h1>
<h2>About</h2>
<p>My name is Camperbot and I love learning new things.</p>
<h3>Background and Interests</h3>
<p>I enjoy solving puzzles.</p>`;
// The hotkeys are attached to specific elements, so we need to wait for the
// wrapper to be focused before we can test the hotkeys.
const waitUntilListening = async (page: Page) =>
@@ -50,6 +61,31 @@ const waitUntilHydrated = async (page: Page, pageId: PageId) => {
await waitUntilListening(page);
};
const completeMultifileLabWithHotkey = async ({
browserName,
hotkey,
page
}: {
browserName: string;
hotkey: 'Control+Enter' | 'Meta+Enter';
page: Page;
}) => {
await page.goto(links.multifileLab);
const editor = getEditors(page);
await editor.focus();
await expect(editor).toBeFocused();
await clearEditor({ page, browserName });
await editor.fill(multifileLabSolution);
await page.keyboard.press(hotkey);
await expect(
page.getByTestId('independentLowerJaw-submit-button')
).toBeVisible();
await expect(page.getByRole('dialog')).toHaveCount(0);
};
test.beforeAll(async ({ request }) => {
await authedRequest({
request,
@@ -215,3 +251,25 @@ test('User can use Cmd+Enter to submit their answer in an assignment-type challe
// Completion modal shows up
await expect(page.getByRole('dialog')).toBeVisible();
});
test('Ctrl+Enter should not open completion modal in multifile editor (uses lower jaw)', async ({
page,
browserName
}) => {
await completeMultifileLabWithHotkey({
browserName,
hotkey: 'Control+Enter',
page
});
});
test('Cmd+Enter should not open completion modal in multifile editor (uses lower jaw)', async ({
page,
browserName
}) => {
await completeMultifileLabWithHotkey({
browserName,
hotkey: 'Meta+Enter',
page
});
});
+6 -4
View File
@@ -1,4 +1,4 @@
import { test } from '@playwright/test';
import { test, expect } from '@playwright/test';
import solution from './fixtures/build-a-personal-portfolio-webpage.json';
import { clearEditor, focusEditor } from './utils/editor';
import { isMacOS } from './utils/user-agent';
@@ -81,9 +81,11 @@ test.describe('Should take you to the next superblock (with editor solution)', (
await page.keyboard.press('Control+Enter');
await page
.getByRole('button', { name: 'Submit and go to next challenge' })
.click();
const submitButton = page.locator(
'[data-playwright-test-label="independentLowerJaw-submit-button"]'
);
await expect(submitButton).toBeVisible();
await submitButton.click();
await page.waitForURL(rwdChallenge.nextUrl);
});
});
+5 -3
View File
@@ -243,13 +243,13 @@ test.describe('JavaScript projects can be submitted and then viewed in /settings
});
});
test.describe('Completion modal should be shown after submitting a project', () => {
test.describe('Submit button should be shown after submitting a project', () => {
test.skip(
({ browserName }) => browserName !== 'chromium',
'Only chromium allows us to use the clipboard API.'
);
test('Ctrl + enter triggers the completion modal on multifile projects', async ({
test('Ctrl + enter triggers the submit button on multifile projects', async ({
page,
context,
isMobile
@@ -280,7 +280,9 @@ test.describe('Completion modal should be shown after submitting a project', ()
await page.keyboard.press('Control+Enter');
await page
.getByRole('button', { name: 'Go to next challenge', exact: false })
.locator(
'[data-playwright-test-label="independentLowerJaw-submit-button"]'
)
.click();
});
});