The fixture's schema entry lived in makedata's schema object (as a second, later key in the same literal) and did not survive the move to createdemodata. saveTable falls back to the file already on the drive, so a reseed looked fine - but CI deletes the appLoc before seeding, and a fresh estate wrote mpe_x_search.json with columns: [], losing the column order the full-table-search spec derives its counts from. Carry the nine columns (name/type/length/format/label/notnull) in createdemodata's schema, and add a case that every fixture table is written with column metadata covering its rows, plus the MPE_X_SEARCH order. It fails against the previous service.
175 lines
5.2 KiB
JavaScript
175 lines
5.2 KiB
JavaScript
/**
|
|
* createdemodata carries the estate the Cypress suite needs but a Data
|
|
* Controller install does not have: the TESTDATA demo library, the deep and
|
|
* wide viewer fixtures and the multi-load library.
|
|
*
|
|
* It runs after makedata, so it must both add those and leave the control
|
|
* library alone otherwise; and it must be safe to run twice, because a reseed
|
|
* runs it twice on the same drive.
|
|
*
|
|
* Run with: node --test sas/mocks/test/
|
|
*/
|
|
const test = require('node:test')
|
|
const assert = require('node:assert')
|
|
const fs = require('node:fs')
|
|
const path = require('node:path')
|
|
|
|
const { seededEstate, runService, readTable } = require('./harness')
|
|
|
|
const FIXTURE_LIBS = ['TESTDATA', 'DC996664']
|
|
|
|
test('the fixtures are added to a makedata estate', () => {
|
|
const estate = seededEstate()
|
|
const data = path.join(estate.appDir, 'data')
|
|
assert.deepEqual(fs.readdirSync(data).sort(), [
|
|
'DC996664',
|
|
'DC_JSLIB',
|
|
'TESTDATA'
|
|
])
|
|
|
|
const tables = readTable(estate, 'MPE_TABLES')
|
|
for (const lib of FIXTURE_LIBS) {
|
|
assert.ok(
|
|
tables.some((row) => String(row.libref).toUpperCase() === lib),
|
|
lib + ' is registered in MPE_TABLES'
|
|
)
|
|
}
|
|
for (const name of ['MPE_X_SEARCH', 'MPE_X_WIDE']) {
|
|
assert.ok(
|
|
tables.some((row) => String(row.dsn).toUpperCase() === name),
|
|
name + ' is registered in MPE_TABLES'
|
|
)
|
|
}
|
|
|
|
assert.equal(readTable(estate, 'MPE_X_SEARCH').length, 1000)
|
|
assert.equal(readTable(estate, 'MPE_X_WIDE').length, 200)
|
|
assert.ok(readTable(estate, 'MPE_DERIVED').length > 0)
|
|
assert.ok(
|
|
readTable(estate, 'MPE_VALIDATIONS').some(
|
|
(row) => String(row.base_lib).toUpperCase() === 'TESTDATA'
|
|
),
|
|
'the TESTDATA rules are present'
|
|
)
|
|
assert.ok(
|
|
fs.existsSync(path.join(data, 'TESTDATA', 'demo_01.json')),
|
|
'the TESTDATA tables are written'
|
|
)
|
|
})
|
|
|
|
test('every fixture table is written with its column metadata', () => {
|
|
// saveTable falls back to the columns of the file already on the drive, and
|
|
// a fresh estate has none - so a fixture with no schema of its own is
|
|
// written with columns: [] and the viewer loses the order it renders.
|
|
const estate = seededEstate()
|
|
const tables = [
|
|
['DC_JSLIB', 'MPE_X_SEARCH'],
|
|
['DC_JSLIB', 'MPE_X_WIDE'],
|
|
['TESTDATA', 'MPE_X_NEW'],
|
|
['TESTDATA', 'DEMO_01'],
|
|
['DC996664', 'MPE_X_TEST']
|
|
]
|
|
for (const [lib, name] of tables) {
|
|
const file = path.join(
|
|
estate.appDir,
|
|
'data',
|
|
lib,
|
|
name.toLowerCase() + '.json'
|
|
)
|
|
const table = JSON.parse(fs.readFileSync(file, 'utf8'))
|
|
assert.ok(table.columns.length > 0, lib + '.' + name + ' has no columns')
|
|
const described = table.columns.map((column) => column.name.toUpperCase())
|
|
for (const field of Object.keys(table.rows[0] || {})) {
|
|
assert.ok(
|
|
described.includes(field.toUpperCase()),
|
|
lib + '.' + name + '.' + field + ' has no column metadata'
|
|
)
|
|
}
|
|
}
|
|
|
|
const search = JSON.parse(
|
|
fs.readFileSync(
|
|
path.join(estate.appDir, 'data', 'DC_JSLIB', 'mpe_x_search.json'),
|
|
'utf8'
|
|
)
|
|
)
|
|
assert.deepEqual(
|
|
search.columns.map((column) => column.name),
|
|
[
|
|
'PRIMARY_KEY_FIELD',
|
|
'SITE_NAME',
|
|
'VESSEL',
|
|
'SAMPLE_COUNT',
|
|
'DEPTH_M',
|
|
'SPECIES',
|
|
'CRUISE_DATE',
|
|
'EXPEDITION_ID',
|
|
'NOTES'
|
|
],
|
|
'the demo column order the search spec derives its counts from'
|
|
)
|
|
})
|
|
|
|
test('a second run does not accumulate rows', () => {
|
|
const estate = seededEstate()
|
|
const counted = () =>
|
|
[
|
|
'MPE_TABLES',
|
|
'MPE_VALIDATIONS',
|
|
'MPE_SELECTBOX',
|
|
'MPE_SECURITY',
|
|
'MPE_DERIVED'
|
|
]
|
|
.map((name) => name + '=' + readTable(estate, name).length)
|
|
.join(' ')
|
|
|
|
const first = counted()
|
|
runService(estate, 'admin/createdemodata', {})
|
|
assert.equal(counted(), first, 'createdemodata must be idempotent')
|
|
})
|
|
|
|
test('a derived row makedata owns survives the fixture rows', () => {
|
|
// MPE_DERIVED is a control table: createdemodata must add its TESTDATA rows
|
|
// without replacing what makedata wrote, or the first real derived rule on
|
|
// the estate would vanish on the next reseed.
|
|
const { writeTable } = require('./harness')
|
|
const estate = seededEstate()
|
|
const owned = {
|
|
tx_from: 0,
|
|
tx_to: 127490111999,
|
|
libref: 'DC_JSLIB',
|
|
dsn: 'MPE_X_TEST',
|
|
var_nm: 'MOCK_OWNED',
|
|
var_logic: 'SOME_NUM * 2',
|
|
var_type: 'N',
|
|
active: 1
|
|
}
|
|
writeTable(estate, 'MPE_DERIVED', readTable(estate, 'MPE_DERIVED').concat([owned]))
|
|
|
|
runService(estate, 'admin/createdemodata', {})
|
|
|
|
const rows = readTable(estate, 'MPE_DERIVED')
|
|
assert.ok(
|
|
rows.some((row) => row.var_nm === 'MOCK_OWNED'),
|
|
'the makedata-owned row is kept'
|
|
)
|
|
assert.equal(
|
|
rows.filter((row) => row.var_nm === 'MOCK_OWNED').length,
|
|
1,
|
|
'and it is not duplicated'
|
|
)
|
|
assert.ok(
|
|
rows.some((row) => String(row.libref).toUpperCase() === 'TESTDATA'),
|
|
'the fixture rows are still added'
|
|
)
|
|
})
|
|
|
|
test('it refuses to run before makedata', () => {
|
|
const { makeEstate } = require('./harness')
|
|
const estate = makeEstate()
|
|
assert.throws(
|
|
() => runService(estate, 'admin/createdemodata', {}),
|
|
/run services\/admin\/makedata first/,
|
|
'a missing control library is reported, not half-created'
|
|
)
|
|
})
|