mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 10:22:16 +00:00
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:
committed by
GitHub
parent
9372acecf7
commit
5f60026666
@@ -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
@@ -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
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user