Skip to content

Commit e411c1e

Browse files
fix(client): fix backend code source submission (freeCodeCamp#58832)
Co-authored-by: sembauke <semboot699@gmail.com>
1 parent 3504247 commit e411c1e

File tree

6 files changed

+46
-11
lines changed

6 files changed

+46
-11
lines changed

client/i18n/locales/english/translations.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -981,7 +981,8 @@
981981
"publicly-visible-url": "Remember to submit a publicly visible app URL.",
982982
"ms-learn-link": "Please use a valid Microsoft Learn trophy link.",
983983
"path-url": "You probably want to submit the root path i.e. https://example.com, not https://example.com/path",
984-
"source-code-link-required": "Remember to submit the link to your source code."
984+
"source-code-link-required": "Remember to submit the link to your source code.",
985+
"source-code-link-public": "Source code link must be publicly visible."
985986
},
986987
"certification": {
987988
"executive": "Executive Director, freeCodeCamp.org",

client/src/components/formHelpers/form-fields.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ import {
1515
fCCValidator,
1616
httpValidator,
1717
pathValidator,
18-
sourceCodeLinkExistsValidator
18+
sourceCodeLinkExistsValidator,
19+
sourceCodeLinkPublicValidator
1920
} from './form-validators';
2021

2122
export type FormOptions = {
@@ -67,8 +68,11 @@ function FormFields({ formFields, options }: FormFieldsProps): JSX.Element {
6768
validators.push(pathValidator);
6869
}
6970
}
70-
if (isSourceCodeLinkRequired && name === 'githubLink') {
71-
validators.push(sourceCodeLinkExistsValidator);
71+
if (name === 'githubLink') {
72+
if (isSourceCodeLinkRequired) {
73+
validators.push(sourceCodeLinkExistsValidator);
74+
}
75+
validators.push(sourceCodeLinkPublicValidator);
7276
}
7377
if (!isLocalLinkAllowed) {
7478
validators.push(localhostValidator);

client/src/components/formHelpers/form-validators.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ export const pathValidator: Validator = value =>
4141
export const sourceCodeLinkExistsValidator: Validator = value =>
4242
value ? null : <Trans>validation.source-code-link-required</Trans>;
4343

44+
export const sourceCodeLinkPublicValidator: Validator = value =>
45+
isPrivate(value) ? <Trans>validation.source-code-link-public</Trans> : null;
4446
export function composeValidators(...validators: Validator[]) {
4547
return (value: string): ReturnType<Validator> | null =>
4648
validators.reduce(

client/src/components/formHelpers/form.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import {
99
composeValidators,
1010
fCCValidator,
1111
httpValidator,
12-
sourceCodeLinkExistsValidator
12+
sourceCodeLinkExistsValidator,
13+
sourceCodeLinkPublicValidator
1314
} from './form-validators';
1415
import FormFields, { FormOptions } from './form-fields';
1516

@@ -69,8 +70,11 @@ function validateFormValues(
6970
if (!isLocalLinkAllowed) {
7071
validators.push(localhostValidator);
7172
}
72-
if (isSourceCodeLinkRequired) {
73-
validators.push(sourceCodeLinkExistsValidator);
73+
if (key === 'githubLink') {
74+
if (isSourceCodeLinkRequired) {
75+
validators.push(sourceCodeLinkExistsValidator);
76+
}
77+
validators.push(sourceCodeLinkPublicValidator);
7478
}
7579

7680
const nullOrWarning = composeValidators(...validators)(value);

client/src/templates/Challenges/redux/completion-epic.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ function postChallenge(update) {
5656
const saveChallenge = postUpdate$(update).pipe(
5757
retry(3),
5858
switchMap(({ data }) => {
59-
const { savedChallenges, message, examResults } = data;
59+
const { type, savedChallenges, message, examResults } = data;
6060
const payloadWithClientProperties = {
6161
...omit(update.payload, ['files'])
6262
};
@@ -79,8 +79,15 @@ function postChallenge(update) {
7979
submitChallengeComplete()
8080
];
8181

82-
if (message && challengeType === challengeTypes.msTrophy) {
83-
actions = [createFlashMessage(data), submitChallengeError()];
82+
if (
83+
type === 'error' ||
84+
(message && challengeType === challengeTypes.msTrophy)
85+
) {
86+
actions = [];
87+
if (message) {
88+
actions.push(createFlashMessage(data));
89+
}
90+
actions.push(submitChallengeError());
8491
} else if (challengeType === challengeTypes.msTrophy) {
8592
actions.push(createFlashMessage(msTrophyVerified));
8693
}

e2e/backend.spec.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import { test, expect } from '@playwright/test';
33
const locations = {
44
index:
55
'learn/back-end-development-and-apis/managing-packages-with-npm/' +
6-
'how-to-use-package-json-the-core-of-any-node-js-project-or-npm-package'
6+
'how-to-use-package-json-the-core-of-any-node-js-project-or-npm-package',
7+
project:
8+
'/learn/back-end-development-and-apis/back-end-development-and-apis-projects/timestamp-microservice'
79
};
810

911
const unhandledErrorMessage = 'Something is not quite right';
@@ -28,3 +30,18 @@ test.describe('Backend challenge', () => {
2830
await expect(page.getByText(unhandledErrorMessage)).not.toBeVisible();
2931
});
3032
});
33+
34+
test.describe('Backend project', () => {
35+
test.beforeEach(async ({ page }) => {
36+
await page.goto(locations.project);
37+
});
38+
39+
test('warns against private source code links', async ({ page }) => {
40+
await page.fill('input[name="solution"]', 'https://example.com');
41+
await page.fill('input[name="githubLink"]', 'https://localhost:3000');
42+
43+
await expect(
44+
page.getByText('Source code link must be publicly visible.')
45+
).toBeVisible();
46+
});
47+
});

0 commit comments

Comments
 (0)