355 lines
24 KiB
JavaScript
355 lines
24 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { readFile } from 'node:fs/promises';
|
|
import test from 'node:test';
|
|
import { Sequelize, DataTypes } from 'sequelize';
|
|
import migration from '../migrations-active/20261104000000-add-character-development-ages.cjs';
|
|
import { getCharacterDevelopment, hasReachedFertility } from '../utils/falukant/characterDevelopment.js';
|
|
import { buildPartnerCandidateQuery } from '../utils/falukant/partnerCandidates.js';
|
|
|
|
test('development follows each character, independently of the marriage age', () => {
|
|
const early = { pubertyStartAge: 10, fertileFromAge: 13 };
|
|
const late = { pubertyStartAge: 13, fertileFromAge: 16 };
|
|
assert.equal(hasReachedFertility(early, 12), false);
|
|
assert.equal(hasReachedFertility(early, 13), true);
|
|
assert.equal(hasReachedFertility(late, 14), false);
|
|
assert.equal(hasReachedFertility(late, 16), true);
|
|
assert.deepEqual(getCharacterDevelopment(early, 11), {
|
|
...early, hasReachedPuberty: true, hasReachedFertility: false,
|
|
});
|
|
for (const missing of [null, {}, { fertileFromAge: null }, { fertileFromAge: 0 }]) {
|
|
assert.equal(hasReachedFertility(missing, 30), false);
|
|
}
|
|
assert.equal(getCharacterDevelopment(early, null).hasReachedPuberty, false);
|
|
});
|
|
|
|
// Only an explicitly provided, disposable test database may be used.
|
|
// DAEMON_SQL_PATH additionally exercises the actual Rust SQL against PostgreSQL.
|
|
test('database migration, persistence and daemon conception paths', {
|
|
skip: !process.env.TEST_DATABASE_URL,
|
|
}, async (t) => {
|
|
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;
|
|
DROP SCHEMA IF EXISTS falukant_type CASCADE;
|
|
CREATE SCHEMA falukant_data;
|
|
CREATE SCHEMA falukant_type;
|
|
CREATE TABLE falukant_data.character (
|
|
id SERIAL PRIMARY KEY, gender TEXT, birthdate TIMESTAMPTZ DEFAULT NOW(),
|
|
user_id INT, title_of_nobility INT DEFAULT 1, last_name INT DEFAULT 1,
|
|
region_id INT DEFAULT 1, health INT DEFAULT 100,
|
|
pregnancy_due_at TIMESTAMPTZ, pregnancy_father_character_id INT,
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
INSERT INTO falukant_data.character (gender, pregnancy_due_at)
|
|
VALUES ('female', NOW() + INTERVAL '1 hour'), ('male', NULL);
|
|
`);
|
|
const qi = db.getQueryInterface();
|
|
await migration.up(qi);
|
|
const [before] = await db.query('SELECT * FROM falukant_data.character ORDER BY id');
|
|
assert.ok(before[0].pregnancy_due_at);
|
|
assert.equal(before[0].puberty_start_age >= 8, true);
|
|
assert.equal(before[0].fertile_from_age > before[0].puberty_start_age, true);
|
|
await db.query("UPDATE falukant_data.character SET health = 99, puberty_start_age = NULL, fertile_from_age = NULL");
|
|
const [after] = await db.query('SELECT * FROM falukant_data.character ORDER BY id');
|
|
assert.deepEqual(after.map(c => [c.puberty_start_age, c.fertile_from_age]),
|
|
before.map(c => [c.puberty_start_age, c.fertile_from_age]));
|
|
assert.deepEqual(after[0].pregnancy_due_at, before[0].pregnancy_due_at);
|
|
|
|
// Raw inserts represent newborns/NPCs created outside Sequelize.
|
|
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`);
|
|
const [[stats]] = await db.query(`SELECT
|
|
count(DISTINCT puberty_start_age)::int AS starts,
|
|
count(DISTINCT fertile_from_age)::int AS fertile,
|
|
count(*) FILTER (WHERE fertile_from_age <= puberty_start_age)::int AS invalid
|
|
FROM falukant_data.character`);
|
|
assert.ok(stats.starts > 1 && stats.fertile > 1);
|
|
assert.equal(stats.invalid, 0);
|
|
await assert.rejects(db.query(`INSERT INTO falukant_data.character
|
|
(puberty_start_age, fertile_from_age) VALUES (12, 11)`));
|
|
|
|
await t.test('partner candidates have a minimum age without age-gap or creation-age restrictions', async () => {
|
|
const [inserted] = await db.query(`INSERT INTO falukant_data.character (gender, birthdate)
|
|
VALUES ('male', CURRENT_DATE - INTERVAL '65 days'),
|
|
('male', CURRENT_DATE - INTERVAL '10 days' + INTERVAL '12 hours'),
|
|
('male', CURRENT_DATE - INTERVAL '9 days')
|
|
RETURNING id`);
|
|
const Candidate = db.define('DevelopmentPartnerCandidate', {
|
|
id: { type: DataTypes.INTEGER, primaryKey: true },
|
|
gender: DataTypes.STRING,
|
|
birthdate: DataTypes.DATE,
|
|
regionId: { type: DataTypes.INTEGER, field: 'region_id' },
|
|
titleOfNobility: { type: DataTypes.INTEGER, field: 'title_of_nobility' },
|
|
}, { schema: 'falukant_data', tableName: 'character', timestamps: false });
|
|
const rows = await Candidate.findAll(buildPartnerCandidateQuery({
|
|
characterId: 1, gender: 'female', regionId: 1, titleId: 1, minimumAge: 10,
|
|
}));
|
|
assert.deepEqual(rows.map(c => c.id).sort((a, b) => a - b), [inserted[0].id, inserted[1].id]);
|
|
});
|
|
|
|
await t.test('repeating the migration preserves all existing character data', async () => {
|
|
const [saved] = await db.query('SELECT * FROM falukant_data.character ORDER BY id');
|
|
await migration.up(qi);
|
|
const [repeated] = await db.query('SELECT * FROM falukant_data.character ORDER BY id');
|
|
assert.deepEqual(repeated, saved);
|
|
});
|
|
|
|
for (const bothColumns of [true, false]) {
|
|
await t.test(`manually prepared schema with ${bothColumns ? 'both columns' : 'one column'}`, async () => {
|
|
await migration.down(qi);
|
|
await db.query(`ALTER TABLE falukant_data.character ADD COLUMN puberty_start_age SMALLINT`);
|
|
if (bothColumns) {
|
|
await db.query(`ALTER TABLE falukant_data.character ADD COLUMN fertile_from_age SMALLINT;
|
|
UPDATE falukant_data.character SET fertile_from_age = 13 WHERE id = 1`);
|
|
}
|
|
await db.query(`UPDATE falukant_data.character SET puberty_start_age = 10 WHERE id = 1`);
|
|
await migration.up(qi);
|
|
const [characters] = await db.query('SELECT * FROM falukant_data.character ORDER BY id');
|
|
assert.equal(characters[0].puberty_start_age, 10);
|
|
if (bothColumns) assert.equal(characters[0].fertile_from_age, 13);
|
|
assert.deepEqual(characters[0].pregnancy_due_at, before[0].pregnancy_due_at);
|
|
assert.ok(characters.every(c => c.fertile_from_age > c.puberty_start_age));
|
|
});
|
|
}
|
|
|
|
await t.test('daemon checks both parents and preserves already scheduled births', {
|
|
skip: !process.env.DAEMON_SQL_PATH,
|
|
}, async (t) => {
|
|
const source = await readFile(process.env.DAEMON_SQL_PATH, 'utf8');
|
|
const sql = (name, randomRoll = 0) => {
|
|
const match = source.match(new RegExp(`pub const ${name}: &str = r#"([\\s\\S]*?)"#;`));
|
|
assert.ok(match, name);
|
|
// Remove chance from these eligibility tests only.
|
|
return match[1].replaceAll('random()', `${randomRoll}::double precision`);
|
|
};
|
|
await db.query(`
|
|
TRUNCATE falukant_data.character RESTART IDENTITY;
|
|
CREATE TABLE falukant_type.relationship (id INT PRIMARY KEY, tr TEXT);
|
|
INSERT INTO falukant_type.relationship VALUES (1, 'married'), (2, 'lover'), (3, 'engaged'), (4, 'wooing');
|
|
CREATE TABLE falukant_data.relationship (
|
|
id INT PRIMARY KEY, character1_id INT, character2_id INT,
|
|
relationship_type_id INT, marriage_pregnancy_due_at TIMESTAMPTZ
|
|
);
|
|
CREATE TABLE falukant_data.falukant_user (id INT PRIMARY KEY, user_id INT);
|
|
CREATE TABLE falukant_data.child_relation (
|
|
father_character_id INT, mother_character_id INT, child_character_id INT,
|
|
name_set BOOLEAN, legitimacy TEXT, birth_context TEXT, public_known BOOLEAN,
|
|
created_at TIMESTAMPTZ, updated_at TIMESTAMPTZ
|
|
);
|
|
CREATE TABLE falukant_data.relationship_state (
|
|
relationship_id INT, active BOOLEAN, affection INT, maintenance_level INT,
|
|
last_monthly_processed_at TIMESTAMPTZ, lover_role TEXT, visibility INT
|
|
);
|
|
INSERT INTO falukant_data.character
|
|
(gender, birthdate, puberty_start_age, fertile_from_age)
|
|
VALUES ('female', CURRENT_DATE - INTERVAL '13 days', 10, 13),
|
|
('male', CURRENT_DATE - INTERVAL '13 days', 10, 13);
|
|
INSERT INTO falukant_data.relationship VALUES (1, 1, 2, 1, NULL);
|
|
INSERT INTO falukant_data.relationship_state VALUES (1, true, 80, 50, NOW(), 'lover', 20);
|
|
`);
|
|
for (const [queryName, type] of [
|
|
['QUERY_TRY_MARRIAGE_CONCEPTION_UPDATE', 1],
|
|
['QUERY_GET_LEGACY_MARRIAGE_INSTANT_PREGNANCY_CANDIDATES', 1],
|
|
['QUERY_GET_LOVER_PREGNANCY_CANDIDATES', 2],
|
|
['QUERY_GET_LOVER_PREGNANCY_CANDIDATES', 3],
|
|
]) {
|
|
for (const [motherAge, fatherAge, eligible] of [[13, 13, true], [12, 13, false], [13, 12, false]]) {
|
|
await db.query(`UPDATE falukant_data.character SET birthdate = CURRENT_DATE -
|
|
(CASE WHEN id = 1 THEN :motherAge ELSE :fatherAge END) * INTERVAL '1 day',
|
|
pregnancy_due_at = NULL;
|
|
UPDATE falukant_data.relationship SET relationship_type_id = :type,
|
|
marriage_pregnancy_due_at = NULL`, {
|
|
replacements: { motherAge, fatherAge, type },
|
|
});
|
|
const [rows] = await db.query(sql(queryName));
|
|
if (queryName === 'QUERY_TRY_MARRIAGE_CONCEPTION_UPDATE') {
|
|
const [[relationship]] = await db.query('SELECT marriage_pregnancy_due_at FROM falukant_data.relationship');
|
|
assert.equal(relationship.marriage_pregnancy_due_at != null, eligible, `${queryName}: ${motherAge}/${fatherAge}`);
|
|
} else {
|
|
assert.equal(rows.length > 0, eligible, `${queryName}: ${motherAge}/${fatherAge}`);
|
|
}
|
|
}
|
|
}
|
|
await t.test('marriage, engagement and every lover role use exactly fifty percent', async () => {
|
|
for (const [name, type, role] of [
|
|
['QUERY_TRY_MARRIAGE_CONCEPTION_UPDATE', 1, null],
|
|
['QUERY_GET_LEGACY_MARRIAGE_INSTANT_PREGNANCY_CANDIDATES', 1, null],
|
|
['QUERY_GET_LOVER_PREGNANCY_CANDIDATES', 3, null],
|
|
...['secret_affair', 'lover', 'mistress_or_favorite'].map(role => ['QUERY_GET_LOVER_PREGNANCY_CANDIDATES', 2, role]),
|
|
]) {
|
|
for (const [roll, expected] of [[0.499, true], [0.5, false], [0.99, false]]) {
|
|
await db.query(`UPDATE falukant_data.character SET birthdate = CURRENT_DATE - INTERVAL '20 days', pregnancy_due_at = NULL;
|
|
UPDATE falukant_data.relationship SET relationship_type_id = :type, marriage_pregnancy_due_at = NULL;
|
|
UPDATE falukant_data.relationship_state SET lover_role = :role, affection = 80, visibility = 80`, {
|
|
replacements: { type, role },
|
|
});
|
|
const [rows] = await db.query(sql(name, roll));
|
|
if (name === 'QUERY_TRY_MARRIAGE_CONCEPTION_UPDATE') {
|
|
const [[row]] = await db.query('SELECT marriage_pregnancy_due_at FROM falukant_data.relationship');
|
|
assert.equal(row.marriage_pregnancy_due_at != null, expected, `${name}/${role}/${roll}`);
|
|
} else {
|
|
assert.equal(rows.length > 0, expected, `${name}/${role}/${roll}`);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
await t.test('engaged couples need no lover maintenance and retain their relationship', async () => {
|
|
const candidates = () => db.query(sql('QUERY_GET_LOVER_PREGNANCY_CANDIDATES')).then(([rows]) => rows);
|
|
await db.query(`UPDATE falukant_data.character SET birthdate = CURRENT_DATE - INTERVAL '13 days',
|
|
pregnancy_due_at = NULL, health = 100;
|
|
UPDATE falukant_data.relationship SET relationship_type_id = 3, marriage_pregnancy_due_at = NULL;
|
|
UPDATE falukant_data.relationship_state SET affection = 50, lover_role = NULL,
|
|
maintenance_level = 0, last_monthly_processed_at = NULL`);
|
|
let rows = await candidates();
|
|
assert.equal(rows.length, 1);
|
|
assert.equal(rows[0].relationship_type, 'engaged');
|
|
assert.equal(rows[0].mother_cid, 1);
|
|
assert.equal(rows[0].father_cid, 2);
|
|
// Selection and conception must work for either partner as the player.
|
|
await db.query('INSERT INTO falukant_data.falukant_user VALUES (10, 100)');
|
|
for (const playerId of [1, 2]) {
|
|
await db.query('UPDATE falukant_data.character SET user_id = CASE WHEN id = :id THEN 10 ELSE NULL END', {
|
|
replacements: { id: playerId },
|
|
});
|
|
rows = await candidates();
|
|
assert.equal(rows.length, 1);
|
|
assert.equal(rows[0][playerId === 1 ? 'mother_uid' : 'father_uid'], 10);
|
|
}
|
|
await db.query('UPDATE falukant_data.relationship SET character1_id = 2, character2_id = 1');
|
|
rows = await candidates();
|
|
assert.equal(rows[0].mother_cid, 1);
|
|
assert.equal(rows[0].father_cid, 2);
|
|
|
|
for (const id of [1, 2]) {
|
|
await db.query('UPDATE falukant_data.character SET health = 0 WHERE id = :id', { replacements: { id } });
|
|
assert.equal((await candidates()).length, 0);
|
|
await db.query('UPDATE falukant_data.character SET health = 100');
|
|
}
|
|
await db.query('UPDATE falukant_data.relationship_state SET active = false');
|
|
assert.equal((await candidates()).length, 0);
|
|
await db.query('UPDATE falukant_data.relationship_state SET active = true, affection = 44');
|
|
assert.equal((await candidates()).length, 0);
|
|
await db.query('DELETE FROM falukant_data.relationship_state');
|
|
assert.equal((await candidates()).length, 1);
|
|
for (const type of [1, 2, 4]) {
|
|
await db.query('UPDATE falukant_data.relationship SET relationship_type_id = :type', { replacements: { type } });
|
|
assert.equal((await candidates()).length, 0);
|
|
}
|
|
await db.query('UPDATE falukant_data.relationship SET relationship_type_id = 3');
|
|
await db.query(sql('QUERY_SET_CHARACTER_PREGNANCY_FROM_LOVER'), { bind: [1, 2] });
|
|
assert.equal((await candidates()).length, 0, 'Existing pregnancy blocks another conception');
|
|
const [[pregnancy]] = await db.query('SELECT pregnancy_due_at, pregnancy_father_character_id FROM falukant_data.character WHERE id = 1');
|
|
assert.equal(pregnancy.pregnancy_father_character_id, 2);
|
|
assert.ok(pregnancy.pregnancy_due_at > new Date());
|
|
const [notDue] = await db.query(sql('QUERY_GET_PLANNED_CHARACTER_BIRTH_DELIVERIES'));
|
|
assert.equal(notDue.length, 0);
|
|
await db.query("UPDATE falukant_data.character SET pregnancy_due_at = NOW() - INTERVAL '1 hour' WHERE id = 1");
|
|
for (const [type, context] of [[3, 'lover'], [1, 'marriage']]) {
|
|
await db.query('UPDATE falukant_data.relationship SET relationship_type_id = :type', { replacements: { type } });
|
|
const [births] = await db.query(sql('QUERY_GET_PLANNED_CHARACTER_BIRTH_DELIVERIES'));
|
|
assert.equal(births.length, 1);
|
|
assert.equal(births[0].birth_context, context);
|
|
const [[stillPregnant]] = await db.query('SELECT pregnancy_father_character_id FROM falukant_data.character WHERE id = 1');
|
|
assert.equal(stillPregnant.pregnancy_father_character_id, 2);
|
|
}
|
|
await db.query('UPDATE falukant_data.relationship SET relationship_type_id = 3');
|
|
await db.query(sql('QUERY_INSERT_CHILD_RELATION_PLANNED_BIRTH'), { bind: [2, 1, 3, 'lover'] });
|
|
const [[child]] = await db.query('SELECT legitimacy, birth_context, public_known FROM falukant_data.child_relation');
|
|
assert.deepEqual(child, { legitimacy: 'hidden_bastard', birth_context: 'lover', public_known: false });
|
|
const [[relationship]] = await db.query('SELECT relationship_type_id FROM falukant_data.relationship');
|
|
assert.equal(relationship.relationship_type_id, 3);
|
|
await db.query('DELETE FROM falukant_data.child_relation');
|
|
});
|
|
await db.query(`UPDATE falukant_data.relationship SET marriage_pregnancy_due_at = NULL`);
|
|
for (const [motherAge, fatherAge, eligible] of [[12, 13, false], [13, 12, false], [13, 13, true]]) {
|
|
await db.query(`UPDATE falukant_data.character SET birthdate = CURRENT_DATE -
|
|
(CASE WHEN id = 1 THEN :motherAge ELSE :fatherAge END) * INTERVAL '1 day',
|
|
pregnancy_due_at = NULL`, { replacements: { motherAge, fatherAge } });
|
|
const [rows] = await db.query(sql('QUERY_SET_CHARACTER_PREGNANCY_FROM_LOVER'), { bind: [1, 2] });
|
|
assert.equal(rows.length > 0, eligible);
|
|
}
|
|
// A backfilled threshold must not cancel an existing marriage pregnancy.
|
|
await db.query(`UPDATE falukant_data.character SET fertile_from_age = 17, pregnancy_due_at = NULL;
|
|
UPDATE falukant_data.relationship SET relationship_type_id = 1,
|
|
marriage_pregnancy_due_at = NOW() - INTERVAL '1 hour'`);
|
|
const [births] = await db.query(sql('QUERY_GET_MARRIAGE_BIRTH_DELIVERIES'));
|
|
assert.equal(births.length, 1);
|
|
|
|
await t.test('a married mother can conceive with a lover and keeps the correct father', async () => {
|
|
await db.query(`
|
|
UPDATE falukant_data.character SET birthdate = CURRENT_DATE - INTERVAL '20 days',
|
|
fertile_from_age = 13, pregnancy_due_at = NULL;
|
|
INSERT INTO falukant_data.character (gender, birthdate, puberty_start_age, fertile_from_age)
|
|
VALUES ('male', CURRENT_DATE - INTERVAL '24 days', 10, 13);
|
|
UPDATE falukant_data.relationship SET relationship_type_id = 2, marriage_pregnancy_due_at = NULL;
|
|
INSERT INTO falukant_data.relationship VALUES (2, 1, 3, 1, NULL);
|
|
INSERT INTO falukant_data.relationship_state VALUES (1, true, 80, 50, NOW(), 'lover', 20);
|
|
`);
|
|
const [candidates] = await db.query(sql('QUERY_GET_LOVER_PREGNANCY_CANDIDATES'));
|
|
assert.equal(candidates.length, 1);
|
|
assert.equal(candidates[0].father_cid, 2);
|
|
// An already pending marital pregnancy blocks the same mother.
|
|
await db.query("UPDATE falukant_data.relationship SET marriage_pregnancy_due_at = NOW() + INTERVAL '18 hours' WHERE id = 2");
|
|
const [blocked] = await db.query(sql('QUERY_GET_LOVER_PREGNANCY_CANDIDATES'));
|
|
assert.equal(blocked.length, 0);
|
|
await db.query('UPDATE falukant_data.relationship SET marriage_pregnancy_due_at = NULL WHERE id = 2');
|
|
await db.query(sql('QUERY_SET_CHARACTER_PREGNANCY_FROM_LOVER'), { bind: [1, 2] });
|
|
await db.query(sql('QUERY_TRY_MARRIAGE_CONCEPTION_UPDATE'));
|
|
const [[marriage]] = await db.query('SELECT marriage_pregnancy_due_at FROM falukant_data.relationship WHERE id = 2');
|
|
assert.equal(marriage.marriage_pregnancy_due_at, null);
|
|
await db.query("UPDATE falukant_data.character SET pregnancy_due_at = NOW() - INTERVAL '1 hour' WHERE id = 1");
|
|
const [deliveries] = await db.query(sql('QUERY_GET_PLANNED_CHARACTER_BIRTH_DELIVERIES'));
|
|
assert.equal(deliveries.length, 1);
|
|
assert.equal(deliveries[0].father_cid, 2);
|
|
assert.equal(deliveries[0].birth_context, 'lover');
|
|
await db.query(sql('QUERY_INSERT_CHILD_RELATION_PLANNED_BIRTH'), { bind: [2, 1, 4, deliveries[0].birth_context] });
|
|
const [[child]] = await db.query('SELECT father_character_id, mother_character_id, birth_context FROM falukant_data.child_relation');
|
|
assert.deepEqual(child, { father_character_id: 2, mother_character_id: 1, birth_context: 'lover' });
|
|
});
|
|
|
|
await t.test('lover upkeep and penalties use game years rather than real years', async () => {
|
|
await db.query(`
|
|
ALTER TABLE falukant_data.character ADD COLUMN reputation INT DEFAULT 50;
|
|
ALTER TABLE falukant_data.relationship_state
|
|
ADD COLUMN discretion INT DEFAULT 50,
|
|
ADD COLUMN status_fit INT DEFAULT 0,
|
|
ADD COLUMN monthly_base_cost INT DEFAULT 30,
|
|
ADD COLUMN months_underfunded INT DEFAULT 0,
|
|
ADD COLUMN last_daily_processed_at TIMESTAMPTZ,
|
|
ADD COLUMN lover_last_installment_at TIMESTAMPTZ;
|
|
UPDATE falukant_data.relationship_state SET last_monthly_processed_at = NULL;
|
|
CREATE TABLE falukant_type.title (id INT PRIMARY KEY, tr TEXT);
|
|
INSERT INTO falukant_type.title VALUES (1, 'civil');
|
|
CREATE TABLE falukant_data.user_house (user_id INT, servant_discretion_modifier INT);
|
|
`);
|
|
for (const [motherAge, fatherAge, youngerAge] of [[20, 34, 20], [35, 16, 16]]) {
|
|
await db.query(`UPDATE falukant_data.character SET birthdate = CURRENT_DATE -
|
|
(CASE WHEN id = 1 THEN :motherAge ELSE :fatherAge END) * INTERVAL '1 day'`, {
|
|
replacements: { motherAge, fatherAge },
|
|
});
|
|
for (const name of [
|
|
'QUERY_GET_ACTIVE_LOVER_ROWS_FOR_DAILY',
|
|
'QUERY_GET_ACTIVE_LOVER_ROWS_FOR_MONTHLY',
|
|
'QUERY_GET_ACTIVE_LOVER_ROWS_FOR_INSTALLMENT',
|
|
]) {
|
|
const [rows] = await db.query(sql(name));
|
|
assert.equal(rows.length, 1, name);
|
|
assert.equal(rows[0].min_age_years, youngerAge, name);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
await migration.down(qi);
|
|
const [[columns]] = await db.query(`SELECT count(*)::int AS count FROM information_schema.columns
|
|
WHERE table_schema = 'falukant_data' AND table_name = 'character'
|
|
AND column_name IN ('puberty_start_age', 'fertile_from_age')`);
|
|
assert.equal(columns.count, 0);
|
|
} finally {
|
|
await db.close();
|
|
}
|
|
});
|