Files
MyIP/tests/sections.test.js
T
jason5ng32andClaude Opus 4.6 2e489c00cd refactor: extract store.js hardcoded data to frontend/data/
refactor/04 complete. Four families of constants that used to live inline
in store.js are now dedicated modules under frontend/data/ with their
own tests. Consumers still read the same store shape — zero call-site
changes required for the 20+ consumers of userAchievements / ipDBs /
mountingStatus / userPreferences.

New data modules (frontend/data/):
- achievements.js
    ACHIEVEMENTS_DEFINITIONS          — 21 {name, img} entries
    createInitialAchievementsState()  — factory, returns fresh keyed map
  Bonus fix: IAmHuman.img previously used 'achievements/iamhuman.webp'
  (missing leading slash). All 21 entries now uniformly start with
  '/achievements/'. No consumer had the legacy path string baked in.

- ip-databases.js
    IP_DATABASES        — 7 {id, text, url, enabled} entries
    createInitialIpDBs()— factory for store.ipDBs
    buildDbUrl(db, ip, lang) — pure URL template substitution,
                               extracted from store.getDbUrl so it can
                               be tested without instantiating Pinia

- default-preferences.js
    DEFAULT_PREFERENCES      — Object.freeze'd canonical defaults
    createDefaultPreferences() — writable copy factory

- sections.js (new shared source of truth)
    SECTION_IDS      — ['IPInfo', 'Connectivity', ..., 'AdvancedTools']
    DEFAULT_SECTION  — 'IPInfo'
    createMountingStatus() / createLoadingStatus() — key-set factories
  Previously, the same 6 section names were duplicated in three places:
  store.mountingStatus keys, store.loadingStatus keys (subset), and a
  hardcoded local array inside Patch.vue's checkSectionsAndTrack().
  Patch.vue now imports SECTION_IDS from data/.

store.js changes:
- Import factories from data/*, replace 60+ lines of inline literal state
  with factory calls
- getDbUrl() delegates URL substitution to buildDbUrl pure function
- loadPreferences() uses createDefaultPreferences()
- currentSection default uses DEFAULT_SECTION

Tests (23 new, brings total 23 → 46, all green):
- tests/achievements.test.js       — definitions shape, path format,
                                      factory isolation, runtime shape
- tests/ip-databases.test.js       — definitions integrity, factory
                                      isolation, buildDbUrl substitution
                                      / default lang / missing placeholder
                                      / null-guard
- tests/default-preferences.test.js — freeze, shape, copy isolation
- tests/sections.test.js           — id order, factory isolation

Plan updates:
- refactor/04: status → ✅ done, all checkboxes ticked, audit table
  (Phase A "audit results") filled in with line numbers and routing decisions
- refactor/README.md: total status for #04 → ✅
- This also ticks the store / utils sections of refactor/03 indirectly
  (the new data/ tests plus existing valid-ip and api-smoke suites).

Verified: npm run check — 46 tests pass, vite build succeeds.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 12:19:19 +08:00

69 lines
1.6 KiB
JavaScript

import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import {
SECTION_IDS,
DEFAULT_SECTION,
createMountingStatus,
createLoadingStatus,
} from '../frontend/data/sections.js';
describe('SECTION_IDS', () => {
it('lists all 6 section DOM ids in render order', () => {
assert.deepEqual(SECTION_IDS, [
'IPInfo',
'Connectivity',
'WebRTC',
'DNSLeakTest',
'SpeedTest',
'AdvancedTools',
]);
});
it('DEFAULT_SECTION is the first entry', () => {
assert.equal(DEFAULT_SECTION, SECTION_IDS[0]);
});
});
describe('createMountingStatus()', () => {
it('returns all 6 mount keys set to false', () => {
const s = createMountingStatus();
assert.deepEqual(s, {
ipcheck: false,
connectivity: false,
webrtc: false,
dnsleaktest: false,
speedtest: false,
advancedtools: false,
});
});
it('returns a fresh object each call', () => {
const a = createMountingStatus();
const b = createMountingStatus();
assert.notEqual(a, b);
a.ipcheck = true;
assert.equal(b.ipcheck, false);
});
});
describe('createLoadingStatus()', () => {
it('returns the 4 loading keys set to false (subset of mounting keys)', () => {
const s = createLoadingStatus();
assert.deepEqual(s, {
ipcheck: false,
connectivity: false,
webrtc: false,
dnsleaktest: false,
});
});
it('returns a fresh object each call', () => {
const a = createLoadingStatus();
const b = createLoadingStatus();
assert.notEqual(a, b);
a.webrtc = true;
assert.equal(b.webrtc, false);
});
});