mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-11 00:08:30 +01:00
feat: insights project filtering hooks with tests (#6403)
Hooks to filter and aggregate insights data on frontend
This commit is contained in:
parent
446b2b2a2d
commit
ae077558c0
@ -0,0 +1,122 @@
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import { useFilteredFlagsSummary } from './useFilteredFlagsSummary';
|
||||
|
||||
describe('useFilteredFlagTrends', () => {
|
||||
it('should summarize only last week of project flag trends', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useFilteredFlagsSummary([
|
||||
{
|
||||
week: '2024-01',
|
||||
project: 'project1',
|
||||
total: 1,
|
||||
active: 1,
|
||||
stale: 0,
|
||||
potentiallyStale: 0,
|
||||
users: 1,
|
||||
date: '',
|
||||
},
|
||||
{
|
||||
week: '2024-01',
|
||||
project: 'project2',
|
||||
total: 2,
|
||||
active: 2,
|
||||
stale: 0,
|
||||
potentiallyStale: 0,
|
||||
users: 2,
|
||||
date: '',
|
||||
},
|
||||
{
|
||||
week: '2024-02',
|
||||
project: 'project1',
|
||||
total: 4,
|
||||
active: 3,
|
||||
stale: 0,
|
||||
potentiallyStale: 1,
|
||||
users: 1,
|
||||
date: '',
|
||||
},
|
||||
{
|
||||
week: '2024-02',
|
||||
project: 'project3',
|
||||
total: 10,
|
||||
active: 8,
|
||||
stale: 2,
|
||||
potentiallyStale: 0,
|
||||
users: 3,
|
||||
date: '',
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
expect(result.current).toEqual({
|
||||
total: 14,
|
||||
active: 11,
|
||||
stale: 2,
|
||||
potentiallyStale: 1,
|
||||
averageUsers: '2.00',
|
||||
averageHealth: '79',
|
||||
});
|
||||
});
|
||||
|
||||
it('should work with project with zero users', () => {
|
||||
const { result, rerender } = renderHook(() =>
|
||||
useFilteredFlagsSummary([
|
||||
{
|
||||
week: '2024-01',
|
||||
project: 'project1',
|
||||
total: 5,
|
||||
active: 5,
|
||||
stale: 0,
|
||||
potentiallyStale: 0,
|
||||
users: 0,
|
||||
date: '',
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
expect(result.current).toEqual({
|
||||
total: 5,
|
||||
active: 5,
|
||||
stale: 0,
|
||||
potentiallyStale: 0,
|
||||
averageUsers: '0.00',
|
||||
averageHealth: '100',
|
||||
});
|
||||
});
|
||||
|
||||
it('should work with projects where some have with zero users', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useFilteredFlagsSummary([
|
||||
{
|
||||
week: '2024-01',
|
||||
project: 'project1',
|
||||
total: 5,
|
||||
active: 5,
|
||||
stale: 0,
|
||||
potentiallyStale: 0,
|
||||
users: 0,
|
||||
date: '',
|
||||
},
|
||||
{
|
||||
week: '2024-01',
|
||||
project: 'project2',
|
||||
total: 5,
|
||||
active: 5,
|
||||
stale: 0,
|
||||
potentiallyStale: 0,
|
||||
users: 2,
|
||||
date: '',
|
||||
},
|
||||
]),
|
||||
);
|
||||
|
||||
expect(result.current).toEqual({
|
||||
total: 10,
|
||||
active: 10,
|
||||
stale: 0,
|
||||
potentiallyStale: 0,
|
||||
averageUsers: '1.00',
|
||||
averageHealth: '100',
|
||||
});
|
||||
});
|
||||
});
|
@ -0,0 +1,46 @@
|
||||
import { useMemo } from 'react';
|
||||
import { ExecutiveSummarySchemaProjectFlagTrendsItem } from 'openapi';
|
||||
|
||||
export const useFilteredFlagsSummary = (
|
||||
filteredProjectFlagTrends: ExecutiveSummarySchemaProjectFlagTrendsItem[],
|
||||
) =>
|
||||
useMemo(() => {
|
||||
const lastWeekId = filteredProjectFlagTrends.reduce((prev, current) => {
|
||||
if (current.week > prev) return current.week;
|
||||
return prev;
|
||||
}, '');
|
||||
|
||||
const lastWeekSummary = filteredProjectFlagTrends.filter(
|
||||
(summary) => summary.week === lastWeekId,
|
||||
);
|
||||
|
||||
const averageUsers = (
|
||||
lastWeekSummary.reduce(
|
||||
(acc, current) => acc + (current.users || 0),
|
||||
0,
|
||||
) / lastWeekSummary.length
|
||||
).toFixed(2);
|
||||
|
||||
const sum = lastWeekSummary.reduce(
|
||||
(acc, current) => ({
|
||||
total: acc.total + current.total,
|
||||
active: acc.active + current.active,
|
||||
stale: acc.stale + current.stale,
|
||||
potentiallyStale:
|
||||
acc.potentiallyStale + current.potentiallyStale,
|
||||
averageUsers,
|
||||
}),
|
||||
{
|
||||
total: 0,
|
||||
active: 0,
|
||||
stale: 0,
|
||||
potentiallyStale: 0,
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
...sum,
|
||||
averageUsers,
|
||||
averageHealth: ((sum.active / (sum.total || 1)) * 100).toFixed(0),
|
||||
};
|
||||
}, [filteredProjectFlagTrends]);
|
@ -0,0 +1,107 @@
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import { useFilteredTrends } from './useFilteredTrends';
|
||||
|
||||
const mockProjectFlagTrends = [
|
||||
{
|
||||
week: '2024-01',
|
||||
project: 'project1',
|
||||
},
|
||||
{
|
||||
week: '2024-01',
|
||||
project: 'project2',
|
||||
},
|
||||
{
|
||||
week: '2024-02',
|
||||
project: 'project1',
|
||||
},
|
||||
{
|
||||
week: '2024-02',
|
||||
project: 'project3',
|
||||
},
|
||||
];
|
||||
|
||||
describe('useFilteredFlagTrends', () => {
|
||||
it('should return all project flag trends when all projects option is selected', () => {
|
||||
const projects = ['*'];
|
||||
const { result } = renderHook(() =>
|
||||
useFilteredTrends(mockProjectFlagTrends, projects),
|
||||
);
|
||||
expect(result.current).toEqual(mockProjectFlagTrends);
|
||||
});
|
||||
|
||||
it('should return all project flag trends project selection is empty', () => {
|
||||
const projects: string[] = [];
|
||||
const { result } = renderHook(() =>
|
||||
useFilteredTrends(mockProjectFlagTrends, projects),
|
||||
);
|
||||
expect(result.current).toEqual(mockProjectFlagTrends);
|
||||
});
|
||||
|
||||
it('should return filtered project when specific project is selected', () => {
|
||||
const projects = ['project1'];
|
||||
const { result } = renderHook(() =>
|
||||
useFilteredTrends(mockProjectFlagTrends, projects),
|
||||
);
|
||||
expect(result.current).toEqual([
|
||||
{
|
||||
week: '2024-01',
|
||||
project: 'project1',
|
||||
},
|
||||
{
|
||||
week: '2024-02',
|
||||
project: 'project1',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return filtered project flag trends when specific projects are selected', () => {
|
||||
const projects = ['project1', 'project2'];
|
||||
const { result } = renderHook(() =>
|
||||
useFilteredTrends(mockProjectFlagTrends, projects),
|
||||
);
|
||||
expect(result.current).toEqual([
|
||||
{
|
||||
week: '2024-01',
|
||||
project: 'project1',
|
||||
},
|
||||
{
|
||||
week: '2024-01',
|
||||
project: 'project2',
|
||||
},
|
||||
{
|
||||
week: '2024-02',
|
||||
project: 'project1',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should re-render if input has changed', () => {
|
||||
const projects = ['project1'];
|
||||
const { result, rerender } = renderHook(
|
||||
({ input, projects }) => useFilteredTrends(input, projects),
|
||||
{
|
||||
initialProps: {
|
||||
input: mockProjectFlagTrends,
|
||||
projects,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
rerender({
|
||||
input: [
|
||||
{
|
||||
week: '2024-01',
|
||||
project: 'project1',
|
||||
},
|
||||
],
|
||||
projects,
|
||||
});
|
||||
|
||||
expect(result.current).toEqual([
|
||||
{
|
||||
week: '2024-01',
|
||||
project: 'project1',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
@ -0,0 +1,22 @@
|
||||
import { useMemo } from 'react';
|
||||
import { allOption } from '../ProjectSelect/ProjectSelect';
|
||||
|
||||
export const useFilteredTrends = <
|
||||
T extends {
|
||||
project: string;
|
||||
},
|
||||
>(
|
||||
input: T[],
|
||||
projects: string[],
|
||||
) =>
|
||||
useMemo<T[]>(() => {
|
||||
if (projects.length < 1 || projects[0] === allOption.id) {
|
||||
return input;
|
||||
}
|
||||
|
||||
const output = input.filter((trend) =>
|
||||
projects.includes(trend.project),
|
||||
) as T[];
|
||||
|
||||
return output;
|
||||
}, [input, projects]);
|
Loading…
Reference in New Issue
Block a user