Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 120 additions & 0 deletions frontend/server/data/tinybird/forks-data-source.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import {
describe, test, expect, vi, beforeEach
} from 'vitest';
import {DateTime} from "luxon";
import {
mockCurrentSummaryData,
mockPreviousSummaryData,
mockCurrentCumulativeTimeseries,
mockCurrentNewTimeseries,
} from '../../mocks/tinybird-forks-response.mock';
import {ActivityFilterActivityType, ActivityFilterCountType, FilterGranularity} from "../types";
import type {ForksData} from "~~/types/popularity/responses.types";

const mockFetchFromTinybird = vi.fn();

describe('Forks Data Source', () => {
beforeEach(() => {
mockFetchFromTinybird.mockClear();

// Here be dragons! vi.doMock is not hoisted, and thus it is executed after the original import statement.
// This means that the import for tinybird.ts inside active-contributors-data-source.ts would still be used,
// and thus not mocked. This means we need to import the module again after the mock is set, whenever we want to
// use it.
vi.doMock(import("./tinybird"), () => ({
fetchFromTinybird: mockFetchFromTinybird,
}));
})

test('should fetch cumulative forks data with correct parameters', async () => {
// We have to import this here again because vi.doMock is not hoisted. See the explanation in beforeEach().
const {fetchForksActivities} = await import("~~/server/data/tinybird/forks-data-source");

mockFetchFromTinybird.mockResolvedValueOnce(mockCurrentSummaryData)
.mockResolvedValueOnce(mockPreviousSummaryData)
.mockResolvedValueOnce(mockCurrentCumulativeTimeseries);

const startDate = DateTime.utc(2024, 3, 20);
const endDate = DateTime.utc(2025, 3, 20);

const filter = {
granularity: FilterGranularity.WEEKLY,
project: 'the-linux-kernel-organization',
countType: ActivityFilterCountType.CUMULATIVE,
activityType: ActivityFilterActivityType.FORKS,
onlyContributions: false,
startDate,
endDate
};

const result = await fetchForksActivities(filter);

const currentCumulativeCount = mockCurrentSummaryData.data[0]?.activityCount || 0;
const previousCumulativeCount = mockPreviousSummaryData.data[0]?.activityCount || 0;

const expectedResult: ForksData = {
summary: {
current: currentCumulativeCount,
previous: previousCumulativeCount,
percentageChange: 100,
changeValue: currentCumulativeCount - previousCumulativeCount,
periodFrom: filter.startDate?.toString(),
periodTo: filter.endDate?.toString(),
},
data: mockCurrentCumulativeTimeseries.data.map((item) => ({
startDate: item.startDate,
endDate: item.endDate,
forks: item.cumulativeActivityCount,
}))
};

expect(result).toEqual(expectedResult);
});

test('should fetch new forks data with correct parameters', async () => {
// We have to import this here again because vi.doMock is not hoisted. See the explanation in beforeEach().
const {fetchForksActivities} = await import("~~/server/data/tinybird/forks-data-source");

mockFetchFromTinybird.mockResolvedValueOnce(mockCurrentSummaryData)
.mockResolvedValueOnce(mockPreviousSummaryData)
.mockResolvedValueOnce(mockCurrentNewTimeseries);

const startDate = DateTime.utc(2024, 3, 20);
const endDate = DateTime.utc(2025, 3, 20);

const filter = {
granularity: FilterGranularity.WEEKLY,
project: 'the-linux-kernel-organization',
countType: ActivityFilterCountType.NEW,
activityType: ActivityFilterActivityType.FORKS,
onlyContributions: false,
startDate,
endDate
};

const result = await fetchForksActivities(filter);

const currentCumulativeCount = mockCurrentSummaryData.data[0]?.activityCount || 0;
const previousCumulativeCount = mockPreviousSummaryData.data[0]?.activityCount || 0;

const expectedResult: ForksData = {
summary: {
current: currentCumulativeCount,
previous: previousCumulativeCount,
percentageChange: 100,
changeValue: currentCumulativeCount - previousCumulativeCount,
periodFrom: filter.startDate?.toString(),
periodTo: filter.endDate?.toString(),
},
data: mockCurrentNewTimeseries.data.map((item) => ({
startDate: item.startDate,
endDate: item.endDate,
forks: item.activityCount,
}))
};

expect(result).toEqual(expectedResult);
});

// TODO: Add checks for invalid dates, invalid data, sql injections, and other edge cases.
});
219 changes: 219 additions & 0 deletions frontend/server/mocks/tinybird-forks-response.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
export const mockCurrentSummaryData = {
meta: [
{
name: "activityCount",
type: "UInt64"
}
],
data: [
{
activityCount: 100
}
],
rows: 1,
statistics: {
elapsed: 0.320078864,
rows_read: 357628,
bytes_read: 18362864
}
};

