Skip to content

Commit 973a933

Browse files
committed
add test
1 parent 1fdcad3 commit 973a933

10 files changed

Lines changed: 1400 additions & 10 deletions

File tree

public/file.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

public/globe.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

public/next.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

public/vercel.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

public/window.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/lib/utils/array.test.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { describe, it, expect } from 'vitest';
2+
import { groupBy, unique, chunk } from './array';
3+
4+
describe('array utils', () => {
5+
describe('groupBy', () => {
6+
it('groups objects by key', () => {
7+
const data = [
8+
{ category: 'A', value: 1 },
9+
{ category: 'B', value: 2 },
10+
{ category: 'A', value: 3 },
11+
];
12+
const result = groupBy(data, 'category');
13+
14+
expect(result['A']).toHaveLength(2);
15+
expect(result['A'][0].value).toBe(1);
16+
expect(result['A'][1].value).toBe(3);
17+
expect(result['B']).toHaveLength(1);
18+
expect(result['B'][0].value).toBe(2);
19+
});
20+
21+
it('handles empty array', () => {
22+
expect(groupBy([], 'category')).toEqual({});
23+
});
24+
});
25+
26+
describe('unique', () => {
27+
it('removes duplicates from array', () => {
28+
expect(unique([1, 2, 2, 3, 1])).toEqual([1, 2, 3]);
29+
});
30+
31+
it('works with strings', () => {
32+
expect(unique(['a', 'b', 'a'])).toEqual(['a', 'b']);
33+
});
34+
35+
it('handles empty array', () => {
36+
expect(unique([])).toEqual([]);
37+
});
38+
});
39+
40+
describe('chunk', () => {
41+
it('chunks array into smaller arrays', () => {
42+
const data = [1, 2, 3, 4, 5];
43+
const result = chunk(data, 2);
44+
45+
expect(result).toHaveLength(3);
46+
expect(result[0]).toEqual([1, 2]);
47+
expect(result[1]).toEqual([3, 4]);
48+
expect(result[2]).toEqual([5]);
49+
});
50+
51+
it('handles empty array', () => {
52+
expect(chunk([], 2)).toEqual([]);
53+
});
54+
55+
it('returns one chunk if size is larger than array length', () => {
56+
expect(chunk([1, 2], 5)).toEqual([[1, 2]]);
57+
});
58+
});
59+
});

