@@ -8,9 +8,141 @@ import {
88 collectDefinitionTermTitleChanges ,
99 collectTermSyncChanges ,
1010 toDefaultTitleCase ,
11+ type TermSyncChange ,
1112} from "../src/terms" ;
1213import type { RulesDocument } from "../src/types" ;
1314
15+ function createTermSyncDocument ( ignoreInTerms ?: boolean ) : RulesDocument {
16+ return {
17+ info : {
18+ title : "Test" ,
19+ description : "Test" ,
20+ version : "1.0.0" ,
21+ last_updated : "2026-09-13" ,
22+ } ,
23+ FRD : {
24+ info : { } ,
25+ data : {
26+ all : {
27+ "FRD-MST" : {
28+ term : "MUST" ,
29+ alts : [ "required" ] ,
30+ ...( ignoreInTerms === undefined
31+ ? { }
32+ : { ignore_in_terms : ignoreInTerms } ) ,
33+ definition : "Test definition" ,
34+ } ,
35+ "FRD-AGY" : {
36+ term : "Agency" ,
37+ definition : "Test definition" ,
38+ } ,
39+ "FRD-PVD" : {
40+ term : "Provider" ,
41+ alts : [ "providers" ] ,
42+ ignore_in_terms : false ,
43+ definition : "Test definition" ,
44+ } ,
45+ } ,
46+ } ,
47+ } ,
48+ FRR : {
49+ MAS : {
50+ info : { } ,
51+ data : {
52+ all : {
53+ CSO : {
54+ "MAS-CSO-TST" : {
55+ name : "Test requirement" ,
56+ affects : [ "Providers" ] ,
57+ statement : "Providers MUST notify an agency." ,
58+ force : "MUST" ,
59+ terms : [ ] ,
60+ } ,
61+ } ,
62+ } ,
63+ } ,
64+ } ,
65+ } ,
66+ KSI : {
67+ IAM : {
68+ id : "KSI-IAM" ,
69+ name : "Test theme" ,
70+ web_name : "Test theme" ,
71+ short_name : "Test" ,
72+ theme : "Test" ,
73+ indicators : {
74+ "KSI-IAM-TST" : {
75+ name : "Test indicator" ,
76+ varies_by_class : {
77+ b : { statement : "Providers are required to notify an agency." } ,
78+ c : { statement : "Providers are required to notify an agency." } ,
79+ } ,
80+ terms : [ ] ,
81+ } ,
82+ } ,
83+ } ,
84+ } ,
85+ } ;
86+ }
87+
88+ test . each ( [
89+ [ "absent" , undefined ] ,
90+ [ "false" , false ] ,
91+ [ "true" , true ] ,
92+ ] as const ) ( "term sync honors ignore_in_terms=%s for terms and aliases" , ( _ , ignoreInTerms ) => {
93+ const document = createTermSyncDocument ( ignoreInTerms ) ;
94+ const expectedTerms = ignoreInTerms === true
95+ ? [ "Agency" , "Provider" ]
96+ : [ "Agency" , "MUST" , "Provider" ] ;
97+ const expectedChanges : TermSyncChange [ ] = [
98+ {
99+ id : "MAS-CSO-TST" ,
100+ location : "FRR.MAS.data.all.CSO.MAS-CSO-TST" ,
101+ kind : "requirement" ,
102+ currentTerms : [ ] ,
103+ nextTerms : expectedTerms ,
104+ } ,
105+ {
106+ id : "KSI-IAM-TST" ,
107+ location : "KSI.IAM.indicators.KSI-IAM-TST" ,
108+ kind : "indicator" ,
109+ currentTerms : [ ] ,
110+ nextTerms : expectedTerms ,
111+ } ,
112+ ] ;
113+ const original = structuredClone ( document ) ;
114+
115+ expect ( collectTermSyncChanges ( document ) ) . toEqual ( expectedChanges ) ;
116+ expect ( document ) . toEqual ( original ) ;
117+ expect ( applyTermSync ( document ) ) . toEqual ( expectedChanges ) ;
118+ expect ( collectTermSyncChanges ( document ) ) . toEqual ( [ ] ) ;
119+ expect ( applyTermSync ( document ) ) . toEqual ( [ ] ) ;
120+ } ) ;
121+
122+ test . each ( [ "all" , "20x" , "rev5" ] ) ( "term sync removes ignored definitions from %s even when their text still matches" , ( scope ) => {
123+ const document = createTermSyncDocument ( true ) ;
124+ const definitions = document . FRD . data . all ! ;
125+ document . FRD . data = { [ scope ] : definitions } ;
126+ const requirement = document . FRR . MAS ! . data . all ! . CSO ! [ "MAS-CSO-TST" ] ! ;
127+ const indicator = Object . values ( document . KSI . IAM ! . indicators ) [ 0 ] ! ;
128+ requirement . terms = [ "Agency" , "MUST" , "Provider" ] ;
129+ indicator . varies_by_class = {
130+ b : { statement : "This behavior is required." } ,
131+ c : { statement : "This behavior is required." } ,
132+ } ;
133+ indicator . terms = [ "MUST" ] ;
134+
135+ const changes = collectTermSyncChanges ( document ) ;
136+
137+ expect ( changes ) . toHaveLength ( 2 ) ;
138+ expect ( changes [ 0 ] ! . nextTerms ) . toEqual ( [ "Agency" , "Provider" ] ) ;
139+ expect ( changes [ 1 ] ! . nextTerms ) . toEqual ( [ ] ) ;
140+ expect ( applyTermSync ( document ) ) . toEqual ( changes ) ;
141+ expect ( requirement . terms ) . toEqual ( [ "Agency" , "Provider" ] ) ;
142+ expect ( indicator . terms ) . toEqual ( [ ] ) ;
143+ expect ( collectTermSyncChanges ( document ) ) . toEqual ( [ ] ) ;
144+ } ) ;
145+
14146test ( "all FRD terms use the default title casing" , ( ) => {
15147 const changes = collectDefinitionTermTitleChanges ( loadRulesDocument ( ) ) ;
16148 expect ( changes ) . toEqual ( [ ] ) ;
0 commit comments