mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-06-13 21:02:08 +08:00
fix(client): only use contents from savedChallenges (#55364)
This commit is contained in:
parent
3a20e90e5d
commit
5cc10ef7b7
@ -357,6 +357,8 @@ export type SavedChallenge = {
|
||||
challengeFiles: SavedChallengeFiles;
|
||||
};
|
||||
|
||||
// TODO: remove unused properties and stop returning them from api? (e.g.
|
||||
// history, ext, name)
|
||||
export type SavedChallengeFile = {
|
||||
fileKey: string;
|
||||
ext: Ext;
|
||||
|
||||
132
client/src/templates/Challenges/classic/saved-challenges.test.ts
Normal file
132
client/src/templates/Challenges/classic/saved-challenges.test.ts
Normal file
@ -0,0 +1,132 @@
|
||||
import type {
|
||||
ChallengeFile,
|
||||
SavedChallengeFile
|
||||
} from '../../../redux/prop-types';
|
||||
import { mergeChallengeFiles } from './saved-challenges';
|
||||
|
||||
const jsChallenge = {
|
||||
id: '1',
|
||||
contents: 'js contents',
|
||||
fileKey: 'jsFileKey',
|
||||
name: 'name',
|
||||
ext: 'js' as const,
|
||||
head: 'head',
|
||||
tail: 'tail',
|
||||
history: [],
|
||||
seed: 'original js contents'
|
||||
};
|
||||
|
||||
const cssChallenge = {
|
||||
id: '2',
|
||||
contents: 'css contents',
|
||||
fileKey: 'cssFileKey',
|
||||
name: 'name',
|
||||
ext: 'css' as const,
|
||||
head: 'head',
|
||||
tail: 'tail',
|
||||
history: [],
|
||||
seed: 'original css contents'
|
||||
};
|
||||
|
||||
const htmlChallenge = {
|
||||
id: '3',
|
||||
contents: 'html contents',
|
||||
fileKey: 'htmlFileKey',
|
||||
name: 'name',
|
||||
ext: 'html' as const,
|
||||
head: 'head',
|
||||
tail: 'tail',
|
||||
history: [],
|
||||
seed: 'original html contents'
|
||||
};
|
||||
|
||||
const savedJsChallenge: SavedChallengeFile = {
|
||||
contents: 'saved js contents',
|
||||
fileKey: 'jsFileKey',
|
||||
name: 'name',
|
||||
ext: 'js' as const
|
||||
};
|
||||
|
||||
const savedCssChallenge: SavedChallengeFile = {
|
||||
contents: 'saved css contents',
|
||||
fileKey: 'cssFileKey',
|
||||
name: 'name',
|
||||
ext: 'css' as const
|
||||
};
|
||||
|
||||
const savedHtmlChallenge: SavedChallengeFile = {
|
||||
contents: 'saved html contents',
|
||||
fileKey: 'htmlFileKey',
|
||||
name: 'name',
|
||||
ext: 'html' as const
|
||||
};
|
||||
|
||||
describe('mergeChallengeFiles', () => {
|
||||
it('should return files if savedChallengeFiles is undefined', () => {
|
||||
const files: ChallengeFile[] = [htmlChallenge];
|
||||
const savedChallengeFiles = undefined;
|
||||
|
||||
const result = mergeChallengeFiles(files, savedChallengeFiles);
|
||||
|
||||
expect(result).toEqual(files);
|
||||
});
|
||||
|
||||
it('should return an empty array if files is undefined', () => {
|
||||
const files = undefined;
|
||||
const savedChallengeFiles = [savedJsChallenge];
|
||||
|
||||
const result = mergeChallengeFiles(files, savedChallengeFiles);
|
||||
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it('should return files if savedChallengeFiles has a different length', () => {
|
||||
const files: ChallengeFile[] = [cssChallenge];
|
||||
const savedChallengeFiles: SavedChallengeFile[] = [
|
||||
savedCssChallenge,
|
||||
savedJsChallenge
|
||||
];
|
||||
|
||||
const result = mergeChallengeFiles(files, savedChallengeFiles);
|
||||
|
||||
expect(result).toEqual(files);
|
||||
});
|
||||
|
||||
it('should return files if the fileKey properties do not match', () => {
|
||||
const files: ChallengeFile[] = [jsChallenge, cssChallenge];
|
||||
const savedChallengeFiles: SavedChallengeFile[] = [
|
||||
savedHtmlChallenge,
|
||||
savedCssChallenge
|
||||
];
|
||||
|
||||
const result = mergeChallengeFiles(files, savedChallengeFiles);
|
||||
|
||||
expect(result).toEqual(files);
|
||||
});
|
||||
|
||||
it('should use the contents from the saved file', () => {
|
||||
const files: ChallengeFile[] = [cssChallenge, htmlChallenge, jsChallenge];
|
||||
const savedChallengeFiles = [
|
||||
savedJsChallenge,
|
||||
savedCssChallenge,
|
||||
savedHtmlChallenge
|
||||
];
|
||||
|
||||
const result = mergeChallengeFiles(files, savedChallengeFiles);
|
||||
|
||||
expect(result).toEqual([
|
||||
{
|
||||
...cssChallenge,
|
||||
contents: savedCssChallenge.contents
|
||||
},
|
||||
{
|
||||
...htmlChallenge,
|
||||
contents: savedHtmlChallenge.contents
|
||||
},
|
||||
{
|
||||
...jsChallenge,
|
||||
contents: savedJsChallenge.contents
|
||||
}
|
||||
]);
|
||||
});
|
||||
});
|
||||
28
client/src/templates/Challenges/classic/saved-challenges.ts
Normal file
28
client/src/templates/Challenges/classic/saved-challenges.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { ChallengeFile, SavedChallengeFile } from '../../../redux/prop-types';
|
||||
|
||||
export function mergeChallengeFiles(
|
||||
files?: ChallengeFile[] | null,
|
||||
savedFiles?: SavedChallengeFile[] | null
|
||||
): ChallengeFile[] {
|
||||
if (!files) return [];
|
||||
if (!savedFiles) return files;
|
||||
if (files.length !== savedFiles.length) return files;
|
||||
|
||||
const sortedChallengeFiles = files.sort((a, b) =>
|
||||
a.fileKey.localeCompare(b.fileKey)
|
||||
);
|
||||
const sortedSavedChallengeFiles = savedFiles.sort((a, b) =>
|
||||
a.fileKey.localeCompare(b.fileKey)
|
||||
);
|
||||
|
||||
const fileKeysMatch = sortedChallengeFiles.every(
|
||||
(file, index) => file.fileKey === sortedSavedChallengeFiles[index].fileKey
|
||||
);
|
||||
|
||||
if (!fileKeysMatch) return files;
|
||||
|
||||
return sortedChallengeFiles.map((file, index) => ({
|
||||
...file,
|
||||
contents: sortedSavedChallengeFiles[index].contents
|
||||
}));
|
||||
}
|
||||
@ -62,6 +62,7 @@ import { XtermTerminal } from './xterm';
|
||||
import MultifileEditor from './multifile-editor';
|
||||
import DesktopLayout from './desktop-layout';
|
||||
import MobileLayout from './mobile-layout';
|
||||
import { mergeChallengeFiles } from './saved-challenges';
|
||||
|
||||
import './classic.css';
|
||||
import '../components/test-frame.css';
|
||||
@ -351,7 +352,9 @@ function ShowClassic({
|
||||
return challenge.id === challengeMeta.id;
|
||||
});
|
||||
|
||||
createFiles(savedChallenge?.challengeFiles || challengeFiles || []);
|
||||
createFiles(
|
||||
mergeChallengeFiles(challengeFiles, savedChallenge?.challengeFiles)
|
||||
);
|
||||
|
||||
initTests(tests);
|
||||
if (showProjectPreview) openModal('projectPreview');
|
||||
|
||||
Loading…
Reference in New Issue
Block a user