Migrated progress and fallback visits actions to payload actions

This commit is contained in:
Alejandro Celaya 2022-11-12 09:01:43 +01:00
parent c6eec8b266
commit 32f7374d92
13 changed files with 55 additions and 47 deletions

View file

@ -33,4 +33,4 @@ export default (container: IContainer) => combineReducers<ShlinkState>({
visitsOverview: container.visitsOverviewReducer, visitsOverview: container.visitsOverviewReducer,
appUpdated: appUpdatesReducer, appUpdated: appUpdatesReducer,
sidebar: sidebarReducer, sidebar: sidebarReducer,
}); } as any); // TODO Fix this

View file

@ -1,7 +1,7 @@
import { flatten, prop, range, splitEvery } from 'ramda'; import { flatten, prop, range, splitEvery } from 'ramda';
import { Action, Dispatch } from 'redux'; import { Action, Dispatch } from 'redux';
import { ShlinkPaginator, ShlinkVisits, ShlinkVisitsParams } from '../../api/types'; import { ShlinkPaginator, ShlinkVisits, ShlinkVisitsParams } from '../../api/types';
import { Visit } from '../types'; import { Visit, VisitsLoadProgressChangedAction } from '../types';
import { parseApiError } from '../../api/utils'; import { parseApiError } from '../../api/utils';
import { ApiErrorAction } from '../../api/types/actions'; import { ApiErrorAction } from '../../api/types/actions';
import { dateToMatchingInterval } from '../../utils/dates/types'; import { dateToMatchingInterval } from '../../utils/dates/types';
@ -36,9 +36,9 @@ export const getVisitsWithLoader = async <T extends Action<string> & { visits: V
const data = await loadVisitsInParallel(pagesBlocks[index]); const data = await loadVisitsInParallel(pagesBlocks[index]);
dispatch({ dispatch<VisitsLoadProgressChangedAction>({
type: `${actionsPrefix}/progressChanged`, type: `${actionsPrefix}/progressChanged`,
progress: calcProgress(pagesBlocks.length, index + PARALLEL_STARTING_PAGE), payload: calcProgress(pagesBlocks.length, index + PARALLEL_STARTING_PAGE),
}); });
if (index < pagesBlocks.length - 1) { if (index < pagesBlocks.length - 1) {
@ -72,7 +72,7 @@ export const getVisitsWithLoader = async <T extends Action<string> & { visits: V
dispatch( dispatch(
!visits.length && lastVisit !visits.length && lastVisit
? { type: `${actionsPrefix}/fallbackToInterval`, fallbackInterval: dateToMatchingInterval(lastVisit.date) } ? { type: `${actionsPrefix}/fallbackToInterval`, payload: dateToMatchingInterval(lastVisit.date) }
: { ...extraFinishActionData, visits, type: `${actionsPrefix}/fulfilled` }, : { ...extraFinishActionData, visits, type: `${actionsPrefix}/fulfilled` },
); );
} catch (e: any) { } catch (e: any) {

View file

@ -56,11 +56,11 @@ export default buildReducer<DomainVisits, DomainVisitsCombinedAction>({
), ),
[`${REDUCER_PREFIX}/getDomainVisits/large`]: (state) => ({ ...state, loadingLarge: true }), [`${REDUCER_PREFIX}/getDomainVisits/large`]: (state) => ({ ...state, loadingLarge: true }),
[`${REDUCER_PREFIX}/getDomainVisits/cancel`]: (state) => ({ ...state, cancelLoad: true }), [`${REDUCER_PREFIX}/getDomainVisits/cancel`]: (state) => ({ ...state, cancelLoad: true }),
[`${REDUCER_PREFIX}/getDomainVisits/progressChanged`]: (state, { progress }) => ({ ...state, progress }), [`${REDUCER_PREFIX}/getDomainVisits/progressChanged`]: (state, { payload: progress }) => ({ ...state, progress }),
[`${REDUCER_PREFIX}/getDomainVisits/fallbackToInterval`]: (state, { fallbackInterval }) => ( [`${REDUCER_PREFIX}/getDomainVisits/fallbackToInterval`]: (state, { payload: fallbackInterval }) => (
{ ...state, fallbackInterval } { ...state, fallbackInterval }
), ),
[createNewVisits.toString()]: (state, { payload }) => { [createNewVisits.toString()]: (state, { payload }: CreateVisitsAction) => {
const { domain, visits, query = {} } = state; const { domain, visits, query = {} } = state;
const { startDate, endDate } = query; const { startDate, endDate } = query;
const newVisits = payload.createdVisits const newVisits = payload.createdVisits

View file

@ -54,11 +54,11 @@ export default buildReducer<VisitsInfo, NonOrphanVisitsCombinedAction>({
), ),
[`${REDUCER_PREFIX}/getNonOrphanVisits/large`]: (state) => ({ ...state, loadingLarge: true }), [`${REDUCER_PREFIX}/getNonOrphanVisits/large`]: (state) => ({ ...state, loadingLarge: true }),
[`${REDUCER_PREFIX}/getNonOrphanVisits/cancel`]: (state) => ({ ...state, cancelLoad: true }), [`${REDUCER_PREFIX}/getNonOrphanVisits/cancel`]: (state) => ({ ...state, cancelLoad: true }),
[`${REDUCER_PREFIX}/getNonOrphanVisits/progressChanged`]: (state, { progress }) => ({ ...state, progress }), [`${REDUCER_PREFIX}/getNonOrphanVisits/progressChanged`]: (state, { payload: progress }) => ({ ...state, progress }),
[`${REDUCER_PREFIX}/getNonOrphanVisits/fallbackToInterval`]: (state, { fallbackInterval }) => ( [`${REDUCER_PREFIX}/getNonOrphanVisits/fallbackToInterval`]: (state, { payload: fallbackInterval }) => (
{ ...state, fallbackInterval } { ...state, fallbackInterval }
), ),
[createNewVisits.toString()]: (state, { payload }) => { [createNewVisits.toString()]: (state, { payload }: CreateVisitsAction) => {
const { visits, query = {} } = state; const { visits, query = {} } = state;
const { startDate, endDate } = query; const { startDate, endDate } = query;
const newVisits = payload.createdVisits const newVisits = payload.createdVisits

View file

@ -55,11 +55,11 @@ export default buildReducer<VisitsInfo, OrphanVisitsCombinedAction>({
), ),
[`${REDUCER_PREFIX}/getOrphanVisits/large`]: (state) => ({ ...state, loadingLarge: true }), [`${REDUCER_PREFIX}/getOrphanVisits/large`]: (state) => ({ ...state, loadingLarge: true }),
[`${REDUCER_PREFIX}/getOrphanVisits/cancel`]: (state) => ({ ...state, cancelLoad: true }), [`${REDUCER_PREFIX}/getOrphanVisits/cancel`]: (state) => ({ ...state, cancelLoad: true }),
[`${REDUCER_PREFIX}/getOrphanVisits/progressChanged`]: (state, { progress }) => ({ ...state, progress }), [`${REDUCER_PREFIX}/getOrphanVisits/progressChanged`]: (state, { payload: progress }) => ({ ...state, progress }),
[`${REDUCER_PREFIX}/getOrphanVisits/fallbackToInterval`]: (state, { fallbackInterval }) => ( [`${REDUCER_PREFIX}/getOrphanVisits/fallbackToInterval`]: (state, { payload: fallbackInterval }) => (
{ ...state, fallbackInterval } { ...state, fallbackInterval }
), ),
[createNewVisits.toString()]: (state, { payload }) => { [createNewVisits.toString()]: (state, { payload }: CreateVisitsAction) => {
const { visits, query = {} } = state; const { visits, query = {} } = state;
const { startDate, endDate } = query; const { startDate, endDate } = query;
const newVisits = payload.createdVisits const newVisits = payload.createdVisits

View file

@ -60,11 +60,11 @@ export default buildReducer<ShortUrlVisits, ShortUrlVisitsCombinedAction>({
}), }),
[`${REDUCER_PREFIX}/getShortUrlVisits/large`]: (state) => ({ ...state, loadingLarge: true }), [`${REDUCER_PREFIX}/getShortUrlVisits/large`]: (state) => ({ ...state, loadingLarge: true }),
[`${REDUCER_PREFIX}/getShortUrlVisits/cancel`]: (state) => ({ ...state, cancelLoad: true }), [`${REDUCER_PREFIX}/getShortUrlVisits/cancel`]: (state) => ({ ...state, cancelLoad: true }),
[`${REDUCER_PREFIX}/getShortUrlVisits/progressChanged`]: (state, { progress }) => ({ ...state, progress }), [`${REDUCER_PREFIX}/getShortUrlVisits/progressChanged`]: (state, { payload: progress }) => ({ ...state, progress }),
[`${REDUCER_PREFIX}/getShortUrlVisits/fallbackToInterval`]: (state, { fallbackInterval }) => ( [`${REDUCER_PREFIX}/getShortUrlVisits/fallbackToInterval`]: (state, { payload: fallbackInterval }) => (
{ ...state, fallbackInterval } { ...state, fallbackInterval }
), ),
[createNewVisits.toString()]: (state, { payload }) => { [createNewVisits.toString()]: (state, { payload }: CreateVisitsAction) => {
const { shortCode, domain, visits, query = {} } = state; const { shortCode, domain, visits, query = {} } = state;
const { startDate, endDate } = query; const { startDate, endDate } = query;
const newVisits = payload.createdVisits const newVisits = payload.createdVisits

View file

@ -53,11 +53,11 @@ export default buildReducer<TagVisits, TagsVisitsCombinedAction>({
), ),
[`${REDUCER_PREFIX}/getTagVisits/large`]: (state) => ({ ...state, loadingLarge: true }), [`${REDUCER_PREFIX}/getTagVisits/large`]: (state) => ({ ...state, loadingLarge: true }),
[`${REDUCER_PREFIX}/getTagVisits/cancel`]: (state) => ({ ...state, cancelLoad: true }), [`${REDUCER_PREFIX}/getTagVisits/cancel`]: (state) => ({ ...state, cancelLoad: true }),
[`${REDUCER_PREFIX}/getTagVisits/progressChanged`]: (state, { progress }) => ({ ...state, progress }), [`${REDUCER_PREFIX}/getTagVisits/progressChanged`]: (state, { payload: progress }) => ({ ...state, progress }),
[`${REDUCER_PREFIX}/getTagVisits/fallbackToInterval`]: (state, { fallbackInterval }) => ( [`${REDUCER_PREFIX}/getTagVisits/fallbackToInterval`]: (state, { payload: fallbackInterval }) => (
{ ...state, fallbackInterval } { ...state, fallbackInterval }
), ),
[createNewVisits.toString()]: (state, { payload }) => { [createNewVisits.toString()]: (state, { payload }: CreateVisitsAction) => {
const { tag, visits, query = {} } = state; const { tag, visits, query = {} } = state;
const { startDate, endDate } = query; const { startDate, endDate } = query;
const newVisits = payload.createdVisits const newVisits = payload.createdVisits

View file

@ -1,4 +1,4 @@
import { Action } from 'redux'; import { PayloadAction } from '@reduxjs/toolkit';
import { ShortUrl } from '../../short-urls/data'; import { ShortUrl } from '../../short-urls/data';
import { ShlinkVisitsParams } from '../../api/types'; import { ShlinkVisitsParams } from '../../api/types';
import { DateInterval, DateRange } from '../../utils/dates/types'; import { DateInterval, DateRange } from '../../utils/dates/types';
@ -16,13 +16,9 @@ export interface VisitsInfo {
fallbackInterval?: DateInterval; fallbackInterval?: DateInterval;
} }
export interface VisitsLoadProgressChangedAction extends Action<string> { export type VisitsLoadProgressChangedAction = PayloadAction<number>;
progress: number;
}
export interface VisitsFallbackIntervalAction extends Action<string> { export type VisitsFallbackIntervalAction = PayloadAction<DateInterval>;
fallbackInterval: DateInterval;
}
export type OrphanVisitType = 'base_url' | 'invalid_short_url' | 'regular_404'; export type OrphanVisitType = 'base_url' | 'invalid_short_url' | 'regular_404';

View file

@ -142,14 +142,17 @@ describe('domainVisitsReducer', () => {
}); });
it('returns new progress on GET_DOMAIN_VISITS_PROGRESS_CHANGED', () => { it('returns new progress on GET_DOMAIN_VISITS_PROGRESS_CHANGED', () => {
const state = reducer(undefined, { type: GET_DOMAIN_VISITS_PROGRESS_CHANGED, progress: 85 } as any); const state = reducer(undefined, { type: GET_DOMAIN_VISITS_PROGRESS_CHANGED, payload: 85 } as any);
expect(state).toEqual(expect.objectContaining({ progress: 85 })); expect(state).toEqual(expect.objectContaining({ progress: 85 }));
}); });
it('returns fallbackInterval on GET_DOMAIN_VISITS_FALLBACK_TO_INTERVAL', () => { it('returns fallbackInterval on GET_DOMAIN_VISITS_FALLBACK_TO_INTERVAL', () => {
const fallbackInterval: DateInterval = 'last30Days'; const fallbackInterval: DateInterval = 'last30Days';
const state = reducer(undefined, { type: GET_DOMAIN_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval } as any); const state = reducer(
undefined,
{ type: GET_DOMAIN_VISITS_FALLBACK_TO_INTERVAL, payload: fallbackInterval } as any,
);
expect(state).toEqual(expect.objectContaining({ fallbackInterval })); expect(state).toEqual(expect.objectContaining({ fallbackInterval }));
}); });
@ -205,11 +208,11 @@ describe('domainVisitsReducer', () => {
it.each([ it.each([
[ [
[Mock.of<Visit>({ date: formatISO(subDays(new Date(), 20)) })], [Mock.of<Visit>({ date: formatISO(subDays(new Date(), 20)) })],
{ type: GET_DOMAIN_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval: 'last30Days' }, { type: GET_DOMAIN_VISITS_FALLBACK_TO_INTERVAL, payload: 'last30Days' },
], ],
[ [
[Mock.of<Visit>({ date: formatISO(subDays(new Date(), 100)) })], [Mock.of<Visit>({ date: formatISO(subDays(new Date(), 100)) })],
{ type: GET_DOMAIN_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval: 'last180Days' }, { type: GET_DOMAIN_VISITS_FALLBACK_TO_INTERVAL, payload: 'last180Days' },
], ],
[[], expect.objectContaining({ type: GET_DOMAIN_VISITS })], [[], expect.objectContaining({ type: GET_DOMAIN_VISITS })],
])('dispatches fallback interval when the list of visits is empty', async (lastVisits, expectedSecondDispatch) => { ])('dispatches fallback interval when the list of visits is empty', async (lastVisits, expectedSecondDispatch) => {

View file

@ -114,14 +114,17 @@ describe('nonOrphanVisitsReducer', () => {
}); });
it('returns new progress on GET_NON_ORPHAN_VISITS_PROGRESS_CHANGED', () => { it('returns new progress on GET_NON_ORPHAN_VISITS_PROGRESS_CHANGED', () => {
const state = reducer(undefined, { type: GET_NON_ORPHAN_VISITS_PROGRESS_CHANGED, progress: 85 } as any); const state = reducer(undefined, { type: GET_NON_ORPHAN_VISITS_PROGRESS_CHANGED, payload: 85 } as any);
expect(state).toEqual(expect.objectContaining({ progress: 85 })); expect(state).toEqual(expect.objectContaining({ progress: 85 }));
}); });
it('returns fallbackInterval on GET_NON_ORPHAN_VISITS_FALLBACK_TO_INTERVAL', () => { it('returns fallbackInterval on GET_NON_ORPHAN_VISITS_FALLBACK_TO_INTERVAL', () => {
const fallbackInterval: DateInterval = 'last30Days'; const fallbackInterval: DateInterval = 'last30Days';
const state = reducer(undefined, { type: GET_NON_ORPHAN_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval } as any); const state = reducer(
undefined,
{ type: GET_NON_ORPHAN_VISITS_FALLBACK_TO_INTERVAL, payload: fallbackInterval } as any,
);
expect(state).toEqual(expect.objectContaining({ fallbackInterval })); expect(state).toEqual(expect.objectContaining({ fallbackInterval }));
}); });
@ -176,11 +179,11 @@ describe('nonOrphanVisitsReducer', () => {
it.each([ it.each([
[ [
[Mock.of<Visit>({ date: formatISO(subDays(new Date(), 5)) })], [Mock.of<Visit>({ date: formatISO(subDays(new Date(), 5)) })],
{ type: GET_NON_ORPHAN_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval: 'last7Days' }, { type: GET_NON_ORPHAN_VISITS_FALLBACK_TO_INTERVAL, payload: 'last7Days' },
], ],
[ [
[Mock.of<Visit>({ date: formatISO(subDays(new Date(), 200)) })], [Mock.of<Visit>({ date: formatISO(subDays(new Date(), 200)) })],
{ type: GET_NON_ORPHAN_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval: 'last365Days' }, { type: GET_NON_ORPHAN_VISITS_FALLBACK_TO_INTERVAL, payload: 'last365Days' },
], ],
[[], expect.objectContaining({ type: GET_NON_ORPHAN_VISITS })], [[], expect.objectContaining({ type: GET_NON_ORPHAN_VISITS })],
])('dispatches fallback interval when the list of visits is empty', async (lastVisits, expectedSecondDispatch) => { ])('dispatches fallback interval when the list of visits is empty', async (lastVisits, expectedSecondDispatch) => {

View file

@ -114,14 +114,17 @@ describe('orphanVisitsReducer', () => {
}); });
it('returns new progress on GET_ORPHAN_VISITS_PROGRESS_CHANGED', () => { it('returns new progress on GET_ORPHAN_VISITS_PROGRESS_CHANGED', () => {
const state = reducer(undefined, { type: GET_ORPHAN_VISITS_PROGRESS_CHANGED, progress: 85 } as any); const state = reducer(undefined, { type: GET_ORPHAN_VISITS_PROGRESS_CHANGED, payload: 85 } as any);
expect(state).toEqual(expect.objectContaining({ progress: 85 })); expect(state).toEqual(expect.objectContaining({ progress: 85 }));
}); });
it('returns fallbackInterval on GET_ORPHAN_VISITS_FALLBACK_TO_INTERVAL', () => { it('returns fallbackInterval on GET_ORPHAN_VISITS_FALLBACK_TO_INTERVAL', () => {
const fallbackInterval: DateInterval = 'last30Days'; const fallbackInterval: DateInterval = 'last30Days';
const state = reducer(undefined, { type: GET_ORPHAN_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval } as any); const state = reducer(
undefined,
{ type: GET_ORPHAN_VISITS_FALLBACK_TO_INTERVAL, payload: fallbackInterval } as any,
);
expect(state).toEqual(expect.objectContaining({ fallbackInterval })); expect(state).toEqual(expect.objectContaining({ fallbackInterval }));
}); });
@ -176,11 +179,11 @@ describe('orphanVisitsReducer', () => {
it.each([ it.each([
[ [
[Mock.of<Visit>({ date: formatISO(subDays(new Date(), 5)) })], [Mock.of<Visit>({ date: formatISO(subDays(new Date(), 5)) })],
{ type: GET_ORPHAN_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval: 'last7Days' }, { type: GET_ORPHAN_VISITS_FALLBACK_TO_INTERVAL, payload: 'last7Days' },
], ],
[ [
[Mock.of<Visit>({ date: formatISO(subDays(new Date(), 200)) })], [Mock.of<Visit>({ date: formatISO(subDays(new Date(), 200)) })],
{ type: GET_ORPHAN_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval: 'last365Days' }, { type: GET_ORPHAN_VISITS_FALLBACK_TO_INTERVAL, payload: 'last365Days' },
], ],
[[], expect.objectContaining({ type: GET_ORPHAN_VISITS })], [[], expect.objectContaining({ type: GET_ORPHAN_VISITS })],
])('dispatches fallback interval when the list of visits is empty', async (lastVisits, expectedSecondDispatch) => { ])('dispatches fallback interval when the list of visits is empty', async (lastVisits, expectedSecondDispatch) => {

View file

@ -135,14 +135,17 @@ describe('shortUrlVisitsReducer', () => {
}); });
it('returns new progress on GET_SHORT_URL_VISITS_PROGRESS_CHANGED', () => { it('returns new progress on GET_SHORT_URL_VISITS_PROGRESS_CHANGED', () => {
const state = reducer(undefined, { type: GET_SHORT_URL_VISITS_PROGRESS_CHANGED, progress: 85 } as any); const state = reducer(undefined, { type: GET_SHORT_URL_VISITS_PROGRESS_CHANGED, payload: 85 } as any);
expect(state).toEqual(expect.objectContaining({ progress: 85 })); expect(state).toEqual(expect.objectContaining({ progress: 85 }));
}); });
it('returns fallbackInterval on GET_SHORT_URL_VISITS_FALLBACK_TO_INTERVAL', () => { it('returns fallbackInterval on GET_SHORT_URL_VISITS_FALLBACK_TO_INTERVAL', () => {
const fallbackInterval: DateInterval = 'last30Days'; const fallbackInterval: DateInterval = 'last30Days';
const state = reducer(undefined, { type: GET_SHORT_URL_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval } as any); const state = reducer(
undefined,
{ type: GET_SHORT_URL_VISITS_FALLBACK_TO_INTERVAL, payload: fallbackInterval } as any,
);
expect(state).toEqual(expect.objectContaining({ fallbackInterval })); expect(state).toEqual(expect.objectContaining({ fallbackInterval }));
}); });
@ -222,11 +225,11 @@ describe('shortUrlVisitsReducer', () => {
it.each([ it.each([
[ [
[Mock.of<Visit>({ date: formatISO(subDays(new Date(), 5)) })], [Mock.of<Visit>({ date: formatISO(subDays(new Date(), 5)) })],
{ type: GET_SHORT_URL_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval: 'last7Days' }, { type: GET_SHORT_URL_VISITS_FALLBACK_TO_INTERVAL, payload: 'last7Days' },
], ],
[ [
[Mock.of<Visit>({ date: formatISO(subDays(new Date(), 200)) })], [Mock.of<Visit>({ date: formatISO(subDays(new Date(), 200)) })],
{ type: GET_SHORT_URL_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval: 'last365Days' }, { type: GET_SHORT_URL_VISITS_FALLBACK_TO_INTERVAL, payload: 'last365Days' },
], ],
[[], expect.objectContaining({ type: GET_SHORT_URL_VISITS })], [[], expect.objectContaining({ type: GET_SHORT_URL_VISITS })],
])('dispatches fallback interval when the list of visits is empty', async (lastVisits, expectedSecondDispatch) => { ])('dispatches fallback interval when the list of visits is empty', async (lastVisits, expectedSecondDispatch) => {

View file

@ -135,14 +135,14 @@ describe('tagVisitsReducer', () => {
}); });
it('returns new progress on GET_TAG_VISITS_PROGRESS_CHANGED', () => { it('returns new progress on GET_TAG_VISITS_PROGRESS_CHANGED', () => {
const state = reducer(undefined, { type: GET_TAG_VISITS_PROGRESS_CHANGED, progress: 85 } as any); const state = reducer(undefined, { type: GET_TAG_VISITS_PROGRESS_CHANGED, payload: 85 } as any);
expect(state).toEqual(expect.objectContaining({ progress: 85 })); expect(state).toEqual(expect.objectContaining({ progress: 85 }));
}); });
it('returns fallbackInterval on GET_TAG_VISITS_FALLBACK_TO_INTERVAL', () => { it('returns fallbackInterval on GET_TAG_VISITS_FALLBACK_TO_INTERVAL', () => {
const fallbackInterval: DateInterval = 'last30Days'; const fallbackInterval: DateInterval = 'last30Days';
const state = reducer(undefined, { type: GET_TAG_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval } as any); const state = reducer(undefined, { type: GET_TAG_VISITS_FALLBACK_TO_INTERVAL, payload: fallbackInterval } as any);
expect(state).toEqual(expect.objectContaining({ fallbackInterval })); expect(state).toEqual(expect.objectContaining({ fallbackInterval }));
}); });
@ -198,11 +198,11 @@ describe('tagVisitsReducer', () => {
it.each([ it.each([
[ [
[Mock.of<Visit>({ date: formatISO(subDays(new Date(), 20)) })], [Mock.of<Visit>({ date: formatISO(subDays(new Date(), 20)) })],
{ type: GET_TAG_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval: 'last30Days' }, { type: GET_TAG_VISITS_FALLBACK_TO_INTERVAL, payload: 'last30Days' },
], ],
[ [
[Mock.of<Visit>({ date: formatISO(subDays(new Date(), 100)) })], [Mock.of<Visit>({ date: formatISO(subDays(new Date(), 100)) })],
{ type: GET_TAG_VISITS_FALLBACK_TO_INTERVAL, fallbackInterval: 'last180Days' }, { type: GET_TAG_VISITS_FALLBACK_TO_INTERVAL, payload: 'last180Days' },
], ],
[[], expect.objectContaining({ type: GET_TAG_VISITS })], [[], expect.objectContaining({ type: GET_TAG_VISITS })],
])('dispatches fallback interval when the list of visits is empty', async (lastVisits, expectedSecondDispatch) => { ])('dispatches fallback interval when the list of visits is empty', async (lastVisits, expectedSecondDispatch) => {