@ng-forge/dynamic-forms 0.4.0 → 0.5.0

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 (22) hide show
  1. package/README.md +3 -0
  2. package/fesm2022/ng-forge-dynamic-forms-integration.mjs +18 -52
  3. package/fesm2022/ng-forge-dynamic-forms-integration.mjs.map +1 -1
  4. package/fesm2022/{ng-forge-dynamic-forms-ng-forge-dynamic-forms-DHxoGouT.mjs → ng-forge-dynamic-forms-ng-forge-dynamic-forms-WGww2nXx.mjs} +3401 -294
  5. package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-WGww2nXx.mjs.map +1 -0
  6. package/fesm2022/{ng-forge-dynamic-forms-page-field.component-Bt6blv9I.mjs → ng-forge-dynamic-forms-page-field.component-CrO9WTDw.mjs} +2 -2
  7. package/fesm2022/{ng-forge-dynamic-forms-page-field.component-Bt6blv9I.mjs.map → ng-forge-dynamic-forms-page-field.component-CrO9WTDw.mjs.map} +1 -1
  8. package/fesm2022/ng-forge-dynamic-forms-schema.mjs +92 -0
  9. package/fesm2022/ng-forge-dynamic-forms-schema.mjs.map +1 -0
  10. package/fesm2022/{ng-forge-dynamic-forms-text-field.component-DKCx7Z_U.mjs → ng-forge-dynamic-forms-text-field.component-BcFx_kOz.mjs} +2 -2
  11. package/fesm2022/{ng-forge-dynamic-forms-text-field.component-DKCx7Z_U.mjs.map → ng-forge-dynamic-forms-text-field.component-BcFx_kOz.mjs.map} +1 -1
  12. package/fesm2022/ng-forge-dynamic-forms.mjs +1 -1
  13. package/package.json +5 -4
  14. package/types/ng-forge-dynamic-forms-integration.d.ts +3 -14
  15. package/types/ng-forge-dynamic-forms-schema.d.ts +178 -0
  16. package/types/ng-forge-dynamic-forms.d.ts +766 -35
  17. package/fesm2022/ng-forge-dynamic-forms-ng-forge-dynamic-forms-DHxoGouT.mjs.map +0 -1
  18. package/fesm2022/ng-forge-dynamic-forms-testing-test-button.harness-C79EBW0o.mjs +0 -31
  19. package/fesm2022/ng-forge-dynamic-forms-testing-test-button.harness-C79EBW0o.mjs.map +0 -1
  20. package/fesm2022/ng-forge-dynamic-forms-testing.mjs +0 -973
  21. package/fesm2022/ng-forge-dynamic-forms-testing.mjs.map +0 -1
  22. package/types/ng-forge-dynamic-forms-testing.d.ts +0 -603
