Skip to content

Commit c68f05b

Browse files
authored
Finish feature/116
2 parents b042029 + 727e807 commit c68f05b

File tree

6 files changed

+186
-2
lines changed

6 files changed

+186
-2
lines changed

.github/workflows/test.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: Run Tests
2+
3+
on:
4+
push:
5+
branches: [main, master]
6+
pull_request:
7+
branches: [main, master]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
13+
strategy:
14+
matrix:
15+
node-version: [18, 20, 22]
16+
17+
steps:
18+
- name: Checkout code
19+
uses: actions/checkout@v4
20+
21+
- name: Set up Node.js
22+
uses: actions/setup-node@v4
23+
with:
24+
node-version: ${{ matrix.node-version }}
25+
26+
- name: Install dependencies
27+
run: npm install
28+
29+
- name: Run tests
30+
run: npm test
31+

package.json

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@
66
"scripts": {
77
"dev": "vite",
88
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
9-
"preview": "vite preview"
9+
"prettier": "prettier --check .",
10+
"test": "vitest run",
11+
"test:watch": "vitest --watch"
1012
},
1113
"devDependencies": {
14+
"@testing-library/react": "^16.3.0",
15+
"@types/jsdom": "^21.1.7",
1216
"@types/react": "19.0.1",
1317
"@types/react-dom": "19.0.1",
1418
"@typescript-eslint/eslint-plugin": "8.17.0",
@@ -17,10 +21,12 @@
1721
"eslint": "9.16.0",
1822
"eslint-plugin-react-hooks": "5.1.0",
1923
"eslint-plugin-react-refresh": "0.4.16",
24+
"jsdom": "^26.1.0",
2025
"prettier": "3.4.2",
2126
"react": "19.0.0",
2227
"react-dom": "19.0.0",
2328
"typescript": "5.7.2",
24-
"vite": "6.0.3"
29+
"vite": "6.0.3",
30+
"vitest": "^3.1.2"
2531
}
2632
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2+
import { renderHook, act } from '@testing-library/react';
3+
import { useLang } from '../useLang';
4+
5+
describe('useLang Hook', () => {
6+
const originalNavigatorLanguage = navigator.language;
7+
8+
beforeEach(() => {
9+
Object.defineProperty(navigator, 'language', {
10+
writable: true,
11+
value: 'en-US'
12+
});
13+
});
14+
15+
afterEach(() => {
16+
// Restore the original language value
17+
Object.defineProperty(navigator, 'language', {
18+
writable: true,
19+
value: originalNavigatorLanguage
20+
});
21+
});
22+
23+
it('should return the initial language', () => {
24+
const { result } = renderHook(() => useLang());
25+
expect(result.current).toBe('en-US');
26+
});
27+
28+
it('should update language on "languagechange" event', () => {
29+
const { result } = renderHook(() => useLang());
30+
31+
act(() => {
32+
// Trigger the languagechange event
33+
Object.defineProperty(navigator, 'language', {
34+
writable: true,
35+
value: 'es-ES'
36+
});
37+
window.dispatchEvent(new Event('languagechange'));
38+
});
39+
40+
// Verify that the hook updates the value
41+
expect(result.current).toBe('es-ES');
42+
});
43+
});
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 { renderHook, act } from '@testing-library/react';
3+
import useArray from '../useArray';
4+
5+
describe('useArray', () => {
6+
it('should initialize with the given array', () => {
7+
const { result } = renderHook(() => useArray([1, 2, 3]));
8+
expect(result.current.array).toEqual([1, 2, 3]);
9+
});
10+
11+
it('should push an element', () => {
12+
const { result } = renderHook(() => useArray([1, 2]));
13+
act(() => {
14+
result.current.push(3);
15+
});
16+
expect(result.current.array).toEqual([1, 2, 3]);
17+
});
18+
19+
it('should filter elements', () => {
20+
const { result } = renderHook(() => useArray([1, 2, 3, 4]));
21+
act(() => {
22+
result.current.filter((n: number) => n % 2 === 0);
23+
});
24+
expect(result.current.array).toEqual([2, 4]);
25+
});
26+
27+
it('should update an element at a given index', () => {
28+
const { result } = renderHook(() => useArray(['a', 'b', 'c']));
29+
act(() => {
30+
result.current.update(1, 'z');
31+
});
32+
expect(result.current.array).toEqual(['a', 'z', 'c']);
33+
});
34+
35+
it('should remove an element at a given index', () => {
36+
const { result } = renderHook(() => useArray([10, 20, 30]));
37+
act(() => {
38+
result.current.remove(1);
39+
});
40+
expect(result.current.array).toEqual([10, 30]);
41+
});
42+
43+
it('should clear the array', () => {
44+
const { result } = renderHook(() => useArray([1, 2, 3]));
45+
act(() => {
46+
result.current.clear();
47+
});
48+
expect(result.current.array).toEqual([]);
49+
});
50+
51+
it('should set the array directly', () => {
52+
const { result } = renderHook(() => useArray([1, 2, 3]));
53+
act(() => {
54+
result.current.set([7, 8, 9]);
55+
});
56+
expect(result.current.array).toEqual([7, 8, 9]);
57+
});
58+
});
59+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
2+
import { renderHook, act } from '@testing-library/react';
3+
import { useLang } from '../useLang';
4+
5+
describe('useLang Hook', () => {
6+
const originalNavigatorLanguage = navigator.language;
7+
8+
beforeEach(() => {
9+
Object.defineProperty(navigator, 'language', {
10+
writable: true,
11+
value: 'en-US',
12+
});
13+
});
14+
15+
afterEach(() => {
16+
// Restore the original language value
17+
Object.defineProperty(navigator, 'language', {
18+
writable: true,
19+
value: originalNavigatorLanguage,
20+
});
21+
});
22+
23+
it('should return the initial language', () => {
24+
const { result } = renderHook(() => useLang());
25+
expect(result.current).toBe('en-US');
26+
});
27+
28+
it('should update language on "languagechange" event', () => {
29+
const { result } = renderHook(() => useLang());
30+
31+
act(() => {
32+
// Trigger the languagechange event
33+
Object.defineProperty(navigator, 'language', { writable: true, value: 'es-ES' });
34+
window.dispatchEvent(new Event('languagechange'));
35+
});
36+
37+
// Verify that the hook updates the value
38+
expect(result.current).toBe('es-ES');
39+
});
40+
});

vite.config.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1+
/// <reference types="vitest/config" />
12
import { defineConfig } from 'vite'
23
import react from '@vitejs/plugin-react'
34

45
// https://vitejs.dev/config/
56
export default defineConfig({
67
plugins: [react()],
8+
test: {
9+
globals: true, // Enables global test APIs like `describe`, `it`, etc.
10+
environment: 'jsdom', // Simulates the DOM for React components
11+
},
712
})

0 commit comments

Comments
 (0)