406 lines
12 KiB
JavaScript
406 lines
12 KiB
JavaScript
const fs = require("fs");
|
|
const path = require("path");
|
|
const vm = require("vm");
|
|
const assert = require("assert");
|
|
|
|
const rootDir = path.resolve(__dirname, "..", "..");
|
|
|
|
const loadSelectQueryTypesModule = (relayPath) => {
|
|
const filePath = path.join(rootDir, "actions", "selectQueryTypes.js");
|
|
|
|
let source = fs.readFileSync(filePath, "utf8");
|
|
source = source.replace(
|
|
/export const\s+getSelectQuery\s*=\s*/,
|
|
"const getSelectQuery = "
|
|
);
|
|
source += `
|
|
module.exports = {
|
|
getSelectQuery
|
|
};
|
|
`;
|
|
|
|
const context = {
|
|
module: { exports: {} },
|
|
exports: {},
|
|
require,
|
|
process: {
|
|
env: {
|
|
RELAYPATH: relayPath
|
|
}
|
|
}
|
|
};
|
|
|
|
vm.runInNewContext(source, context, { filename: filePath });
|
|
return context.module.exports;
|
|
};
|
|
|
|
const tests = [];
|
|
const test = (name, fn) => tests.push({ name, fn });
|
|
|
|
const splitFields = (query) => {
|
|
assert.ok(
|
|
query.startsWith("&$select="),
|
|
`Expected query to start with &$select= but received: ${query}`
|
|
);
|
|
|
|
return query
|
|
.replace(/^&\$select=/, "")
|
|
.split(",")
|
|
.map((field) => field.trim())
|
|
.filter(Boolean);
|
|
};
|
|
|
|
const getFieldSet = (appealTypeName, relayPath) =>
|
|
new Set(
|
|
splitFields(
|
|
loadSelectQueryTypesModule(relayPath).getSelectQuery(appealTypeName)
|
|
)
|
|
);
|
|
|
|
const assertHasFields = (fieldSet, expectedFields, label) => {
|
|
for (const field of expectedFields) {
|
|
assert.ok(fieldSet.has(field), `${label}: expected field \`${field}\``);
|
|
}
|
|
};
|
|
|
|
test("planning-style family preserves common base, location, decision, and status fields across representative bundles", () => {
|
|
const s78Dev = getFieldSet("pinswg_planningappeals78s", "dev-pedw-hc");
|
|
const rows = getFieldSet("pinswg_rows");
|
|
const householder = getFieldSet("pinswg_householderappealhases");
|
|
|
|
const planningBaseFamily = [
|
|
"modifiedon",
|
|
"_pinswg_appellant_value",
|
|
"pinswg_name",
|
|
"pinswg_dateeventrequested",
|
|
"statuscode"
|
|
];
|
|
|
|
for (const [label, fields] of [
|
|
["S78 dev", s78Dev],
|
|
["ROW", rows],
|
|
["Householder", householder]
|
|
]) {
|
|
assertHasFields(fields, planningBaseFamily, label);
|
|
}
|
|
|
|
assertHasFields(
|
|
s78Dev,
|
|
[
|
|
"pinswg_siteaddressline1",
|
|
"pinswg_siteaddressline2",
|
|
"pinswg_siteaddresspostcode",
|
|
"pinswg_siteaddresstown",
|
|
"pinswg_siteaddresscounty",
|
|
"pinswg_casedecisiondate",
|
|
"pinswg_dicision"
|
|
],
|
|
"S78 dev planning family"
|
|
);
|
|
|
|
assertHasFields(
|
|
rows,
|
|
[
|
|
"pinswg_siteaddressline1",
|
|
"pinswg_siteaddressline2",
|
|
"pinswg_siteaddresspostcode",
|
|
"pinswg_siteaddresstown",
|
|
"pinswg_casedecisiondate",
|
|
"pinswg_decision"
|
|
],
|
|
"ROW planning family"
|
|
);
|
|
|
|
assertHasFields(
|
|
householder,
|
|
[
|
|
"pinswg_siteaddressline1",
|
|
"pinswg_siteaddressline2",
|
|
"pinswg_siteaddresspostcode",
|
|
"pinswg_siteaddresstown",
|
|
"pinswg_casedecisiondate",
|
|
"pinswg_decision"
|
|
],
|
|
"Householder planning family"
|
|
);
|
|
});
|
|
|
|
test("representation-window family preserves current start and end date variants without normalization", () => {
|
|
const rows = getFieldSet("pinswg_rows");
|
|
const enforcementListed = getFieldSet(
|
|
"pinswg_enforcementlistedbuildingconservationaps"
|
|
);
|
|
const dns = getFieldSet("pinswg_dnses");
|
|
const callIns = getFieldSet("pinswg_callinss77s");
|
|
|
|
assertHasFields(
|
|
rows,
|
|
[
|
|
"pinswg_startdate",
|
|
"pinswg_statementduedate",
|
|
"pinswg_finalcommentsduedate"
|
|
],
|
|
"ROW representation-window family"
|
|
);
|
|
|
|
assertHasFields(
|
|
enforcementListed,
|
|
[
|
|
"pinswg_startdates",
|
|
"pinswg_statementduedate",
|
|
"pinswg_finalcommentsduedate"
|
|
],
|
|
"Enforcement listed representation-window family"
|
|
);
|
|
|
|
assertHasFields(
|
|
dns,
|
|
[
|
|
"pinswg_applicationacceptedasvalid",
|
|
"pinswg_endofrepresentationperiod"
|
|
],
|
|
"DNS representation-window family"
|
|
);
|
|
|
|
assertHasFields(
|
|
callIns,
|
|
[
|
|
"pinswg_startdate",
|
|
"pinswg_statementsduedate",
|
|
"pinswg_finalcommentsduedate"
|
|
],
|
|
"Call-ins representation-window family"
|
|
);
|
|
|
|
assert.ok(
|
|
!dns.has("pinswg_startdate") && !dns.has("pinswg_startdates"),
|
|
"DNS should preserve infrastructure-style start-date variant rather than planning-style start fields"
|
|
);
|
|
});
|
|
|
|
test("specialist-process family preserves intentional field-variant divergence across bundles", () => {
|
|
const rows = getFieldSet("pinswg_rows");
|
|
const adverts = getFieldSet("pinswg_advertses");
|
|
const hedges = getFieldSet(
|
|
"pinswg_hedgeshedgerowstreepreservationreplacems"
|
|
);
|
|
const householder = getFieldSet("pinswg_householderappealhases");
|
|
|
|
assert.ok(
|
|
rows.has("pinswg_specialistcaseprocess") &&
|
|
!rows.has("pinswg_speacialistcaseprocess"),
|
|
"ROW should preserve canonical-only specialist-process selection"
|
|
);
|
|
|
|
assert.ok(
|
|
adverts.has("pinswg_speacialistcaseprocess") &&
|
|
!adverts.has("pinswg_specialistcaseprocess"),
|
|
"Adverts should preserve misspelled-only specialist-process selection"
|
|
);
|
|
|
|
assert.ok(
|
|
hedges.has("pinswg_specialistcaseprocess") &&
|
|
!hedges.has("pinswg_speacialistcaseprocess"),
|
|
"Hedges should preserve canonical-only specialist-process selection"
|
|
);
|
|
|
|
assert.ok(
|
|
!householder.has("pinswg_specialistcaseprocess") &&
|
|
!householder.has("pinswg_speacialistcaseprocess"),
|
|
"Householder should preserve absence of specialist-process fields"
|
|
);
|
|
});
|
|
|
|
test("infrastructure-style family preserves project-oriented fields and schema variants across representative bundles", () => {
|
|
const dns = getFieldSet("pinswg_dnses");
|
|
const harbour = getFieldSet("pinswg_harbourrevisionorders");
|
|
const electricity = getFieldSet("pinswg_electricityacts");
|
|
|
|
const commonInfrastructureFields = [
|
|
"pinswg_eiarequired",
|
|
"pinswg_name",
|
|
"pinswg_addressline1",
|
|
"pinswg_addresstown",
|
|
"pinswg_postcode",
|
|
"pinswg_applicationacceptedasvalid",
|
|
"pinswg_endofrepresentationperiod",
|
|
"pinswg_projectlocation",
|
|
"pinswg_recommendation",
|
|
"pinswg_reportdueby",
|
|
"pinswg_validnoticeofintentiontosubmitanapplicati",
|
|
"pinswg_writtenacceptanceofnotification",
|
|
"pinswg_startdateofevent",
|
|
"pinswg_typeofevent",
|
|
"statuscode"
|
|
];
|
|
|
|
for (const [label, fields] of [
|
|
["DNS", dns],
|
|
["Harbour", harbour],
|
|
["Electricity", electricity]
|
|
]) {
|
|
assertHasFields(fields, commonInfrastructureFields, label);
|
|
}
|
|
|
|
assert.ok(
|
|
dns.has("pinswg_projectdescription") &&
|
|
!dns.has("pinswg_projectdiscription"),
|
|
"DNS should preserve canonical project description field"
|
|
);
|
|
|
|
assert.ok(
|
|
harbour.has("pinswg_projectdiscription") &&
|
|
!harbour.has("pinswg_projectdescription"),
|
|
"Harbour should preserve misspelled project description variant"
|
|
);
|
|
|
|
assert.ok(
|
|
dns.has("pinswg_suspensionstartdates") &&
|
|
!dns.has("pinswg_suspensionstartdate"),
|
|
"DNS should preserve plural suspension start field"
|
|
);
|
|
|
|
assert.ok(
|
|
harbour.has("pinswg_suspensionstartdate") &&
|
|
!harbour.has("pinswg_suspensionstartdates"),
|
|
"Harbour should preserve singular suspension start field variant"
|
|
);
|
|
|
|
assert.ok(
|
|
electricity.has("modifiedon") && !dns.has("modifiedon"),
|
|
"Electricity should preserve current modifiedon overlap while DNS preserves its current omission"
|
|
);
|
|
});
|
|
|
|
test("authority and LPA family preserves current field distinctions rather than collapsing them", () => {
|
|
const s78Dev = getFieldSet("pinswg_planningappeals78s", "dev-pedw-hc");
|
|
const rows = getFieldSet("pinswg_rows");
|
|
const dns = getFieldSet("pinswg_dnses");
|
|
|
|
assert.ok(
|
|
s78Dev.has("_pinswg_localplanningauthority_value") &&
|
|
!s78Dev.has("_pinswg_associatedlpa_value"),
|
|
"S78 should preserve local-planning-authority field variant"
|
|
);
|
|
|
|
assert.ok(
|
|
rows.has("_pinswg_associatedlpa_value") &&
|
|
rows.has("pinswg_relevantauthorityname"),
|
|
"ROW should preserve overlap of associated LPA and relevant authority fields"
|
|
);
|
|
|
|
assert.ok(
|
|
dns.has("_pinswg_associatedlpa_value") &&
|
|
!dns.has("pinswg_relevantauthorityname"),
|
|
"DNS should preserve associated LPA without planning-style relevant-authority field"
|
|
);
|
|
});
|
|
|
|
test("consultation family is currently specific to SIPS-style profiles", () => {
|
|
const sips = getFieldSet("pinswg_sipses");
|
|
const dns = getFieldSet("pinswg_dnses");
|
|
const rows = getFieldSet("pinswg_rows");
|
|
|
|
assertHasFields(
|
|
sips,
|
|
["pinswg_consultationopen", "pinswg_consultationclose"],
|
|
"SIPS consultation family"
|
|
);
|
|
|
|
assert.ok(
|
|
!dns.has("pinswg_consultationopen") &&
|
|
!dns.has("pinswg_consultationclose") &&
|
|
!rows.has("pinswg_consultationopen") &&
|
|
!rows.has("pinswg_consultationclose"),
|
|
"Consultation fields should preserve their current absence from non-SIPS representative bundles"
|
|
);
|
|
});
|
|
|
|
test("minimal-profile family preserves intentionally small bundles and divergence from larger families", () => {
|
|
const nonValidation = getFieldSet("pinswg_nonvalidations");
|
|
const ldp = getFieldSet("pinswg_ldps");
|
|
const rows = getFieldSet("pinswg_rows");
|
|
|
|
assert.deepStrictEqual([...ldp], ["modifiedon", "pinswg_name"]);
|
|
|
|
assertHasFields(
|
|
nonValidation,
|
|
[
|
|
"modifiedon",
|
|
"_pinswg_appellant_value",
|
|
"pinswg_name",
|
|
"pinswg_siteaddressline1",
|
|
"pinswg_siteaddresspostcode",
|
|
"_pinswg_associatedlpa_value",
|
|
"statuscode"
|
|
],
|
|
"Nonvalidation minimal family"
|
|
);
|
|
|
|
assert.ok(
|
|
!nonValidation.has("pinswg_questionnaireduedate") &&
|
|
!nonValidation.has("pinswg_startdate") &&
|
|
!nonValidation.has("pinswg_applicationacceptedasvalid"),
|
|
"Nonvalidation should preserve absence of representation-window and questionnaire family fields"
|
|
);
|
|
|
|
assert.ok(
|
|
rows.size > nonValidation.size && nonValidation.size > ldp.size,
|
|
"Minimal bundles should preserve their intentionally smaller profiles relative to larger planning bundles"
|
|
);
|
|
});
|
|
|
|
test("family overlaps and divergences are preserved across representative bundles", () => {
|
|
const rows = getFieldSet("pinswg_rows");
|
|
const dns = getFieldSet("pinswg_dnses");
|
|
const sips = getFieldSet("pinswg_sipses");
|
|
const nonValidation = getFieldSet("pinswg_nonvalidations");
|
|
|
|
assert.ok(
|
|
rows.has("pinswg_startdate") && rows.has("pinswg_finalcommentsduedate"),
|
|
"Planning + representation overlap should be preserved for ROW"
|
|
);
|
|
|
|
assert.ok(
|
|
dns.has("pinswg_applicationacceptedasvalid") &&
|
|
dns.has("pinswg_endofrepresentationperiod") &&
|
|
dns.has("pinswg_projectlocation"),
|
|
"Infrastructure + representation overlap should be preserved for DNS"
|
|
);
|
|
|
|
assert.ok(
|
|
sips.has("pinswg_consultationopen") &&
|
|
sips.has("pinswg_consultationclose") &&
|
|
!sips.has("pinswg_finalcommentsduedate"),
|
|
"SIPS + consultation overlap and planning-style divergence should be preserved"
|
|
);
|
|
|
|
assert.ok(
|
|
!nonValidation.has("pinswg_projectlocation") &&
|
|
!nonValidation.has("pinswg_consultationopen") &&
|
|
!nonValidation.has("pinswg_questionnaireduedate"),
|
|
"Minimal profiles should preserve divergence from infrastructure, consultation, and richer planning families"
|
|
);
|
|
});
|
|
|
|
const run = async () => {
|
|
let passed = 0;
|
|
for (const currentTest of tests) {
|
|
await currentTest.fn();
|
|
passed += 1;
|
|
}
|
|
|
|
console.log(
|
|
`Phase 22 select-query-types field family tests passed (${passed}/${tests.length}).`
|
|
);
|
|
};
|
|
|
|
module.exports = run;
|
|
|
|
if (require.main === module) {
|
|
run().catch((error) => {
|
|
console.error(error);
|
|
process.exit(1);
|
|
});
|
|
}
|