@pikku/core 0.12.125 → 0.12.126

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/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 0.12.126
2
+
3
+ ### Patch Changes
4
+
5
+ - 44da33f: A scenario run records which version of the suite it ran against — the commit, and which attempt against that commit it is
6
+ - 44da33f: The scenarios screen and the runs screen are one surface: the declared suite is the document and a run is a lens over it. A scenario is filed as `running` the moment it starts, so a console watching a run in progress can tell what is on screen now from what is still waiting, and the run snapshots each scenario's title, description and cast so the record reads as prose.
7
+
1
8
  ## 0.12.125
2
9
 
3
10
  ### Patch Changes
@@ -15,6 +15,7 @@ export const scenarioRunSummary = (record) => ({
15
15
  runId: record.runId,
16
16
  environment: record.environment,
17
17
  surface: record.surface,
18
+ ...(record.version ? { version: record.version } : {}),
18
19
  status: record.status,
19
20
  startedAt: record.startedAt,
20
21
  finishedAt: record.finishedAt,
@@ -82,7 +83,18 @@ export class FileScenarioRunStore {
82
83
  if (!record) {
83
84
  return;
84
85
  }
85
- record.results.push(result);
86
+ const existing = record.results.findIndex((candidate) => candidate.name === result.name);
87
+ if (existing === -1) {
88
+ record.results.push(result);
89
+ }
90
+ else {
91
+ record.results[existing] = {
92
+ ...(record.results[existing].artifacts
93
+ ? { artifacts: record.results[existing].artifacts }
94
+ : {}),
95
+ ...result,
96
+ };
97
+ }
86
98
  await this.write(record);
87
99
  });
88
100
  }
@@ -8,7 +8,7 @@ import type { ScenarioBrowserProvider, ScenarioEnvironment, ScenarioSurface } fr
8
8
  import type { PikkuWorkflowWire, WorkflowQueueOptions } from './workflow.types.js';
9
9
  export { addFeature, resolveFeatureScenarios } from './feature.js';
10
10
  export type { CoreFeature, CoreFeatureScenario, FeatureMeta, FeaturesMeta, PikkuBrowserWire, PikkuScenarioWire, ScenarioBrowserFailure, ScenarioBrowserProvider, ScenarioEnvironment, ScenarioStepKind, ScenarioStepMeta, ScenarioStepOptions, ScenarioScreenshotOptions, ScenarioStepPhase, ScenarioSurface, TestIdSelector, } from './scenario.types.js';
11
- export type { ScenarioArtifact, ScenarioFailureDetail, ScenarioResult, ScenarioRunRecord, ScenarioRunReport, ScenarioRunSelection, ScenarioRunStatus, ScenarioRunStore, ScenarioRunSummary, ScenarioStepRow, ScenarioStepVideoOffset, } from './scenario-run.types.js';
11
+ export type { ScenarioArtifact, ScenarioFailureDetail, ScenarioResult, ScenarioRunRecord, ScenarioRunReport, ScenarioRunSelection, ScenarioRunStatus, ScenarioRunStore, ScenarioRunSummary, ScenarioRunVersion, ScenarioStepRow, ScenarioStepVideoOffset, } from './scenario-run.types.js';
12
12
  export { SCENARIO_SURFACES } from './scenario-step.types.js';
13
13
  export { resolveScenarioSurfaces } from './scenario-surface.js';
14
14
  export { pollUntil, type PollOptions } from './scenario-poll.js';
@@ -95,7 +95,12 @@ export interface ScenarioFailureDetail {
95
95
  }
