All files / generators form-suite.generator.ts

97.19% Statements 104/107
90% Branches 18/20
100% Functions 1/1
97.19% Lines 104/107

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 1081x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 23x 23x 1x 1x 1x 1x 23x 23x 23x 23x 23x 23x 23x 23x 23x 23x       22x 22x 22x 22x 22x 22x 22x 23x 23x 23x 23x 23x 23x 23x 16x 16x 16x 16x 15x 15x 15x 15x 15x 15x 15x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 1x  
import { DyE2E_TestRunMode_Type } from '../contracts/_enums/test-run-mode-type.enum';
import { getTestCaseSet } from '../contracts/_collections/test-case-sets/field-type-registry.const';
import { DyE2E_FieldTestSuite_Override } from '../contracts/_models/interfaces/form-test-suite-settings.interface';
import { DyE2E_FieldEmission_Util } from './_collections/field-emission.util';
import { DyE2E_FormLevelEmission_Util } from './_collections/form-level-emission.util';
import { DyE2E_SpecEmission_Util } from './_collections/spec-emission.util';
import { DyE2E_TestCaseFilter_Util } from './_collections/test-case-filter.util';
import { DyE2E_FormSuiteGenerate_Options } from './_models/form-suite-generate-options.interface';
 
/**
 * A FŐ GENERATOR. Bemenet: a `formSettings` (duck-typed POJO) + `formRoute` +
 * opcionális `suiteSettings`. Kimenet: emit-elt Playwright `spec.ts` string.
 *
 * Sample usage:
 * ```ts
 * import { DyE2E_FormSuite_Generator } from '@futdevpro/dynamo-e2e/generators';
 *
 * const spec: string = DyE2E_FormSuite_Generator.emit({
 *   formSettings: myFormSettings,
 *   formRoute: '/login',
 *   formSelector: 'dynamo-form-new',
 * });
 *
 * // → fs.writeFileSync('e2e/tests/generated/my-form.spec.ts', spec);
 * ```
 */
export class DyE2E_FormSuite_Generator {
 
  /** A Wave-2-ben dátum-stamp; Wave-1: stable string a snapshot-teszt miatt. */
  static readonly STAMP_BUILT_AT: string = 'WAVE-1-STAMP';
 
  static emit(options: DyE2E_FormSuiteGenerate_Options): string {
    const { formSettings, formRoute, formSelector, suiteSettings, headerComment } = options;
    const runMode: DyE2E_TestRunMode_Type = suiteSettings?.runMode ?? DyE2E_TestRunMode_Type.full;
 
    const header: string = DyE2E_SpecEmission_Util.headerComment(
      formSettings.key,
      formRoute,
      DyE2E_FormSuite_Generator.STAMP_BUILT_AT,
      headerComment,
    );
 
    const imports: string[] = [
      `import { test, expect, Locator } from '@playwright/test';`,
      ...(suiteSettings?.extraImports ?? []),
    ];
 
    const describePrefix: string = suiteSettings?.describePrefix ?? `Form: ${formSettings.key}`;
 
    const fieldBlocks: string[] = [];
    for (const field of formSettings.fields) {
      const set = getTestCaseSet(field.type);
      if (!set) {
        // Wave-2b: ismeretlen field-type → marker-comment.
        fieldBlocks.push(`// field "${field.key}" type="${field.type}" — no curated test-case-set registered (Wave-2b extensibility hook).`);
        continue;
      }
      const override: DyE2E_FieldTestSuite_Override | undefined = suiteSettings?.fieldOverrides?.find(
        (o: DyE2E_FieldTestSuite_Override): boolean => o.fieldKey === field.key,
      );
      const filtered = DyE2E_TestCaseFilter_Util.filter(
        set.cases,
        field,
        runMode,
        override,
      );
      if (filtered.length === 0) {
        fieldBlocks.push(`// field "${field.key}" → no test-cases after filter (runMode=${runMode}).`);
        continue;
      }
      const cases: string = filtered
        .map((c) => DyE2E_FieldEmission_Util.emitTestCase(formSettings, field, c))
        .join('\n\n');
      fieldBlocks.push(
        `test.describe('Field: ${field.key} (${field.type})', (): void => {
${DyE2E_SpecEmission_Util.indent(`test.beforeEach(async ({ page }): Promise<void> => {
  const response = await page.goto('${formRoute}');
  expect(response?.ok()).toBeTruthy();${formSelector ? `\n  await page.locator('${formSelector}').first().waitFor({ state: 'visible' });` : ''}
});
 
${cases}`, 1)}
});`,
      );
    }
 
    const formLevelBlock: string = suiteSettings?.skipFormLevelTests
      ? ''
      : `\n\ntest.describe('Form-level orchestration', (): void => {
${DyE2E_SpecEmission_Util.indent(`test.beforeEach(async ({ page }): Promise<void> => {
  const response = await page.goto('${formRoute}');
  expect(response?.ok()).toBeTruthy();
});
 
${DyE2E_FormLevelEmission_Util.emitAll(formSettings)}`, 1)}
});`;
 
    return `${header}
${imports.join('\n')}
 
test.describe('${DyE2E_SpecEmission_Util.escapeString(describePrefix)}', (): void => {
 
${fieldBlocks.join('\n\n')}${formLevelBlock}
 
});
`;
  }
}