Add Prettier and ESLint tooling (Refs #77)

This commit is contained in:
2026-10-09 15:56:13 -04:00
parent 8ed059b8d3
commit 16469e2d43
711 changed files with 99737 additions and 28286 deletions
+82 -18
View File
@@ -1,17 +1,44 @@
import { beforeEach, afterEach, describe, it, expect, vi } from 'vitest';
import { newFixture, type Fixture } from '../helpers/fixture.js';
vi.mock('../../src/lib/server/pipeline/worker.js', () => ({ kick: vi.fn().mockResolvedValue(undefined) }));
vi.mock('../../src/lib/server/pipeline/worker.js', () => ({
kick: vi.fn().mockResolvedValue(undefined)
}));
let fixture: Fixture;
beforeEach(async () => { vi.resetModules(); fixture = await newFixture(); });
afterEach(async () => { await fixture.cleanup(); });
const request = (body: unknown) => new Request('http://localhost/api/maintenance', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
beforeEach(async () => {
vi.resetModules();
fixture = await newFixture();
});
afterEach(async () => {
await fixture.cleanup();
});
const request = (body: unknown) =>
new Request('http://localhost/api/maintenance', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body)
});
describe('Maintenance API', () => {
it('saves independent policies and the global pause without changing the restart schedule', async () => {
const { POST, GET } = await import('../../src/routes/api/maintenance/+server.js');
expect((await POST({ request: request({ action: 'schedule', enabled: true, time: '06:00', timeZone: 'America/Indiana/Indianapolis' }) })).status).toBe(200);
const before = (await (GET()).json()).runtime.schedule;
for (const body of [{ action: 'policy', policy: 'health', enabled: false }, { action: 'policy', policy: 'updates', enabled: true }, { action: 'pause', paused: true }]) {
expect(
(
await POST({
request: request({
action: 'schedule',
enabled: true,
time: '06:00',
timeZone: 'America/Indiana/Indianapolis'
})
})
).status
).toBe(200);
const before = (await GET().json()).runtime.schedule;
for (const body of [
{ action: 'policy', policy: 'health', enabled: false },
{ action: 'policy', policy: 'updates', enabled: true },
{ action: 'pause', paused: true }
]) {
expect((await POST({ request: request(body) })).status).toBe(200);
}
const data = await GET().json();
@@ -22,32 +49,69 @@ describe('Maintenance API', () => {
it('rejects malformed actions without changing policies or queuing work', async () => {
const { POST, GET } = await import('../../src/routes/api/maintenance/+server.js');
const before = await GET().json();
for (const body of [null, [], {}, { action: 'pause', paused: 'yes' }, { action: 'policy', policy: 'unknown', enabled: true },
{ action: 'policy', policy: 'updates', enabled: 1 }, { action: 'schedule', enabled: true, time: '25:00', timeZone: 'UTC' },
{ action: 'schedule', enabled: true, time: '06:00', timeZone: 'invalid' }, { action: 'update', servers: [] },
{ action: 'update', servers: [1] }, { action: 'retry', id: '1' }]) {
for (const body of [
null,
[],
{},
{ action: 'pause', paused: 'yes' },
{ action: 'policy', policy: 'unknown', enabled: true },
{ action: 'policy', policy: 'updates', enabled: 1 },
{ action: 'schedule', enabled: true, time: '25:00', timeZone: 'UTC' },
{ action: 'schedule', enabled: true, time: '06:00', timeZone: 'invalid' },
{ action: 'update', servers: [] },
{ action: 'update', servers: [1] },
{ action: 'retry', id: '1' }
]) {
expect((await POST({ request: request(body) })).status).toBe(400);
}
expect(await GET().json()).toEqual(before);
});
it('opens one retained request outside the recent history window without changing normal history', async () => {
const { db } = await import('../../src/lib/server/db/index.js');
const insert = db().prepare("INSERT INTO maintenance_jobs(server,state,requested_at,kind,origin) VALUES(?,'done',?,'schedule','schedule')");
db().transaction(() => { for (let i = 0; i < 105; i++) insert.run('t5_zombie_theater_1', new Date(Date.UTC(2026, 0, 1, 0, i)).toISOString()); })();
const insert = db().prepare(
"INSERT INTO maintenance_jobs(server,state,requested_at,kind,origin) VALUES(?,'done',?,'schedule','schedule')"
);
db().transaction(() => {
for (let i = 0; i < 105; i++)
insert.run(
't5_zombie_theater_1',
new Date(Date.UTC(2026, 0, 1, 0, i)).toISOString()
);
})();
const { GET } = await import('../../src/routes/api/maintenance/+server.js');
const ordinary = await GET().json();
expect(ordinary.runtime.jobs).toHaveLength(100);
expect(ordinary.runtime.jobs.some((job: { id: number }) => job.id === 1)).toBe(false);
const selected = await GET({ url: new URL('http://localhost/api/maintenance?job=1') }).json();
const selected = await GET({
url: new URL('http://localhost/api/maintenance?job=1')
}).json();
expect(selected.runtime.jobs).toHaveLength(101);
expect(selected.runtime.jobs.find((job: { id: number }) => job.id === 1)).toMatchObject({ state: 'done', kind: 'schedule' });
for (const job of ['0', '-1', '', '1.5', 'bad', '99999999999999999999']) expect(GET({ url: new URL(`http://localhost/api/maintenance?job=${job}`) }).status).toBe(400);
expect(selected.runtime.jobs.find((job: { id: number }) => job.id === 1)).toMatchObject({
state: 'done',
kind: 'schedule'
});
for (const job of ['0', '-1', '', '1.5', 'bad', '99999999999999999999'])
expect(
GET({ url: new URL(`http://localhost/api/maintenance?job=${job}`) }).status
).toBe(400);
expect(await GET().json()).toEqual(ordinary);
});
it('keeps old Watchdog URLs working through query-preserving redirects', async () => {
const index = await import('../../src/routes/watchdog/+page.server.js');
const detail = await import('../../src/routes/watchdog/[id]/+page.server.js');
expect(() => index.load({ url: new URL('http://localhost/watchdog?kind=drift&server=test') })).toThrow(expect.objectContaining({ status: 308, location: '/maintenance?kind=drift&server=test' }));
expect(() => detail.load({ params: { id: 'abc' }, url: new URL('http://localhost/watchdog/abc?test=1') })).toThrow(expect.objectContaining({ status: 308, location: '/maintenance/abc?test=1' }));
expect(() =>
index.load({ url: new URL('http://localhost/watchdog?kind=drift&server=test') })
).toThrow(
expect.objectContaining({
status: 308,
location: '/maintenance?kind=drift&server=test'
})
);
expect(() =>
detail.load({
params: { id: 'abc' },
url: new URL('http://localhost/watchdog/abc?test=1')
})
).toThrow(expect.objectContaining({ status: 308, location: '/maintenance/abc?test=1' }));
});
});