@toolstackhq/create-qa-patterns 1.0.11 → 1.0.12

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toolstackhq/create-qa-patterns",
3
- "version": "1.0.11",
3
+ "version": "1.0.12",
4
4
  "description": "CLI for generating QA framework templates.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -8,7 +8,7 @@ type EnvironmentDefaults = {
8
8
  };
9
9
  };
10
10
 
11
- const environmentDefaults: Record<TestEnvironment, EnvironmentDefaults> = {
11
+ const DEFAULTS: Record<TestEnvironment, EnvironmentDefaults> = {
12
12
  dev: {
13
13
  uiBaseUrl: "http://127.0.0.1:3000",
14
14
  credentials: {
@@ -20,18 +20,18 @@ const environmentDefaults: Record<TestEnvironment, EnvironmentDefaults> = {
20
20
  uiBaseUrl: "https://staging-ui.example.internal",
21
21
  credentials: {
22
22
  username: "staging-user",
23
- password: "staging-password"
23
+ password: "replace-me"
24
24
  }
25
25
  },
26
26
  prod: {
27
27
  uiBaseUrl: "https://ui.example.internal",
28
28
  credentials: {
29
29
  username: "prod-user",
30
- password: "prod-password"
30
+ password: "replace-me"
31
31
  }
32
32
  }
33
33
  };
34
34
 
35
- export function getEnvironmentDefaults(environment: TestEnvironment): EnvironmentDefaults {
36
- return environmentDefaults[environment];
35
+ export function getEnvironmentDefaults(testEnv: TestEnvironment): EnvironmentDefaults {
36
+ return DEFAULTS[testEnv];
37
37
  }
@@ -27,6 +27,7 @@ export type RuntimeConfig = z.infer<typeof runtimeConfigSchema>;
27
27
  export function loadRuntimeConfig(): RuntimeConfig {
28
28
  const defaults = getEnvironmentDefaults(environment);
29
29
  const secretManager = new SecretManager(new EnvSecretProvider());
30
+
30
31
  const uiBaseUrl =
31
32
  process.env[`${environment.toUpperCase()}_UI_BASE_URL`] ??
32
33
  process.env.UI_BASE_URL ??
@@ -1,19 +1,28 @@
1
1
  import type { TestEnvironment } from "./test-env";
2
2
 
3
3
  export interface SecretProvider {
4
- getOptionalSecret(secretName: string, environment: TestEnvironment): string | undefined;
4
+ getSecret(key: string, testEnv: TestEnvironment): string | undefined;
5
5
  }
6
6
 
7
7
  export class EnvSecretProvider implements SecretProvider {
8
- getOptionalSecret(secretName: string, environment: TestEnvironment): string | undefined {
9
- return process.env[`${environment.toUpperCase()}_${secretName}`] ?? process.env[secretName];
8
+ getSecret(key: string, testEnv: TestEnvironment): string | undefined {
9
+ const envPrefix = testEnv.toUpperCase();
10
+ return process.env[`${envPrefix}_${key}`] ?? process.env[key];
10
11
  }
11
12
  }
12
13
 
13
14
  export class SecretManager {
14
- constructor(private readonly secretProvider: SecretProvider) {}
15
+ constructor(private readonly provider: SecretProvider) {}
15
16
 
16
- getOptionalSecret(secretName: string, environment: TestEnvironment): string | undefined {
17
- return this.secretProvider.getOptionalSecret(secretName, environment);
17
+ getRequiredSecret(key: string, testEnv: TestEnvironment): string {
18
+ const value = this.provider.getSecret(key, testEnv);
19
+ if (!value) {
20
+ throw new Error(`Missing secret "${key}" for TEST_ENV=${testEnv}`);
21
+ }
22
+ return value;
23
+ }
24
+
25
+ getOptionalSecret(key: string, testEnv: TestEnvironment): string | undefined {
26
+ return this.provider.getSecret(key, testEnv);
18
27
  }
19
28
  }
@@ -1,13 +1,9 @@
1
- export type TestEnvironment = "dev" | "staging" | "prod";
1
+ import { z } from "zod";
2
2
 
3
- const testEnvironmentValues = new Set<TestEnvironment>(["dev", "staging", "prod"]);
3
+ export const testEnvironmentSchema = z.enum(["dev", "staging", "prod"]);
4
4
 
5
- export function loadTestEnvironment(): TestEnvironment {
6
- const testEnv = process.env.TEST_ENV ?? "dev";
7
-
8
- if (!testEnvironmentValues.has(testEnv as TestEnvironment)) {
9
- throw new Error(`Unsupported TEST_ENV "${testEnv}". Expected one of: dev, staging, prod.`);
10
- }
5
+ export type TestEnvironment = z.infer<typeof testEnvironmentSchema>;
11
6
 
12
- return testEnv as TestEnvironment;
7
+ export function loadTestEnvironment(): TestEnvironment {
8
+ return testEnvironmentSchema.parse(process.env.TEST_ENV ?? "dev");
13
9
  }
@@ -1,5 +1,5 @@
1
- import { IdGenerator } from "./id-generator";
2
1
  import { createSeededFaker } from "./seeded-faker";
2
+ import { IdGenerator } from "./id-generator";
3
3
 
4
4
  export type PersonRecord = {
5
5
  personId: string;
@@ -1,13 +1,17 @@
1
1
  export class IdGenerator {
2
2
  private readonly counters = new Map<string, number>();
3
3
 
4
- constructor(private readonly testRunId: string) {}
4
+ constructor(private readonly runId: string) {}
5
5
 
6
6
  next(prefix: string): string {
7
- const currentCount = this.counters.get(prefix) ?? 0;
8
- const nextCount = currentCount + 1;
9
- this.counters.set(prefix, nextCount);
7
+ const counter = (this.counters.get(prefix) ?? 0) + 1;
8
+ this.counters.set(prefix, counter);
9
+ return `${prefix}-${this.runId}-${String(counter).padStart(4, "0")}`;
10
+ }
10
11
 
11
- return `${prefix}-${this.testRunId}-${String(nextCount).padStart(4, "0")}`;
12
+ nextSequence(prefix: string): number {
13
+ const counter = (this.counters.get(prefix) ?? 0) + 1;
14
+ this.counters.set(prefix, counter);
15
+ return counter;
12
16
  }
13
17
  }
@@ -1,11 +1,13 @@
1
1
  import { Faker, en } from "@faker-js/faker";
2
2
 
3
- function toNumericSeed(seed: string): number {
4
- return seed.split("").reduce((accumulator, character) => accumulator + character.charCodeAt(0), 0);
3
+ function hashSeed(value: string): number {
4
+ return value.split("").reduce((seed, character) => {
5
+ return ((seed << 5) - seed + character.charCodeAt(0)) | 0;
6
+ }, 0);
5
7
  }
6
8
 
7
- export function createSeededFaker(seed: string): Faker {
8
- const faker = new Faker({ locale: [en] });
9
- faker.seed(toNumericSeed(seed));
10
- return faker;
9
+ export function createSeededFaker(seedInput: string): Faker {
10
+ const instance = new Faker({ locale: [en] });
11
+ instance.seed(Math.abs(hashSeed(seedInput)));
12
+ return instance;
11
13
  }
@@ -26,20 +26,6 @@ jobs:
26
26
  working-directory: templates/playwright-template
27
27
  run: npx playwright install --with-deps chromium
28
28
 
29
- - name: Start API demo server
30
- run: npm run dev --workspace @toolstackhq/api-demo-server &
31
-
32
- - name: Start UI demo app
33
- run: npm run dev --workspace @toolstackhq/ui-demo-app &
34
-
35
- - name: Wait for demo services
36
- run: |
37
- for target in http://127.0.0.1:3000/health http://127.0.0.1:3001/health; do
38
- until curl --silent --fail "$target" >/dev/null; do
39
- sleep 1
40
- done
41
- done
42
-
43
29
  - name: Run Playwright validation
44
30
  working-directory: templates/playwright-template
45
31
  env:
@@ -1,4 +1,4 @@
1
- import { faker } from "@faker-js/faker";
1
+ import { Faker, en } from "@faker-js/faker";
2
2
 
3
3
  function hashSeed(value: string): number {
4
4
  return value.split("").reduce((seed, character) => {
@@ -6,8 +6,8 @@ function hashSeed(value: string): number {
6
6
  }, 0);
7
7
  }
8
8
 
9
- export function createSeededFaker(seedInput: string) {
10
- const instance = faker;
9
+ export function createSeededFaker(seedInput: string): Faker {
10
+ const instance = new Faker({ locale: [en] });
11
11
  instance.seed(Math.abs(hashSeed(seedInput)));
12
12
  return instance;
13
13
  }