fix(demo): seed NPC profiles, factions and chat styles (DM26)
The demo's first restored wipes brought the default set's groups and permissions back, but not its NPCs or chat titles. The restored rig's RunicNPC says it is already managed (by the site before this one), so the fresh site adopts nothing (D244) and its first push empties the profiles; the placements then wait on missing profiles. The import never adopts a group's chat style either. onDemoSeed now also takes: - npcs.factions: the faction table, through the NPC model's setFactions; - npcs.profiles: each profile through the model's create/update, so it is checked exactly as the admin page checks it (an existing one is updated); - chat: a BetterChat style per server and group, the defaults filled in. A group the rig's import has not brought in yet is created for that server, and the import then adopts the rig's title, rank and permissions into it. The section's new parts are checked before anything is written. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
@@ -375,6 +375,76 @@ test('a re-seed leaves a link the right owner holds, and moves one held by someo
|
||||
assert.deepEqual(writes, ['DELETE', 'INSERT'])
|
||||
})
|
||||
|
||||
// ── NPCs and chat styles from the seed (DM26) ──────────────────────────────
|
||||
|
||||
const NPC_SECTION = {
|
||||
npcs: {
|
||||
factions: [{ a: 'bandits', b: 'guards', relation: 'allied' }],
|
||||
profiles: [
|
||||
{ name: 'bandit', servers: ['main'], body: { kits: ['rnpc_raider'], role: 'roamer' } },
|
||||
{ name: 'guard', servers: ['main'], body: { kits: ['rnpc_campguard'], role: 'sentry' } },
|
||||
],
|
||||
},
|
||||
chat: [
|
||||
{ serverId: 'main', group: 'vip', style: { Title: '[VIP]', TitleColor: '#ffaa00' } },
|
||||
{ serverId: 'main', group: 'moderator', style: { Title: '[MOD]' } },
|
||||
],
|
||||
}
|
||||
|
||||
/** Stubs the models the seed writes NPCs and chat styles through; returns the calls. */
|
||||
function stubSeedModels({ profiles = [], groups = {} } = {}) {
|
||||
const calls = []
|
||||
const npcs = require('../model/npcs/npcs.model')
|
||||
const npcsDb = require('../model/npcs/npcs.db')
|
||||
const apply = require('../model/permissions/permissions.apply')
|
||||
const permDb = require('../model/permissions/permissions.db')
|
||||
npcs.setFactions = async (f) => calls.push(['setFactions', f])
|
||||
npcs.create = async (input) => calls.push(['create', input.name, input.servers])
|
||||
npcs.update = async (id, input) => calls.push(['update', id, input.name])
|
||||
npcsDb.listProfiles = async () => profiles
|
||||
apply.groupOn = async (name) => groups[name] || null
|
||||
permDb.insertGroup = async ({ name }) => {
|
||||
calls.push(['insertGroup', name])
|
||||
return 50
|
||||
}
|
||||
permDb.setGroupServers = async (id, s) => calls.push(['setGroupServers', id, s.servers])
|
||||
permDb.setGroupChat = async (id, style) => calls.push(['setGroupChat', id, style.Title, style.TitleColor, Object.keys(style).length])
|
||||
permDb.markDirty = async (scope) => calls.push(['markDirty', scope])
|
||||
return calls
|
||||
}
|
||||
|
||||
test('the NPC and chat parts of the seed section are checked before anything is written', async () => {
|
||||
withCore()
|
||||
const seed = require('../demoSeed')
|
||||
assert.deepEqual(seed.checkSection(NPC_SECTION, {}), [])
|
||||
const problems = seed.checkSection({
|
||||
npcs: { factions: [{ a: 'scientists', b: 'animals', relation: 'hostile' }], profiles: [{ name: 'Bad Name', body: [] }] },
|
||||
chat: [{ serverId: 'Main', group: '', style: { Title: '[VIP]', Nope: 1 } }],
|
||||
}, {})
|
||||
assert.equal(problems.length, 6, problems.join(' | '))
|
||||
assert.deepEqual(seed.checkSection({ npcs: [] }, {}), ['modules.rust.npcs must be an object'])
|
||||
const calls = stubSeedModels()
|
||||
await assert.rejects(seed.onDemoSeed({ chat: [{ serverId: 'main', group: 'vip', style: { Priority: 'x' } }] }, { accounts: {} }), /style/)
|
||||
assert.deepEqual(calls, [])
|
||||
})
|
||||
|
||||
test('the seed sets the faction table, saves each profile, and styles each group', async () => {
|
||||
withCore()
|
||||
const calls = stubSeedModels({ profiles: [{ id: 7, name: 'bandit', replaced: false }], groups: { vip: { id: 13 } } })
|
||||
await require('../demoSeed').onDemoSeed(NPC_SECTION, { accounts: {} })
|
||||
assert.deepEqual(calls, [
|
||||
['setFactions', NPC_SECTION.npcs.factions],
|
||||
['update', 7, 'bandit'], // already there: updated, not created twice
|
||||
['create', 'guard', ['main']],
|
||||
['setGroupChat', 13, '[VIP]', '#ffaa00', 12], // all twelve fields, the defaults filled in
|
||||
['markDirty', 'main'],
|
||||
['insertGroup', 'moderator'], // the rig's import has not brought it in yet
|
||||
['setGroupServers', 50, ['main']],
|
||||
['setGroupChat', 50, '[MOD]', '#55aaff', 12],
|
||||
['markDirty', 'main'],
|
||||
])
|
||||
})
|
||||
|
||||
// ── The manifest (§3.2) ────────────────────────────────────────────────────
|
||||
|
||||
test('module.json locks the two link routes and needs a core that asks demoRefuses', () => {
|
||||
|
||||
Reference in New Issue
Block a user