Skip to content

Commit 242fb7d

Browse files
Align atStart and atEnd length checks, get rid of createSourceIsSelect, add function to reset storage queues for testing
1 parent 4ec6393 commit 242fb7d

5 files changed

Lines changed: 24 additions & 26 deletions

File tree

src/__tests__/components/ProjectModals.test.tsx

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ describe('ProjectModals', () => {
268268
expect(setModal).toHaveBeenCalledWith('none');
269269
});
270270

271-
it('calls setModal with create and sets createSourceIsSelect when create new is clicked', async () => {
271+
it('calls setModal with create when create new is clicked', async () => {
272272
const { setModal } = renderModals({ modal: 'select' });
273273
await userEvent.click(screen.getByTestId('select-create-new'));
274274
expect(setModal).toHaveBeenCalledWith('create');
@@ -282,19 +282,16 @@ describe('ProjectModals', () => {
282282
});
283283

284284
describe('create modal', () => {
285-
it('calls setModal with none when create modal closes without a select source', async () => {
285+
it('calls setModal with none when create modal is closed', async () => {
286286
const { setModal } = renderModals({ modal: 'create' });
287287
await userEvent.click(screen.getByTestId('create-close'));
288288
expect(setModal).toHaveBeenCalledWith('none');
289289
});
290290

291-
it('calls setModal with select on close when createSourceIsSelect is true', async () => {
292-
// To set createSourceIsSelect, we must open create from the select modal.
293-
// Render with select open first, then trigger create-new.
291+
it('calls setModal with none when create modal is closed after opening from select', async () => {
294292
const setModal = jest.fn();
295293
const state = makeWebViewState();
296294

297-
// Render with select modal so create-new can be clicked
298295
const { rerender } = render(
299296
<ProjectModals
300297
activeProject={undefined}
@@ -305,7 +302,6 @@ describe('ProjectModals', () => {
305302
/>,
306303
);
307304
await userEvent.click(screen.getByTestId('select-create-new'));
308-
// setModal was called with 'create' — now re-render with modal='create'
309305
rerender(
310306
<ProjectModals
311307
activeProject={undefined}
@@ -317,15 +313,14 @@ describe('ProjectModals', () => {
317313
);
318314
setModal.mockClear();
319315
await userEvent.click(screen.getByTestId('create-close'));
320-
expect(setModal).toHaveBeenCalledWith('select');
316+
expect(setModal).toHaveBeenCalledWith('none');
321317
});
322318

323-
it('keeps the create modal open and does not call setModal when a project is created', async () => {
319+
it('selects the created project and calls setModal with none when a project is created', async () => {
324320
const state = makeWebViewState();
325321
const { setModal } = renderModals({ modal: 'create', useWebViewState: state });
326322
await userEvent.click(screen.getByTestId('create-created'));
327-
expect(screen.getByTestId('create-modal')).toBeInTheDocument();
328-
expect(setModal).not.toHaveBeenCalled();
323+
expect(setModal).toHaveBeenCalledWith('none');
329324
});
330325
});
331326

src/__tests__/services/projectStorage.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
getProject,
99
getProjectsForSource,
1010
listProjects,
11+
resetQueuesForTesting,
1112
updateProjectMetadata,
1213
} from '../../services/projectStorage';
1314
import { createTestActivationContext } from '../test-helpers';
@@ -62,6 +63,7 @@ function enoentError(): Error {
6263

6364
describe('projectStorage', () => {
6465
beforeEach(() => {
66+
resetQueuesForTesting();
6567
__mockWriteUserData.mockResolvedValue(undefined);
6668
__mockDeleteUserData.mockResolvedValue(undefined);
6769
jest.spyOn(crypto, 'randomUUID').mockReturnValue('00000000-0000-0000-0000-000000000001');

src/components/ContinuousView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ export default function ContinuousView({
248248
const phraseRefs = useRef<(HTMLSpanElement | null)[]>([]);
249249

250250
const atStart = phraseEntries.length === 0 || focusPhraseIndex === 0;
251-
const atEnd = !phraseEntries.length || focusPhraseIndex >= phraseEntries.length - 1;
251+
const atEnd = phraseEntries.length === 0 || focusPhraseIndex >= phraseEntries.length - 1;
252252
const stripOpacityClass = isVisible ? 'tw:opacity-100' : 'tw:opacity-0';
253253

254254
/**

src/components/ProjectModals.tsx

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,6 @@ export default function ProjectModals({
5858
*/
5959
const [metadataSourceIsSelect, setMetadataSourceIsSelect] = useState(false);
6060

61-
/**
62-
* Tracks whether the create modal was opened from the select modal, so the correct modal is
63-
* restored on close.
64-
*/
65-
const [createSourceIsSelect, setCreateSourceIsSelect] = useState(false);
66-
6761
const resolvedMetadataProject = metadataProject ?? activeProject;
6862

6963
/**
@@ -117,10 +111,7 @@ export default function ProjectModals({
117111
setActiveProject(project);
118112
setModal('none');
119113
}}
120-
onCreateNew={() => {
121-
setCreateSourceIsSelect(true);
122-
setModal('create');
123-
}}
114+
onCreateNew={() => setModal('create')}
124115
onClose={() => setModal('none')}
125116
onViewInfo={handleViewInfo}
126117
/>
@@ -129,11 +120,11 @@ export default function ProjectModals({
129120
{modal === 'create' && (
130121
<CreateProjectModal
131122
projectId={projectId}
132-
onClose={() => {
133-
setModal(createSourceIsSelect ? 'select' : 'none');
134-
setCreateSourceIsSelect(false);
123+
onClose={() => setModal('none')}
124+
onProjectCreated={(project) => {
125+
setActiveProject(project);
126+
setModal('none');
135127
}}
136-
onProjectCreated={setActiveProject}
137128
/>
138129
)}
139130

src/services/projectStorage.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,3 +287,13 @@ export async function deleteProject(token: ExecutionToken, id: string): Promise<
287287
});
288288
});
289289
}
290+
291+
/**
292+
* Resets module-level queue state between tests. Jest's `resetMocks` resets mock implementations
293+
* but does not re-execute modules, so `indexQueue` and `projectQueues` would otherwise persist
294+
* across tests and allow promise chains from one test to bleed into the next.
295+
*/
296+
export function resetQueuesForTesting(): void {
297+
indexQueue = Promise.resolve();
298+
projectQueues.clear();
299+
}

0 commit comments

Comments
 (0)