feat(client): truncate long logs in the client rather than test evaluator (#60235)

This commit is contained in:
Oliver Eyton-Williams
2025-05-14 22:16:31 +02:00
committed by GitHub
parent b629884fea
commit f606e19a1a
6 changed files with 18 additions and 28 deletions
@@ -5,7 +5,6 @@ import { createSelector } from 'reselect';
import { isDonationModalOpenSelector } from '../../../redux/selectors';
import {
canFocusEditorSelector,
consoleOutputSelector,
visibleEditorsSelector
} from '../redux/selectors';
import { getTargetEditor } from '../utils/get-target-editor';
@@ -44,17 +43,10 @@ type MultifileEditorProps = Pick<
const mapStateToProps = createSelector(
visibleEditorsSelector,
canFocusEditorSelector,
consoleOutputSelector,
isDonationModalOpenSelector,
(
visibleEditors: VisibleEditors,
canFocus: boolean,
output: string[],
open
) => ({
(visibleEditors: VisibleEditors, canFocus: boolean, open) => ({
visibleEditors,
canFocus: open ? false : canFocus,
output
canFocus: open ? false : canFocus
})
);
@@ -76,7 +76,7 @@ import '../components/test-frame.css';
const mapStateToProps = (state: unknown) => ({
challengeFiles: challengeFilesSelector(state) as ChallengeFiles,
output: consoleOutputSelector(state) as string[],
output: consoleOutputSelector(state) as string,
isChallengeCompleted: isChallengeCompletedSelector(state) as boolean,
savedChallenges: savedChallengesSelector(state) as SavedChallenge[]
});
@@ -113,7 +113,7 @@ interface ShowClassicProps extends Pick<PreviewProps, 'previewMounted'> {
initHooks: (hooks?: { beforeAll: string }) => void;
initVisibleEditors: () => void;
isChallengeCompleted: boolean;
output: string[];
output: string;
pageContext: {
challengeMeta: ChallengeMeta;
projectPreview: {
@@ -7,16 +7,13 @@ import './output.css';
interface OutputProps {
defaultOutput: string;
output: string[];
output: string;
}
function Output({ defaultOutput, output }: OutputProps): JSX.Element {
const message = sanitizeHtml(
!isEmpty(output) ? output.join('\n') : defaultOutput,
{
allowedTags: ['b', 'i', 'em', 'strong', 'code', 'wbr']
}
);
const message = sanitizeHtml(!isEmpty(output) ? output : defaultOutput, {
allowedTags: ['b', 'i', 'em', 'strong', 'code', 'wbr']
});
return (
<pre
className='output-text'
@@ -49,7 +49,7 @@ const mapStateToProps = createSelector(
isChallengeCompletedSelector,
isSignedInSelector,
(
output: string[],
output: string,
tests: Test[],
isChallengeCompleted: boolean,
isSignedIn: boolean
@@ -82,7 +82,7 @@ interface BackEndProps {
initTests: (tests: Test[]) => void;
isChallengeCompleted: boolean;
isSignedIn: boolean;
output: string[];
output: string;
pageContext: {
challengeMeta: ChallengeMeta;
};
@@ -18,7 +18,13 @@ export const challengeFilesSelector = state => state[ns].challengeFiles;
export const challengeMetaSelector = state => state[ns].challengeMeta;
export const challengeHooksSelector = state => state[ns].challengeHooks;
export const challengeTestsSelector = state => state[ns].challengeTests;
export const consoleOutputSelector = state => state[ns].consoleOut;
export const consoleOutputSelector = state => {
const TRUNCATE_AT = 500000;
const out = state[ns].consoleOut?.join('\n');
return out?.length > TRUNCATE_AT
? `${out.substring(0, TRUNCATE_AT)} Logs truncated. See browser console for more`
: out;
};
export const isChallengeCompletedSelector = createSelector(
[completedChallengesIdsSelector, challengeMetaSelector],
(ids, meta) => ids.includes(meta.id)
@@ -8,19 +8,14 @@ const ctx: Worker & typeof globalThis = self as unknown as Worker &
const __utils = (() => {
const MAX_LOGS_SIZE = 64 * 1024;
const TRUNCATE_AT = 500_000;
let logs: string[] = [];
function flushLogs() {
if (logs.length) {
let data = logs.join('\n');
if (data.length > TRUNCATE_AT) {
data = `${data.substring(0, TRUNCATE_AT)} Logs truncated. See browser console for more`;
}
ctx.postMessage({
type: 'LOG',
data: data
data: logs.join('\n')
});
logs = [];
}