@@ -1,973 +0,0 @@
1
- import { vi } from 'vitest';
2
- import { ConsoleLogger, DynamicFormLogger, DynamicForm, BUILT_IN_FIELDS, FIELD_SIGNAL_CONTEXT, DEFAULT_VALIDATION_MESSAGES, FORM_OPTIONS, provideDynamicForm, EventBus, FIELD_REGISTRY } from '@ng-forge/dynamic-forms';
3
- import { TestBed } from '@angular/core/testing';
4
- import * as i0 from '@angular/core';
5
- import { computed, signal, Injector, runInInjectionContext, input, Component, ChangeDetectionStrategy, Injectable } from '@angular/core';
6
- import { firstValueFrom, race, timer, BehaviorSubject } from 'rxjs';
7
- import { map } from 'rxjs/operators';
8
- import { valueFieldMapper, checkboxFieldMapper } from '@ng-forge/dynamic-forms/integration';
9
- import { form, FormField } from '@angular/forms/signals';
10
-
11
- /**
12
- * Creates a promise that resolves after the specified delay.
13
- *
14
- * Utility function for testing scenarios where you need to wait for
15
- * asynchronous operations, animations, or timing-dependent behavior.
16
- *
17
- * @param ms - Delay in milliseconds (defaults to 0 for next tick)
18
- * @returns Promise that resolves after the specified delay
19
- *
20
- * @example
21
- * ```typescript
22
- * // Wait for async operations in tests
23
- * await delay(100);
24
- * expect(component.isLoaded).toBe(true);
25
- *
26
- * // Wait for next tick (micro-task)
27
- * await delay();
28
- * fixture.detectChanges();
29
- * ```
30
- */
31
- function delay(ms = 0) {
32
- return new Promise((resolve) => setTimeout(resolve, ms));
33
- }
34
-
35
- /**
36
- * Creates a mock logger with vitest spies for all methods.
37
- * Useful for testing code that uses the logger.
38
- */
39
- function createMockLogger() {
40
- return {
41
- debug: vi.fn(),
42
- info: vi.fn(),
43
- warn: vi.fn(),
44
- error: vi.fn(),
45
- };
46
- }
47
- /**
48
- * Provider for a console logger in tests.
49
- * Add this to TestBed.configureTestingModule providers when not using provideDynamicForm().
50
- */
51
- function provideTestLogger() {
52
- return { provide: DynamicFormLogger, useValue: new ConsoleLogger() };
53
- }
54
-
55
- /**
56
- * Fluent API for building form configurations
57
- */
58
- class FormConfigBuilder {
59
- fields = [];
60
- field(field) {
61
- this.fields.push(field);
62
- return this;
63
- }
64
- inputField(key, props) {
65
- return this.field({
66
- key,
67
- type: 'input',
68
- label: key.charAt(0).toUpperCase() + key.slice(1),
69
- props: { placeholder: `Enter ${key}`, ...props },
70
- });
71
- }
72
- requiredInputField(key, props) {
73
- const inputField = {
74
- key,
75
- type: 'input',
76
- label: key.charAt(0).toUpperCase() + key.slice(1),
77
- required: true,
78
- props: { placeholder: `Enter ${key}`, ...props },
79
- };
80
- return this.field(inputField);
81
- }
82
- selectField(key, options, props) {
83
- const selectField = {
84
- key,
85
- type: 'select',
86
- label: key.charAt(0).toUpperCase() + key.slice(1),
87
- options,
88
- props: props || {},
89
- };
90
- return this.field(selectField);
91
- }
92
- checkboxField(key, props) {
93
- return this.field({
94
- key,
95
- type: 'checkbox',
96
- label: key.charAt(0).toUpperCase() + key.slice(1),
97
- props: props || {},
98
- });
99
- }
100
- rowField(key, fields) {
101
- return this.field({
102
- key,
103
- type: 'row',
104
- fields,
105
- });
106
- }
107
- groupField(key, fields) {
108
- return this.field({
109
- key,
110
- type: 'group',
111
- fields,
112
- });
113
- }
114
- buttonField(key, props) {
115
- return this.field({
116
- key,
117
- type: 'button',
118
- label: key.charAt(0).toUpperCase() + key.slice(1),
119
- props: props || {},
120
- });
121
- }
122
- pageField(key, fields, title) {
123
- const pageFields = title ? [{ key: `${key}-title`, type: 'text', label: title }, ...fields] : fields;
124
- return this.field({
125
- key,
126
- type: 'page',
127
- fields: pageFields,
128
- });
129
- }
130
- build() {
131
- return { fields: this.fields };
132
- }
133
- }
134
- /**
135
- * Utility class for testing dynamic forms
136
- */
137
- class DynamicFormTestUtils {
138
- /**
139
- * Creates a new form config builder
140
- */
141
- static builder() {
142
- return new FormConfigBuilder();
143
- }
144
- /**
145
- * Creates a dynamic form test setup with optional test field registration
146
- */
147
- static async createTest(testConfig) {
148
- const fixture = TestBed.createComponent(DynamicForm);
149
- const component = fixture.componentInstance;
150
- // Access fieldRegistry from the component instance (injected by Angular DI)
151
- const fieldRegistry = component['fieldRegistry'];
152
- // Register test fields if requested
153
- if (testConfig.registerTestFields !== false) {
154
- DynamicFormTestUtils.registerTestFields(fieldRegistry);
155
- }
156
- // Set up the component - use 'dynamic-form' as the input name since config uses alias: 'dynamic-form'
157
- fixture.componentRef.setInput('dynamic-form', testConfig.config);
158
- if (testConfig.initialValue !== undefined) {
159
- fixture.componentRef.setInput('value', testConfig.initialValue);
160
- }
161
- fixture.detectChanges();
162
- await DynamicFormTestUtils.waitForInit(fixture);
163
- return {
164
- component: component,
165
- fixture: fixture,
166
- };
167
- }
168
- /**
169
- * Registers common test field types including built-in types like page, row, group
170
- * @internal
171
- */
172
- static registerTestFields(fieldRegistry) {
173
- // Input field mapper that extends value field mapper (returns Signal)
174
- const inputMapper = (fieldDef) => {
175
- const baseInputsSignal = valueFieldMapper(fieldDef);
176
- // Return computed signal that adds input-specific inputs
177
- return computed(() => ({
178
- ...baseInputsSignal(),
179
- type: fieldDef.props?.['type'] || 'text',
180
- placeholder: fieldDef.props?.['placeholder'] || '',
181
- }));
182
- };
183
- // Select field mapper that extends value field mapper (returns Signal)
184
- const selectMapper = (fieldDef) => {
185
- const baseInputsSignal = valueFieldMapper(fieldDef);
186
- // Return computed signal that adds select-specific inputs
187
- return computed(() => ({
188
- ...baseInputsSignal(),
189
- options: fieldDef.options || [], // Safe cast: SelectField extends FieldDef with options property
190
- }));
191
- };
192
- // Checkbox field mapper - uses checked instead of value (already returns Signal)
193
- const checkboxMapper = (fieldDef) => {
194
- return checkboxFieldMapper(fieldDef);
195
- };
196
- // Button field mapper that extends value field mapper (already returns Signal)
197
- const buttonMapper = (fieldDef) => {
198
- return valueFieldMapper(fieldDef);
199
- };
200
- // Register built-in fields first (page, row, group)
201
- fieldRegistry.registerTypes(BUILT_IN_FIELDS);
202
- // Then register test field types
203
- fieldRegistry.registerTypes([
204
- {
205
- name: 'input',
206
- loadComponent: () => Promise.resolve().then(function () { return testInput_harness; }),
207
- mapper: inputMapper,
208
- },
209
- {
210
- name: 'select',
211
- loadComponent: () => Promise.resolve().then(function () { return testSelect_harness; }),
212
- mapper: selectMapper,
213
- },
214
- {
215
- name: 'checkbox',
216
- loadComponent: () => Promise.resolve().then(function () { return testCheckbox_harness; }),
217
- mapper: checkboxMapper,
218
- },
219
- {
220
- name: 'button',
221
- loadComponent: () => import('./ng-forge-dynamic-forms-testing-test-button.harness-C79EBW0o.mjs'),
222
- mapper: buttonMapper,
223
- },
224
- ]);
225
- }
226
- /**
227
- * Waits for the dynamic form to initialize.
228
- * Uses the initialized$ observable directly which has shareReplay for late subscribers.
229
- * @param fixture - The component fixture
230
- * @param timeoutMs - Maximum time to wait for initialization (default: 100ms)
231
- */
232
- static async waitForInit(fixture, timeoutMs = 100) {
233
- const component = fixture.componentInstance;
234
- // Trigger initial change detection
235
- fixture.detectChanges();
236
- TestBed.flushEffects();
237
- // Use the initialized$ observable directly (with shareReplay) for proper replay behavior
238
- // Race against a timeout to prevent hanging if initialization already happened
239
- await firstValueFrom(race(component.initialized$.pipe(map(() => true)), timer(timeoutMs).pipe(map(() => false))));
240
- // Stabilization cycles for async components
241
- for (let i = 0; i < 2; i++) {
242
- TestBed.flushEffects();
243
- fixture.detectChanges();
244
- await delay(0);
245
- }
246
- await fixture.whenStable();
247
- TestBed.flushEffects();
248
- fixture.detectChanges();
249
- }
250
- /**
251
- * Waits for an element to appear in the DOM with retries
252
- */
253
- static async waitForElement(fixture, selector, maxAttempts = 10) {
254
- for (let attempt = 0; attempt < maxAttempts; attempt++) {
255
- const element = fixture.nativeElement.querySelector(selector);
256
- if (element) {
257
- return element;
258
- }
259
- // Wait and retry
260
- TestBed.flushEffects();
261
- fixture.detectChanges();
262
- await delay(50);
263
- }
264
- throw new Error(`[Dynamic Forms] Element not found with selector: ${selector} after ${maxAttempts} attempts`);
265
- }
266
- /**
267
- * Simulates user input on a field element
268
- */
269
- static async simulateInput(fixture, selector, value) {
270
- const input = await DynamicFormTestUtils.waitForElement(fixture, selector);
271
- input.value = value;
272
- input.dispatchEvent(new Event('input', { bubbles: true }));
273
- fixture.detectChanges();
274
- await delay(0);
275
- }
276
- /**
277
- * Simulates user blur on a field element
278
- */
279
- static async simulateBlur(fixture, selector) {
280
- const element = await DynamicFormTestUtils.waitForElement(fixture, selector);
281
- element.dispatchEvent(new Event('blur', { bubbles: true }));
282
- fixture.detectChanges();
283
- await delay(0);
284
- }
285
- /**
286
- * Simulates user selection on a select element
287
- */
288
- static async simulateSelect(fixture, selector, value) {
289
- const select = await DynamicFormTestUtils.waitForElement(fixture, selector);
290
- select.value = value;
291
- select.dispatchEvent(new Event('change', { bubbles: true }));
292
- fixture.detectChanges();
293
- await delay(0);
294
- }
295
- /**
296
- * Simulates checkbox toggle
297
- */
298
- static async simulateCheckbox(fixture, selector, checked) {
299
- const checkbox = await DynamicFormTestUtils.waitForElement(fixture, selector);
300
- checkbox.checked = checked;
301
- checkbox.dispatchEvent(new Event('input', { bubbles: true }));
302
- checkbox.dispatchEvent(new Event('change', { bubbles: true }));
303
- fixture.detectChanges();
304
- await delay(0);
305
- }
306
- /**
307
- * Simulates button click
308
- */
309
- static async simulateButtonClick(fixture, selector) {
310
- const button = await DynamicFormTestUtils.waitForElement(fixture, selector);
311
- button.click();
312
- fixture.detectChanges();
313
- await delay(0);
314
- }
315
- /**
316
- * Gets the current form value from the component
317
- */
318
- static getFormValue(component) {
319
- return component.formValue();
320
- }
321
- /**
322
- * Gets validation errors from the component
323
- */
324
- static getFormErrors(component) {
325
- return component.errors();
326
- }
327
- /**
328
- * Checks if the form is valid
329
- */
330
- static isFormValid(component) {
331
- return component.valid();
332
- }
333
- /**
334
- * Gets all field elements from the fixture
335
- */
336
- static getFieldElements(fixture, fieldType) {
337
- return fixture.nativeElement.querySelectorAll(`df-test-${fieldType}`);
338
- }
339
- /**
340
- * Asserts that a field has a specific value
341
- */
342
- static async assertFieldValue(fixture, fieldSelector, expectedValue) {
343
- const element = await DynamicFormTestUtils.waitForElement(fixture, fieldSelector);
344
- const actualValue = element.type === 'checkbox' ? element.checked.toString() : element.value;
345
- if (actualValue !== expectedValue) {
346
- throw new Error(`[Dynamic Forms] Expected field value to be "${expectedValue}", but got "${actualValue}"`);
347
- }
348
- }
349
- /**
350
- * Asserts that the form has a specific value
351
- */
352
- static assertFormValue(component, expectedValue) {
353
- const actualValue = component.formValue();
354
- if (JSON.stringify(actualValue) !== JSON.stringify(expectedValue)) {
355
- throw new Error(`[Dynamic Forms] Expected form value to be ${JSON.stringify(expectedValue)}, but got ${JSON.stringify(actualValue)}`);
356
- }
357
- }
358
- }
359
-
360
- /**
361
- * Creates a test injector with FIELD_SIGNAL_CONTEXT provided.
362
- *
363
- * This utility simplifies testing of mappers and components that inject FIELD_SIGNAL_CONTEXT.
364
- *
365
- * @example
366
- * ```typescript
367
- * // Basic usage
368
- * const testInjector = createTestFormInjector();
369
- *
370
- * // With custom initial value
371
- * const testInjector = createTestFormInjector({
372
- * initialValue: { username: 'test' }
373
- * });
374
- *
375
- * // With validation messages
376
- * const testInjector = createTestFormInjector({
377
- * defaultValidationMessages: { required: 'This field is required' }
378
- * });
379
- * ```
380
- */
381
- function createTestFormInjector(config = {}) {
382
- const { parentInjector, initialValue = {}, defaultValues = () => initialValue, defaultValidationMessages, formOptions, valueSignal, form: customForm, } = config;
383
- // Create value signal
384
- const value = valueSignal ?? signal(initialValue);
385
- // Create form instance in injection context
386
- let formInstance;
387
- if (customForm) {
388
- formInstance = customForm;
389
- }
390
- else {
391
- const tempInjector = parentInjector || Injector.create({ providers: [] });
392
- formInstance = runInInjectionContext(tempInjector, () => form(value));
393
- }
394
- // Create field signal context (form-level config now provided via dedicated tokens)
395
- const fieldSignalContext = {
396
- injector: parentInjector || Injector.create({ providers: [] }),
397
- value,
398
- defaultValues,
399
- form: formInstance,
400
- };
401
- // Build providers array with all tokens
402
- const providers = [{ provide: FIELD_SIGNAL_CONTEXT, useValue: fieldSignalContext }];
403
- if (defaultValidationMessages !== undefined) {
404
- providers.push({ provide: DEFAULT_VALIDATION_MESSAGES, useValue: defaultValidationMessages });
405
- }
406
- if (formOptions !== undefined) {
407
- providers.push({ provide: FORM_OPTIONS, useValue: formOptions });
408
- }
409
- // Create injector with context and tokens
410
- return Injector.create({
411
- parent: parentInjector,
412
- providers,
413
- });
414
- }
415
- /**
416
- * Runs a mapper function in a test injection context.
417
- *
418
- * This is a convenience wrapper that creates a test injector and runs the mapper
419
- * function within it, returning the result.
420
- *
421
- * @example
422
- * ```typescript
423
- * // Test a mapper without context overrides
424
- * const bindings = testMapper(() => mapValueField(fieldDef));
425
- *
426
- * // Test a mapper with custom context
427
- * const bindings = testMapper(
428
- * () => mapValueField(fieldDef),
429
- * { initialValue: { username: 'test' } }
430
- * );
431
- *
432
- * // Test a mapper with validation messages
433
- * const bindings = testMapper(
434
- * () => mapValueField(fieldDef),
435
- * { defaultValidationMessages: { required: 'Required field' } }
436
- * );
437
- * ```
438
- */
439
- function testMapper(mapperFn, context) {
440
- const testInjector = createTestFormInjector(context);
441
- return runInInjectionContext(testInjector, mapperFn);
442
- }
443
- /**
444
- * Creates a field signal context for testing without creating an injector.
445
- *
446
- * Useful when you need to manually provide the context or test context creation logic.
447
- *
448
- * @example
449
- * ```typescript
450
- * const context = createTestFieldContext({
451
- * initialValue: { name: 'test' }
452
- * });
453
- *
454
- * // Use in your own injector
455
- * const injector = Injector.create({
456
- * providers: [
457
- * { provide: FIELD_SIGNAL_CONTEXT, useValue: context }
458
- * ]
459
- * });
460
- * ```
461
- */
462
- function createTestFieldContext(config = {}) {
463
- const { parentInjector, initialValue = {}, defaultValues = () => initialValue, valueSignal, form: customForm, } = config;
464
- const injector = parentInjector || Injector.create({ providers: [] });
465
- const value = valueSignal ?? signal(initialValue);
466
- let formInstance;
467
- if (customForm) {
468
- formInstance = customForm;
469
- }
470
- else {
471
- formInstance = runInInjectionContext(injector, () => form(value));
472
- }
473
- // Note: defaultValidationMessages and formOptions are no longer in FieldSignalContext
474
- // They should be provided via their respective injection tokens
475
- return {
476
- injector,
477
- value,
478
- defaultValues,
479
- form: formInstance,
480
- };
481
- }
482
-
483
- /**
484
- * Fluent API for building form configurations using existing field structure
485
- */
486
- class TestFormConfigBuilder {
487
- fields = [];
488
- field(field) {
489
- this.fields.push(field);
490
- return this;
491
- }
492
- inputField(key, props) {
493
- return this.field({
494
- key,
495
- type: 'input',
496
- label: key.charAt(0).toUpperCase() + key.slice(1),
497
- ...props,
498
- });
499
- }
500
- requiredInputField(key, props) {
501
- return this.inputField(key, { required: true, ...props });
502
- }
503
- checkboxField(key, props) {
504
- return this.field({
505
- key,
506
- type: 'checkbox',
507
- label: key.charAt(0).toUpperCase() + key.slice(1),
508
- ...props,
509
- });
510
- }
511
- build() {
512
- return { fields: this.fields };
513
- }
514
- }
515
- /**
516
- * Simple utility class for testing dynamic forms
517
- */
518
- class SimpleTestUtils {
519
- /**
520
- * Creates a new form config builder
521
- */
522
- static builder() {
523
- return new TestFormConfigBuilder();
524
- }
525
- /**
526
- * Creates a simple test component - assumes TestBed is already configured
527
- */
528
- static createComponent(config = { fields: [] }, initialValue) {
529
- const fixture = TestBed.createComponent(DynamicForm);
530
- const component = fixture.componentInstance;
531
- // Use 'dynamic-form' as the input name since config uses alias: 'dynamic-form'
532
- fixture.componentRef.setInput('dynamic-form', config);
533
- if (initialValue !== undefined) {
534
- fixture.componentRef.setInput('value', initialValue);
535
- }
536
- fixture.detectChanges();
537
- TestBed.flushEffects();
538
- // Cast to SimpleTestResult - type variance in DynamicForm generics doesn't affect runtime behavior
539
- return { component, fixture };
540
- }
541
- /**
542
- * Waits for the dynamic form to initialize
543
- */
544
- static async waitForInit(fixture) {
545
- await delay(0);
546
- fixture.detectChanges();
547
- TestBed.flushEffects();
548
- await delay(0);
549
- }
550
- /**
551
- * Simulates user input on a field element
552
- */
553
- static async simulateInput(fixture, selector, value) {
554
- const input = fixture.nativeElement.querySelector(selector);
555
- if (!input) {
556
- throw new Error(`[Dynamic Forms] Input element not found with selector: ${selector}`);
557
- }
558
- input.value = value;
559
- input.dispatchEvent(new Event('input', { bubbles: true }));
560
- fixture.detectChanges();
561
- await delay(0);
562
- }
563
- /**
564
- * Simulates checkbox toggle
565
- */
566
- static async simulateCheckbox(fixture, selector, checked) {
567
- const checkbox = fixture.nativeElement.querySelector(selector);
568
- if (!checkbox) {
569
- throw new Error(`[Dynamic Forms] Checkbox element not found with selector: ${selector}`);
570
- }
571
- checkbox.checked = checked;
572
- checkbox.dispatchEvent(new Event('change', { bubbles: true }));
573
- fixture.detectChanges();
574
- await delay(0);
575
- }
576
- /**
577
- * Gets the current form value from the component
578
- */
579
- static getFormValue(component) {
580
- return component.formValue();
581
- }
582
- /**
583
- * Checks if the form is valid
584
- */
585
- static isFormValid(component) {
586
- return component.valid();
587
- }
588
- /**
589
- * Asserts that the form has a specific value
590
- */
591
- static assertFormValue(component, expectedValue) {
592
- const actualValue = component.formValue();
593
- if (JSON.stringify(actualValue) !== JSON.stringify(expectedValue)) {
594
- throw new Error(`[Dynamic Forms] Expected form value to be ${JSON.stringify(expectedValue)}, but got ${JSON.stringify(actualValue)}`);
595
- }
596
- }
597
- }
598
- // Mock field component for testing
599
- // Includes all inputs that baseFieldMapper and valueFieldMapper might create bindings for
600
- class TestFieldComponent {
601
- // Field tree input
602
- field = input(...(ngDevMode ? [undefined, { debugName: "field" }] : []));
603
- // Required inputs from baseFieldMapper
604
- key = input('', ...(ngDevMode ? [{ debugName: "key" }] : []));
605
- label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
606
- className = input('', ...(ngDevMode ? [{ debugName: "className" }] : []));
607
- tabIndex = input(undefined, ...(ngDevMode ? [{ debugName: "tabIndex" }] : []));
608
- props = input(undefined, ...(ngDevMode ? [{ debugName: "props" }] : []));
609
- placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
610
- // Array-related inputs
611
- arrayContext = input(undefined, ...(ngDevMode ? [{ debugName: "arrayContext" }] : []));
612
- fields = input([], ...(ngDevMode ? [{ debugName: "fields" }] : []));
613
- // Validation inputs from valueFieldMapper
614
- validationMessages = input(undefined, ...(ngDevMode ? [{ debugName: "validationMessages" }] : []));
615
- defaultValidationMessages = input(undefined, ...(ngDevMode ? [{ debugName: "defaultValidationMessages" }] : []));
616
- value = signal('test', ...(ngDevMode ? [{ debugName: "value" }] : []));
617
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TestFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
618
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.0", type: TestFieldComponent, isStandalone: true, selector: "df-test-field", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: false, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, arrayContext: { classPropertyName: "arrayContext", publicName: "arrayContext", isSignal: true, isRequired: false, transformFunction: null }, fields: { classPropertyName: "fields", publicName: "fields", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '<div>Test Field: {{ value() }}</div>', isInline: true });
619
- }
620
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TestFieldComponent, decorators: [{
621
- type: Component,
622
- args: [{
623
- selector: 'df-test-field',
624
- template: '<div>Test Field: {{ value() }}</div>',
625
- }]
626
- }], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: false }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], arrayContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "arrayContext", required: false }] }], fields: [{ type: i0.Input, args: [{ isSignal: true, alias: "fields", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
627
- /**
628
- * Creates a simple test setup for individual field components
629
- */
630
- function setupSimpleTest(componentType, config) {
631
- const mockFieldType = {
632
- name: 'test',
633
- loadComponent: async () => TestFieldComponent,
634
- mapper: () => computed(() => ({})), // Simple mapper that returns empty inputs signal for testing
635
- };
636
- TestBed.configureTestingModule({
637
- imports: [componentType],
638
- providers: [
639
- provideDynamicForm(),
640
- EventBus,
641
- {
642
- provide: FIELD_REGISTRY,
643
- useValue: new Map([['test', mockFieldType]]),
644
- },
645
- {
646
- provide: FIELD_SIGNAL_CONTEXT,
647
- useFactory: (injector) => {
648
- // Create test context using factory
649
- return runInInjectionContext(injector, () => {
650
- const defaultValue = (config.value || {});
651
- const valueSignal = signal(defaultValue, ...(ngDevMode ? [{ debugName: "valueSignal" }] : []));
652
- const formInstance = form(valueSignal);
653
- return {
654
- injector,
655
- value: valueSignal,
656
- defaultValues: () => defaultValue,
657
- form: formInstance,
658
- };
659
- });
660
- },
661
- deps: [Injector],
662
- },
663
- ],
664
- });
665
- const fixture = TestBed.createComponent(componentType);
666
- const component = fixture.componentInstance;
667
- fixture.componentRef.setInput('field', config.field);
668
- fixture.componentRef.setInput('key', config.field.key);
669
- if (config.value !== undefined) {
670
- fixture.componentRef.setInput('value', config.value);
671
- }
672
- if (config.pageIndex !== undefined) {
673
- fixture.componentRef.setInput('pageIndex', config.pageIndex);
674
- }
675
- if (config.isVisible !== undefined) {
676
- fixture.componentRef.setInput('isVisible', config.isVisible);
677
- }
678
- // Set any additional inputs provided in config
679
- Object.keys(config).forEach((key) => {
680
- if (!['field', 'value', 'pageIndex', 'isVisible'].includes(key) && config[key] !== undefined) {
681
- fixture.componentRef.setInput(key, config[key]);
682
- }
683
- });
684
- fixture.detectChanges();
685
- return { component, fixture };
686
- }
687
- /**
688
- * Creates a simple test field definition
689
- */
690
- function createSimpleTestField(key, label) {
691
- return {
692
- key,
693
- type: 'test',
694
- label,
695
- };
696
- }
697
-
698
- class TestInputHarness {
699
- field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
700
- key = input.required(...(ngDevMode ? [{ debugName: "key" }] : []));
701
- // Field-specific properties
702
- label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
703
- placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
704
- type = input('text', ...(ngDevMode ? [{ debugName: "type" }] : []));
705
- props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : []));
706
- className = input('', ...(ngDevMode ? [{ debugName: "className" }] : []));
707
- validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : []));
708
- defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : []));
709
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TestInputHarness, deps: [], target: i0.ɵɵFactoryTarget.Component });
710
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.0", type: TestInputHarness, isStandalone: true, selector: "df-test-input", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `<input [type]="type()" [formField]="field()" />`, isInline: true, dependencies: [{ kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
711
- }
712
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TestInputHarness, decorators: [{
713
- type: Component,
714
- args: [{
715
- selector: 'df-test-input',
716
- template: `<input [type]="type()" [formField]="field()" />`,
717
- changeDetection: ChangeDetectionStrategy.OnPush,
718
- imports: [FormField],
719
- }]
720
- }], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
721
-
722
- var testInput_harness = /*#__PURE__*/Object.freeze({
723
- __proto__: null,
724
- default: TestInputHarness
725
- });
726
-
727
- class TestCheckboxHarness {
728
- field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
729
- key = input.required(...(ngDevMode ? [{ debugName: "key" }] : []));
730
- // Field-specific properties
731
- label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
732
- props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : []));
733
- className = input('', ...(ngDevMode ? [{ debugName: "className" }] : []));
734
- validationMessages = input(...(ngDevMode ? [undefined, { debugName: "validationMessages" }] : []));
735
- defaultValidationMessages = input(...(ngDevMode ? [undefined, { debugName: "defaultValidationMessages" }] : []));
736
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TestCheckboxHarness, deps: [], target: i0.ɵɵFactoryTarget.Component });
737
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.0", type: TestCheckboxHarness, isStandalone: true, selector: "df-test-checkbox", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, validationMessages: { classPropertyName: "validationMessages", publicName: "validationMessages", isSignal: true, isRequired: false, transformFunction: null }, defaultValidationMessages: { classPropertyName: "defaultValidationMessages", publicName: "defaultValidationMessages", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: ` <input type="checkbox" [formField]="field()" /> `, isInline: true, dependencies: [{ kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
738
- }
739
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TestCheckboxHarness, decorators: [{
740
- type: Component,
741
- args: [{
742
- selector: 'df-test-checkbox',
743
- template: ` <input type="checkbox" [formField]="field()" /> `,
744
- changeDetection: ChangeDetectionStrategy.OnPush,
745
- imports: [FormField],
746
- }]
747
- }], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], validationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationMessages", required: false }] }], defaultValidationMessages: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValidationMessages", required: false }] }] } });
748
-
749
- var testCheckbox_harness = /*#__PURE__*/Object.freeze({
750
- __proto__: null,
751
- default: TestCheckboxHarness
752
- });
753
-
754
- /**
755
- * Test harness component for select fields
756
- */
757
- class TestSelectHarness {
758
- field = input.required(...(ngDevMode ? [{ debugName: "field" }] : []));
759
- key = input.required(...(ngDevMode ? [{ debugName: "key" }] : []));
760
- // Field-specific properties
761
- label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
762
- options = input([], ...(ngDevMode ? [{ debugName: "options" }] : []));
763
- className = input('', ...(ngDevMode ? [{ debugName: "className" }] : []));
764
- tabIndex = input(undefined, ...(ngDevMode ? [{ debugName: "tabIndex" }] : []));
765
- hidden = input(false, ...(ngDevMode ? [{ debugName: "hidden" }] : []));
766
- readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : []));
767
- props = input({}, ...(ngDevMode ? [{ debugName: "props" }] : []));
768
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TestSelectHarness, deps: [], target: i0.ɵɵFactoryTarget.Component });
769
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: TestSelectHarness, isStandalone: true, selector: "df-test-select", inputs: { field: { classPropertyName: "field", publicName: "field", isSignal: true, isRequired: true, transformFunction: null }, key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, tabIndex: { classPropertyName: "tabIndex", publicName: "tabIndex", isSignal: true, isRequired: false, transformFunction: null }, hidden: { classPropertyName: "hidden", publicName: "hidden", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, props: { classPropertyName: "props", publicName: "props", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
770
- @let f = field();
771
- <select [formField]="f">
772
- <option value="">Select...</option>
773
- @for (option of options(); track option.value) {
774
- <option [value]="option.value">{{ option.label }}</option>
775
- }
776
- </select>
777
- `, isInline: true, dependencies: [{ kind: "directive", type: FormField, selector: "[formField]", inputs: ["formField"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
778
- }
779
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TestSelectHarness, decorators: [{
780
- type: Component,
781
- args: [{
782
- selector: 'df-test-select',
783
- template: `
784
- @let f = field();
785
- <select [formField]="f">
786
- <option value="">Select...</option>
787
- @for (option of options(); track option.value) {
788
- <option [value]="option.value">{{ option.label }}</option>
789
- }
790
- </select>
791
- `,
792
- changeDetection: ChangeDetectionStrategy.OnPush,
793
- imports: [FormField],
794
- }]
795
- }], propDecorators: { field: [{ type: i0.Input, args: [{ isSignal: true, alias: "field", required: true }] }], key: [{ type: i0.Input, args: [{ isSignal: true, alias: "key", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], tabIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabIndex", required: false }] }], hidden: [{ type: i0.Input, args: [{ isSignal: true, alias: "hidden", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], props: [{ type: i0.Input, args: [{ isSignal: true, alias: "props", required: false }] }] } });
796
-
797
- var testSelect_harness = /*#__PURE__*/Object.freeze({
798
- __proto__: null,
799
- default: TestSelectHarness
800
- });
801
-
802
- /**
803
- * Fake translation service for testing dynamic text functionality.
804
- * Provides Observable-based translation methods with language switching simulation.
805
- *
806
- * @example
807
- * ```typescript
808
- * TestBed.configureTestingModule({
809
- * providers: [
810
- * { provide: TranslationService, useClass: FakeTranslationService }
811
- * ]
812
- * });
813
- *
814
- * const service = TestBed.inject(FakeTranslationService);
815
- * service.setTranslations({
816
- * 'form.username.label': 'Username',
817
- * 'validation.required': 'This field is required'
818
- * });
819
- * ```
820
- *
821
- * @public
822
- */
823
- class FakeTranslationService {
824
- translations = new BehaviorSubject({});
825
- currentLanguage = signal('en', ...(ngDevMode ? [{ debugName: "currentLanguage" }] : []));
826
- /**
827
- * Set the translation dictionary
828
- */
829
- setTranslations(translations) {
830
- this.translations.next(translations);
831
- }
832
- /**
833
- * Add translations to the existing dictionary
834
- */
835
- addTranslations(translations) {
836
- const current = this.translations.value;
837
- this.translations.next({ ...current, ...translations });
838
- }
839
- /**
840
- * Simulate language change
841
- */
842
- setLanguage(language) {
843
- this.currentLanguage.set(language);
844
- // Trigger translation updates by emitting current translations
845
- this.translations.next(this.translations.value);
846
- }
847
- /**
848
- * Get current language as signal
849
- */
850
- getLanguage() {
851
- return this.currentLanguage;
852
- }
853
- /**
854
- * Translate a key and return an Observable
855
- * Supports parameter interpolation using {{param}} syntax
856
- */
857
- translate(key, params) {
858
- return this.translations.pipe(map((translations) => {
859
- const translatedValue = translations[key] || key;
860
- return this.interpolateParams(translatedValue, params);
861
- }));
862
- }
863
- /**
864
- * Get instant translation (synchronous)
865
- * Supports parameter interpolation using {{param}} syntax
866
- */
867
- instant(key, params) {
868
- const translations = this.translations.value;
869
- const translatedValue = translations[key] || key;
870
- return this.interpolateParams(translatedValue, params);
871
- }
872
- /**
873
- * Simulate translation for validation errors
874
- * Uses validation.${errorKind} pattern
875
- */
876
- translateValidationError(errorKind, params) {
877
- const key = `validation.${errorKind}`;
878
- return this.translate(key, params);
879
- }
880
- /**
881
- * Get all current translations
882
- */
883
- getTranslations() {
884
- return this.translations.value;
885
- }
886
- /**
887
- * Clear all translations
888
- */
889
- clearTranslations() {
890
- this.translations.next({});
891
- }
892
- interpolateParams(template, params) {
893
- if (!params) {
894
- return template;
895
- }
896
- let result = template;
897
- Object.entries(params).forEach(([key, value]) => {
898
- const placeholder = new RegExp(`{{\\s*${key}\\s*}}`, 'g');
899
- result = result.replace(placeholder, String(value));
900
- });
901
- return result;
902
- }
903
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: FakeTranslationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
904
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: FakeTranslationService, providedIn: 'root' });
905
- }
906
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: FakeTranslationService, decorators: [{
907
- type: Injectable,
908
- args: [{
909
- providedIn: 'root',
910
- }]
911
- }] });
912
- /**
913
- * Default translations for common form fields and validation messages
914
- * Useful for quick testing setup
915
- */
916
- const DEFAULT_TEST_TRANSLATIONS = {
917
- // Form field labels
918
- 'form.username.label': 'Username',
919
- 'form.email.label': 'Email Address',
920
- 'form.password.label': 'Password',
921
- 'form.firstName.label': 'First Name',
922
- 'form.lastName.label': 'Last Name',
923
- 'form.phone.label': 'Phone Number',
924
- 'form.address.label': 'Address',
925
- // Form field placeholders
926
- 'form.username.placeholder': 'Enter your username',
927
- 'form.email.placeholder': 'Enter your email address',
928
- 'form.password.placeholder': 'Enter your password',
929
- // Validation messages
930
- 'validation.required': 'This field is required',
931
- 'validation.email': 'Please enter a valid email address',
932
- 'validation.min': 'Value must be at least {{min}}',
933
- 'validation.max': 'Value must be at most {{max}}',
934
- 'validation.minLength': 'Must be at least {{requiredLength}} characters',
935
- 'validation.maxLength': 'Must be at most {{requiredLength}} characters',
936
- 'validation.pattern': 'Invalid format',
937
- // Button labels
938
- 'buttons.submit': 'Submit',
939
- 'buttons.cancel': 'Cancel',
940
- 'buttons.save': 'Save',
941
- 'buttons.delete': 'Delete',
942
- 'buttons.edit': 'Edit',
943
- // Multi-language examples for testing language switching
944
- greeting: 'Hello',
945
- goodbye: 'Goodbye',
946
- };
947
- /**
948
- * Alternative translations for testing language switching
949
- */
950
- const SPANISH_TEST_TRANSLATIONS = {
951
- 'form.username.label': 'Nombre de usuario',
952
- 'form.email.label': 'Dirección de correo electrónico',
953
- 'form.password.label': 'Contraseña',
954
- 'validation.required': 'Este campo es obligatorio',
955
- 'validation.email': 'Por favor ingrese una dirección de correo válida',
956
- greeting: 'Hola',
957
- goodbye: 'Adiós',
958
- };
959
- /**
960
- * Test utility to create a configured FakeTranslationService with default translations
961
- */
962
- function createTestTranslationService(initialTranslations = DEFAULT_TEST_TRANSLATIONS) {
963
- const service = new FakeTranslationService();
964
- service.setTranslations(initialTranslations);
965
- return service;
966
- }
967
-
968
- /**
969
- * Generated bundle index. Do not edit.
970
- */
971
-
972
- export { DEFAULT_TEST_TRANSLATIONS, DynamicFormTestUtils, FakeTranslationService, FormConfigBuilder, SPANISH_TEST_TRANSLATIONS, TestFormConfigBuilder as SimpleFormConfigBuilder, SimpleTestUtils, TestCheckboxHarness as TestCheckboxHarnessComponent, TestFieldComponent, TestInputHarness as TestInputHarnessComponent, TestSelectHarness as TestSelectHarnessComponent, createMockLogger, createSimpleTestField, createTestFieldContext, createTestFormInjector, createTestTranslationService, delay, provideTestLogger, setupSimpleTest, testMapper };
973
- //# sourceMappingURL=ng-forge-dynamic-forms-testing.mjs.map