export const mockPreviousSummaryData = {
meta: [
{
name: "activityCount",
type: "UInt64"
}
],
data: [
{
activityCount: 50
}
],
rows: 1,
statistics: {
elapsed: 0.279353225,
rows_read: 474679,
bytes_read: 24215414
}
};

export const mockCurrentCumulativeTimeseries = {
meta: [
{
name: "startDate",
type: "Nullable(Date)"
},
{
name: "endDate",
type: "Nullable(Date)"
},
{
name: "cumulativeActivityCount",
type: "Nullable(UInt64)"
}
],
data: [
{
startDate: "2024-03-01",
endDate: "2024-03-31",
cumulativeActivityCount: 0
},
{
startDate: "2024-04-01",
endDate: "2024-04-30",
cumulativeActivityCount: 0
},
{
startDate: "2024-05-01",
endDate: "2024-05-31",
cumulativeActivityCount: 0
},
{
startDate: "2024-06-01",
endDate: "2024-06-30",
cumulativeActivityCount: 0
},
{
startDate: "2024-07-01",
endDate: "2024-07-31",
cumulativeActivityCount: 0
},
{
startDate: "2024-08-01",
endDate: "2024-08-31",
cumulativeActivityCount: 0
},
{
startDate: "2024-09-01",
endDate: "2024-09-30",
cumulativeActivityCount: 0
},
{
startDate: "2024-10-01",
endDate: "2024-10-31",
cumulativeActivityCount: 0
},
{
startDate: "2024-11-01",
endDate: "2024-11-30",
cumulativeActivityCount: 0
},
{
startDate: "2024-12-01",
endDate: "2024-12-31",
cumulativeActivityCount: 0
},
{
startDate: "2025-01-01",
endDate: "2025-01-31",
cumulativeActivityCount: 0
},
{
startDate: "2025-02-01",
endDate: "2025-02-28",
cumulativeActivityCount: 0
},
{
startDate: "2025-03-01",
endDate: "2025-03-31",
cumulativeActivityCount: 0
}
],
rows: 13,
statistics: {
elapsed: 0.680491604,
rows_read: 5847561,
bytes_read: 292784030
}
};

export const mockCurrentNewTimeseries = {
meta: [
{
name: "startDate",
type: "Nullable(Date)"
},
{
name: "endDate",
type: "Nullable(Date)"
},
{
name: "activityCount",
type: "UInt64"
}
],
data: [
{
startDate: "2023-03-01",
endDate: "2023-03-31",
activityCount: 0
},
{
startDate: "2023-04-01",
endDate: "2023-04-30",
activityCount: 0
},
{
startDate: "2023-05-01",
endDate: "2023-05-31",
activityCount: 0
},
{
startDate: "2023-06-01",
endDate: "2023-06-30",
activityCount: 0
},
{
startDate: "2023-07-01",
endDate: "2023-07-31",
activityCount: 0
},
{
startDate: "2023-08-01",
endDate: "2023-08-31",
activityCount: 0
},
{
startDate: "2023-09-01",
endDate: "2023-09-30",
activityCount: 0
},
{
startDate: "2023-10-01",
endDate: "2023-10-31",
activityCount: 0
},
{
startDate: "2023-11-01",
endDate: "2023-11-30",
activityCount: 0
},
{
startDate: "2023-12-01",
endDate: "2023-12-31",
activityCount: 0
},
{
startDate: "2024-01-01",
endDate: "2024-01-31",
activityCount: 0
},
{
startDate: "2024-02-01",
endDate: "2024-02-29",
activityCount: 0
},
{
startDate: "2024-03-01",
endDate: "2024-03-31",
activityCount: 0
}
],
rows: 13,
statistics: {
elapsed: 0.031928949,
rows_read: 475680,
bytes_read: 24223415
}
};