@appthrust/kest 0.3.1 → 0.3.2

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/README.md CHANGED
@@ -254,8 +254,8 @@ await ns.label({
254
254
  kind: "ConfigMap",
255
255
  name: "my-config",
256
256
  labels: {
257
- env: "production", // add a label
258
- deprecated: null, // remove a label
257
+ env: "production", // add a label
258
+ deprecated: null, // remove a label
259
259
  },
260
260
  });
261
261
  ```
@@ -310,33 +310,51 @@ test("ConfigMap lifecycle", async (s) => {
310
310
 
311
311
  ### Markdown Test Reports
312
312
 
313
- When a test fails (or when `KEST_SHOW_REPORT=1` is set), Kest generates a detailed Markdown report showing every action, the exact `kubectl` commands executed, stdout/stderr output, and cleanup results. This provides full transparency into what happened during the test, making troubleshooting straightforward -- for both humans and AI assistants.
313
+ When a test fails (or when `KEST_SHOW_REPORT=1` is set), Kest generates a detailed Markdown report showing every action, the exact `kubectl` commands executed (including stdin manifests), stdout/stderr output, and cleanup results. This provides full transparency into what happened during the test, making troubleshooting straightforward -- for both humans and AI assistants.
314
314
 
315
- ```markdown
315
+ ````markdown
316
316
  # ConfigMap lifecycle
317
317
 
318
318
  ## Scenario Overview
319
319
 
320
- | # | Action | Resource | Status |
321
- | --- | ---------------- | ------------------- | ------ |
322
- | 1 | Create namespace | kest-9hdhj | ✅ |
323
- | 2 | Apply | ConfigMap/my-config | ✅ |
324
- | 3 | Assert | ConfigMap/my-config | ✅ |
320
+ | # | Action | Status |
321
+ | --- | ------------------------------ | ------ |
322
+ | 1 | Apply Namespace `kest-9hdhj` | ✅ |
323
+ | 2 | Apply `ConfigMap` "my-config" | ✅ |
324
+ | 3 | Assert `ConfigMap` "my-config" | ✅ |
325
325
 
326
326
  ## Scenario Details
327
327
 
328
328
  ### Given: a namespace exists
329
329
 
330
- Create Namespace "kest-9hdhj"
330
+ **✅ Apply Namespace `kest-9hdhj`**
331
+
332
+ ```shell
333
+ kubectl apply -f - <<EOF
334
+ apiVersion: v1
335
+ kind: Namespace
336
+ metadata:
337
+ name: kest-9hdhj
338
+ EOF
339
+ ```
340
+
331
341
  ...
332
342
 
333
343
  ### Cleanup
334
344
 
335
- | # | Action | Resource | Status |
336
- | --- | ---------------- | ------------------- | ------ |
337
- | 1 | Delete | ConfigMap/my-config | ✅ |
338
- | 2 | Delete namespace | kest-9hdhj | ✅ |
345
+ | # | Action | Status |
346
+ | --- | ------------------------------ | ------ |
347
+ | 1 | Delete `ConfigMap` "my-config" | ✅ |
348
+ | 2 | Delete Namespace `kest-9hdhj` | ✅ |
349
+
350
+ ```shellsession
351
+ $ kubectl delete ConfigMap/my-config -n kest-9hdhj
352
+ configmap "my-config" deleted
353
+
354
+ $ kubectl delete namespace/kest-9hdhj
355
+ namespace "kest-9hdhj" deleted
339
356
  ```
357
+ ````
340
358
 
341
359
  ## Getting Started
342
360
 
@@ -410,21 +428,21 @@ Entry point for defining a test scenario. The callback receives a `Scenario` obj
410
428
 
411
429
  The top-level API surface available in every test callback.
412
430
 
413
- | Method | Description |
414
- | ----------------------------------------------------------------------- | ------------------------------------------------- |
415
- | `apply(manifest, options?)` | Apply a Kubernetes manifest and register cleanup |
416
- | `create(manifest, options?)` | Create a Kubernetes resource and register cleanup |
417
- | `applyStatus(manifest, options?)` | Apply a status subresource (server-side apply) |
418
- | `delete(resource, options?)` | Delete a resource by API version, kind, and name |
419
- | `label(input, options?)` | Add, update, or remove labels on a resource |
420
- | `get(resource, options?)` | Fetch a resource by API version, kind, and name |
421
- | `assert(resource, options?)` | Fetch a resource and run assertions with retries |
422
- | `assertAbsence(resource, options?)` | Assert that a resource does not exist |
423
- | `assertList(resource, options?)` | Fetch a list of resources and run assertions |
431
+ | Method | Description |
432
+ | ----------------------------------------------------------------------- | ----------------------------------------------------------- |
433
+ | `apply(manifest, options?)` | Apply a Kubernetes manifest and register cleanup |
434
+ | `create(manifest, options?)` | Create a Kubernetes resource and register cleanup |
435
+ | `applyStatus(manifest, options?)` | Apply a status subresource (server-side apply) |
436
+ | `delete(resource, options?)` | Delete a resource by API version, kind, and name |
437
+ | `label(input, options?)` | Add, update, or remove labels on a resource |
438
+ | `get(resource, options?)` | Fetch a resource by API version, kind, and name |
439
+ | `assert(resource, options?)` | Fetch a resource and run assertions with retries |
440
+ | `assertAbsence(resource, options?)` | Assert that a resource does not exist |
441
+ | `assertList(resource, options?)` | Fetch a list of resources and run assertions |
424
442
  | `newNamespace(name?, options?)` | Create an ephemeral namespace (supports `{ generateName }`) |
