fix(client): only use contents from savedChallenges (#55364)

This commit is contained in:
Oliver Eyton-Williams 2024-06-28 19:50:02 +02:00 committed by GitHub
parent 3a20e90e5d
commit 5cc10ef7b7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 166 additions and 1 deletions

View File

@ -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;

View 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
}
]);
});
});

View 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
}));
}

View File

@ -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');