Skip to content

Commit 6a3cb4d

Browse files
committed
feat: add testing templates
1 parent c3f675c commit 6a3cb4d

File tree

22 files changed

+724
-0
lines changed

22 files changed

+724
-0
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script setup lang="ts">
2+
const msg = 'testing'
3+
</script>
4+
5+
<template>
6+
<h1>{{ msg }}</h1>
7+
</template>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// TODO: write unit tests for CountDown component
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<script setup lang="ts">
2+
// This component is a countdown timer for the end of the year.
3+
// It will display the number of days, hours, minutes, and seconds until the end of the year.
4+
// It also displays the number of weeks remaining in the year.
5+
6+
const countdown = ref({
7+
days: 0,
8+
hours: 0,
9+
minutes: 0,
10+
seconds: 0,
11+
})
12+
13+
const endOfYear = new Date(new Date().getFullYear() + 1, 0, 1)
14+
15+
function updateCountdown() {
16+
const now = new Date()
17+
const diff = endOfYear.getTime() - now.getTime()
18+
19+
const days = Math.floor(diff / (1000 * 60 * 60 * 24))
20+
const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))
21+
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60))
22+
const seconds = Math.floor((diff % (1000 * 60)) / 1000)
23+
24+
countdown.value.days = days
25+
countdown.value.hours = hours
26+
countdown.value.minutes = minutes
27+
countdown.value.seconds = seconds
28+
}
29+
30+
let intervalId: NodeJS.Timeout
31+
32+
onMounted(() => {
33+
// Call updateCountdown immediately to set the initial state
34+
updateCountdown()
35+
36+
// Update the countdown every second
37+
intervalId = setInterval(updateCountdown, 1000)
38+
})
39+
40+
onUnmounted(() => {
41+
// Clear the interval when the component is unmounted
42+
clearInterval(intervalId)
43+
})
44+
45+
const { totalWeeks, currentWeekNumber } = useWeek()
46+
</script>
47+
48+
<template>
49+
<div class="flex flex-col justify-between gap-x-16 gap-y-6 border-4 bg-white p-6 md:flex-row md:items-center dark:border-gray-600 dark:bg-gray-800" data-test-id="countdown-timer">
50+
<div class="text-gray-800 dark:text-gray-200">
51+
<h2 class="mb-2 text-lg text-gray-900 font-bold uppercase dark:text-gray-100">
52+
Time Until New Year
53+
</h2>
54+
<p class="flex flex-wrap gap-2 text-xl font-bold tracking-wide md:text-2xl" data-test-id="countdown">
55+
<span class="whitespace-nowrap">
56+
<span class="tabular-nums" data-test-id="countdown-days">{{ countdown.days }}</span> days,
57+
</span>
58+
<span class="whitespace-nowrap">
59+
<span class="tabular-nums" data-test-id="countdown-hours">{{ countdown.hours }}</span> hours,
60+
</span>
61+
<span class="whitespace-nowrap">
62+
<span class="tabular-nums" data-test-id="countdown-minutes">{{ countdown.minutes }}</span> minutes and
63+
</span>
64+
<span class="whitespace-nowrap">
65+
<span class="tabular-nums" data-test-id="countdown-seconds">{{ countdown.seconds }}</span> seconds
66+
</span>
67+
</p>
68+
</div>
69+
<div class="flex gap-1 text-gray-800 md:flex-col md:items-end dark:text-gray-200">
70+
<div class="text-lg font-bold uppercase md:text-xl" data-test-id="weeks">
71+
<div class="w-fit md:ml-auto">
72+
<span class="text-yellow-700 dark:text-yellow-400" data-test-id="current-week">Week {{ currentWeekNumber }}</span>
73+
<span class="text-gray-700 dark:text-gray-300" data-test-id="total-weeks"> of {{ totalWeeks }}</span>
74+
</div>
75+
<div class="whitespace-nowrap text-base text-gray-600 dark:text-gray-400" data-test-id="weeks-remaining">
76+
({{ totalWeeks - currentWeekNumber }} weeks remaining)
77+
</div>
78+
</div>
79+
</div>
80+
</div>
81+
</template>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { useWeek } from './useWeek'
2+
3+
describe('useWeek', () => {
4+
beforeEach(() => {
5+
// Mock the current date to a fixed value for consistent testing
6+
vi.useFakeTimers()
7+
vi.setSystemTime(new Date('2024-03-14'))
8+
})
9+
10+
afterEach(() => {
11+
vi.useRealTimers()
12+
})
13+
14+
it('initializes with current year', () => {
15+
const { weeks, currentWeekNumber, totalWeeks } = useWeek()
16+
17+
expect(weeks.value.length).toBeGreaterThan(0)
18+
expect(currentWeekNumber.value).toBe(11) // Week 11 in March 14, 2024
19+
expect(totalWeeks.value).toBe(53)
20+
})
21+
22+
it('calculates remaining weeks correctly', () => {
23+
const { remainingWeeks, currentWeekNumber, totalWeeks } = useWeek()
24+
25+
expect(remainingWeeks.value).toBe(totalWeeks.value - currentWeekNumber.value)
26+
})
27+
28+
it('changes year correctly', () => {
29+
const { changeYear, weeks, currentWeekNumber } = useWeek()
30+
31+
// Change to previous year
32+
changeYear(2023)
33+
expect(weeks.value.length).toBe(53)
34+
35+
expect(currentWeekNumber.value).toBe(0)
36+
})
37+
38+
it('handles leap years correctly', () => {
39+
const { changeYear, weeks } = useWeek()
40+
41+
// 2024 is a leap year
42+
changeYear(2024)
43+
expect(weeks.value.length).toBe(53)
44+
45+
// 2025 is not a leap year
46+
changeYear(2025)
47+
expect(weeks.value.length).toBe(53)
48+
})
49+
})
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
export function useWeek() {
2+
const yearRef = ref(new Date().getFullYear())
3+
const weeks = computed(() => calculateWeeks(yearRef.value))
4+
5+
const currentWeekNumber = computed(() => weeks.value.find(week => week.isCurrentWeek)?.number ?? 0)
6+
7+
const totalWeeks = computed(() => weeks.value.length)
8+
9+
const remainingWeeks = computed(() => totalWeeks.value - currentWeekNumber.value)
10+
11+
const changeYear = (year: number) => {
12+
yearRef.value = year
13+
}
14+
15+
return {
16+
weeks,
17+
currentWeekNumber,
18+
totalWeeks,
19+
remainingWeeks,
20+
changeYear,
21+
}
22+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export default defineNuxtConfig({
2+
modules: ['@nuxt/test-utils/module'],
3+
4+
compatibilityDate: '2025-02-25',
5+
})
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"type": "module",
3+
"private": true,
4+
"packageManager": "pnpm@9.15.4",
5+
"scripts": {
6+
"dev": "nuxt dev",
7+
"prepare": "nuxt prepare",
8+
"test:unit": "vitest",
9+
"test:unit-coverage": "vitest --coverage",
10+
"test:unit-ui": "vitest --coverage --ui"
11+
},
12+
"devDependencies": {
13+
"@nuxt/test-utils": "latest",
14+
"@vitest/coverage-v8": "latest",
15+
"@vitest/ui": "latest",
16+
"@vue/test-utils": "latest",
17+
"happy-dom": "latest",
18+
"nuxt": "latest",
19+
"typescript": "latest",
20+
"vitest": "latest",
21+
"vue": "latest"
22+
}
23+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { calculateWeeks } from './TimeUtils'
2+
3+
describe('timeUtils', () => {
4+
beforeEach(() => {
5+
// Set fixed date for consistent testing
6+
vi.useFakeTimers()
7+
vi.setSystemTime(new Date('2024-03-14T12:00:00.000Z'))
8+
})
9+
10+
afterEach(() => {
11+
vi.useRealTimers()
12+
})
13+
14+
describe('calculateWeeks', () => {
15+
it('calculates correct number of weeks for a year', () => {
16+
// Test a regular year (2023)
17+
const weeks2023 = calculateWeeks(2023)
18+
expect(weeks2023.length).toBe(53)
19+
20+
// Test a leap year (2024)
21+
const weeks2024 = calculateWeeks(2024)
22+
expect(weeks2024.length).toBe(53)
23+
})
24+
25+
it('sets correct start and end dates for weeks', () => {
26+
const weeks = calculateWeeks(2024)
27+
const firstWeek = weeks[0]
28+
const lastWeek = weeks[weeks.length - 1]
29+
30+
// Check date components separately to avoid timezone issues
31+
expect(firstWeek?.weekStart.getFullYear()).toBe(2024)
32+
expect(firstWeek?.weekStart.getMonth()).toBe(0) // January
33+
expect(firstWeek?.weekStart.getDate()).toBe(1) // 1st
34+
35+
expect(lastWeek?.weekEnd.getFullYear()).toBe(2024)
36+
expect(lastWeek?.weekEnd.getMonth()).toBe(11) // December
37+
expect(lastWeek?.weekEnd.getDate()).toBe(31) // 31st
38+
})
39+
40+
it('marks current week correctly', () => {
41+
const weeks = calculateWeeks(2024)
42+
const currentWeek = weeks.find(week => week.isCurrentWeek)
43+
44+
expect(currentWeek).toBeDefined()
45+
expect(currentWeek?.number).toBe(11) // March 14, 2024 is in week 11
46+
})
47+
})
48+
})
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
export interface Week {
2+
number: number
3+
weekStart: Date
4+
weekEnd: Date
5+
isCurrentWeek: boolean
6+
}
7+
8+
// Function to calculate weeks with start and end dates
9+
// This function calculates all weeks for a given year and returns an array of Week objects
10+
// Each Week object contains:
11+
// - number: The week number (1-53)
12+
// - weekStart: Date object for the start of week (Jan 1st for first week)
13+
// - weekEnd: Date object for end of week (Dec 31st for last week)
14+
// - isCurrentWeek: Boolean indicating if this is the current week
15+
export function calculateWeeks(year: number): Week[] {
16+
const today = new Date() // Get current date for comparing current week
17+
const weeks: Week[] = []
18+
19+
// Start from January 1st of the selected year
20+
const date = new Date(year, 0, 1)
21+
22+
// Calculate weeks by iterating through the year
23+
let weekNumber = 1
24+
while (date.getFullYear() === year) {
25+
// Start of week is the current date
26+
const weekStart = new Date(date)
27+
28+
// Move date to the end of the week (next Sunday)
29+
// For first week, this could be less than 7 days if year starts mid-week
30+
date.setDate(date.getDate() + ((7 - date.getDay()) % 7))
31+
32+
// Handle edge case for year boundary
33+
const weekEnd
34+
= date.getFullYear() !== year
35+
? new Date(year, 11, 31, 23, 59, 59) // December 31st 23:59:59
36+
: new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59)
37+
38+
// Check if this week contains today's date
39+
const isCurrentWeek = today >= weekStart && today <= weekEnd
40+
41+
// Add the week to our array
42+
weeks.push({ number: weekNumber, weekStart, weekEnd, isCurrentWeek })
43+
44+
// Move to start of next week
45+
date.setDate(date.getDate() + 1)
46+
weekNumber++
47+
}
48+
49+
return weeks
50+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { defineVitestConfig } from '@nuxt/test-utils/config'
2+
import 'dotenv/config'
3+
4+
export default defineVitestConfig({
5+
test: {
6+
name: 'unit',
7+
globals: true,
8+
environment: 'node',
9+
include: ['**/tests/unit/**/*.test.ts', '**/components/**/*.test.ts', '**/composables/**/*.test.ts', '**/utils/**/*.test.ts'],
10+
coverage: {
11+
provider: 'v8',
12+
include: ['**/components/**/*.vue', '**/composables/**/*.ts'],
13+
},
14+
},
15+
})

0 commit comments

Comments
 (0)