box-ui-elements 23.4.0-beta.36 → 23.4.0-beta.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/dist/explorer.css +1 -1
  2. package/dist/explorer.js +1 -1
  3. package/dist/preview.css +1 -1
  4. package/dist/preview.js +1 -1
  5. package/dist/sidebar.css +1 -1
  6. package/dist/sidebar.js +1 -1
  7. package/es/common/types/metadata.js.flow +5 -4
  8. package/es/common/types/metadata.js.map +1 -1
  9. package/es/elements/content-explorer/stories/tests/MetadataView-visual.stories.js +43 -22
  10. package/es/elements/content-explorer/stories/tests/MetadataView-visual.stories.js.map +1 -1
  11. package/es/elements/content-preview/PreviewNavigation.js +0 -2
  12. package/es/elements/content-preview/PreviewNavigation.js.flow +0 -2
  13. package/es/elements/content-preview/PreviewNavigation.js.map +1 -1
  14. package/es/elements/content-sidebar/versions/VersionsSidebarContainer.js +29 -7
  15. package/es/elements/content-sidebar/versions/VersionsSidebarContainer.js.flow +44 -5
  16. package/es/elements/content-sidebar/versions/VersionsSidebarContainer.js.map +1 -1
  17. package/es/elements/content-sidebar/withSidebarAnnotations.js +141 -35
  18. package/es/elements/content-sidebar/withSidebarAnnotations.js.flow +199 -37
  19. package/es/elements/content-sidebar/withSidebarAnnotations.js.map +1 -1
  20. package/es/features/metadata-instance-editor/CascadePolicy.js +6 -3
  21. package/es/features/metadata-instance-editor/CascadePolicy.js.flow +8 -2
  22. package/es/features/metadata-instance-editor/CascadePolicy.js.map +1 -1
  23. package/es/features/metadata-instance-editor/Instance.js +1 -0
  24. package/es/features/metadata-instance-editor/Instance.js.flow +1 -0
  25. package/es/features/metadata-instance-editor/Instance.js.map +1 -1
  26. package/es/src/elements/content-explorer/stories/tests/MetadataView-visual.stories.d.ts +1 -1
  27. package/i18n/bn-IN.js +1 -1
  28. package/i18n/bn-IN.properties +4 -0
  29. package/i18n/da-DK.js +1 -1
  30. package/i18n/da-DK.properties +4 -0
  31. package/i18n/de-DE.js +1 -1
  32. package/i18n/de-DE.properties +4 -0
  33. package/i18n/en-AU.js +1 -1
  34. package/i18n/en-AU.properties +4 -0
  35. package/i18n/en-CA.js +1 -1
  36. package/i18n/en-CA.properties +4 -0
  37. package/i18n/en-GB.js +1 -1
  38. package/i18n/en-GB.properties +4 -0
  39. package/i18n/es-419.js +1 -1
  40. package/i18n/es-419.properties +4 -0
  41. package/i18n/es-ES.js +1 -1
  42. package/i18n/es-ES.properties +4 -0
  43. package/i18n/fi-FI.js +1 -1
  44. package/i18n/fi-FI.properties +4 -0
  45. package/i18n/fr-CA.js +1 -1
  46. package/i18n/fr-CA.properties +4 -0
  47. package/i18n/fr-FR.js +1 -1
  48. package/i18n/fr-FR.properties +4 -0
  49. package/i18n/hi-IN.js +1 -1
  50. package/i18n/hi-IN.properties +4 -0
  51. package/i18n/it-IT.js +1 -1
  52. package/i18n/it-IT.properties +4 -0
  53. package/i18n/ja-JP.js +1 -1
  54. package/i18n/ja-JP.properties +4 -0
  55. package/i18n/ko-KR.js +1 -1
  56. package/i18n/ko-KR.properties +4 -0
  57. package/i18n/nb-NO.js +1 -1
  58. package/i18n/nb-NO.properties +4 -0
  59. package/i18n/nl-NL.js +1 -1
  60. package/i18n/nl-NL.properties +4 -0
  61. package/i18n/pl-PL.js +1 -1
  62. package/i18n/pl-PL.properties +4 -0
  63. package/i18n/pt-BR.js +1 -1
  64. package/i18n/pt-BR.properties +4 -0
  65. package/i18n/ru-RU.js +1 -1
  66. package/i18n/ru-RU.properties +4 -0
  67. package/i18n/sv-SE.js +1 -1
  68. package/i18n/sv-SE.properties +4 -0
  69. package/i18n/tr-TR.js +1 -1
  70. package/i18n/tr-TR.properties +4 -0
  71. package/i18n/zh-CN.js +1 -1
  72. package/i18n/zh-CN.properties +4 -0
  73. package/i18n/zh-TW.js +1 -1
  74. package/i18n/zh-TW.properties +4 -0
  75. package/package.json +3 -3
  76. package/src/common/types/metadata.js +5 -4
  77. package/src/elements/content-explorer/stories/tests/MetadataView-visual.stories.tsx +47 -31
  78. package/src/elements/content-preview/PreviewNavigation.js +0 -2
  79. package/src/elements/content-preview/__tests__/PreviewNavigation.test.js +12 -12
  80. package/src/elements/content-sidebar/__tests__/withSidebarAnnotations.rtl.test.js +1152 -0
  81. package/src/elements/content-sidebar/versions/VersionsSidebarContainer.js +44 -5
  82. package/src/elements/content-sidebar/versions/__tests__/VersionsSidebarContainer.test.js +200 -43
  83. package/src/elements/content-sidebar/versions/__tests__/__snapshots__/VersionsSidebarContainer.test.js.snap +2 -2
  84. package/src/elements/content-sidebar/withSidebarAnnotations.js +199 -37
  85. package/src/features/metadata-instance-editor/CascadePolicy.js +8 -2
  86. package/src/features/metadata-instance-editor/Instance.js +1 -0
  87. package/src/features/metadata-instance-editor/__tests__/CascadePolicy.test.js +45 -0
  88. package/src/elements/content-sidebar/__tests__/withSidebarAnnotations.test.js +0 -626
