Files
dc/sas/mocks/test/getdata-rules.test.js
T
dc f32027fe59
Build / Build-and-ng-test (pull_request) Successful in 3m50s
Lighthouse Checks / lighthouse (pull_request) Successful in 10m2s
Build / Build-and-test-development (pull_request) Failing after 34m37s
fix(mocks): read the control rows as they are stored, and say what is gated
Nine findings from review, all taken.

Row reads (getdata):
- approversForTable reads every column through field(): the security and group
  rows are seeded with UPPERCASE keys and an edited row comes back lower-cased,
  so a direct property read compared undefined with 'UNDEFINED' and found no
  grant - silently falling back to the admin group for every table.
- tx_to is handled by rowInForce(): epoch seconds, which is what Date.now()/1000
  assumes, with an ISO string accepted; a blank, absent or unparseable end date
  is open-ended rather than expired, so a rule or a grant that omits it is no
  longer dropped as NaN. The dqrules filter reads rule_active/base_lib/base_ds
  through field() for the same reason.

Rows and the text that describes them (getdata):
- the current-rows clause in FILTER_TEXT is now applied to the selection: the
  grid no longer shows expired rows while telling the user they were excluded.
- the primary-key sort resolves each key to the column's own casing, so a
  lowercase DDL sorts on real values instead of comparing undefined.

Settings (getdata, viewlibs):
- dcLibref falls back to 'DC_JSLIB' like dcAdminGroup already did: a deploy that
  has not run makedata has no settings.js, and viewlibs must still list the
  control library.

Wording that had gone stale:
- the parity README's Status paragraph now states the invariant (every scenario
  is gated; gated:false is advisory) instead of counts and a list of differences
  that were fixed, and the scenarios.json notes say what each scenario pins now.
- viewdata's comment states the contract rather than the behaviour it replaced,
  and the synthetic no-data row writes the same space for a blank character cell
  as the data rows do.

Tests: getdata-rules.test.js covers an uppercase-keyed APPROVE grant and an
open-ended rule (both fail on the previous code); viewdata.test.js covers the
numeric missing and the empty-table row.
2026-11-07 00:57:05 +00:00

81 lines
2.3 KiB
JavaScript

/**
* Two reads in getdata go through the control library's own rows, and both have
* a case that looks like an empty answer rather than a bug:
*
* - the security and group rows are seeded with UPPERCASE keys (`SAS_GROUP`)
* while a row that has been through the edit flow comes back lower-cased, so
* a direct property read compares against undefined and finds no approver;
* - a `tx_to` that is blank or absent is an open-ended row, not an expired
* one, and reading it as NaN drops the rule or the grant with no signal.
*/
const test = require('node:test')
const assert = require('node:assert')
const { seededEstate, runService, readTable, writeTable } = require('./harness')
function getdata(estate, libds) {
return JSON.parse(
runService(estate, 'editors/getdata', {
tableName: 'SASControlTable',
rows: [{ LIBDS: libds, FILTER_RK: -1 }]
})
)
}
test('an APPROVE grant whose keys are upper case still yields its group', () => {
const estate = seededEstate({ demo: false })
const security = readTable(estate, 'MPE_SECURITY')
writeTable(
estate,
'MPE_SECURITY',
security.concat([
{
TX_FROM: 0,
TX_TO: 127490111999,
LIBREF: 'DC_JSLIB',
DSN: 'MPE_TABLES',
ACCESS_LEVEL: 'APPROVE',
SAS_GROUP: 'dc-admin'
}
])
)
const body = getdata(estate, 'DC_JSLIB.MPE_TABLES')
assert.equal(body.sasjsAbort, undefined)
const users = body.approvers.map((row) => row.USERID).sort()
assert.deepEqual(
users,
['allbow', 'dctestuser1', 'mihmed'],
'the grant is found and its group expanded, rather than falling back'
)
})
test('a rule with no end date is in force, not dropped', () => {
const estate = seededEstate({ demo: false })
const validations = readTable(estate, 'MPE_VALIDATIONS')
writeTable(
estate,
'MPE_VALIDATIONS',
validations.concat([
{
tx_from: 0,
TX_TO: ' ',
BASE_LIB: 'DC_JSLIB',
BASE_DS: 'MPE_TABLES',
BASE_COL: 'LOADTYPE',
RULE_TYPE: 'NOTNULL',
RULE_VALUE: ' ',
RULE_ACTIVE: 1
}
])
)
const body = getdata(estate, 'DC_JSLIB.MPE_TABLES')
const rule = body.dqrules.find(
(row) => row.BASE_COL === 'LOADTYPE' && row.RULE_TYPE === 'NOTNULL'
)
assert.ok(rule, 'a blank end date means open-ended, so the rule is returned')
})