fix(client): fix backend code source submission (#58832)

Co-authored-by: sembauke <semboot699@gmail.com>
This commit is contained in:
Arif Khalid
2025-03-27 07:26:33 +08:00
committed by GitHub
parent 350424701f
commit e411c1eea6
6 changed files with 46 additions and 11 deletions

View File

@@ -981,7 +981,8 @@
"publicly-visible-url": "Remember to submit a publicly visible app URL.",
"ms-learn-link": "Please use a valid Microsoft Learn trophy link.",
"path-url": "You probably want to submit the root path i.e. https://example.com, not https://example.com/path",
"source-code-link-required": "Remember to submit the link to your source code."
"source-code-link-required": "Remember to submit the link to your source code.",
"source-code-link-public": "Source code link must be publicly visible."
},
"certification": {
"executive": "Executive Director, freeCodeCamp.org",

View File

@@ -15,7 +15,8 @@ import {
fCCValidator,
httpValidator,
pathValidator,
sourceCodeLinkExistsValidator
sourceCodeLinkExistsValidator,
sourceCodeLinkPublicValidator
} from './form-validators';
export type FormOptions = {
@@ -67,8 +68,11 @@ function FormFields({ formFields, options }: FormFieldsProps): JSX.Element {
validators.push(pathValidator);
}
}
if (isSourceCodeLinkRequired && name === 'githubLink') {
validators.push(sourceCodeLinkExistsValidator);
if (name === 'githubLink') {
if (isSourceCodeLinkRequired) {
validators.push(sourceCodeLinkExistsValidator);
}
validators.push(sourceCodeLinkPublicValidator);
}
if (!isLocalLinkAllowed) {
validators.push(localhostValidator);

View File

@@ -41,6 +41,8 @@ export const pathValidator: Validator = value =>
export const sourceCodeLinkExistsValidator: Validator = value =>
value ? null : <Trans>validation.source-code-link-required</Trans>;
export const sourceCodeLinkPublicValidator: Validator = value =>
isPrivate(value) ? <Trans>validation.source-code-link-public</Trans> : null;
export function composeValidators(...validators: Validator[]) {
return (value: string): ReturnType<Validator> | null =>
validators.reduce(

View File

@@ -9,7 +9,8 @@ import {
composeValidators,
fCCValidator,
httpValidator,
sourceCodeLinkExistsValidator
sourceCodeLinkExistsValidator,
sourceCodeLinkPublicValidator
} from './form-validators';
import FormFields, { FormOptions } from './form-fields';
@@ -69,8 +70,11 @@ function validateFormValues(
if (!isLocalLinkAllowed) {
validators.push(localhostValidator);
}
if (isSourceCodeLinkRequired) {
validators.push(sourceCodeLinkExistsValidator);
if (key === 'githubLink') {
if (isSourceCodeLinkRequired) {
validators.push(sourceCodeLinkExistsValidator);
}
validators.push(sourceCodeLinkPublicValidator);
}
const nullOrWarning = composeValidators(...validators)(value);

View File

@@ -56,7 +56,7 @@ function postChallenge(update) {
const saveChallenge = postUpdate$(update).pipe(
retry(3),
switchMap(({ data }) => {
const { savedChallenges, message, examResults } = data;
const { type, savedChallenges, message, examResults } = data;
const payloadWithClientProperties = {
...omit(update.payload, ['files'])
};
@@ -79,8 +79,15 @@ function postChallenge(update) {
submitChallengeComplete()
];
if (message && challengeType === challengeTypes.msTrophy) {
actions = [createFlashMessage(data), submitChallengeError()];
if (
type === 'error' ||
(message && challengeType === challengeTypes.msTrophy)
) {
actions = [];
if (message) {
actions.push(createFlashMessage(data));
}
actions.push(submitChallengeError());
} else if (challengeType === challengeTypes.msTrophy) {
actions.push(createFlashMessage(msTrophyVerified));
}

View File

@@ -3,7 +3,9 @@ import { test, expect } from '@playwright/test';
const locations = {
index:
'learn/back-end-development-and-apis/managing-packages-with-npm/' +
'how-to-use-package-json-the-core-of-any-node-js-project-or-npm-package'
'how-to-use-package-json-the-core-of-any-node-js-project-or-npm-package',
project:
'/learn/back-end-development-and-apis/back-end-development-and-apis-projects/timestamp-microservice'
};
const unhandledErrorMessage = 'Something is not quite right';
@@ -28,3 +30,18 @@ test.describe('Backend challenge', () => {
await expect(page.getByText(unhandledErrorMessage)).not.toBeVisible();
});
});
test.describe('Backend project', () => {
test.beforeEach(async ({ page }) => {
await page.goto(locations.project);
});
test('warns against private source code links', async ({ page }) => {
await page.fill('input[name="solution"]', 'https://example.com');
await page.fill('input[name="githubLink"]', 'https://localhost:3000');
await expect(
page.getByText('Source code link must be publicly visible.')
).toBeVisible();
});
});