The parity gate's Cypress job went red after the seed work landed, and the two
causes are the same change seen from the fixture side:
- makedata now carries SAS's demo validation rules for MPE_X_TEST, including the
HARDREGEX on SOME_CHAR that blocks any text but 'the'/'data'. The excel
fixtures upload arbitrary values into that table and expect the submission to
reach the approval screen, so ten excel specs timed out with no Approve
button. createdemodata drops MPE_X_TEST's rules, which is what editor.cy.ts
already documents ("MPE_X_TEST stays clean to match the excel fixtures").
- the LABELs the viewer-labels spec asserts went with the hand-written schema.
createdemodata restores them, because a SAS estate has none and the control
library should not claim otherwise.
Both are declared as fixture divergences in the parity README and asserted in
createdemodata.test.js, so the next change to either side fails a test instead
of a Cypress run.
Review findings:
- the SYSTIMEZONEOFFSET acceptance depended on the host's zone; both entry
points pin TZ=UTC before the harness loads, so the accepted list is the same
everywhere.
- the sas9 mock still published '+0100'; it now answers seconds east of UTC
like the standard estate.
- the README promised an eight-digit id scan that IDENTIFIER_CLASSES no longer
had. A DC-prefixed eight-digit class is back (a plain digit class would fire
on a yyyymmdd date), with a case proving a date is not refused.
80 lines
2.8 KiB
JavaScript
80 lines
2.8 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Replays every recorded golden against a mock estate and prints the
|
|
* differences.
|
|
*
|
|
* node sas/mocks/test/parity/check.js
|
|
* node sas/mocks/test/parity/check.js --scenario public/startupservice
|
|
* node sas/mocks/test/parity/check.js --advisory # report, exit 0
|
|
*
|
|
* This is the human-facing half of the same comparison `test/parity-check.test.js`
|
|
* runs as a gate; both go through `parity/replay.js`, so neither can drift from
|
|
* the other.
|
|
*
|
|
* Both sides are projections, so the values printed here are the placeholders
|
|
* the golden already carries - <LIBREF>, <PATH>, <STAGING_ID> - and a log of a
|
|
* failure is as safe to paste as the golden itself.
|
|
*/
|
|
// The mock derives SYSTIMEZONEOFFSET from the host, and the golden carries the
|
|
// estate's own offset: pin the zone so the accepted difference is the same on
|
|
// every machine, not only on the UTC container the suite usually runs in.
|
|
process.env.TZ = 'UTC'
|
|
const fs = require('fs')
|
|
const path = require('path')
|
|
|
|
const { seededEstate, runService } = require('../harness')
|
|
const { replay } = require('./replay')
|
|
|
|
function arg(name, fallback) {
|
|
const index = process.argv.indexOf('--' + name)
|
|
if (index < 0) return fallback
|
|
const next = process.argv[index + 1]
|
|
return next && next.indexOf('--') !== 0 ? next : true
|
|
}
|
|
|
|
try {
|
|
const only = arg('scenario', null)
|
|
const advisory = arg('advisory', false) === true
|
|
const scenarios = JSON.parse(
|
|
fs.readFileSync(path.join(__dirname, 'scenarios.json'), 'utf8')
|
|
).scenarios.filter(function (scenario) {
|
|
return !only || scenario.id === only || scenario.service === only
|
|
})
|
|
if (!scenarios.length) throw new Error('no scenario matched ' + only)
|
|
|
|
// the golden is recorded against a stock estate (makedata only), so the mock
|
|
// side is built the same way - fixtures would add datasets the golden never saw
|
|
const estate = seededEstate({ demo: false })
|
|
let failed = 0
|
|
|
|
for (const result of replay(estate, runService, scenarios)) {
|
|
const id = result.scenario.service + '/' + result.scenario.id
|
|
if (!result.golden) {
|
|
console.log('SKIP ' + id + ' - no golden')
|
|
continue
|
|
}
|
|
if (result.unexpected.length || result.stale.length) {
|
|
console.log(
|
|
'DIFF ' + id + ' - ' + result.unexpected.length +
|
|
' unaccepted, ' + result.stale.length + ' stale acceptance(s)'
|
|
)
|
|
for (const difference of result.unexpected.slice(0, 40)) {
|
|
console.log(' ' + difference)
|
|
}
|
|
for (const stale of result.stale) {
|
|
console.log(' ' + stale + ': accepted, but no longer differs')
|
|
}
|
|
failed++
|
|
continue
|
|
}
|
|
console.log(
|
|
'ok ' + id + ' (' + result.accepted.length + ' accepted difference(s))'
|
|
)
|
|
}
|
|
|
|
if (failed && !advisory) process.exitCode = 1
|
|
} catch (err) {
|
|
console.error(err.message)
|
|
process.exitCode = 1
|
|
}
|