@@ -173,3 +173,96 @@ describe('AuthOptionFactory rich-text action', () => {
173173 expect ( ( ) => container . querySelector < HTMLAnchorElement > ( 'a' ) ! . click ( ) ) . not . toThrow ( ) ;
174174 } ) ;
175175} ) ;
176+
177+ describe ( 'AuthOptionFactory stack grid layout' , ( ) => {
178+ const stackWith = ( extra : Record < string , unknown > , childCount = 4 ) : EmbeddedFlowComponent =>
179+ ( {
180+ components : Array . from ( { length : childCount } , ( _ , index ) => ( {
181+ id : `text_${ index } ` ,
182+ label : `<p>Option ${ index } </p>` ,
183+ type : EmbeddedFlowComponentType . RichText ,
184+ } ) ) ,
185+ id : 'stack_1' ,
186+ type : EmbeddedFlowComponentType . Stack ,
187+ ...extra ,
188+ } ) as EmbeddedFlowComponent ;
189+
190+ const stackElement = ( component : EmbeddedFlowComponent ) : HTMLElement => {
191+ const { container} = renderInto ( component ) ;
192+ return container . querySelector < HTMLElement > ( '#stack_1' ) ! ;
193+ } ;
194+
195+ it ( 'renders a grid with the configured number of columns when items is 2' , ( ) => {
196+ const stack = stackElement ( stackWith ( { items : 2 } ) ) ;
197+
198+ expect ( stack . style . display ) . toBe ( 'grid' ) ;
199+ expect ( stack . style . gridTemplateColumns ) . toBe ( 'repeat(2, 1fr)' ) ;
200+ expect ( stack . children ) . toHaveLength ( 4 ) ;
201+ } ) ;
202+
203+ it ( 'supports arbitrary column counts provided as a numeric string' , ( ) => {
204+ const stack = stackElement ( stackWith ( { items : '3' } , 5 ) ) ;
205+
206+ expect ( stack . style . display ) . toBe ( 'grid' ) ;
207+ expect ( stack . style . gridTemplateColumns ) . toBe ( 'repeat(3, 1fr)' ) ;
208+ expect ( stack . children ) . toHaveLength ( 5 ) ;
209+ } ) ;
210+
211+ it ( 'keeps the flex layout when items is absent' , ( ) => {
212+ const stack = stackElement ( stackWith ( { direction : 'column' } ) ) ;
213+
214+ expect ( stack . style . display ) . toBe ( 'flex' ) ;
215+ expect ( stack . style . flexDirection ) . toBe ( 'column' ) ;
216+ } ) ;
217+
218+ it ( 'keeps the flex layout when items is 1' , ( ) => {
219+ // Stacks authored in the flow builder are seeded with items 1, so a single slot
220+ // must not promote them to a grid.
221+ const stack = stackElement ( stackWith ( { items : 1 } ) ) ;
222+
223+ expect ( stack . style . display ) . toBe ( 'flex' ) ;
224+ } ) ;
225+
226+ it ( 'falls back to the base axis for the reverse directions' , ( ) => {
227+ expect ( stackElement ( stackWith ( { direction : 'column-reverse' , items : 2 } ) ) . style . gridAutoFlow ) . toBe ( 'column' ) ;
228+ expect ( stackElement ( stackWith ( { direction : 'row-reverse' , items : 2 } ) ) . style . gridAutoFlow ) . toBe ( 'row' ) ;
229+ } ) ;
230+
231+ it ( 'uses content-sized tracks when justify has to distribute free space' , ( ) => {
232+ const stack = stackElement ( stackWith ( { items : 2 , justify : 'space-between' } ) ) ;
233+
234+ expect ( stack . style . gridTemplateColumns ) . toBe ( 'repeat(2, auto)' ) ;
235+ expect ( stack . style . justifyContent ) . toBe ( 'space-between' ) ;
236+ } ) ;
237+
238+ it ( 'keeps equal tracks when justify is unset' , ( ) => {
239+ expect ( stackElement ( stackWith ( { items : 2 } ) ) . style . gridTemplateColumns ) . toBe ( 'repeat(2, 1fr)' ) ;
240+ } ) ;
241+
242+ it ( 'clamps absurd slot counts' , ( ) => {
243+ const stack = stackElement ( stackWith ( { items : 5000 } ) ) ;
244+
245+ expect ( stack . style . gridTemplateColumns ) . toBe ( 'repeat(12, 1fr)' ) ;
246+ } ) ;
247+
248+ it ( 'treats items as the row count when direction is column' , ( ) => {
249+ const stack = stackElement ( stackWith ( { direction : 'column' , items : 2 } ) ) ;
250+
251+ expect ( stack . style . display ) . toBe ( 'grid' ) ;
252+ expect ( stack . style . gridTemplateRows ) . toBe ( 'repeat(2, 1fr)' ) ;
253+ expect ( stack . style . gridAutoFlow ) . toBe ( 'column' ) ;
254+ expect ( stack . style . gridTemplateColumns ) . toBe ( '' ) ;
255+ } ) ;
256+
257+ it ( 'falls back to the flex layout when items is not numeric' , ( ) => {
258+ const stack = stackElement ( stackWith ( { items : 'garbage' } ) ) ;
259+
260+ expect ( stack . style . display ) . toBe ( 'flex' ) ;
261+ } ) ;
262+
263+ it ( 'falls back to the flex layout when items is a malformed numeric string' , ( ) => {
264+ const stack = stackElement ( stackWith ( { items : '2invalid' } ) ) ;
265+
266+ expect ( stack . style . display ) . toBe ( 'flex' ) ;
267+ } ) ;
268+ } ) ;
0 commit comments