courseSummary groups courses by topic, ordered by course time; courseMatches searches title, provider, topic and keywords; formatHours and monthYear format the numbers the page shows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
59 lines
2.4 KiB
TypeScript
59 lines
2.4 KiB
TypeScript
import { describe, expect, test } from 'bun:test';
|
|
import { courseMatches, courseSummary, formatHours, monthYear, type CourseLike } from '../../src/core/courses.ts';
|
|
|
|
const c = (over: Partial<CourseLike>): CourseLike => ({
|
|
title: 'T', provider: 'P', kind: 'course', topic: 'A', completed: '2025-03-01', minutes: 60, certificate: false,
|
|
keywords: [], ...over,
|
|
});
|
|
|
|
describe('courseSummary', () => {
|
|
test('counts, certificates, minutes, earliest month and topics by time', () => {
|
|
const s = courseSummary([
|
|
c({ topic: 'Beta', minutes: 100, certificate: true, completed: '2025-04-02' }),
|
|
c({ topic: 'Alpha', minutes: 30, kind: 'lab', completed: '2025-02-20' }),
|
|
c({ topic: 'Alpha', minutes: 70, certificate: true, completed: '2025-05-01' }),
|
|
c({ topic: 'Gamma', minutes: 300, kind: 'lab', certificate: true, completed: '2025-06-01' }),
|
|
]);
|
|
expect(s).toEqual({
|
|
count: 4, certificates: 3, minutes: 500, since: '2025-02',
|
|
topics: [
|
|
{ topic: 'Gamma', courses: 0, labs: 1, certificates: 1, minutes: 300 },
|
|
{ topic: 'Alpha', courses: 1, labs: 1, certificates: 1, minutes: 100 },
|
|
{ topic: 'Beta', courses: 1, labs: 0, certificates: 1, minutes: 100 },
|
|
],
|
|
});
|
|
});
|
|
|
|
test('no courses', () => {
|
|
expect(courseSummary([])).toEqual({ count: 0, certificates: 0, minutes: 0, since: '', topics: [] });
|
|
});
|
|
});
|
|
|
|
describe('courseMatches', () => {
|
|
const course = c({ title: 'Containers from Scratch', provider: 'Sample School', topic: 'Docker', keywords: ['Images'] });
|
|
test('case-insensitive over title, provider, topic and keywords', () => {
|
|
expect(courseMatches(course, 'scratch')).toBe(true);
|
|
expect(courseMatches(course, 'SAMPLE')).toBe(true);
|
|
expect(courseMatches(course, 'docker')).toBe(true);
|
|
expect(courseMatches(course, 'images')).toBe(true);
|
|
expect(courseMatches(course, ' images ')).toBe(true);
|
|
expect(courseMatches(course, 'kotlin')).toBe(false);
|
|
});
|
|
test('an empty query matches nothing', () => {
|
|
expect(courseMatches(course, '')).toBe(false);
|
|
expect(courseMatches(course, ' ')).toBe(false);
|
|
});
|
|
});
|
|
|
|
test('formatHours gives one decimal', () => {
|
|
expect(formatHours(564)).toBe('9.4h');
|
|
expect(formatHours(24)).toBe('0.4h');
|
|
expect(formatHours(60)).toBe('1.0h');
|
|
});
|
|
|
|
test('monthYear', () => {
|
|
expect(monthYear('2025-02')).toBe('Feb 2025');
|
|
expect(monthYear('2024-12-31')).toBe('Dec 2024');
|
|
expect(monthYear('')).toBe('');
|
|
});
|