fix: only run one previewChallengeSaga at once (#52244)

This commit is contained in:
Oliver Eyton-Williams
2024-01-11 08:03:20 -08:00
committed by GitHub
parent 26a9735d07
commit 964be252ed
2 changed files with 52 additions and 7 deletions
@@ -234,7 +234,8 @@ function* executeTests(testRunner, tests, testTimeout = 5000) {
}
// updates preview frame and the fcc console.
function* previewChallengeSaga({ flushLogs = true } = {}) {
export function* previewChallengeSaga(action) {
const flushLogs = action?.type !== actionTypes.previewMounted;
yield delay(700);
const isBuildEnabled = yield select(isBuildEnabledSelector);
@@ -299,13 +300,16 @@ function* previewChallengeSaga({ flushLogs = true } = {}) {
}
}
function* updatePreviewSaga() {
// TODO: refactor this so that we can use a single saga for all challenge
// updates (then they can all go in the same `takeLatest` call and be cancelled
// appropriately)
function* updatePreviewSaga(action) {
const challengeData = yield select(challengeDataSelector);
if (challengeData.challengeType === challengeTypes.python) {
yield updatePython(challengeData);
} else {
// all other challenges have to recreate the preview
yield previewChallengeSaga();
yield previewChallengeSaga(action);
}
}
@@ -348,12 +352,9 @@ export function createExecuteChallengeSaga(types) {
takeLatest(types.executeChallenge, executeCancellableChallengeSaga),
takeLatest(types.updateFile, updatePreviewSaga),
takeLatest(
[types.challengeMounted, types.resetChallenge],
[types.challengeMounted, types.resetChallenge, types.previewMounted],
previewChallengeSaga
),
takeLatest(types.previewMounted, previewChallengeSaga, {
flushLogs: false
}),
takeLatest(types.projectPreviewMounted, previewProjectSolutionSaga)
];
}
@@ -0,0 +1,44 @@
import { expectSaga } from 'redux-saga-test-plan';
jest.mock('redux-saga/effects', () => ({
...jest.requireActual('redux-saga/effects'),
delay: jest.fn()
}));
const initialState = {
challenge: { isBuildEnabled: true, isExecuting: false, challengeMeta: {} }
};
// We're not testing the reducer here, so just return the initial state
function reducer(state = initialState, _action) {
return state;
}
import { previewChallengeSaga } from './execute-challenge-saga';
const challengeMounted = { type: 'challenge.challengeMounted' };
const previewMounted = { type: 'challenge.previewMounted' };
const resetChallenge = { type: 'challenge.resetChallenge' };
describe('execute-challenge-saga', () => {
it('flushes logs on challengeMounted', () => {
return expectSaga(previewChallengeSaga, challengeMounted)
.withReducer(reducer)
.put({ type: 'challenge.initLogs' })
.silentRun();
// TODO: figure out why silentRun is necessary. Without it, we get timeout
// warnings. Increasing the timeout just makes the tests take longer.
});
it('flushes logs on reset', () => {
return expectSaga(previewChallengeSaga, resetChallenge)
.withReducer(reducer)
.put({ type: 'challenge.initLogs' })
.silentRun();
});
it('does not flush logs on previewMounted', () => {
return expectSaga(previewChallengeSaga, previewMounted)
.withReducer(reducer)
.not.put({ type: 'challenge.initLogs' })
.silentRun();
});
});