src/lib/utils/date.test.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { describe, it, expect } from 'vitest';
2+
import { formatDate, timeAgo, daysBetween } from './date';
3+
4+
describe('date utils', () => {
5+
describe('formatDate', () => {
6+
it('formats date correctly with default locale', () => {
7+
const date = new Date('2023-01-01T12:00:00Z');
8+
// Note: This test might be sensitive to the running environment's time zone if not handled carefully.
9+
// However, Intl.DateTimeFormat uses local time by default.
10+
// To make it deterministic in tests, we can check if it returns a string format.
11+
// Better yet, for basic smoke test, checking the structure or specific parts.
12+
// Given the implementation uses Intl.DateTimeFormat, exact output depends on browser/node locale support.
13+
// We will assume "ja-JP" default and check for typical format or parts.
14+
15+
const formatted = formatDate(date);
16+
expect(formatted).toMatch(/2023/);
17+
expect(formatted).toMatch(/01/);
18+
});
19+
20+
it('formats date string correctly', () => {
21+
const formatted = formatDate('2023-12-31');
22+
expect(formatted).toMatch(/2023/);
23+
expect(formatted).toMatch(/12/);
24+
expect(formatted).toMatch(/31/);
25+
});
26+
27+
it('respects custom locale and options', () => {
28+
const date = new Date('2023-01-01T00:00:00');
29+
const formatted = formatDate(date, 'en-US', { month: 'long', year: 'numeric' });
30+
expect(formatted).toBe('January 2023');
31+
});
32+
});
33+
34+
describe('timeAgo', () => {
35+
it('returns "seconds ago" for recent times', () => {
36+
const now = new Date();
37+
const past = new Date(now.getTime() - 1000 * 30); // 30 seconds ago
38+
expect(timeAgo(past)).toBe('30 seconds ago');
39+
});
40+
41+
it('returns "minutes ago"', () => {
42+
const now = new Date();
43+
const past = new Date(now.getTime() - 1000 * 60 * 5); // 5 minutes ago
44+
expect(timeAgo(past)).toBe('5 minutes ago');
45+
});
46+
47+
it('returns "hours ago"', () => {
48+
const now = new Date();
49+
const past = new Date(now.getTime() - 1000 * 60 * 60 * 2); // 2 hours ago
50+
expect(timeAgo(past)).toBe('2 hours ago');
51+
});
52+
53+
it('returns "days ago"', () => {
54+
const now = new Date();
55+
const past = new Date(now.getTime() - 1000 * 60 * 60 * 24 * 5); // 5 days ago
56+
expect(timeAgo(past)).toBe('5 days ago');
57+
});
58+
59+
it('returns "months ago"', () => {
60+
const now = new Date();
61+
const past = new Date(now.getTime() - 1000 * 60 * 60 * 24 * 60); // 60 days ~ 2 months
62+
expect(timeAgo(past)).toBe('2 months ago');
63+
});
64+
65+
it('returns "years ago"', () => {
66+
const now = new Date();
67+
const past = new Date(now.getTime() - 1000 * 60 * 60 * 24 * 400); // 400 days ~ 1 year
68+
expect(timeAgo(past)).toBe('1 years ago');
69+
});
70+
});
71+
72+
describe('daysBetween', () => {
73+
it('calculates days correctly', () => {
74+
const start = new Date('2023-01-01');
75+
const end = new Date('2023-01-10');
76+
expect(daysBetween(start, end)).toBe(9);
77+
});
78+
79+
it('returns 0 for same day', () => {
80+
const start = new Date('2023-01-01T10:00:00');
81+
const end = new Date('2023-01-01T20:00:00');
82+
expect(daysBetween(start, end)).toBe(0);
83+
});
84+
85+
it('works with string inputs', () => {
86+
expect(daysBetween('2023-01-01', '2023-01-02')).toBe(1);
87+
});
88+
});
89+
});

src/lib/utils/string.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { describe, it, expect } from 'vitest';
2+
import { truncate, toTitleCase } from './string';
3+
4+
describe('string utils', () => {
5+
describe('truncate', () => {
6+
it('truncates string longer than length', () => {
7+
expect(truncate('hello world', 5)).toBe('hello...');
8+
});
9+
10+
it('returns original string if shorter than or equal to length', () => {
11+
expect(truncate('hello', 10)).toBe('hello');
12+
expect(truncate('hello', 5)).toBe('hello');
13+
});
14+
15+
it('returns empty string for empty input', () => {
16+
expect(truncate('', 5)).toBe('');
17+
});
18+
});
19+
20+
describe('toTitleCase', () => {
21+
it('converts string to title case', () => {
22+
expect(toTitleCase('hello world')).toBe('Hello World');
23+
expect(toTitleCase('HELLO WORLD')).toBe('Hello World');
24+
expect(toTitleCase('hElLo wOrLd')).toBe('Hello World');
25+
});
26+
27+
it('handles empty string', () => {
28+
expect(toTitleCase('')).toBe('');
29+
});
30+
31+
it('handles single word', () => {
32+
expect(toTitleCase('javascript')).toBe('Javascript');
33+
});
34+
});
35+
});

vitest.config.mts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { defineConfig } from 'vitest/config'
2+
import react from '@vitejs/plugin-react'
3+
import { resolve } from 'path'
4+
5+
export default defineConfig({
6+
plugins: [react()],
7+
test: {
8+
environment: 'jsdom',
9+
globals: true,
10+
exclude: ['node_modules', 'e2e', '.next', 'out'],
11+
},
12+
resolve: {
13+
alias: {
14+
'@': resolve(__dirname, './src'),
15+
},
16+
},
17+
})

0 commit comments

Comments
 (0)