425
- | `exec(input, options?)` | Execute shell commands with optional revert |
426
- | `useCluster(ref)` | Create a cluster-bound API surface |
427
- | `given(desc)` / `when(desc)` / `then(desc)` / `and(desc)` / `but(desc)` | BDD annotations for reporting |
443
+ | `exec(input, options?)` | Execute shell commands with optional revert |
444
+ | `useCluster(ref)` | Create a cluster-bound API surface |
445
+ | `given(desc)` / `when(desc)` / `then(desc)` / `and(desc)` / `but(desc)` | BDD annotations for reporting |
428
446
 
429
447
  ### Namespace / Cluster
430
448
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appthrust/kest",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Kubernetes E2E testing framework designed for humans and AI alike",
5
5
  "type": "module",
6
6
  "module": "ts/index.ts",
@@ -1,4 +1,4 @@
1
- import { apply } from "./apply";
1
+ import { create } from "./create";
2
2
  import type { MutateDef } from "./types";
3
3
 
4
4
  /**
@@ -9,19 +9,19 @@ import type { MutateDef } from "./types";
9
9
  * - `{ generateName: string }` -- use the string as a prefix followed by
10
10
  * random characters (e.g. `{ generateName: "foo-" }` → `"foo-d7kpn"`).
11
11
  */
12
- export type ApplyNamespaceInput =
12
+ export type CreateNamespaceInput =
13
13
  | undefined
14
14
  | string
15
15
  | { readonly generateName: string };
16
16
 
17
- export const applyNamespace = {
17
+ export const createNamespace = {
18
18
  type: "mutate",
19
- name: "ApplyNamespace",
19
+ name: "CreateNamespace",
20
20
  mutate:
21
21
  ({ kubectl }) =>
22
22
  async (input) => {
23
23
  const name = resolveNamespaceName(input);
24
- const { revert } = await apply.mutate({ kubectl })({
24
+ const { revert } = await create.mutate({ kubectl })({
25
25
  apiVersion: "v1",
26
26
  kind: "Namespace",
27
27
  metadata: {
@@ -32,16 +32,16 @@ export const applyNamespace = {
32
32
  },
33
33
  describe: (input) => {
34
34
  if (input === undefined) {
35
- return "Apply `Namespace` with auto-generated name";
35
+ return "Create `Namespace` with auto-generated name";
36
36
  }
37
37
  if (typeof input === "string") {
38
- return `Apply \`Namespace\` "${input}"`;
38
+ return `Create \`Namespace\` "${input}"`;
39
39
  }
40
- return `Apply \`Namespace\` with prefix "${input.generateName}"`;
40
+ return `Create \`Namespace\` with prefix "${input.generateName}"`;
41
41
  },
42
- } satisfies MutateDef<ApplyNamespaceInput, string>;
42
+ } satisfies MutateDef<CreateNamespaceInput, string>;
43
43
 
44
- function resolveNamespaceName(input: ApplyNamespaceInput): string {
44
+ function resolveNamespaceName(input: CreateNamespaceInput): string {
45
45
  if (input === undefined) {
46
46
  return `kest-${randomConsonantDigits(5)}`;
47
47
  }
@@ -1,13 +1,13 @@
1
1
  import { apply } from "../actions/apply";
2
- import {
3
- type ApplyNamespaceInput,
4
- applyNamespace,
5
- } from "../actions/apply-namespace";
6
2
  import { applyStatus } from "../actions/apply-status";
7
3
  import { assert } from "../actions/assert";
8
4
  import { assertAbsence } from "../actions/assert-absence";
9
5
  import { assertList } from "../actions/assert-list";
10
6
  import { create } from "../actions/create";
7
+ import {
8
+ type CreateNamespaceInput,
9
+ createNamespace,
10
+ } from "../actions/create-namespace";
11
11
  import { deleteResource } from "../actions/delete";
12
12
  import { exec } from "../actions/exec";
13
13
  import { get } from "../actions/get";
@@ -187,10 +187,10 @@ const createQueryFn =
187
187
  const createNewNamespaceFn =
188
188
  (scenarioDeps: CreateScenarioOptions) =>
189
189
  async (
190
- name?: ApplyNamespaceInput,
190
+ name?: CreateNamespaceInput,
191
191
  options?: undefined | ActionOptions
192
192
  ): Promise<Namespace> => {
193
- const namespaceName = await createMutateFn(scenarioDeps, applyNamespace)(
193
+ const namespaceName = await createMutateFn(scenarioDeps, createNamespace)(
194
194
  name,
195
195
  options
196
196
  );