Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
TypeScript
at sv-fe
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115import { describe, expect, it } from "vitest";import { ACTIVITY_METRICS, layoutActivityChart, type ActivityMetric} from "$lib/components/profile/profileActivityChart";
const values = { pulls: [10, 20, 30, 40, 50, 60], commits: [600, 500, 400, 300, 200, 100], repos: [0, 1, 0, 2, 1, 3], issues: [5, 5, 5, 5, 5, 5]} satisfies Record<ActivityMetric, number[]>;
describe("layoutActivityChart", () => { it("fills wide containers and preserves the Figma column proportions", () => { const layout = layoutActivityChart(values, 1976);
expect(layout.width).toBe(1976); expect(layout.columns.at(-1)!.left + layout.columns.at(-1)!.width).toBe(1976); expect(layout.columns[0].width).toBe(292); expect(layout.columns.at(-1)!.width).toBe(516); });
it("anchors every metric 12px inside its month column", () => { const layout = layoutActivityChart(values, 1976);
for (const [month, column] of layout.columns.entries()) { for (const metric of ACTIVITY_METRICS) { expect(layout.points[metric][month].x).toBe(column.left + 12); } } });
it("keeps a scrollable minimum width and omits the first divider", () => { const layout = layoutActivityChart(values, 320);
expect(layout.width).toBe(988); expect(layout.columns[0].divider).toBe(false); expect(layout.columns.slice(1).every((column) => column.divider)).toBe(true); });
it("normalizes every metric independently across the shared plot", () => { const layout = layoutActivityChart(values, 988);
expect(layout.points.pulls[0].y).toBeGreaterThan(layout.points.pulls[5].y); expect(layout.points.commits[0].y).toBeLessThan(layout.points.commits[5].y); });
it("keeps every value card legible and bounded by the plot", () => { const layout = layoutActivityChart(values, 988);
for (let month = 0; month < 6; month += 1) { const stacked = ACTIVITY_METRICS.map( (metric) => layout.points[metric][month].y ).toSorted((a, b) => a - b); for (const [index, y] of stacked.slice(1).entries()) { expect(y - stacked[index]).toBeGreaterThanOrEqual(30); } }
const flat = layout.points.issues.map((point) => point.y); expect(Math.max(...flat) - Math.min(...flat)).toBeLessThanOrEqual( 30 * (ACTIVITY_METRICS.length - 1) );
for (const metric of ACTIVITY_METRICS) { for (const point of layout.points[metric]) { expect(point.y).toBeGreaterThanOrEqual(20); expect(point.y).toBeLessThanOrEqual(196); } } });
it("uses the same points as the visible value anchors and path endpoints", () => { const layout = layoutActivityChart(values, 988);
for (const metric of ACTIVITY_METRICS) { const connectors = layout.segments[metric].slice(1, -1); for (const [index, segment] of connectors.entries()) { const point = layout.points[metric][index]; const next = layout.points[metric][index + 1]; expect(segment.d).toMatch(new RegExp(`^M ${point.x} ${point.y} C`)); expect(segment.d).toMatch(new RegExp(`${next.x} ${next.y}$`)); } } });
it("separates each column's metrics from top to bottom", () => { const layout = layoutActivityChart(values, 988);
for (let month = 0; month < 6; month += 1) { const byY = ACTIVITY_METRICS.toSorted( (a, b) => layout.points[a][month].y - layout.points[b][month].y ); for (const [index, metric] of byY.slice(1).entries()) { expect(layout.points[metric][month].y).toBeGreaterThan( layout.points[byY[index]][month].y ); } } });
it("runs each metric from the left edge to the right edge", () => { const layout = layoutActivityChart(values, 988);
for (const metric of ACTIVITY_METRICS) { const first = layout.points[metric][0]; const last = layout.points[metric].at(-1)!; expect(layout.segments[metric].at(0)!.d).toBe(`M 0 ${first.y} L ${first.x} ${first.y}`); expect(layout.segments[metric].at(-1)!.d).toBe(`M ${last.x} ${last.y} L 988 ${last.y}`); } });});