Files
immich-folio/app/api/admin/__tests__/settings-env-locks.test.ts

93 lines
2.9 KiB
TypeScript
Raw Normal View History

import { describe, it, expect, vi, beforeEach } from 'vitest';
vi.mock('@/lib/admin/auth', () => ({
isAdminEnabled: vi.fn(() => true),
isAdminAuthenticated: vi.fn(async () => true),
COOKIE_NAME: 'folio_admin_session',
}));
vi.mock('@/lib/admin/yaml-service', () => ({
readSettingsYaml: vi.fn(async () => ({
sitePassword: 'scrypt:stored:hash',
contact: { enabled: true, notifyUrl: 'https://ntfy.sh/stored' },
})),
readSettingsYamlVersioned: vi.fn(async () => ({
data: {
sitePassword: 'scrypt:stored:hash',
contact: { enabled: true, notifyUrl: 'https://ntfy.sh/stored' },
},
version: 'v1',
})),
writeSettingsYaml: vi.fn(async () => undefined),
}));
vi.mock('@/lib/config', () => ({
invalidateConfigCache: vi.fn(),
getConfigOrNull: vi.fn(() => null),
}));
vi.mock('@/lib/immich', () => ({ immich: { invalidateAll: vi.fn() } }));
vi.mock('next/cache', () => ({ revalidatePath: vi.fn() }));
const env = vi.hoisted(() => ({
SITE_PASSWORD: 'env-secret-password' as string | undefined,
CONTACT_NOTIFY_URL: 'https://ntfy.sh/env-secret-topic' as string | undefined,
SITE_TITLE: 'Env Title',
}));
vi.mock('@/lib/env', () => ({ env }));
import { writeSettingsYaml } from '@/lib/admin/yaml-service';
import { GET, PUT } from '../settings/route';
/**
* The panel renders these fields locked (#605). The payload carries only the
* variable names: the values are a password and an ntfy topic.
*/
describe('/api/admin/settings env locks (#605)', () => {
beforeEach(() => {
vi.clearAllMocks();
env.SITE_PASSWORD = 'env-secret-password';
env.CONTACT_NOTIFY_URL = 'https://ntfy.sh/env-secret-topic';
});
it('GET names the locking variables and never their values', async () => {
const res = await GET();
const text = await res.text();
expect(JSON.parse(text).envLocks).toEqual({
sitePassword: 'SITE_PASSWORD',
'contact.notifyUrl': 'CONTACT_NOTIFY_URL',
});
expect(text).not.toContain('env-secret-password');
expect(text).not.toContain('env-secret-topic');
});
it('GET reports no locks when the variables are unset', async () => {
env.SITE_PASSWORD = undefined;
env.CONTACT_NOTIFY_URL = undefined;
const body = await (await GET()).json();
expect(body.envLocks).toEqual({});
});
it('PUT keeps the stored value of a locked field', async () => {
const res = await PUT(
new Request('http://localhost/api/admin/settings', {
method: 'PUT',
body: JSON.stringify({
settings: {
title: 'Folio',
sitePassword: 'typed-in-panel',
contact: { enabled: true, notifyUrl: 'https://ntfy.sh/typed' },
},
}),
}),
);
expect(res.status).toBe(200);
expect(vi.mocked(writeSettingsYaml).mock.calls[0][0]).toMatchObject({
title: 'Folio',
sitePassword: 'scrypt:stored:hash',
contact: { enabled: true, notifyUrl: 'https://ntfy.sh/stored' },
});
});
});