Full tests coverage
This commit is contained in:
parent
99134d8556
commit
02d782c3da
157 changed files with 1074 additions and 34670 deletions
|
|
@ -399,6 +399,9 @@ describe('StoresPage', () => {
|
|||
fireEvent.change(screen.getByPlaceholderText('123 Main St'), {
|
||||
target: { value: '456 Oak Ave' },
|
||||
});
|
||||
fireEvent.change(screen.getByPlaceholderText('https://walgreens.com'), {
|
||||
target: { value: 'https://newurl.com' },
|
||||
});
|
||||
fireEvent.change(screen.getByPlaceholderText('Any notes'), {
|
||||
target: { value: 'Good prices' },
|
||||
});
|
||||
|
|
@ -449,6 +452,73 @@ describe('StoresPage', () => {
|
|||
await waitFor(() => expect(screen.getByText('keytag')).toBeInTheDocument());
|
||||
});
|
||||
|
||||
it('ignores custom tag via non-Enter keydown', async () => {
|
||||
mockUseApi.mockReturnValue({ householdId: 'hh1', isLoading: false });
|
||||
mockListStores.mockResolvedValue({ data: [], pagination: { cursor: null, hasMore: false } });
|
||||
|
||||
render(<StoresPage />);
|
||||
|
||||
await waitFor(() => screen.getByText('Add Store'));
|
||||
await userEvent.click(screen.getByText('Add Store'));
|
||||
|
||||
await waitFor(() => screen.getByPlaceholderText('Custom tag...'));
|
||||
fireEvent.change(screen.getByPlaceholderText('Custom tag...'), { target: { value: 'escapetag' } });
|
||||
fireEvent.keyDown(screen.getByPlaceholderText('Custom tag...'), { key: 'Escape' });
|
||||
|
||||
expect(screen.queryByText('escapetag')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders store card with missing optional parameters correctly', async () => {
|
||||
mockUseApi.mockReturnValue({ householdId: 'hh1', isLoading: false });
|
||||
mockListStores.mockResolvedValue({
|
||||
data: [
|
||||
{
|
||||
_id: 'st-addr',
|
||||
name: 'Address Only Store',
|
||||
tags: [],
|
||||
isActive: true,
|
||||
createdAt: '2026-01-01T00:00:00.000Z',
|
||||
householdId: 'hh1',
|
||||
createdBy: 'u-1',
|
||||
address: '123 Unique Way',
|
||||
url: undefined,
|
||||
notes: undefined
|
||||
},
|
||||
{
|
||||
_id: 'st-url',
|
||||
name: 'URL Only Store',
|
||||
tags: [],
|
||||
isActive: true,
|
||||
createdAt: '2026-01-01T00:00:00.000Z',
|
||||
householdId: 'hh1',
|
||||
createdBy: 'u-1',
|
||||
address: undefined,
|
||||
url: 'https://onlyurl.com',
|
||||
notes: undefined
|
||||
},
|
||||
{
|
||||
_id: 'st-notes',
|
||||
name: 'Notes Only Store',
|
||||
tags: [],
|
||||
isActive: true,
|
||||
createdAt: '2026-01-01T00:00:00.000Z',
|
||||
householdId: 'hh1',
|
||||
createdBy: 'u-1',
|
||||
address: undefined,
|
||||
url: undefined,
|
||||
notes: 'Special instruction notes'
|
||||
}
|
||||
],
|
||||
pagination: { cursor: null, hasMore: false }
|
||||
});
|
||||
|
||||
render(<StoresPage />);
|
||||
await waitFor(() => expect(screen.getByText('Address Only Store')).toBeInTheDocument());
|
||||
expect(screen.getByText('123 Unique Way')).toBeInTheDocument();
|
||||
expect(screen.getByText('https://onlyurl.com')).toBeInTheDocument();
|
||||
expect(screen.getByText('Special instruction notes')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('changes search filter', async () => {
|
||||
mockUseApi.mockReturnValue({ householdId: 'hh1', isLoading: false });
|
||||
mockListStores.mockResolvedValue({
|
||||
|
|
@ -548,4 +618,132 @@ describe('StoresPage', () => {
|
|||
|
||||
expect(screen.getByText('Old Store')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('handles create store generic error fallback', async () => {
|
||||
mockUseApi.mockReturnValue({ householdId: 'hh1', isLoading: false });
|
||||
mockListStores.mockResolvedValue({ data: [], pagination: { cursor: null, hasMore: false } });
|
||||
mockCreateStore.mockRejectedValue('Generic store save error');
|
||||
|
||||
render(<StoresPage />);
|
||||
await waitFor(() => screen.getByText('Add Store'));
|
||||
await userEvent.click(screen.getByText('Add Store'));
|
||||
|
||||
await waitFor(() => screen.getByPlaceholderText('e.g. Walgreens'));
|
||||
fireEvent.change(screen.getByPlaceholderText('e.g. Walgreens'), { target: { value: 'Walmart' } });
|
||||
fireEvent.submit(screen.getByPlaceholderText('e.g. Walgreens').closest('form')!);
|
||||
|
||||
await waitFor(() => expect(screen.getByText('Failed to save store')).toBeInTheDocument());
|
||||
});
|
||||
|
||||
it('handles list stores generic error fallback', async () => {
|
||||
mockUseApi.mockReturnValue({ householdId: 'hh1', isLoading: false });
|
||||
mockListStores.mockRejectedValue('Generic list error');
|
||||
|
||||
render(<StoresPage />);
|
||||
await waitFor(() => expect(screen.getByText('Failed to load stores')).toBeInTheDocument());
|
||||
});
|
||||
|
||||
it('handles deactivate store generic error fallback', async () => {
|
||||
mockUseApi.mockReturnValue({ householdId: 'hh1', isLoading: false });
|
||||
mockListStores.mockResolvedValue({
|
||||
data: [
|
||||
{ _id: 'st-1', name: 'CVS', tags: [], isActive: true, createdAt: '2026-01-01T00:00:00.000Z', householdId: 'hh1', createdBy: 'u-1' }
|
||||
],
|
||||
pagination: { cursor: null, hasMore: false },
|
||||
});
|
||||
mockDeactivateStore.mockRejectedValue('Generic deactivate error');
|
||||
vi.spyOn(window, 'confirm').mockReturnValue(true);
|
||||
|
||||
render(<StoresPage />);
|
||||
await waitFor(() => screen.getByTitle('Deactivate'));
|
||||
await userEvent.click(screen.getByTitle('Deactivate'));
|
||||
|
||||
await waitFor(() => expect(screen.getByText('Failed to deactivate store')).toBeInTheDocument());
|
||||
});
|
||||
|
||||
it('skips deactivation if confirmation is rejected', async () => {
|
||||
mockUseApi.mockReturnValue({ householdId: 'hh1', isLoading: false });
|
||||
mockListStores.mockResolvedValue({
|
||||
data: [
|
||||
{ _id: 'st-1', name: 'CVS', tags: [], isActive: true, createdAt: '2026-01-01T00:00:00.000Z', householdId: 'hh1', createdBy: 'u-1' }
|
||||
],
|
||||
pagination: { cursor: null, hasMore: false },
|
||||
});
|
||||
vi.spyOn(window, 'confirm').mockReturnValue(false);
|
||||
|
||||
render(<StoresPage />);
|
||||
await waitFor(() => screen.getByTitle('Deactivate'));
|
||||
await userEvent.click(screen.getByTitle('Deactivate'));
|
||||
|
||||
expect(mockDeactivateStore).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('handles empty optional fields creation gracefully', async () => {
|
||||
mockUseApi.mockReturnValue({ householdId: 'hh1', isLoading: false });
|
||||
mockListStores.mockResolvedValue({ data: [], pagination: { cursor: null, hasMore: false } });
|
||||
mockCreateStore.mockResolvedValue({} as any);
|
||||
|
||||
render(<StoresPage />);
|
||||
await waitFor(() => screen.getByText('Add Store'));
|
||||
await userEvent.click(screen.getByText('Add Store'));
|
||||
|
||||
await waitFor(() => screen.getByPlaceholderText('e.g. Walgreens'));
|
||||
fireEvent.change(screen.getByPlaceholderText('e.g. Walgreens'), { target: { value: 'Walmart' } });
|
||||
|
||||
fireEvent.change(screen.getByPlaceholderText('123 Main St'), { target: { value: ' ' } });
|
||||
fireEvent.change(screen.getByPlaceholderText('https://walgreens.com'), { target: { value: ' ' } });
|
||||
fireEvent.change(screen.getByPlaceholderText('Any notes'), { target: { value: ' ' } });
|
||||
|
||||
fireEvent.submit(screen.getByPlaceholderText('e.g. Walgreens').closest('form')!);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockCreateStore).toHaveBeenCalledWith('hh1', {
|
||||
name: 'Walmart',
|
||||
address: undefined,
|
||||
url: undefined,
|
||||
notes: undefined,
|
||||
tags: [],
|
||||
isActive: true
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('renders empty search message when filters are applied with no match', async () => {
|
||||
mockUseApi.mockReturnValue({ householdId: 'hh1', isLoading: false });
|
||||
mockListStores.mockResolvedValue({ data: [], pagination: { cursor: null, hasMore: false } });
|
||||
|
||||
render(<StoresPage />);
|
||||
await waitFor(() => expect(screen.getByText(/No stores yet/)).toBeInTheDocument());
|
||||
|
||||
fireEvent.change(screen.getByPlaceholderText('Search stores...'), { target: { value: 'MissingName' } });
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('No stores match your filters.')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it('prevents adding duplicate custom tags', async () => {
|
||||
mockUseApi.mockReturnValue({ householdId: 'hh1', isLoading: false });
|
||||
mockListStores.mockResolvedValue({ data: [], pagination: { cursor: null, hasMore: false } });
|
||||
|
||||
render(<StoresPage />);
|
||||
|
||||
await waitFor(() => screen.getByText('Add Store'));
|
||||
await userEvent.click(screen.getByText('Add Store'));
|
||||
|
||||
await waitFor(() => screen.getByPlaceholderText('Custom tag...'));
|
||||
const input = screen.getByPlaceholderText('Custom tag...');
|
||||
|
||||
// Add tag once
|
||||
fireEvent.change(input, { target: { value: 'duplicated' } });
|
||||
fireEvent.keyDown(input, { key: 'Enter' });
|
||||
await waitFor(() => expect(screen.getByText('duplicated')).toBeInTheDocument());
|
||||
|
||||
// Attempt to add it again
|
||||
fireEvent.change(input, { target: { value: 'duplicated' } });
|
||||
fireEvent.keyDown(input, { key: 'Enter' });
|
||||
|
||||
// Should only exist once in the document
|
||||
expect(screen.getAllByText('duplicated')).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue