mirror of
https://github.com/dcarrillo/atalaya.git
synced 2026-05-18 06:24:12 +00:00
add testing to status-page functions (#12)
This commit is contained in:
@@ -13,20 +13,9 @@ interface Props {
|
||||
};
|
||||
}
|
||||
|
||||
import { formatAbsoluteTime } from '../lib/header.js';
|
||||
|
||||
const { summary, lastUpdated, title, banner } = Astro.props;
|
||||
|
||||
function formatAbsoluteTime(unixTimestamp: number): string {
|
||||
const date = new Date(unixTimestamp * 1000);
|
||||
return date.toLocaleString('en-US', {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
hour12: false,
|
||||
timeZoneName: 'short'
|
||||
});
|
||||
}
|
||||
|
||||
const absoluteTime = formatAbsoluteTime(lastUpdated);
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
import type { ApiMonitorStatus } from '@worker/types';
|
||||
import UptimeBars from './UptimeBars.astro';
|
||||
import { formatLastChecked } from '../lib/monitor-card.js';
|
||||
|
||||
interface Props {
|
||||
monitor: ApiMonitorStatus;
|
||||
@@ -9,25 +10,6 @@ interface Props {
|
||||
const { monitor } = Astro.props;
|
||||
|
||||
const uptimeFormatted = monitor.uptimePercent.toFixed(2);
|
||||
|
||||
function formatLastChecked(timestamp: number | undefined): string {
|
||||
if (timestamp == null) return 'Never';
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
const diffSeconds = now - timestamp;
|
||||
|
||||
if (diffSeconds < 60) return '';
|
||||
if (diffSeconds < 3600) {
|
||||
const minutes = Math.floor(diffSeconds / 60);
|
||||
return `${minutes}m ago`;
|
||||
}
|
||||
if (diffSeconds < 86400) {
|
||||
const hours = Math.floor(diffSeconds / 3600);
|
||||
return `${hours}h ago`;
|
||||
}
|
||||
const days = Math.floor(diffSeconds / 86400);
|
||||
return `${days}d ago`;
|
||||
}
|
||||
|
||||
const lastCheckedText = formatLastChecked(monitor.lastChecked);
|
||||
|
||||
const chartData = JSON.stringify({
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
---
|
||||
import type { ApiDayStatus } from '@worker/types';
|
||||
import { getBarColor } from '../lib/uptime-bars.js';
|
||||
|
||||
interface Props {
|
||||
dailyHistory: ApiDayStatus[];
|
||||
}
|
||||
|
||||
const { dailyHistory } = Astro.props;
|
||||
|
||||
function getBarColor(uptimePercent: number | undefined): string {
|
||||
if (uptimePercent == null) return 'no-data';
|
||||
if (uptimePercent >= 99.8) return 'up';
|
||||
if (uptimePercent >= 95) return 'degraded';
|
||||
return 'down';
|
||||
}
|
||||
---
|
||||
|
||||
<div class="uptime-section">
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { describe, it, expect, afterAll } from 'vitest';
|
||||
import { formatAbsoluteTime } from './header.js';
|
||||
|
||||
describe('formatAbsoluteTime', () => {
|
||||
const origTZ = process.env.TZ;
|
||||
|
||||
afterAll(() => {
|
||||
process.env.TZ = origTZ;
|
||||
});
|
||||
|
||||
it('formats timestamp in UTC', () => {
|
||||
process.env.TZ = 'UTC';
|
||||
// 1704067200 = 2024-01-01 00:00:00 UTC
|
||||
const result = formatAbsoluteTime(1704067200);
|
||||
expect(result).toContain('Jan');
|
||||
expect(result).toContain('1,');
|
||||
expect(result).toContain('00:00');
|
||||
});
|
||||
|
||||
it('returns month abbreviation in English', () => {
|
||||
process.env.TZ = 'UTC';
|
||||
// 1719792000 = 2024-07-01 00:00:00 UTC
|
||||
const result = formatAbsoluteTime(1719792000);
|
||||
expect(result).toContain('Jul');
|
||||
expect(result).toContain('1,');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
export function formatAbsoluteTime(unixTimestamp: number): string {
|
||||
const date = new Date(unixTimestamp * 1000);
|
||||
return date.toLocaleString('en-US', {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
hour12: false,
|
||||
timeZoneName: 'short',
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||
import { formatLastChecked } from './monitor-card.js';
|
||||
|
||||
describe('formatLastChecked', () => {
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date('2024-06-15T12:00:00Z'));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it('returns "Never" for null/undefined', () => {
|
||||
expect(formatLastChecked(undefined)).toBe('Never');
|
||||
expect(formatLastChecked(null as unknown as undefined)).toBe('Never');
|
||||
});
|
||||
|
||||
it('returns empty string for < 60 seconds', () => {
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
expect(formatLastChecked(now - 30)).toBe('');
|
||||
expect(formatLastChecked(now - 0)).toBe('');
|
||||
});
|
||||
|
||||
it('returns minutes ago', () => {
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
expect(formatLastChecked(now - 120)).toBe('2m ago');
|
||||
expect(formatLastChecked(now - 3540)).toBe('59m ago');
|
||||
});
|
||||
|
||||
it('returns hours ago', () => {
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
expect(formatLastChecked(now - 3600)).toBe('1h ago');
|
||||
expect(formatLastChecked(now - 82800)).toBe('23h ago');
|
||||
});
|
||||
|
||||
it('returns days ago', () => {
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
expect(formatLastChecked(now - 86400)).toBe('1d ago');
|
||||
expect(formatLastChecked(now - 172800)).toBe('2d ago');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
export function formatLastChecked(timestamp: number | undefined): string {
|
||||
if (timestamp == null) return 'Never';
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
const diffSeconds = now - timestamp;
|
||||
|
||||
if (diffSeconds < 60) return '';
|
||||
if (diffSeconds < 3600) {
|
||||
const minutes = Math.floor(diffSeconds / 60);
|
||||
return `${minutes}m ago`;
|
||||
}
|
||||
if (diffSeconds < 86400) {
|
||||
const hours = Math.floor(diffSeconds / 3600);
|
||||
return `${hours}h ago`;
|
||||
}
|
||||
const days = Math.floor(diffSeconds / 86400);
|
||||
return `${days}d ago`;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { getBarColor } from './uptime-bars.js';
|
||||
|
||||
describe('getBarColor', () => {
|
||||
it('returns "no-data" for null/undefined', () => {
|
||||
expect(getBarColor(undefined)).toBe('no-data');
|
||||
expect(getBarColor(null as unknown as undefined)).toBe('no-data');
|
||||
});
|
||||
|
||||
it('returns "up" for >= 99.8', () => {
|
||||
expect(getBarColor(100)).toBe('up');
|
||||
expect(getBarColor(99.8)).toBe('up');
|
||||
expect(getBarColor(99.81)).toBe('up');
|
||||
});
|
||||
|
||||
it('returns "degraded" for >= 95 and < 99.8', () => {
|
||||
expect(getBarColor(99.7)).toBe('degraded');
|
||||
expect(getBarColor(97.5)).toBe('degraded');
|
||||
expect(getBarColor(95)).toBe('degraded');
|
||||
});
|
||||
|
||||
it('returns "down" for < 95', () => {
|
||||
expect(getBarColor(94.9)).toBe('down');
|
||||
expect(getBarColor(50)).toBe('down');
|
||||
expect(getBarColor(0)).toBe('down');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,6 @@
|
||||
export function getBarColor(uptimePercent: number | undefined): string {
|
||||
if (uptimePercent == null) return 'no-data';
|
||||
if (uptimePercent >= 99.8) return 'up';
|
||||
if (uptimePercent >= 95) return 'degraded';
|
||||
return 'down';
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { defineConfig } from 'vitest/config';
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
globals: true,
|
||||
environment: 'node',
|
||||
include: ['src/**/*.test.ts'],
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user