Files
yourpart3/backend/tools/characterAppearance.test.mjs
Torsten Schulz (local) bc7a0cb67a
All checks were successful
Deploy to production / deploy (push) Successful in 2m24s
Speichere individuelle Haar- und Augenfarben je Charakter
2026-11-04 16:54:33 +01:00

82 lines
4.7 KiB
JavaScript

import assert from 'node:assert/strict';
import test from 'node:test';
import { Sequelize, DataTypes } from 'sequelize';
import migration from '../migrations-active/20261104000001-add-character-appearance.cjs';
import developmentMigration from '../migrations-active/20261104000000-add-character-development-ages.cjs';
// Only the explicitly supplied disposable database may be changed.
test('appearance migration persists colors for existing characters, Sequelize and raw daemon inserts', {
skip: !process.env.TEST_DATABASE_URL,
}, async () => {
const db = new Sequelize(process.env.TEST_DATABASE_URL, { logging: false });
try {
const [[{ name }]] = await db.query('SELECT current_database() AS name');
assert.equal(name, 'yourpart_development_test', 'Use the isolated development test database');
await db.query(`
DROP SCHEMA IF EXISTS falukant_data CASCADE;
CREATE SCHEMA falukant_data;
CREATE TABLE falukant_data.character (
id SERIAL PRIMARY KEY, gender TEXT, health INT DEFAULT 100,
hair_color VARCHAR(7), updated_at TIMESTAMPTZ DEFAULT NOW()
);
INSERT INTO falukant_data.character (gender, hair_color)
VALUES ('female', '#AbC123'), ('male', NULL);
`);
const qi = db.getQueryInterface();
await developmentMigration.up(qi);
const [developmentBefore] = await db.query('SELECT id, health, puberty_start_age, fertile_from_age, updated_at FROM falukant_data.character ORDER BY id');
await migration.up(qi);
const [developmentAfter] = await db.query('SELECT id, health, puberty_start_age, fertile_from_age, updated_at FROM falukant_data.character ORDER BY id');
assert.deepEqual(developmentAfter, developmentBefore, 'Existing character development remains intact');
const [before] = await db.query('SELECT * FROM falukant_data.character ORDER BY id');
assert.equal(before[0].hair_color, '#AbC123', 'Keep manually prepared values');
for (const row of before) {
assert.match(row.hair_color, /^#[0-9a-fA-F]{6}$/);
assert.match(row.eye_color, /^#[0-9a-fA-F]{6}$/);
}
await migration.up(qi);
await db.query(`UPDATE falukant_data.character SET hair_color = NULL, eye_color = NULL`);
const [after] = await db.query('SELECT * FROM falukant_data.character ORDER BY id');
assert.deepEqual(after, before, 'Repeated migrations and omitted colors keep existing assignments');
// NPCs and newborns created with raw Rust SQL also get stable colors.
const [generated] = await db.query(`INSERT INTO falukant_data.character (gender)
SELECT CASE WHEN i % 2 = 0 THEN 'female' ELSE 'male' END
FROM generate_series(1, 1000) i RETURNING hair_color, eye_color`);
assert.equal(new Set(generated.map(c => c.hair_color)).size, 7);
assert.equal(new Set(generated.map(c => c.eye_color)).size, 6);
assert.ok(generated.every(c => /^#[0-9a-fA-F]{6}$/.test(c.hair_color) && /^#[0-9a-fA-F]{6}$/.test(c.eye_color)));
const Character = db.define('AppearanceTestCharacter', {
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
gender: DataTypes.STRING,
hairColor: { type: DataTypes.STRING(7), field: 'hair_color' },
eyeColor: { type: DataTypes.STRING(7), field: 'eye_color' },
}, { schema: 'falukant_data', tableName: 'character', timestamps: false });
const character = await Character.create({ gender: 'female', eyeColor: '#123456' });
assert.match(character.hairColor, /^#[0-9a-fA-F]{6}$/);
assert.equal(character.eyeColor, '#123456');
const assigned = character.hairColor;
await character.update({ gender: 'male' });
await character.reload();
assert.equal(character.hairColor, assigned);
await character.update({ hairColor: '#654321' });
await character.reload();
assert.equal(character.hairColor, '#654321');
assert.equal(character.eyeColor, '#123456');
for (const color of ['red', '#fff', '#12345z', '']) {
await assert.rejects(db.query('UPDATE falukant_data.character SET eye_color = :color WHERE id = 1', {
replacements: { color },
}));
}
const [[{ count: oldCount }]] = await db.query('SELECT count(*)::int FROM falukant_data.character');
await migration.down(qi);
const [[{ count: newCount }]] = await db.query('SELECT count(*)::int FROM falukant_data.character');
assert.equal(newCount, oldCount, 'Rollback retains characters');
await migration.up(qi);
} finally {
await db.close();
}
});