96
96
  export interface ScenarioResult {
97
97
  name: string;
98
- status: 'passed' | 'failed';
98
+ /**
99
+ * `running` is filed the moment the scenario starts and replaced when it
100
+ * ends, so a console watching a run in progress can tell the scenario on
101
+ * screen right now from the ones still waiting their turn.
102
+ */
103
+ status: 'passed' | 'failed' | 'running';
99
104
  durationMs: number;
100
105
  output?: unknown;
101
106
  error?: string;
@@ -117,6 +122,11 @@ export interface ScenarioResult {
117
122
  * feature under, and it is what survives the title being rewritten.
118
123
  */
119
124
  featureId?: string;
125
+ /** The scenario's declared title, snapshotted so the record reads as prose. */
126
+ title?: string;
127
+ description?: string;
128
+ /** Who the scenario cast, in declaration order. */
129
+ actors?: string[];
120
130
  tags?: string[];
121
131
  /** Images and footage this scenario produced, filed under the run. */
122
132
  artifacts?: ScenarioArtifact[];
@@ -155,6 +165,32 @@ export interface ScenarioRunSelection {
155
165
  tags?: string[];
156
166
  excludeTags?: string[];
157
167
  }
168
+ /**
169
+ * Which version of the suite a run ran against.
170
+ *
171
+ * A run is only comparable to another run of the same thing, and "the same
172
+ * thing" is the commit — two runs a day apart are not a flake and a fix if the
173
+ * suite moved between them. `attempt` counts the runs already filed against
174
+ * that commit, so a suite re-run until it passes reads as one version with
175
+ * several attempts rather than several unrelated runs.
176
+ *
177
+ * Absent when the project is not in a git repository, or has no commits yet:
178
+ * an unversioned run is still a run, and saying nothing is better than
179
+ * inventing a version for it.
180
+ */
181
+ export interface ScenarioRunVersion {
182
+ /** The commit the working tree was at, in full. */
183
+ commit: string;
184
+ /**
185
+ * The tree had uncommitted changes, so the commit does not describe what
186
+ * actually ran. Recorded rather than refused — running against a dirty tree
187
+ * is the normal way to work — but a reader comparing two attempts of the
188
+ * same commit needs to know one of them was not really that commit.
189
+ */
190
+ dirty?: boolean;
191
+ /** Which run this is against that commit, counting from one. */
192
+ attempt: number;
193
+ }
158
194
  /**
159
195
  * A whole run, as it is stored and read back.
160
196
  *
@@ -170,6 +206,8 @@ export interface ScenarioRunRecord extends ScenarioRunReport {
170
206
  surface: string;
171
207
  /** Absent on a run of the whole suite; see {@link ScenarioRunSelection}. */
172
208
  selection?: ScenarioRunSelection;
209
+ /** The suite version this ran against, when the project has one. */
210
+ version?: ScenarioRunVersion;
173
211
  startedAt: string;
174
212
  finishedAt?: string;
175
213
  }
@@ -178,6 +216,7 @@ export interface ScenarioRunSummary {
178
216
  runId: string;
179
217
  environment: string;
180
218
  surface: string;
219
+ version?: ScenarioRunVersion;
181
220
  status: ScenarioRunStatus;
182
221
  startedAt: string;
183
222
  finishedAt?: string;
@@ -202,7 +241,11 @@ export interface ScenarioRunSummary {
202
241
  export interface ScenarioRunStore {
203
242
  /** Open a run. Called before the first scenario, with `status: 'running'`. */
204
243
  start(record: ScenarioRunRecord): Promise<void>;
205
- /** Append one finished scenario to an open run. */
244
+ /**
245
+ * File one scenario's state against an open run, replacing whatever was
246
+ * filed for that name before — a scenario is recorded twice, once as
247
+ * `running` and once with its outcome.
248
+ */
206
249
  recordScenario(runId: string, result: ScenarioResult): Promise<void>;
207
250
  /**
208
251
  * File the run's artifacts against the scenarios that produced them.
@@ -180,6 +180,9 @@ export interface ScenarioScreenshotOptions {
180
180
  /**
181
181
  * One actor's browser session, handed to a step as `wire.browser`.
182
182
  *
183
+ * Every actor gets their own, so a two-actor scenario drives two sessions and
184
+ * `screenshot` files each shot under the actor it belongs to.
185
+ *
183
186
  * Only what every driver can honour is declared here. A driver package adds
184
187
  * the rest by declaration-merging onto this interface — `@pikku/playwright`
185
188
  * contributes `page`, `context` and `locate` — so a step written against the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/core",
3
- "version": "0.12.125",
3
+ "version": "0.12.126",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/pikkujs/pikku.git",