@@ -7,14 +7,23 @@ import { FEED_ITEM_TYPE_VERSION } from '../../constants';
7
7
  import { getBadUserError } from '../../utils/error';
8
8
  import type { WithAnnotatorContextProps } from '../common/annotator-context';
9
9
  import type { BoxItem, User } from '../../common/types/core';
10
+ import {
11
+ ViewType,
12
+ FeedEntryType,
13
+ type InternalSidebarNavigation,
14
+ type InternalSidebarNavigationHandler,
15
+ } from '../common/types/SidebarNavigation';
10
16
 
11
17
  type Props = {
12
18
  ...ContextRouter,
13
19
  currentUser?: User,
14
20
  file: BoxItem,
15
21
  fileId: string,
22
+ internalSidebarNavigation?: InternalSidebarNavigation,
23
+ internalSidebarNavigationHandler?: InternalSidebarNavigationHandler,
16
24
  isOpen: boolean,
17
25
  onVersionChange: Function,
26
+ routerDisabled?: boolean,
18
27
  } & WithAnnotatorContextProps;
19
28
 
20
29
  type SidebarPanelsRefType = {
@@ -44,31 +53,130 @@ export default function withSidebarAnnotations(
44
53
  this.redirectDeeplinkedAnnotation();
45
54
  }
46
55
 
56
+ getInternalNavigationMatch = (
57
+ navigation: InternalSidebarNavigation,
58
+ ): { params: { annotationId?: string, fileVersionId: string } } | null => {
59
+ if (
60
+ !('activeFeedEntryType' in navigation) ||
61
+ navigation.activeFeedEntryType !== FeedEntryType.ANNOTATIONS ||
62
+ !navigation.fileVersionId
63
+ ) {
64
+ return null;
65
+ }
66
+
67
+ // Only include annotationId if it's defined (mirrors router behavior where missing optional params are omitted)
68
+ const params =
69
+ navigation.activeFeedEntryId !== undefined
70
+ ? {
71
+ fileVersionId: navigation.fileVersionId,
72
+ annotationId: navigation.activeFeedEntryId,
73
+ }
74
+ : {
75
+ fileVersionId: navigation.fileVersionId,
76
+ };
77
+
78
+ return { params };
79
+ };
80
+
81
+ getInternalAnnotationsNavigation = (
82
+ fileVersionId?: string,
83
+ annotationId?: string | null,
84
+ ): InternalSidebarNavigation => {
85
+ if (!fileVersionId) {
86
+ return { sidebar: ViewType.ACTIVITY };
87
+ }
88
+
89
+ return {
90
+ sidebar: ViewType.ACTIVITY,
91
+ activeFeedEntryType: FeedEntryType.ANNOTATIONS,
92
+ activeFeedEntryId: annotationId || undefined,
93
+ fileVersionId,
94
+ };
95
+ };
96
+
47
97
  redirectDeeplinkedAnnotation = () => {
48
- const { file, getAnnotationsPath, getAnnotationsMatchPath, history, location } = this.props;
49
- const match = getAnnotationsMatchPath(location);
50
- const annotationId = getProp(match, 'params.annotationId');
98
+ const {
99
+ file,
100
+ getAnnotationsPath,
101
+ getAnnotationsMatchPath,
102
+ history,
103
+ internalSidebarNavigation,
104
+ internalSidebarNavigationHandler,
105
+ location,
106
+ routerDisabled,
107
+ } = this.props;
108
+
51
109
  const currentFileVersionId = getProp(file, 'file_version.id');
52
- const fileVersionId = getProp(match, 'params.fileVersionId');
53
110
 
54
- if (fileVersionId && fileVersionId !== currentFileVersionId) {
55
- history.replace(getAnnotationsPath(currentFileVersionId, annotationId));
111
+ if (routerDisabled && internalSidebarNavigation && internalSidebarNavigationHandler) {
112
+ // Use internal navigation when router is disabled
113
+ const match = this.getInternalNavigationMatch(internalSidebarNavigation);
114
+ const annotationId = getProp(match, 'params.annotationId');
115
+ const fileVersionId = getProp(match, 'params.fileVersionId');
116
+
117
+ if (fileVersionId && fileVersionId !== currentFileVersionId) {
118
+ const correctedNavigation = this.getInternalAnnotationsNavigation(
119
+ currentFileVersionId,
120
+ annotationId,
121
+ );
122
+ internalSidebarNavigationHandler(correctedNavigation, true);
123
+ }
124
+ } else {
125
+ // Use router-based navigation
126
+ const match = getAnnotationsMatchPath(location);
127
+ const annotationId = getProp(match, 'params.annotationId');
128
+ const fileVersionId = getProp(match, 'params.fileVersionId');
129
+
130
+ if (fileVersionId && fileVersionId !== currentFileVersionId) {
131
+ history.replace(getAnnotationsPath(currentFileVersionId, annotationId));
132
+ }
56
133
  }
57
134
  };
58
135
 
59
136
  componentDidUpdate(prevProps: Props) {
60
- const { annotatorState, fileId, getAnnotationsMatchPath, location, onVersionChange }: Props = this.props;
61
- const { annotatorState: prevAnnotatorState, fileId: prevFileId, location: prevLocation }: Props = prevProps;
137
+ const {
138
+ annotatorState,
139
+ fileId,
140
+ getAnnotationsMatchPath,
141
+ internalSidebarNavigation,
142
+ location,
143
+ onVersionChange,
144
+ routerDisabled,
145
+ }: Props = this.props;
146
+ const {
147
+ annotatorState: prevAnnotatorState,
148
+ fileId: prevFileId,
149
+ internalSidebarNavigation: prevInternalSidebarNavigation,
150
+ location: prevLocation,
151
+ }: Props = prevProps;
62
152
  const { action, activeAnnotationId, annotation } = annotatorState;
63
153
  const { activeAnnotationId: prevActiveAnnotationId, annotation: prevAnnotation } = prevAnnotatorState;
64
154
 
65
- const match = getAnnotationsMatchPath(location);
66
- const prevMatch = getAnnotationsMatchPath(prevLocation);
67
- const fileVersionId = getProp(match, 'params.fileVersionId');
68
- const hasActiveAnnotationChanged = prevActiveAnnotationId !== activeAnnotationId;
155
+ let fileVersionId;
156
+ let prevFileVersionId;
157
+ let match;
158
+
159
+ if (routerDisabled && internalSidebarNavigation) {
160
+ // Use internal navigation when router is disabled
161
+ match = this.getInternalNavigationMatch(internalSidebarNavigation);
162
+ const prevMatch = prevInternalSidebarNavigation
163
+ ? this.getInternalNavigationMatch(prevInternalSidebarNavigation)
164
+ : null;
165
+
166
+ fileVersionId = getProp(match, 'params.fileVersionId');
167
+ prevFileVersionId = getProp(prevMatch, 'params.fileVersionId');
168
+ } else {
169
+ // Use router-based navigation
170
+ match = getAnnotationsMatchPath(location);
171
+ const prevMatch = getAnnotationsMatchPath(prevLocation);
172
+
173
+ fileVersionId = getProp(match, 'params.fileVersionId');
174
+ prevFileVersionId = getProp(prevMatch, 'params.fileVersionId');
175
+ }
176
+
69
177
  const isAnnotationsPath = !!match;
70
178
  const isTransitioningToAnnotationPath = activeAnnotationId && !isAnnotationsPath;
71
- const prevFileVersionId = getProp(prevMatch, 'params.fileVersionId');
179
+ const hasActiveAnnotationChanged = prevActiveAnnotationId !== activeAnnotationId;
72
180
 
73
181
  if (action === 'reply_create_start' || action === 'reply_create_end') {
74
182
  this.addAnnotationReply();
@@ -275,19 +383,39 @@ export default function withSidebarAnnotations(
275
383
  getAnnotationsMatchPath,
276
384
  getAnnotationsPath,
277
385
  history,
386
+ internalSidebarNavigation,
387
+ internalSidebarNavigationHandler,
278
388
  location,
389
+ routerDisabled,
279
390
  } = this.props;
280
- const match = getAnnotationsMatchPath(location);
391
+
281
392
  const currentFileVersionId = getProp(file, 'file_version.id');
282
393
  const defaultFileVersionId = activeAnnotationFileVersionId || currentFileVersionId;
283
- const fileVersionId = getProp(match, 'params.fileVersionId', defaultFileVersionId);
284
- const newLocationState = activeAnnotationId ? { open: true } : location.state;
285
-
286
- // Update the location pathname and open state if transitioning to an active annotation id, force the sidebar open
287
- history.push({
288
- pathname: getAnnotationsPath(fileVersionId, activeAnnotationId),
289
- state: newLocationState,
290
- });
394
+
395
+ if (routerDisabled && internalSidebarNavigation && internalSidebarNavigationHandler) {
396
+ // Use internal navigation when router is disabled
397
+ const match = this.getInternalNavigationMatch(internalSidebarNavigation);
398
+ const fileVersionId = getProp(match, 'params.fileVersionId', defaultFileVersionId);
399
+ const newNavigationState = activeAnnotationId ? { open: true } : {};
400
+
401
+ // Update the navigation and open state if transitioning to an active annotation id, force the sidebar open
402
+ const updatedNavigation = {
403
+ ...this.getInternalAnnotationsNavigation(fileVersionId, activeAnnotationId),
404
+ ...newNavigationState,
405
+ };
406
+ internalSidebarNavigationHandler(updatedNavigation);
407
+ } else {
408
+ // Use router-based navigation
409
+ const match = getAnnotationsMatchPath(location);
410
+ const fileVersionId = getProp(match, 'params.fileVersionId', defaultFileVersionId);
411
+ const newLocationState = activeAnnotationId ? { open: true } : location.state;
412
+
413
+ // Update the location pathname and open state if transitioning to an active annotation id, force the sidebar open
414
+ history.push({
415
+ pathname: getAnnotationsPath(fileVersionId, activeAnnotationId),
416
+ state: newLocationState,
417
+ });
418
+ }
291
419
  };
292
420
 
293
421
  updateActiveVersion = () => {
@@ -298,33 +426,67 @@ export default function withSidebarAnnotations(
298
426
  getAnnotationsMatchPath,
299
427
  getAnnotationsPath,
300
428
  history,
429
+ internalSidebarNavigation,
430
+ internalSidebarNavigationHandler,
301
431
  location,
302
432
  onVersionChange,
433
+ routerDisabled,
303
434
  } = this.props;
435
+
304
436
  const feedAPI = api.getFeedAPI(false);
305
- const match = getAnnotationsMatchPath(location);
306
437
  const currentFileVersionId = getProp(file, 'file_version.id');
307
- const fileVersionId = getProp(match, 'params.fileVersionId');
308
438
  const { items: feedItems = [] } = feedAPI.getCachedItems(fileId) || {};
309
- const version = feedItems
310
- .filter(item => item.type === FEED_ITEM_TYPE_VERSION)
311
- .find(item => item.id === fileVersionId);
312
-
313
- if (version) {
314
- onVersionChange(version, {
315
- currentVersionId: currentFileVersionId,
316
- updateVersionToCurrent: () => history.push(getAnnotationsPath(currentFileVersionId)),
317
- });
439
+
440
+ if (routerDisabled && internalSidebarNavigation && internalSidebarNavigationHandler) {
441
+ // Use internal navigation when router is disabled
442
+ const match = this.getInternalNavigationMatch(internalSidebarNavigation);
443
+ const fileVersionId = getProp(match, 'params.fileVersionId');
444
+ const version = feedItems
445
+ .filter(item => item.type === FEED_ITEM_TYPE_VERSION)
446
+ .find(item => item.id === fileVersionId);
447
+
448
+ if (version) {
449
+ onVersionChange(version, {
450
+ currentVersionId: currentFileVersionId,
451
+ updateVersionToCurrent: () => {
452
+ const currentVersionNavigation =
453
+ this.getInternalAnnotationsNavigation(currentFileVersionId);
454
+ internalSidebarNavigationHandler(currentVersionNavigation);
455
+ },
456
+ });
457
+ }
458
+ } else {
459
+ // Use router-based navigation
460
+ const match = getAnnotationsMatchPath(location);
461
+ const fileVersionId = getProp(match, 'params.fileVersionId');
462
+ const version = feedItems
463
+ .filter(item => item.type === FEED_ITEM_TYPE_VERSION)
464
+ .find(item => item.id === fileVersionId);
465
+
466
+ if (version) {
467
+ onVersionChange(version, {
468
+ currentVersionId: currentFileVersionId,
469
+ updateVersionToCurrent: () => history.push(getAnnotationsPath(currentFileVersionId)),
470
+ });
471
+ }
318
472
  }
319
473
  };
320
474
 
321
475
  refreshActivitySidebar = () => {
322
- const { isOpen, location } = this.props;
323
-
324
- const pathname = getProp(location, 'pathname', '');
325
- const isActivity = matchPath(pathname, '/activity');
476
+ const { internalSidebarNavigation, isOpen, location, routerDisabled } = this.props;
326
477
  const { current } = this.sidebarPanels;
327
478
 
479
+ let isActivity = false;
480
+
481
+ if (routerDisabled && internalSidebarNavigation) {
482
+ // Check if current navigation is pointing to activity sidebar
483
+ isActivity = internalSidebarNavigation.sidebar === ViewType.ACTIVITY;
484
+ } else {
485
+ // Use router-based check
486
+ const pathname = getProp(location, 'pathname', '');
487
+ isActivity = !!matchPath(pathname, '/activity');
488
+ }
489
+
328
490
  // If the activity sidebar is currently open, then force it to refresh with the updated data
329
491
  if (current && isActivity && isOpen) {
330
492
  current.refresh(false);
@@ -18,7 +18,8 @@ import Link from '../../components/link/Link';
18
18
  import IconAlertDefault from '../../icons/general/IconAlertDefault';
19
19
  import messages from './messages';
20
20
  import './CascadePolicy.scss';
21
- import { STANDARD_AGENT_ID, ENHANCED_AGENT_ID } from './constants';
21
+ import { STANDARD_AGENT_ID, ENHANCED_AGENT_ID, ENHANCED_AGENT_CONFIGURATION } from './constants';
22
+ import type { MetadataCascadePolicyConfiguration } from '../../common/types/metadata';
22
23
 
23
24
  const COMMUNITY_LINK = 'https://support.box.com/hc/en-us/articles/360044195873-Cascading-metadata-in-folders';
24
25
  const AI_LINK = 'https://www.box.com/ai';
@@ -27,6 +28,7 @@ type Props = {
27
28
  canEdit: boolean,
28
29
  canUseAIFolderExtraction: boolean,
29
30
  canUseAIFolderExtractionAgentSelector: boolean,
31
+ cascadePolicyConfiguration?: MetadataCascadePolicyConfiguration,
30
32
  isAIFolderExtractionEnabled: boolean,
31
33
  isCascadingEnabled: boolean,
32
34
  isCascadingOverwritten: boolean,
@@ -43,6 +45,7 @@ const CascadePolicy = ({
43
45
  canEdit,
44
46
  canUseAIFolderExtraction,
45
47
  canUseAIFolderExtractionAgentSelector,
48
+ cascadePolicyConfiguration,
46
49
  isCascadingEnabled,
47
50
  isCascadingOverwritten,
48
51
  isCustomMetadata,
@@ -62,6 +65,8 @@ const CascadePolicy = ({
62
65
  </div>
63
66
  ) : null;
64
67
 
68
+ const isEnhancedAgentSelected = cascadePolicyConfiguration?.agent === ENHANCED_AGENT_CONFIGURATION;
69
+
65
70
  const agents = React.useMemo(
66
71
  () => [
67
72
  {
@@ -74,9 +79,10 @@ const CascadePolicy = ({
74
79
  name: formatMessage(messages.enhancedAgentName),
75
80
  isEnterpriseDefault: false,
76
81
  customIcon: BoxAiAdvancedColor,
82
+ isSelected: isEnhancedAgentSelected,
77
83
  },
78
84
  ],
79
- [formatMessage],
85
+ [formatMessage, isEnhancedAgentSelected],
80
86
  );
81
87
 
82
88
  // BoxAiAgentSelectorWithApiContainer expects a function that returns a Promise<AgentListResponse>
@@ -700,6 +700,7 @@ class Instance extends React.PureComponent<Props, State> {
700
700
  <div className="metadata-instance-editor-instance">
701
701
  {isCascadingPolicyApplicable && (
702
702
  <CascadePolicy
703
+ cascadePolicyConfiguration={cascadePolicy?.cascadePolicyConfiguration}
703
704
  canEdit={isEditing && !!cascadePolicy.canEdit}
704
705
  canUseAIFolderExtraction={canUseAIFolderExtraction}
705
706
  canUseAIFolderExtractionAgentSelector={
@@ -176,6 +176,51 @@ describe('features/metadata-instance-editor/CascadePolicy', () => {
176
176
 
177
177
  expect(onAIAgentSelect).toHaveBeenCalledWith(expectedAgent);
178
178
  });
179
+
180
+ test('should render with cascadePolicyConfiguration prop and select enhanced agent if configured', async () => {
181
+ const cascadePolicyConfiguration = {
182
+ agent: 'enhanced_extract_agent',
183
+ };
184
+ render(
185
+ <CascadePolicy
186
+ canEdit
187
+ canUseAIFolderExtraction
188
+ canUseAIFolderExtractionAgentSelector
189
+ shouldShowCascadeOptions
190
+ isAIFolderExtractionEnabled
191
+ cascadePolicyConfiguration={cascadePolicyConfiguration}
192
+ onAIFolderExtractionToggle={jest.fn()}
193
+ />,
194
+ );
195
+ const aiToggle = screen.getByRole('switch', { name: 'Box AI Autofill' });
196
+ await userEvent.click(aiToggle); // Enable AI
197
+
198
+ expect(aiToggle).toBeChecked();
199
+
200
+ // The Enhanced agent should be selected in the combobox
201
+ const combobox = screen.getByRole('combobox', { name: 'Enhanced' });
202
+ expect(combobox).toBeInTheDocument();
203
+ });
204
+
205
+ test('should render standard agent if cascadePolicyConfiguration is undefined', async () => {
206
+ render(
207
+ <CascadePolicy
208
+ canEdit
209
+ canUseAIFolderExtraction
210
+ canUseAIFolderExtractionAgentSelector
211
+ shouldShowCascadeOptions
212
+ isAIFolderExtractionEnabled
213
+ onAIFolderExtractionToggle={jest.fn()}
214
+ />,
215
+ );
216
+ const aiToggle = screen.getByRole('switch', { name: 'Box AI Autofill' });
217
+ await userEvent.click(aiToggle); // Enable AI
218
+
219
+ expect(aiToggle).toBeChecked();
220
+
221
+ // Should default to Standard agent
222
+ expect(screen.getByRole('combobox', { name: 'Standard' })).toBeInTheDocument();
223
+ });
179
224
  });
180
225
 
181
226
  describe('AI Autofill Toggle', () => {