mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2026-02-27 20:26:40 +00:00
Created section to display orphan visits stats
This commit is contained in:
@@ -4,6 +4,7 @@ import { OptionalString } from '../../../src/utils/utils';
|
||||
import { Mock } from 'ts-mockery';
|
||||
import { ShlinkDomain, ShlinkVisitsOverview } from '../../../src/api/types';
|
||||
import { ShortUrl } from '../../../src/short-urls/data';
|
||||
import { Visit } from '../../../src/visits/types';
|
||||
|
||||
describe('ShlinkApiClient', () => {
|
||||
const createAxios = (data: AxiosRequestConfig) => (async () => Promise.resolve(data)) as unknown as AxiosInstance;
|
||||
@@ -285,4 +286,18 @@ describe('ShlinkApiClient', () => {
|
||||
expect(result).toEqual(expectedData);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getOrphanVisits', () => {
|
||||
it('returns orphan visits', async () => {
|
||||
const expectedData: Visit[] = [];
|
||||
const resp = { visits: expectedData };
|
||||
const axiosSpy = createAxiosMock({ data: resp });
|
||||
const { getOrphanVisits } = new ShlinkApiClient(axiosSpy, '', '');
|
||||
|
||||
const result = await getOrphanVisits();
|
||||
|
||||
expect(axiosSpy).toHaveBeenCalled();
|
||||
expect(result).toEqual(expectedData);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -150,12 +150,18 @@ describe('shortUrlsListReducer', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('updates visits count on CREATE_VISIT', () => {
|
||||
const createNewShortUrlVisit = (visitsCount: number) => ({
|
||||
shortUrl: { shortCode: 'abc123', visitsCount },
|
||||
});
|
||||
|
||||
it.each([
|
||||
[[ createNewShortUrlVisit(11) ], 11 ],
|
||||
[[ createNewShortUrlVisit(30) ], 30 ],
|
||||
[[ createNewShortUrlVisit(20), createNewShortUrlVisit(40) ], 40 ],
|
||||
[[{}], 10 ],
|
||||
[[], 10 ],
|
||||
])('updates visits count on CREATE_VISITS', (createdVisits, expectedCount) => {
|
||||
const shortCode = 'abc123';
|
||||
const shortUrl = {
|
||||
shortCode,
|
||||
visitsCount: 11,
|
||||
};
|
||||
const state = {
|
||||
shortUrls: Mock.of<ShlinkShortUrlsResponse>({
|
||||
data: [
|
||||
@@ -168,11 +174,11 @@ describe('shortUrlsListReducer', () => {
|
||||
error: false,
|
||||
};
|
||||
|
||||
expect(reducer(state, { type: CREATE_VISITS, createdVisits: [{ shortUrl }] } as any)).toEqual({
|
||||
expect(reducer(state, { type: CREATE_VISITS, createdVisits } as any)).toEqual({
|
||||
shortUrls: {
|
||||
data: [
|
||||
{ shortCode, domain: 'example.com', visitsCount: 5 },
|
||||
{ shortCode, visitsCount: 11 },
|
||||
{ shortCode, visitsCount: expectedCount },
|
||||
{ shortCode: 'foo', visitsCount: 8 },
|
||||
],
|
||||
},
|
||||
|
||||
@@ -7,12 +7,13 @@ import reducer, {
|
||||
VisitsOverview,
|
||||
loadVisitsOverview,
|
||||
} from '../../../src/visits/reducers/visitsOverview';
|
||||
import { CreateVisitsAction } from '../../../src/visits/reducers/visitCreation';
|
||||
import { CREATE_VISITS, CreateVisitsAction } from '../../../src/visits/reducers/visitCreation';
|
||||
import ShlinkApiClient from '../../../src/api/services/ShlinkApiClient';
|
||||
import { ShlinkVisitsOverview } from '../../../src/api/types';
|
||||
import { ShlinkState } from '../../../src/container/types';
|
||||
import { CreateVisit, OrphanVisit, Visit } from '../../../src/visits/types';
|
||||
|
||||
describe('visitsOverview', () => {
|
||||
describe('visitsOverviewReducer', () => {
|
||||
describe('reducer', () => {
|
||||
const action = (type: string) =>
|
||||
Mock.of<GetVisitsOverviewAction>({ type }) as GetVisitsOverviewAction & CreateVisitsAction;
|
||||
@@ -41,6 +42,31 @@ describe('visitsOverview', () => {
|
||||
expect(error).toEqual(false);
|
||||
expect(visitsCount).toEqual(100);
|
||||
});
|
||||
|
||||
it('returns updated amounts on CREATE_VISITS', () => {
|
||||
const { visitsCount, orphanVisitsCount } = reducer(
|
||||
state({ visitsCount: 100, orphanVisitsCount: 50 }),
|
||||
{
|
||||
type: CREATE_VISITS,
|
||||
createdVisits: [
|
||||
Mock.of<CreateVisit>({ visit: Mock.all<Visit>() }),
|
||||
Mock.of<CreateVisit>({ visit: Mock.all<Visit>() }),
|
||||
Mock.of<CreateVisit>({
|
||||
visit: Mock.of<OrphanVisit>({ visitedUrl: '' }),
|
||||
}),
|
||||
Mock.of<CreateVisit>({
|
||||
visit: Mock.of<OrphanVisit>({ visitedUrl: '' }),
|
||||
}),
|
||||
Mock.of<CreateVisit>({
|
||||
visit: Mock.of<OrphanVisit>({ visitedUrl: '' }),
|
||||
}),
|
||||
],
|
||||
} as unknown as GetVisitsOverviewAction & CreateVisitsAction,
|
||||
);
|
||||
|
||||
expect(visitsCount).toEqual(102);
|
||||
expect(orphanVisitsCount).toEqual(53);
|
||||
});
|
||||
});
|
||||
|
||||
describe('loadVisitsOverview', () => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Mock } from 'ts-mockery';
|
||||
import { processStatsFromVisits, normalizeVisits } from '../../../src/visits/services/VisitsParser';
|
||||
import { Visit, VisitsStats } from '../../../src/visits/types';
|
||||
import { OrphanVisit, Visit, VisitsStats } from '../../../src/visits/types';
|
||||
|
||||
describe('VisitsParser', () => {
|
||||
const visits: Visit[] = [
|
||||
@@ -45,6 +45,36 @@ describe('VisitsParser', () => {
|
||||
userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36 OPR/38.0.2220.41',
|
||||
}),
|
||||
];
|
||||
const orphanVisits: OrphanVisit[] = [
|
||||
Mock.of<OrphanVisit>({
|
||||
type: 'base_url',
|
||||
visitedUrl: 'foo',
|
||||
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0',
|
||||
referer: 'https://google.com',
|
||||
visitLocation: {
|
||||
countryName: 'United States',
|
||||
cityName: 'New York',
|
||||
latitude: 1029,
|
||||
longitude: 6758,
|
||||
},
|
||||
}),
|
||||
Mock.of<OrphanVisit>({
|
||||
type: 'regular_404',
|
||||
visitedUrl: 'bar',
|
||||
}),
|
||||
Mock.of<OrphanVisit>({
|
||||
type: 'invalid_short_url',
|
||||
visitedUrl: 'baz',
|
||||
userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36',
|
||||
referer: 'https://m.facebook.com',
|
||||
visitLocation: {
|
||||
countryName: 'Spain',
|
||||
cityName: 'Zaragoza',
|
||||
latitude: 123.45,
|
||||
longitude: -543.21,
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
describe('processStatsFromVisits', () => {
|
||||
let stats: VisitsStats;
|
||||
@@ -180,5 +210,46 @@ describe('VisitsParser', () => {
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('properly parses the list of orphan visits', () => {
|
||||
expect(normalizeVisits(orphanVisits)).toEqual([
|
||||
{
|
||||
browser: 'Firefox',
|
||||
os: 'macOS',
|
||||
referer: 'google.com',
|
||||
country: 'United States',
|
||||
city: 'New York',
|
||||
date: undefined,
|
||||
latitude: 1029,
|
||||
longitude: 6758,
|
||||
type: 'base_url',
|
||||
visitedUrl: 'foo',
|
||||
},
|
||||
{
|
||||
type: 'regular_404',
|
||||
visitedUrl: 'bar',
|
||||
browser: 'Others',
|
||||
city: 'Unknown',
|
||||
country: 'Unknown',
|
||||
date: undefined,
|
||||
latitude: undefined,
|
||||
longitude: undefined,
|
||||
os: 'Others',
|
||||
referer: 'Direct',
|
||||
},
|
||||
{
|
||||
browser: 'Chrome',
|
||||
os: 'Linux',
|
||||
referer: 'm.facebook.com',
|
||||
country: 'Spain',
|
||||
city: 'Zaragoza',
|
||||
date: undefined,
|
||||
latitude: 123.45,
|
||||
longitude: -543.21,
|
||||
type: 'invalid_short_url',
|
||||
visitedUrl: 'baz',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user