Add migration script and work on tests
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
import sqlite3
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
SOURCE_DB = 'backend/data/upload.db'
|
||||
DEST_DB = 'backend/data/sleep.db'
|
||||
|
||||
def migrate():
|
||||
try:
|
||||
src_conn = sqlite3.connect(SOURCE_DB)
|
||||
src_cur = src_conn.cursor()
|
||||
|
||||
dest_conn = sqlite3.connect(DEST_DB)
|
||||
dest_cur = dest_conn.cursor()
|
||||
|
||||
print(f"Connecting to {SOURCE_DB} and {DEST_DB}...")
|
||||
|
||||
# 1. Truncate the destination table
|
||||
print("Truncating sleep_session table...")
|
||||
dest_cur.execute("DELETE FROM sleep_session")
|
||||
dest_conn.commit()
|
||||
|
||||
# Fetch all records from the Sleep table
|
||||
print("Fetching records from source...")
|
||||
src_cur.execute('SELECT "Time", "Duration", "Note" FROM "Sleep"')
|
||||
rows = src_cur.fetchall()
|
||||
|
||||
if not rows:
|
||||
print("No records found in source Sleep table.")
|
||||
return
|
||||
|
||||
migrated_count = 0
|
||||
error_count = 0
|
||||
now = datetime.now()
|
||||
|
||||
for row in rows:
|
||||
timestamp_seconds, duration_minutes, note = row
|
||||
|
||||
# Convert Unix timestamp to datetime object
|
||||
try:
|
||||
start_time = datetime.fromtimestamp(timestamp_seconds)
|
||||
except Exception as e:
|
||||
print(f"Error converting timestamp {timestamp_seconds}: {e}")
|
||||
error_count += 1
|
||||
continue
|
||||
|
||||
# Calculate end time based on duration (NOW ASSUMED MINUTES)
|
||||
end_time = start_time + timedelta(minutes=duration_minutes)
|
||||
|
||||
# VERIFICATION 1: Check if conversion matches source duration
|
||||
actual_duration_minutes = (end_time - start_time).total_seconds() / 60.0
|
||||
if abs(actual_duration_minutes - duration_minutes) > 0.1:
|
||||
print(f"CRITICAL ERROR: Duration mismatch for timestamp {timestamp_seconds}. Source (min): {duration_minutes}, Calculated (min): {actual_duration_minutes}")
|
||||
error_count += 1
|
||||
continue
|
||||
|
||||
notes = note if note is not None else ""
|
||||
|
||||
# Insert the new record
|
||||
try:
|
||||
dest_cur.execute(
|
||||
"""
|
||||
INSERT INTO sleep_session (start_time, end_time, notes, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
""",
|
||||
(
|
||||
start_time.strftime('%Y-%m-%d %H:%M:%S.%f'),
|
||||
end_time.strftime('%Y-%m-%d %H:%M:%S.%f'),
|
||||
notes,
|
||||
now.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
now.strftime('%Y-%m-%d %H:%M:%S')
|
||||
)
|
||||
)
|
||||
migrated_count += 1
|
||||
except Exception as e:
|
||||
print(f"Failed to insert record for timestamp {timestamp_seconds}: {e}")
|
||||
error_count += 1
|
||||
|
||||
dest_conn.commit()
|
||||
print(f"Migration complete.")
|
||||
print(f"Successfully migrated: {migrated_count}")
|
||||
print(f"Errors encountered: {error_count}")
|
||||
|
||||
# 2. FINAL VERIFICATION
|
||||
print("Running final verification...")
|
||||
dest_cur.execute("SELECT start_time, end_time FROM sleep_session")
|
||||
dest_rows = dest_cur.fetchall()
|
||||
|
||||
if len(dest_rows) != migrated_count:
|
||||
print(f"VERIFICATION FAILED: Count mismatch. Source attempted: {migrated_count}, Destination count: {len(dest_rows)}")
|
||||
else:
|
||||
print("VERIFICATION SUCCESS: Count matches.")
|
||||
|
||||
# Sample duration verification in destination
|
||||
print("Verifying sample durations from destination...")
|
||||
for i, (st_str, et_str) in enumerate(dest_rows[:5]):
|
||||
st = datetime.strptime(st_str, '%Y-%m-%d %H:%M:%S.%f')
|
||||
et = datetime.strptime(et_str, '%Y-%m-%d %H:%M:%S.%f')
|
||||
duration_sec = (et - st).total_seconds()
|
||||
print(f" Sample {i+1}: Start={st_str}, End={et_str}, Duration={duration_sec/60.0:.1f}m")
|
||||
|
||||
except Exception as e:
|
||||
print(f"An error occurred during migration: {e}")
|
||||
finally:
|
||||
if 'src_conn' in locals(): src_conn.close()
|
||||
if 'dest_conn' in locals(): dest_conn.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
migrate()
|
||||
Generated
+685
-2577
File diff suppressed because it is too large
Load Diff
+23
-22
@@ -7,35 +7,36 @@
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build",
|
||||
"preview": "vite preview",
|
||||
"test": "vitest run",
|
||||
"test": "DEBUG_PRINT_LIMIT=0 vitest run --reporter=dot --no-color",
|
||||
"test:all": "vitest run && npx playwright test",
|
||||
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tanstack/react-query": "^5.0.0",
|
||||
"lucide-react": "^0.470.0",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-router-dom": "^7.1.0",
|
||||
"recharts": "^2.15.0"
|
||||
"@tanstack/react-query": "^5.100.5",
|
||||
"lucide-react": "^1.11.0",
|
||||
"react": "^19.2.5",
|
||||
"react-dom": "^19.2.5",
|
||||
"react-router-dom": "^7.14.2",
|
||||
"recharts": "^3.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.59.1",
|
||||
"@tailwindcss/vite": "^4.0.0",
|
||||
"@testing-library/jest-dom": "^6.6.0",
|
||||
"@testing-library/react": "^16.1.0",
|
||||
"@testing-library/user-event": "^14.5.0",
|
||||
"@tailwindcss/vite": "^4.2.4",
|
||||
"@testing-library/jest-dom": "^6.9.1",
|
||||
"@testing-library/react": "^16.3.2",
|
||||
"@testing-library/user-event": "^14.6.1",
|
||||
"@types/lodash": "^4.17.24",
|
||||
"@types/react": "^18.3.0",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@vitejs/plugin-react": "^4.3.0",
|
||||
"@vitest/ui": "^2.1.0",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"jsdom": "^29.0.2",
|
||||
"postcss": "^8.4.49",
|
||||
"tailwindcss": "^4.0.0",
|
||||
"typescript": "^5.7.0",
|
||||
"vite": "^6.0.0",
|
||||
"vitest": "2.1.9"
|
||||
"@types/node": "^25.6.0",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^6.0.1",
|
||||
"@vitest/ui": "^4.1.5",
|
||||
"autoprefixer": "^10.5.0",
|
||||
"jsdom": "^29.1.0",
|
||||
"postcss": "^8.5.12",
|
||||
"tailwindcss": "^4.2.4",
|
||||
"typescript": "^6.0.3",
|
||||
"vite": "^8.0.10",
|
||||
"vitest": "^4.1.5"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
> baby-sleep-tracker-frontend@0.1.0 test
|
||||
> DEBUG_PRINT_LIMIT=0 vitest run --reporter=dot --no-color
|
||||
|
||||
|
||||
RUN v4.1.5 /Users/jhag/projects/babymonitor/frontend
|
||||
|
||||
··································xxx····
|
||||
|
||||
Test Files 1 failed | 6 passed (7)
|
||||
Tests 3 failed | 38 passed (41)
|
||||
Start at 15:55:21
|
||||
Duration 924ms (transform 166ms, setup 0ms, import 600ms, tests 173ms, environment 4.31s)
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { vi, describe, it, expect } from 'vitest';
|
||||
import Timetable from './SleepTimetable';
|
||||
import { useStats } from '../../hooks/useStats';
|
||||
|
||||
vi.mock('../../hooks/useStats', () => ({
|
||||
useStats: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('SleepTimetable', () => {
|
||||
const defaultProps = {
|
||||
from_date: '2025-04-20',
|
||||
to_date: '2025-04-21',
|
||||
day_start: '22:00',
|
||||
day_end: '08:00',
|
||||
};
|
||||
|
||||
it('renders loading state', () => {
|
||||
(useStats as any).mockReturnValue({ timetable: null, isLoading: true });
|
||||
render(<Timetable {...defaultProps} />);
|
||||
expect(screen.getByText(/Loading timetable.../i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders empty state when no data is available', () => {
|
||||
(useStats as any).mockReturnValue({ timetable: { slots: [] }, isLoading: false });
|
||||
render(<Timetable {...defaultProps} />);
|
||||
expect(screen.getByText(/No data available/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders the grid correctly with hourly rows and biennial labels', () => {
|
||||
(useStats as any).mockReturnValue({
|
||||
timetable: {
|
||||
slots: [
|
||||
{
|
||||
date: '2025-04-20',
|
||||
sleeping: true,
|
||||
slot_start: '01:00',
|
||||
slot_end: '05:00',
|
||||
},
|
||||
],
|
||||
},
|
||||
isLoading: false,
|
||||
});
|
||||
|
||||
render(<Timetable {...defaultProps} />);
|
||||
|
||||
// Check for day headers
|
||||
expect(screen.getByText(/SUN/i)).toBeInTheDocument(); // 2025-04-20 is Sunday
|
||||
expect(screen.getByText(/MON/i)).toBeInTheDocument(); // 2025-04-21 is Monday
|
||||
|
||||
// Check for time labels (every 2 hours: 00, 02, 04...)
|
||||
expect(screen.getByText('00:00')).toBeInTheDocument();
|
||||
expect(screen.getByText('02:00')).toBeInTheDocument();
|
||||
expect(screen.getByText('04:00')).toBeInTheDocument();
|
||||
expect(screen.getByText('22:00')).toBeInTheDocument();
|
||||
|
||||
// Verify non-labeled hours (every hour that isn't %120 == 0)
|
||||
// We can't easily check for empty text nodes in Vitest/RTL without more precision
|
||||
// but we can check that 01:00 is NOT present as a text label
|
||||
expect(screen.queryByText('01:00')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('colors sleeping intervals correctly', () => {
|
||||
(useStats as any).mockReturnValue({
|
||||
timetable: {
|
||||
slots: [
|
||||
{
|
||||
date: '2025-04-20',
|
||||
sleeping: true,
|
||||
slot_start: '01:00',
|
||||
slot_end: '03:00', // Covers 01:00 and 02:00
|
||||
},
|
||||
],
|
||||
},
|
||||
isLoading: false,
|
||||
});
|
||||
|
||||
const { container } = render(<Timetable {...defaultProps} />);
|
||||
|
||||
// We are looking for the grid cells.
|
||||
// Since they don't have text, we look at their classes/backgrounds.
|
||||
const cells = container.querySelectorAll('.h-8');
|
||||
// Total cells = 24 rows * (1 label col + 2 days) = 72? No, the structure is:
|
||||
// Header row has cells. Time grid rows have (1 label + 2 days) = 3 cells each.
|
||||
// Total elements with .h-8: 1 (header corner) + days.length * 1 (day headers) + 24 * 3 = 75?
|
||||
// Actually, the code has:
|
||||
// Header row: header corner + days.map -> 1 + 2 = 3 cells
|
||||
// Time Rows: (label cell) + days.map -> 24 * 3 = 72 cells
|
||||
// Total = 75.
|
||||
|
||||
// The sleeping cell for 01:00 on 2025-04-20 should be bg-green-500
|
||||
// The cell for 02:00 on 2025-04-20 should be bg-green-500
|
||||
// The cell for 03:00 on 2025-04-20 should be bg-gray-50
|
||||
// Let's just check if ANY cell has bg-green-500 and ALL non-sleeping have bg-gray-50
|
||||
|
||||
const greenCells = container.querySelectorAll('.bg-green-500');
|
||||
expect(greenCells.length).toBeGreaterThan(0);
|
||||
|
||||
const grayCells = container.querySelectorAll('.bg-gray-50');
|
||||
expect(grayCells.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { useStats } from '../../hooks/useStats';
|
||||
import { timeToMinutes, formatMinutesAfter } from '../../utils/time';
|
||||
import { timeToMinutes } from '../../utils/time';
|
||||
|
||||
interface TimetableProps {
|
||||
from_date: string;
|
||||
@@ -25,7 +25,7 @@ const Timetable: React.FC<TimetableProps> = ({ from_date, to_date, day_start, da
|
||||
}, [from_date, to_date]);
|
||||
|
||||
const timeSteps = useMemo(() => {
|
||||
return Array.from({ length: 12 }, (_, i) => i * 120);
|
||||
return Array.from({ length: 24 }, (_, i) => i * 60);
|
||||
}, []);
|
||||
|
||||
if (isLoading) return <div className="text-center p-4">Loading timetable...</div>;
|
||||
@@ -62,58 +62,56 @@ const Timetable: React.FC<TimetableProps> = ({ from_date, to_date, day_start, da
|
||||
|
||||
const currentMins = new Date().getHours() * 60 + new Date().getMinutes();
|
||||
|
||||
// Total rows: 1 (header) + 12 (time steps) = 13
|
||||
const totalRows = 13;
|
||||
return (
|
||||
<div className="bg-white p-4 rounded-xl shadow-sm border border-gray-200 overflow-x-auto">
|
||||
<h3 className="text-lg font-semibold mb-4 text-gray-800">Sleep Timetable</h3>
|
||||
<div className="min-w-[600px] flex flex-col gap-px">
|
||||
{/* Header Row */}
|
||||
<div
|
||||
className="grid"
|
||||
style={{
|
||||
gridTemplateColumns: `4rem repeat(${days.length}, minmax(40px, 1fr))`
|
||||
}}
|
||||
>
|
||||
<div className="h-8" /> {/* Empty corner cell */}
|
||||
{days.map((day) => (
|
||||
<div key={day} className="text-center text-[10px] font-medium text-gray-500 uppercase flex items-center justify-center h-8">
|
||||
{getDayName(day)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
return (
|
||||
<div className="bg-white p-4 rounded-xl shadow-sm border border-gray-200 overflow-x-auto">
|
||||
<h3 className="text-lg font-semibold mb-4 text-gray-800">Sleep Timetable</h3>
|
||||
<div className="min-w-[600px] flex flex-col gap-px">
|
||||
{/* Header Row */}
|
||||
<div
|
||||
className="grid"
|
||||
style={{
|
||||
gridTemplateColumns: `4rem repeat(${days.length}, minmax(40px, 1fr))`
|
||||
}}
|
||||
>
|
||||
<div className="h-8" /> {/* Empty corner cell */}
|
||||
{days.map((day) => (
|
||||
<div key={day} className="text-center text-[10px] font-medium text-gray-500 uppercase flex items-center justify-center h-8">
|
||||
{getDayName(day)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{/* Time Grid Container */}
|
||||
<div className="relative">
|
||||
<div
|
||||
className="grid"
|
||||
style={{
|
||||
gridTemplateColumns: `4rem repeat(${days.length}, minmax(40px, 1fr))`
|
||||
}}
|
||||
>
|
||||
{/* Time Rows */}
|
||||
{timeSteps.map((step) => (
|
||||
<React.Fragment key={step}>
|
||||
{/* Time Label */}
|
||||
<div className="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8">
|
||||
{step % 120 === 0 ? formatTimeLabel(step) : ''}
|
||||
</div>
|
||||
|
||||
{/* Grid Cells */}
|
||||
{days.map((day) => {
|
||||
const sleeping = isSleepingInInterval(day, step, step + 60);
|
||||
return (
|
||||
<div
|
||||
key={`${day}-${step}`}
|
||||
className={`h-8 w-full ${sleeping ? 'bg-green-500' : 'bg-gray-50'}`}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</React.Fragment>
|
||||
))}
|
||||
|
||||
{/* Time Grid Container */}
|
||||
<div className="relative">
|
||||
<div
|
||||
className="grid gap-px"
|
||||
style={{
|
||||
gridTemplateColumns: `4rem repeat(${days.length}, minmax(40px, 1fr))`
|
||||
}}
|
||||
>
|
||||
{/* Time Rows */}
|
||||
{timeSteps.map((step) => (
|
||||
<React.Fragment key={step}>
|
||||
{/* Time Label */}
|
||||
<div className="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8">
|
||||
{formatTimeLabel(step)}
|
||||
</div>
|
||||
|
||||
{/* Grid Cells */}
|
||||
{days.map((day) => {
|
||||
const sleeping = isSleepingInInterval(day, step, step + 120);
|
||||
return (
|
||||
<div
|
||||
key={`${day}-${step}`}
|
||||
className={`h-8 w-full ${sleeping ? 'bg-green-500' : 'bg-gray-50'}`}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</React.Fragment>
|
||||
))}
|
||||
{/* Red Marker Line */}
|
||||
|
||||
{/* Red Marker Line */}
|
||||
<div
|
||||
className="absolute left-[4rem] right-0 h-0.5 bg-red-500 pointer-events-none z-10"
|
||||
style={{
|
||||
|
||||
@@ -0,0 +1,650 @@
|
||||
|
||||
> baby-sleep-tracker-frontend@0.1.0 test
|
||||
> vitest run --reporter=dot
|
||||
|
||||
|
||||
RUN v2.1.9 /Users/jhag/projects/babymonitor/frontend
|
||||
|
||||
✓ tests/simple.test.ts (1 test) 1ms
|
||||
✓ tests/unit/chartHelpers.test.ts (9 tests) 2ms
|
||||
✓ tests/unit/time.test.ts (16 tests) 3ms
|
||||
✓ tests/unit/StatusBanner.test.tsx (5 tests) 19ms
|
||||
✓ tests/unit/TimeAdjuster.test.tsx (3 tests) 24ms
|
||||
❯ src/components/stats/SleepTimetable.test.tsx (4 tests | 3 failed) 42ms
|
||||
× SleepTimetable > renders loading state 17ms
|
||||
→ Invalid Chai property: toBeInTheDocument
|
||||
× SleepTimetable > renders empty state when no data is available 1ms
|
||||
→ Invalid Chai property: toBeInTheDocument
|
||||
× SleepTimetable > renders the grid correctly with hourly rows and biennial labels 19ms
|
||||
→ Unable to find an element with the text: SUN. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
|
||||
|
||||
Ignored nodes: comments, script, style
|
||||
[36m<body>[39m
|
||||
[36m<div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"bg-white p-4 rounded-xl shadow-sm border border-gray-200 overflow-x-auto"[39m
|
||||
[36m>[39m
|
||||
[36m<h3[39m
|
||||
[33mclass[39m=[32m"text-lg font-semibold mb-4 text-gray-800"[39m
|
||||
[36m>[39m
|
||||
[0mSleep Timetable[0m
|
||||
[36m</h3>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"min-w-[600px] flex flex-col gap-px"[39m
|
||||
[36m>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"grid"[39m
|
||||
[33mstyle[39m=[32m"grid-template-columns: 4rem repeat(2, minmax(40px, 1fr));"[39m
|
||||
[36m>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8"[39m
|
||||
[36m/>[39m
|
||||
[0m [0m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-center text-[10px] font-medium text-gray-500 uppercase flex items-center justify-center h-8"[39m
|
||||
[36m>[39m
|
||||
[0mSun[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-center text-[10px] font-medium text-gray-500 uppercase flex items-center justify-center h-8"[39m
|
||||
[36m>[39m
|
||||
[0mMon[0m
|
||||
[36m</div>[39m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"relative"[39m
|
||||
[36m>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"grid"[39m
|
||||
[33mstyle[39m=[32m"grid-template-columns: 4rem repeat(2, minmax(40px, 1fr));"[39m
|
||||
[36m>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m00:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-green-500"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m02:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-green-500"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-green-500"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m04:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-green-500"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m06:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m08:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m10:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m12:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m14:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m16:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m18:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m20:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m22:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"absolute left-[4rem] right-0 h-0.5 bg-red-500 pointer-events-none z-10"[39m
|
||||
[33mstyle[39m=[32m"top: 84.02777777777779%; transform: translateY(-50%);"[39m
|
||||
[36m/>[39m
|
||||
[36m</div>[39m
|
||||
[36m</div>[39m
|
||||
[36m</div>[39m
|
||||
[36m</div>[39m
|
||||
[36m</div>[39m
|
||||
[36m</body>[39m
|
||||
✓ tests/unit/SleepButton.test.tsx (3 tests) 62ms
|
||||
|
||||
⎯⎯⎯⎯⎯⎯⎯ Failed Tests 3 ⎯⎯⎯⎯⎯⎯⎯
|
||||
|
||||
FAIL src/components/stats/SleepTimetable.test.tsx > SleepTimetable > renders loading state
|
||||
Error: Invalid Chai property: toBeInTheDocument
|
||||
❯ src/components/stats/SleepTimetable.test.tsx:21:53
|
||||
19| (useStats as any).mockReturnValue({ timetable: null, isLoading: tr…
|
||||
20| render(<Timetable {...defaultProps} />);
|
||||
21| expect(screen.getByText(/Loading timetable.../i)).toBeInTheDocumen…
|
||||
| ^
|
||||
22| });
|
||||
23|
|
||||
|
||||
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/3]⎯
|
||||
|
||||
FAIL src/components/stats/SleepTimetable.test.tsx > SleepTimetable > renders empty state when no data is available
|
||||
Error: Invalid Chai property: toBeInTheDocument
|
||||
❯ src/components/stats/SleepTimetable.test.tsx:27:50
|
||||
25| (useStats as any).mockReturnValue({ timetable: { slots: [] }, isLo…
|
||||
26| render(<Timetable {...defaultProps} />);
|
||||
27| expect(screen.getByText(/No data available/i)).toBeInTheDocument();
|
||||
| ^
|
||||
28| });
|
||||
29|
|
||||
|
||||
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/3]⎯
|
||||
|
||||
FAIL src/components/stats/SleepTimetable.test.tsx > SleepTimetable > renders the grid correctly with hourly rows and biennial labels
|
||||
TestingLibraryElementError: Unable to find an element with the text: SUN. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
|
||||
|
||||
Ignored nodes: comments, script, style
|
||||
[36m<body>[39m
|
||||
[36m<div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"bg-white p-4 rounded-xl shadow-sm border border-gray-200 overflow-x-auto"[39m
|
||||
[36m>[39m
|
||||
[36m<h3[39m
|
||||
[33mclass[39m=[32m"text-lg font-semibold mb-4 text-gray-800"[39m
|
||||
[36m>[39m
|
||||
[0mSleep Timetable[0m
|
||||
[36m</h3>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"min-w-[600px] flex flex-col gap-px"[39m
|
||||
[36m>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"grid"[39m
|
||||
[33mstyle[39m=[32m"grid-template-columns: 4rem repeat(2, minmax(40px, 1fr));"[39m
|
||||
[36m>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8"[39m
|
||||
[36m/>[39m
|
||||
[0m [0m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-center text-[10px] font-medium text-gray-500 uppercase flex items-center justify-center h-8"[39m
|
||||
[36m>[39m
|
||||
[0mSun[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-center text-[10px] font-medium text-gray-500 uppercase flex items-center justify-center h-8"[39m
|
||||
[36m>[39m
|
||||
[0mMon[0m
|
||||
[36m</div>[39m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"relative"[39m
|
||||
[36m>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"grid"[39m
|
||||
[33mstyle[39m=[32m"grid-template-columns: 4rem repeat(2, minmax(40px, 1fr));"[39m
|
||||
[36m>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m00:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-green-500"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m02:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-green-500"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-green-500"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m04:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-green-500"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m06:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m08:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m10:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m12:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m14:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m16:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m18:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m20:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m>[39m
|
||||
[0m22:00[0m
|
||||
[36m</div>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"h-8 w-full bg-gray-50"[39m
|
||||
[36m/>[39m
|
||||
[36m<div[39m
|
||||
[33mclass[39m=[32m"absolute left-[4rem] right-0 h-0.5 bg-red-500 pointer-events-none z-10"[39m
|
||||
[33mstyle[39m=[32m"top: 84.02777777777779%; transform: translateY(-50%);"[39m
|
||||
[36m/>[39m
|
||||
[36m</div>[39m
|
||||
[36m</div>[39m
|
||||
[36m</div>[39m
|
||||
[36m</div>[39m
|
||||
[36m</div>[39m
|
||||
[36m</body>[39m
|
||||
❯ Object.getElementError node_modules/@testing-library/dom/dist/config.js:37:19
|
||||
❯ node_modules/@testing-library/dom/dist/query-helpers.js:76:38
|
||||
❯ node_modules/@testing-library/dom/dist/query-helpers.js:52:17
|
||||
❯ node_modules/@testing-library/dom/dist/query-helpers.js:95:19
|
||||
❯ src/components/stats/SleepTimetable.test.tsx:48:19
|
||||
46|
|
||||
47| // Check for day headers
|
||||
48| expect(screen.getByText('SUN')).toBeInTheDocument(); // 2025-04-20…
|
||||
| ^
|
||||
49| expect(screen.getByText('MON')).toBeInTheDocument(); // 2025-04-21…
|
||||
50|
|
||||
|
||||
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/3]⎯
|
||||
|
||||
Test Files 1 failed | 6 passed (7)
|
||||
Tests 3 failed | 38 passed (41)
|
||||
Start at 20:10:38
|
||||
Duration 718ms (transform 173ms, setup 0ms, collect 475ms, tests 155ms, environment 2.78s, prepare 242ms)
|
||||
|
||||
@@ -0,0 +1,650 @@
|
||||
|
||||
> baby-sleep-tracker-frontend@0.1.0 test
|
||||
> vitest run --reporter=dot
|
||||
|
||||
|
||||
RUN v2.1.9 /Users/jhag/projects/babymonitor/frontend
|
||||
|
||||
✓ tests/simple.test.ts (1 test) 1ms
|
||||
✓ tests/unit/chartHelpers.test.ts (9 tests) 2ms
|
||||
✓ tests/unit/time.test.ts (16 tests) 2ms
|
||||
✓ tests/unit/StatusBanner.test.tsx (5 tests) 20ms
|
||||
✓ tests/unit/TimeAdjuster.test.tsx (3 tests) 24ms
|
||||
❯ src/components/stats/SleepTimetable.test.tsx (4 tests | 3 failed) 41ms
|
||||
× SleepTimetable > renders loading state 15ms
|
||||
→ Invalid Chai property: toBeInTheDocument
|
||||
× SleepTimetable > renders empty state when no data is available 1ms
|
||||
→ Invalid Chai property: toBeInTheDocument
|
||||
× SleepTimetable > renders the grid correctly with hourly rows and biennial labels 20ms
|
||||
→ Unable to find an element with the text: SUN. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
|
||||
|
||||
Ignored nodes: comments, script, style
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
class="bg-white p-4 rounded-xl shadow-sm border border-gray-200 overflow-x-auto"
|
||||
>
|
||||
<h3
|
||||
class="text-lg font-semibold mb-4 text-gray-800"
|
||||
>
|
||||
Sleep Timetable
|
||||
</h3>
|
||||
<div
|
||||
class="min-w-[600px] flex flex-col gap-px"
|
||||
>
|
||||
<div
|
||||
class="grid"
|
||||
style="grid-template-columns: 4rem repeat(2, minmax(40px, 1fr));"
|
||||
>
|
||||
<div
|
||||
class="h-8"
|
||||
/>
|
||||
|
||||
<div
|
||||
class="text-center text-[10px] font-medium text-gray-500 uppercase flex items-center justify-center h-8"
|
||||
>
|
||||
Sun
|
||||
</div>
|
||||
<div
|
||||
class="text-center text-[10px] font-medium text-gray-500 uppercase flex items-center justify-center h-8"
|
||||
>
|
||||
Mon
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="relative"
|
||||
>
|
||||
<div
|
||||
class="grid"
|
||||
style="grid-template-columns: 4rem repeat(2, minmax(40px, 1fr));"
|
||||
>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
00:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-green-500"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
02:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-green-500"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-green-500"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
04:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-green-500"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
06:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
08:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
10:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
12:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
14:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
16:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
18:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
20:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
22:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="absolute left-[4rem] right-0 h-0.5 bg-red-500 pointer-events-none z-10"
|
||||
style="top: 84.16666666666667%; transform: translateY(-50%);"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
✓ tests/unit/SleepButton.test.tsx (3 tests) 62ms
|
||||
|
||||
⎯⎯⎯⎯⎯⎯⎯ Failed Tests 3 ⎯⎯⎯⎯⎯⎯⎯
|
||||
|
||||
FAIL src/components/stats/SleepTimetable.test.tsx > SleepTimetable > renders loading state
|
||||
Error: Invalid Chai property: toBeInTheDocument
|
||||
❯ src/components/stats/SleepTimetable.test.tsx:21:53
|
||||
19| (useStats as any).mockReturnValue({ timetable: null, isLoading: tr…
|
||||
20| render(<Timetable {...defaultProps} />);
|
||||
21| expect(screen.getByText(/Loading timetable.../i)).toBeInTheDocumen…
|
||||
| ^
|
||||
22| });
|
||||
23|
|
||||
|
||||
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/3]⎯
|
||||
|
||||
FAIL src/components/stats/SleepTimetable.test.tsx > SleepTimetable > renders empty state when no data is available
|
||||
Error: Invalid Chai property: toBeInTheDocument
|
||||
❯ src/components/stats/SleepTimetable.test.tsx:27:50
|
||||
25| (useStats as any).mockReturnValue({ timetable: { slots: [] }, isLo…
|
||||
26| render(<Timetable {...defaultProps} />);
|
||||
27| expect(screen.getByText(/No data available/i)).toBeInTheDocument();
|
||||
| ^
|
||||
28| });
|
||||
29|
|
||||
|
||||
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/3]⎯
|
||||
|
||||
FAIL src/components/stats/SleepTimetable.test.tsx > SleepTimetable > renders the grid correctly with hourly rows and biennial labels
|
||||
TestingLibraryElementError: Unable to find an element with the text: SUN. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
|
||||
|
||||
Ignored nodes: comments, script, style
|
||||
<body>
|
||||
<div>
|
||||
<div
|
||||
class="bg-white p-4 rounded-xl shadow-sm border border-gray-200 overflow-x-auto"
|
||||
>
|
||||
<h3
|
||||
class="text-lg font-semibold mb-4 text-gray-800"
|
||||
>
|
||||
Sleep Timetable
|
||||
</h3>
|
||||
<div
|
||||
class="min-w-[600px] flex flex-col gap-px"
|
||||
>
|
||||
<div
|
||||
class="grid"
|
||||
style="grid-template-columns: 4rem repeat(2, minmax(40px, 1fr));"
|
||||
>
|
||||
<div
|
||||
class="h-8"
|
||||
/>
|
||||
|
||||
<div
|
||||
class="text-center text-[10px] font-medium text-gray-500 uppercase flex items-center justify-center h-8"
|
||||
>
|
||||
Sun
|
||||
</div>
|
||||
<div
|
||||
class="text-center text-[10px] font-medium text-gray-500 uppercase flex items-center justify-center h-8"
|
||||
>
|
||||
Mon
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="relative"
|
||||
>
|
||||
<div
|
||||
class="grid"
|
||||
style="grid-template-columns: 4rem repeat(2, minmax(40px, 1fr));"
|
||||
>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
00:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-green-500"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
02:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-green-500"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-green-500"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
04:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-green-500"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
06:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
08:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
10:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
12:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
14:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
16:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
18:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
20:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
>
|
||||
22:00
|
||||
</div>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="text-[10px] text-gray-400 flex items-center justify-end pr-2 h-8"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="h-8 w-full bg-gray-50"
|
||||
/>
|
||||
<div
|
||||
class="absolute left-[4rem] right-0 h-0.5 bg-red-500 pointer-events-none z-10"
|
||||
style="top: 84.16666666666667%; transform: translateY(-50%);"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
❯ Object.getElementError node_modules/@testing-library/dom/dist/config.js:37:19
|
||||
❯ node_modules/@testing-library/dom/dist/query-helpers.js:76:38
|
||||
❯ node_modules/@testing-library/dom/dist/query-helpers.js:52:17
|
||||
❯ node_modules/@testing-library/dom/dist/query-helpers.js:95:19
|
||||
❯ src/components/stats/SleepTimetable.test.tsx:48:19
|
||||
46|
|
||||
47| // Check for day headers
|
||||
48| expect(screen.getByText('SUN')).toBeInTheDocument(); // 2025-04-20…
|
||||
| ^
|
||||
49| expect(screen.getByText('MON')).toBeInTheDocument(); // 2025-04-21…
|
||||
50|
|
||||
|
||||
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/3]⎯
|
||||
|
||||
Test Files 1 failed | 6 passed (7)
|
||||
Tests 3 failed | 38 passed (41)
|
||||
Start at 20:12:08
|
||||
Duration 722ms (transform 112ms, setup 0ms, collect 483ms, tests 153ms, environment 2.74s, prepare 226ms)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
},
|
||||
"types": ["vite/client"]
|
||||
"types": ["vite/client", "vitest/globals"]
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
||||
@@ -5,12 +5,6 @@ import path from 'path'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react(), tailwindcss()],
|
||||
test: {
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
include: ['src/**/*.{test,spec}.{ts,tsx}', 'tests/**/*.{test,spec}.{ts,tsx}'],
|
||||
exclude: ['**/tests/e2e/**', '**/node_modules/**'],
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.resolve(__dirname, './src'),
|
||||
@@ -24,4 +18,4 @@ export default defineConfig({
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,16 @@
|
||||
import { defineConfig, mergeConfig } from 'vitest/config'
|
||||
import viteConfig from './vite.config'
|
||||
|
||||
export default mergeConfig(
|
||||
viteConfig,
|
||||
defineConfig({
|
||||
test: {
|
||||
globals: true,
|
||||
environment: 'jsdom',
|
||||
setupFiles: ['./vitest.setup.ts'],
|
||||
include: ['src/**/*.{test,spec}.{ts,tsx}', 'tests/**/*.{test,spec}.{ts,tsx}'],
|
||||
exclude: ['**/tests/e2e/**', '**/node_modules/**'],
|
||||
reporters: ['dot'],
|
||||
},
|
||||
})
|
||||
)
|
||||
@@ -0,0 +1 @@
|
||||
import '@testing-library/jest-dom/vitest';
|
||||
Reference in New Issue
Block a user