Skip to content

Commit 02541ff

Browse files
authored
Merge pull request #1313 from revisit-studies/jay/regexBug
Fix dynamic block answer deletion regex
2 parents 14468df + 83008bc commit 02541ff

4 files changed

Lines changed: 31 additions & 6 deletions

File tree

src/routes/tests/utils.spec.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,18 @@ describe('useCurrentComponent', () => {
188188
const { result } = renderHook(() => useCurrentComponent());
189189
expect(result.current).toBe('CompA');
190190
});
191+
192+
test('answer lookup matches the exact funcIndex, not a partial suffix', async () => {
193+
mockParams = { studyId: 'test-study', index: '0', funcIndex: '1' };
194+
mockFlatSequence = ['myFunc', 'end'];
195+
mockAnswers = {
196+
myFunc_0_CompEleven_11: { componentName: 'CompEleven' },
197+
myFunc_0_CompOne_1: { componentName: 'CompOne' },
198+
};
199+
vi.mocked(getComponent).mockReturnValue(null);
200+
const { result } = renderHook(() => useCurrentComponent());
201+
expect(result.current).toBe('CompOne');
202+
});
191203
});
192204

193205
describe('useCurrentIdentifier', () => {

src/routes/utils.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export function useCurrentComponent(): string {
9191
const decryptedFuncIndex = funcIndex ? decryptIndex(funcIndex) : 0;
9292

9393
// Check if answer exists for this index, if so get the component name and return early
94-
const currentAnswer = Object.entries(_answers).find(([key, _]) => key.startsWith(`${funcName}_${currentStep}_`) && key.endsWith(`${decryptedFuncIndex}`));
94+
const currentAnswer = Object.entries(_answers).find(([key, _]) => key.startsWith(`${funcName}_${currentStep}_`) && key.endsWith(`_${decryptedFuncIndex}`));
9595
const answerCompName = currentAnswer ? currentAnswer[1].componentName : null;
9696
if (answerCompName !== null) {
9797
setCompName(answerCompName);

src/store/store.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -369,16 +369,15 @@ export async function studyStoreCreator(
369369
deleteDynamicBlockAnswers(state, { payload }: PayloadAction<{ currentStep: number, funcIndex: number, funcName: string }>) {
370370
const { currentStep, funcIndex, funcName } = payload;
371371

372-
// regex to match all keys that start with the current step and funcIndex
373-
const regex = new RegExp(`.*_${currentStep}_.*_${funcIndex}`);
374-
// delete all keys that match the regex
372+
// Dynamic block keys have the form `${funcName}_${currentStep}_${componentName}_${funcIndex}`
373+
const matchesDeletedIteration = (key: string) => key.startsWith(`${funcName}_${currentStep}_`) && key.endsWith(`_${funcIndex}`);
375374
Object.keys(state.answers).forEach((key) => {
376-
if (key.match(regex)) {
375+
if (matchesDeletedIteration(key)) {
377376
delete state.answers[key];
378377
}
379378
});
380379
Object.keys(state.checkAnswer).forEach((key) => {
381-
if (key.match(regex)) {
380+
if (matchesDeletedIteration(key)) {
382381
delete state.checkAnswer[key];
383382
}
384383
});

src/store/tests/store.spec.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,20 @@ describe('studyStoreCreator', () => {
456456
expect(store.getState().funcSequence.myFunc).toBeUndefined();
457457
});
458458

459+
test('deleteDynamicBlockAnswers only deletes the exact funcIndex, not partial matches', async () => {
460+
const { store, actions } = await studyStoreCreator('test', minimalConfig, minimalSequence, metadata, emptyAnswers, modes, 'p1', false, false);
461+
for (let i = 0; i <= 10; i += 1) {
462+
store.dispatch(actions.pushToFuncSequence({
463+
component: 'intro', funcName: 'myFunc', index: 5, funcIndex: i, parameters: {}, correctAnswer: [],
464+
}));
465+
}
466+
expect(store.getState().answers.myFunc_5_intro_1).toBeDefined();
467+
expect(store.getState().answers.myFunc_5_intro_10).toBeDefined();
468+
store.dispatch(actions.deleteDynamicBlockAnswers({ currentStep: 5, funcIndex: 1, funcName: 'myFunc' }));
469+
expect(store.getState().answers.myFunc_5_intro_1).toBeUndefined();
470+
expect(store.getState().answers.myFunc_5_intro_10).toBeDefined();
471+
});
472+
459473
test('deleteDynamicBlockAnswers clears checkAnswer state for the deleted steps', async () => {
460474
const { store, actions } = await studyStoreCreator('test', minimalConfig, minimalSequence, metadata, emptyAnswers, modes, 'p1', false, false);
461475
store.dispatch(actions.setCheckAnswerResult({

0 commit comments

Comments
 (0)