@@ -30,6 +30,7 @@ describe('reference-integrity suite — membership', () => {
3030 'validateActionBodyWrites' ,
3131 'validateFlowNodeWrites' ,
3232 'validateReadonlyFlowWrites' ,
33+ 'validateReactPageProps' ,
3334 ] ) ;
3435 } ) ;
3536
@@ -107,6 +108,17 @@ describe('reference-integrity suite — every member actually runs', () => {
107108 } ,
108109 ] ,
109110 } ,
111+ // validateReactPageProps: the same component family one surface over,
112+ // authored as JSX. `<ObjectForm>` with no `objectName` binds nothing, so
113+ // this GATES — and it gated on `os validate` alone until this member
114+ // joined the suite. A separate page from `lead_detail` on purpose: the
115+ // metadata walk above must stay the only source of `page-field-unknown`
116+ // here, or this member could go silent behind it.
117+ {
118+ name : 'lead_console' ,
119+ kind : 'react' ,
120+ source : 'function Page(){ return <ObjectForm mode="edit" />; }' ,
121+ } ,
110122 ] ,
111123 datasets : [
112124 {
@@ -221,11 +233,21 @@ describe('reference-integrity suite — every member actually runs', () => {
221233 expect ( rules ) . toContain ( 'agent-authoring-withdrawn' ) ;
222234 expect ( rules ) . toContain ( 'hook-body-write-unknown-field' ) ;
223235 expect ( rules ) . toContain ( 'action-body-write-unknown-field' ) ;
224- // The one member that emits a second rule id — see the suite's comment on
225- // why it rides along instead of becoming its own entry .
236+ // Members that emit a rule id beyond their resolution one — see the suite's
237+ // comments on why these ride along instead of becoming their own entries .
226238 expect ( rules ) . toContain ( 'action-record-write-discarded' ) ;
227239 expect ( rules ) . toContain ( 'flow-node-write-unknown-field' ) ;
228240 expect ( rules ) . toContain ( 'flow-update-readonly-field' ) ;
241+ expect ( rules ) . toContain ( 'react-prop-missing-required' ) ;
242+ } ) ;
243+
244+ it ( 'carries a gating react-page-prop finding through the suite (#4340)' , ( ) => {
245+ const findings = validateReferenceIntegrity ( stack ) ;
246+ const react = findings . find ( ( f ) => f . rule === 'react-prop-missing-required' ) ;
247+ // Must reach the CLI as an ERROR: `os lint` and `os compile` saw NOTHING
248+ // from this rule until it joined the suite, so a react page binding nothing
249+ // sailed through the build the way a readonly flow write did (#4394).
250+ expect ( react ?. severity ) . toBe ( 'error' ) ;
229251 } ) ;
230252
231253 it ( 'carries a gating flow-template finding through the suite (#3810)' , ( ) => {
@@ -247,9 +269,9 @@ describe('reference-integrity suite — every member actually runs', () => {
247269 expect ( typeof f . message ) . toBe ( 'string' ) ;
248270 expect ( typeof f . hint ) . toBe ( 'string' ) ;
249271 }
250- // Object references run first, readonly flow writes last.
272+ // Object references run first, react page props last.
251273 expect ( findings [ 0 ] . rule ) . toBe ( 'object-reference-unknown' ) ;
252- expect ( findings [ findings . length - 1 ] . rule ) . toBe ( 'flow-update-readonly-field ' ) ;
274+ expect ( findings [ findings . length - 1 ] . rule ) . toBe ( 'react-prop-missing-required ' ) ;
253275 } ) ;
254276
255277 it ( 'returns nothing for an empty stack' , ( ) => {
0 commit comments