init
Auto Bump and Publish / bump-and-publish (push) Failing after 8m24s
CI / lint-and-test (20) (push) Successful in 1m1s
CI / lint-and-test (22) (push) Successful in 1m3s

This commit is contained in:
Tom You
2026-06-11 15:16:51 +09:00
commit 083505c952
30 changed files with 8530 additions and 0 deletions
+187
View File
@@ -0,0 +1,187 @@
/**
* config.ts 단위 테스트
* - getDefaultConfig()가 올바른 기본값을 반환하는지 확인
* - 설정 로드/저장은 파일 I/O가 포함되므로 통합 테스트에 가까움
*/
import { describe, it, expect, vi, afterEach } from 'vitest';
import fs from 'fs';
import os from 'os';
import path from 'path';
import inquirer from 'inquirer';
import { checkAndRunMigrations, CURRENT_CONFIG_VERSION } from '../src/migration';
import {
getDefaultConfig,
loadConfig,
saveConfig,
SKT_TERMS_URLS,
SKT_TERMS_VERSION,
validateRequiredFields,
} from '../src/config';
afterEach(() => {
vi.restoreAllMocks();
});
describe('getDefaultConfig', () => {
it('should return valid default config with required fields', () => {
const config = getDefaultConfig();
expect(config._config_version).toBe(4);
expect(config.credentials).toBeDefined();
expect(config.terms).toEqual({
provider: 'skt',
accepted: false,
accepted_at: '',
version: SKT_TERMS_VERSION,
urls: SKT_TERMS_URLS,
});
expect(config.plan.speed_mbps).toBe(1000);
expect(config.schedule.timezone).toBe('Asia/Seoul');
expect(config.headless).toBe(true);
});
it('should have schedule with multi-attempt defaults', () => {
const config = getDefaultConfig();
expect(config.schedule.max_attempts).toBeGreaterThan(1);
expect(config.schedule.retry_interval_minutes).toBeGreaterThan(0);
expect(config.schedule.stop_on_complaint_success).toBe(true);
});
});
describe('validateRequiredFields', () => {
it('should require SKT terms acceptance', () => {
const config = getDefaultConfig();
config.credentials.id = 'user@example.com';
config.credentials.password = 'password';
config.phone = '01012345678';
expect(validateRequiredFields(config)).toContain(
'terms (SKT/SK브로드밴드 공식 이용약관 동의)',
);
});
it('should reject invalid SKT terms acceptance timestamps', () => {
const config = getDefaultConfig();
config.credentials.id = 'user@example.com';
config.credentials.password = 'password';
config.phone = '01012345678';
config.terms = {
provider: 'skt',
accepted: true,
accepted_at: 'not-a-date',
version: SKT_TERMS_VERSION,
urls: SKT_TERMS_URLS,
};
expect(validateRequiredFields(config)).toContain(
'terms (SKT/SK브로드밴드 공식 이용약관 동의)',
);
});
it('should reject normalized or underspecified timestamp strings', () => {
const config = getDefaultConfig();
config.credentials.id = 'user@example.com';
config.credentials.password = 'password';
config.phone = '01012345678';
config.terms = {
provider: 'skt',
accepted: true,
accepted_at: '1',
version: SKT_TERMS_VERSION,
urls: SKT_TERMS_URLS,
};
expect(validateRequiredFields(config)).toContain(
'terms (SKT/SK브로드밴드 공식 이용약관 동의)',
);
config.terms.accepted_at = '2026-02-31T00:00:00.000Z';
expect(validateRequiredFields(config)).toContain(
'terms (SKT/SK브로드밴드 공식 이용약관 동의)',
);
});
it('should accept config with current SKT terms metadata', () => {
const config = getDefaultConfig();
config.credentials.id = 'user@example.com';
config.credentials.password = 'password';
config.phone = '01012345678';
config.terms = {
provider: 'skt',
accepted: true,
accepted_at: '2026-03-30T00:00:00.000Z',
version: SKT_TERMS_VERSION,
urls: SKT_TERMS_URLS,
};
expect(validateRequiredFields(config)).toEqual([]);
});
});
describe('loadConfig and saveConfig terms handling', () => {
it('should default missing terms in old configs safely', () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'skt-config-'));
const configPath = path.join(dir, 'config.yaml');
fs.writeFileSync(configPath, [
'_config_version: 3',
'credentials:',
' id: "user@example.com"',
' password: "password"',
'phone: "01012345678"',
].join('\n'), 'utf8');
const config = loadConfig(configPath);
expect(config.terms.accepted).toBe(false);
expect(config.terms.version).toBe(SKT_TERMS_VERSION);
expect(config.terms.urls).toEqual(SKT_TERMS_URLS);
});
it('should preserve accepted current terms when saving and loading', () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'skt-config-'));
const configPath = path.join(dir, 'config.yaml');
const config = getDefaultConfig();
config.terms = {
provider: 'skt',
accepted: true,
accepted_at: '2026-03-30T00:00:00.000Z',
version: SKT_TERMS_VERSION,
urls: SKT_TERMS_URLS,
};
saveConfig(config, configPath);
const loaded = loadConfig(configPath);
expect(loaded.terms).toEqual(config.terms);
});
});
describe('terms migration', () => {
it('should record SKT terms acceptance when migrating v3 configs to v4', async () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'skt-config-'));
const configPath = path.join(dir, 'config.yaml');
const config = getDefaultConfig();
config._config_version = 3;
config.credentials.id = 'user@example.com';
config.credentials.password = 'password';
config.phone = '01012345678';
vi.spyOn(inquirer, 'prompt').mockResolvedValue({ apply: true });
const migrated = await checkAndRunMigrations(config, configPath, { interactive: true });
expect(migrated._config_version).toBe(CURRENT_CONFIG_VERSION);
expect(migrated.terms).toMatchObject({
provider: 'skt',
accepted: true,
version: SKT_TERMS_VERSION,
urls: SKT_TERMS_URLS,
});
expect(new Date(migrated.terms.accepted_at).toISOString()).toBe(migrated.terms.accepted_at);
expect(loadConfig(configPath).terms.accepted).toBe(true);
});
});