feat(client): allow empty source code testing (#53797)

Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
This commit is contained in:
Shaun Hamilton
2024-06-25 13:27:44 +02:00
committed by GitHub
parent 1b237f3c78
commit 59498e5b09
5 changed files with 65 additions and 36 deletions
@@ -872,7 +872,8 @@
"own-work-url": "Remember to submit your own work.",
"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"
"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."
},
"certification": {
"executive": "Executive Director, freeCodeCamp.org",
@@ -14,13 +14,15 @@ import {
composeValidators,
fCCValidator,
httpValidator,
pathValidator
pathValidator,
sourceCodeLinkExistsValidator
} from './form-validators';
export type FormOptions = {
ignored?: string[];
isEditorLinkAllowed?: boolean;
isLocalLinkAllowed?: boolean;
isSourceCodeLinkRequired?: boolean;
required?: string[];
types?: { [key: string]: string };
placeholders?: { [key: string]: string };
@@ -38,7 +40,8 @@ function FormFields({ formFields, options }: FormFieldsProps): JSX.Element {
required = [],
types = {},
isEditorLinkAllowed = false,
isLocalLinkAllowed = false
isLocalLinkAllowed = false,
isSourceCodeLinkRequired = false
} = options;
const nullOrWarning = (
@@ -64,6 +67,9 @@ function FormFields({ formFields, options }: FormFieldsProps): JSX.Element {
validators.push(pathValidator);
}
}
if (isSourceCodeLinkRequired && name === 'githubLink') {
validators.push(sourceCodeLinkExistsValidator);
}
if (!isLocalLinkAllowed) {
validators.push(localhostValidator);
}
@@ -38,6 +38,9 @@ export const httpValidator: Validator = value =>
export const pathValidator: Validator = value =>
isPathRoot(value) ? <Trans>validation.path-url</Trans> : null;
export const sourceCodeLinkExistsValidator: Validator = value =>
value ? null : <Trans>validation.source-code-link-required</Trans>;
export function composeValidators(...validators: Validator[]) {
return (value: string): ReturnType<Validator> | null =>
validators.reduce(
+48 -31
View File
@@ -8,7 +8,8 @@ import {
editorValidator,
composeValidators,
fCCValidator,
httpValidator
httpValidator,
sourceCodeLinkExistsValidator
} from './form-validators';
import FormFields, { FormOptions } from './form-fields';
@@ -35,43 +36,59 @@ function validateFormValues(
formValues: FormValues,
options: FormOptions
): ValidatedValues {
const { isEditorLinkAllowed, isLocalLinkAllowed, types } = options;
const {
isEditorLinkAllowed,
isLocalLinkAllowed,
isSourceCodeLinkRequired,
types
} = options;
const validatedValues: ValidatedValues = {
values: {},
errors: [],
invalidValues: []
};
const urlValues = Object.entries(formValues).reduce(
(result, [key, value]) => {
// NOTE: pathValidator is not used here, because it is only used as a
// suggestion - should not prevent form submission
const validators = [fCCValidator, httpValidator];
const isSolutionLink = key !== 'githubLink';
if (isSolutionLink && !isEditorLinkAllowed) {
validators.push(editorValidator);
}
if (!isLocalLinkAllowed) {
validators.push(localhostValidator);
}
const nullOrWarning = composeValidators(...validators)(value);
if (nullOrWarning) {
validatedValues.invalidValues.push(nullOrWarning);
const formFields = Object.entries(formValues);
// We don't always get a githubLink field in formValues, so we can't simply
// validate that field like the others. We have to handle it separately.
if (isSourceCodeLinkRequired) {
const githubLink = formValues['githubLink'];
if (!githubLink) {
validatedValues.invalidValues.push(sourceCodeLinkExistsValidator(''));
}
}
const urlValues = formFields.reduce((result, [key, value]) => {
// NOTE: pathValidator is not used here, because it is only used as a
// suggestion - should not prevent form submission
const validators = [fCCValidator, httpValidator];
const isSolutionLink = key !== 'githubLink';
if (isSolutionLink && !isEditorLinkAllowed) {
validators.push(editorValidator);
}
if (!isLocalLinkAllowed) {
validators.push(localhostValidator);
}
if (isSourceCodeLinkRequired) {
validators.push(sourceCodeLinkExistsValidator);
}
const nullOrWarning = composeValidators(...validators)(value);
if (nullOrWarning) {
validatedValues.invalidValues.push(nullOrWarning);
}
if (value && types && types[key] === 'url') {
try {
value = normalizeUrl(value, normalizeOptions);
} catch (err: unknown) {
validatedValues.errors.push({
error: err as { message?: string },
value
});
}
if (value && types && types[key] === 'url') {
try {
value = normalizeUrl(value, normalizeOptions);
} catch (err: unknown) {
validatedValues.errors.push({
error: err as { message?: string },
value
});
}
}
return { ...result, [key]: value };
},
{}
);
}
return { ...result, [key]: value };
}, {});
validatedValues.values = urlValues;
return validatedValues;
}
@@ -63,7 +63,8 @@ export class SolutionForm extends Component<SolutionFormProps> {
},
required: ['solution'],
isEditorLinkAllowed: false,
isLocalLinkAllowed: false
isLocalLinkAllowed: false,
isSourceCodeLinkRequired: false
};
let formFields = solutionField;
@@ -85,7 +86,8 @@ export class SolutionForm extends Component<SolutionFormProps> {
case challengeTypes.backEndProject:
formFields = backEndProjectFields;
options.required.push('githubLink');
// options.required.push('githubLink');
options.isSourceCodeLinkRequired = true;
options.isLocalLinkAllowed = true;
solutionLink = solutionLink + 'https://3000-project-url.gitpod.io/';
solutionFormID = 'back-end-form';