118 lines
3.6 KiB
JavaScript
118 lines
3.6 KiB
JavaScript
import { setActivePinia, createPinia } from 'pinia';
|
|
import CallsAPI from 'dashboard/api/calls';
|
|
import { throwErrorMessage } from 'dashboard/store/utils/api';
|
|
import { useCallHistoryStore } from '../callHistory';
|
|
|
|
vi.mock('dashboard/api/calls', () => ({
|
|
default: {
|
|
get: vi.fn(),
|
|
},
|
|
}));
|
|
|
|
vi.mock('dashboard/store/utils/api', () => ({
|
|
throwErrorMessage: vi.fn(error => error),
|
|
}));
|
|
|
|
const createDeferred = () => {
|
|
let resolve;
|
|
const promise = new Promise(res => {
|
|
resolve = res;
|
|
});
|
|
|
|
return { promise, resolve };
|
|
};
|
|
|
|
const buildResponse = (payload, meta) => ({ data: { payload, meta } });
|
|
|
|
describe('callHistory store', () => {
|
|
beforeEach(() => {
|
|
setActivePinia(createPinia());
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
it('fetches calls and stores camelized records and meta', async () => {
|
|
CallsAPI.get.mockResolvedValue(
|
|
buildResponse(
|
|
[{ id: 1, recording_url: 'rec.mp3', contact: { phone_number: '+1' } }],
|
|
{ count: 44, current_page: 1, total_pages: 2 }
|
|
)
|
|
);
|
|
const store = useCallHistoryStore();
|
|
|
|
await store.fetchCalls({ page: 1, status: 'no-answer' });
|
|
|
|
expect(CallsAPI.get).toHaveBeenCalledWith({ page: 1, status: 'no-answer' });
|
|
expect(store.records).toEqual([
|
|
{ id: 1, recordingUrl: 'rec.mp3', contact: { phoneNumber: '+1' } },
|
|
]);
|
|
expect(store.meta).toEqual({ count: 44, currentPage: 1, totalPages: 2 });
|
|
expect(store.uiFlags.isFetching).toBe(false);
|
|
});
|
|
|
|
it('drops a superseded response that resolves after the latest one', async () => {
|
|
const firstRequest = createDeferred();
|
|
const secondRequest = createDeferred();
|
|
CallsAPI.get
|
|
.mockImplementationOnce(() => firstRequest.promise)
|
|
.mockImplementationOnce(() => secondRequest.promise);
|
|
const store = useCallHistoryStore();
|
|
|
|
const staleFetch = store.fetchCalls({ page: 1 });
|
|
const currentFetch = store.fetchCalls({ page: 2 });
|
|
|
|
secondRequest.resolve(
|
|
buildResponse([{ id: 2 }], { count: 1, current_page: 2, total_pages: 2 })
|
|
);
|
|
await currentFetch;
|
|
|
|
firstRequest.resolve(
|
|
buildResponse([{ id: 1 }], { count: 99, current_page: 1, total_pages: 9 })
|
|
);
|
|
await staleFetch;
|
|
|
|
expect(store.records).toEqual([{ id: 2 }]);
|
|
expect(store.meta.count).toBe(1);
|
|
expect(store.uiFlags.isFetching).toBe(false);
|
|
});
|
|
|
|
it('keeps fetching state when a superseded response resolves first', async () => {
|
|
const firstRequest = createDeferred();
|
|
const secondRequest = createDeferred();
|
|
CallsAPI.get
|
|
.mockImplementationOnce(() => firstRequest.promise)
|
|
.mockImplementationOnce(() => secondRequest.promise);
|
|
const store = useCallHistoryStore();
|
|
|
|
const staleFetch = store.fetchCalls({ page: 1 });
|
|
const currentFetch = store.fetchCalls({ page: 2 });
|
|
|
|
firstRequest.resolve(
|
|
buildResponse([{ id: 1 }], { count: 99, current_page: 1, total_pages: 9 })
|
|
);
|
|
await staleFetch;
|
|
|
|
expect(store.records).toEqual([]);
|
|
expect(store.uiFlags.isFetching).toBe(true);
|
|
|
|
secondRequest.resolve(
|
|
buildResponse([{ id: 2 }], { count: 1, current_page: 2, total_pages: 2 })
|
|
);
|
|
await currentFetch;
|
|
|
|
expect(store.records).toEqual([{ id: 2 }]);
|
|
expect(store.uiFlags.isFetching).toBe(false);
|
|
});
|
|
|
|
it('surfaces the error and resets fetching state on failure', async () => {
|
|
const error = new Error('Request failed');
|
|
CallsAPI.get.mockRejectedValue(error);
|
|
const store = useCallHistoryStore();
|
|
|
|
await store.fetchCalls();
|
|
|
|
expect(throwErrorMessage).toHaveBeenCalledWith(error);
|
|
expect(store.records).toEqual([]);
|
|
expect(store.uiFlags.isFetching).toBe(false);
|
|
});
|
|
});
|