@scenarist/core 0.3.0 → 0.3.1
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.
|
@@ -52,6 +52,10 @@ export declare const LogEvents: {
|
|
|
52
52
|
readonly STATE_CAPTURED: "state_captured";
|
|
53
53
|
/** State injected into response */
|
|
54
54
|
readonly STATE_INJECTED: "state_injected";
|
|
55
|
+
/** State set via afterResponse.setState */
|
|
56
|
+
readonly STATE_SET: "state_set";
|
|
57
|
+
/** State response resolved (condition matched or default) */
|
|
58
|
+
readonly STATE_RESPONSE_RESOLVED: "state_response_resolved";
|
|
55
59
|
/** Sequence advanced to next response */
|
|
56
60
|
readonly SEQUENCE_ADVANCED: "sequence_advanced";
|
|
57
61
|
/** Sequence exhausted all responses */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-events.d.ts","sourceRoot":"","sources":["../../src/domain/log-events.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa;IACxB,oEAAoE;;IAEpE,yCAAyC;;IAEzC,yCAAyC;;IAEzC,kCAAkC;;IAElC,8BAA8B;;CAEtB,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,SAAS;IAEpB,uCAAuC;;IAEvC,mDAAmD;;IAEnD,mCAAmC;;IAEnC,kCAAkC;;IAIlC,2CAA2C;;IAE3C,4CAA4C;;IAE5C,sCAAsC;;IAEtC,kCAAkC;;IAIlC,mCAAmC;;IAEnC,mCAAmC;;
|
|
1
|
+
{"version":3,"file":"log-events.d.ts","sourceRoot":"","sources":["../../src/domain/log-events.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,aAAa;IACxB,oEAAoE;;IAEpE,yCAAyC;;IAEzC,yCAAyC;;IAEzC,kCAAkC;;IAElC,8BAA8B;;CAEtB,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,SAAS;IAEpB,uCAAuC;;IAEvC,mDAAmD;;IAEnD,mCAAmC;;IAEnC,kCAAkC;;IAIlC,2CAA2C;;IAE3C,4CAA4C;;IAE5C,sCAAsC;;IAEtC,kCAAkC;;IAIlC,mCAAmC;;IAEnC,mCAAmC;;IAEnC,2CAA2C;;IAE3C,6DAA6D;;IAI7D,yCAAyC;;IAEzC,uCAAuC;;IAIvC,yCAAyC;;IAEzC,8CAA8C;;IAE9C,qCAAqC;;CAE7B,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC"}
|
|
@@ -55,6 +55,10 @@ export const LogEvents = {
|
|
|
55
55
|
STATE_CAPTURED: "state_captured",
|
|
56
56
|
/** State injected into response */
|
|
57
57
|
STATE_INJECTED: "state_injected",
|
|
58
|
+
/** State set via afterResponse.setState */
|
|
59
|
+
STATE_SET: "state_set",
|
|
60
|
+
/** State response resolved (condition matched or default) */
|
|
61
|
+
STATE_RESPONSE_RESOLVED: "state_response_resolved",
|
|
58
62
|
// Sequence progression
|
|
59
63
|
/** Sequence advanced to next response */
|
|
60
64
|
SEQUENCE_ADVANCED: "sequence_advanced",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"response-selector.d.ts","sourceRoot":"","sources":["../../src/domain/response-selector.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,MAAM,EACP,MAAM,mBAAmB,CAAC;AAiB3B;;GAEG;AACH,KAAK,6BAA6B,GAAG;IACnC,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,GACjC,UAAS,6BAAkC,KAC1C,
|
|
1
|
+
{"version":3,"file":"response-selector.d.ts","sourceRoot":"","sources":["../../src/domain/response-selector.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,MAAM,EACP,MAAM,mBAAmB,CAAC;AAiB3B;;GAEG;AACH,KAAK,6BAA6B,GAAG;IACnC,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sBAAsB,GACjC,UAAS,6BAAkC,KAC1C,gBAuQF,CAAC"}
|
|
@@ -72,11 +72,14 @@ export const createResponseSelector = (options = {}) => {
|
|
|
72
72
|
continue;
|
|
73
73
|
}
|
|
74
74
|
// No match criteria = fallback mock (always matches)
|
|
75
|
-
// Log fallback evaluation
|
|
75
|
+
// Log fallback evaluation with response type info for debugging Issue #328
|
|
76
76
|
logger.debug(LogCategories.MATCHING, LogEvents.MOCK_MATCH_EVALUATED, logContext, {
|
|
77
77
|
mockIndex,
|
|
78
78
|
matched: true,
|
|
79
79
|
hasCriteria: false,
|
|
80
|
+
hasSequence: !!mock.sequence,
|
|
81
|
+
hasStateResponse: !!mock.stateResponse,
|
|
82
|
+
hasResponse: !!mock.response,
|
|
80
83
|
});
|
|
81
84
|
// Dynamic response types (sequence, stateResponse) get higher priority than simple responses
|
|
82
85
|
// This ensures they are selected over simple fallback responses
|
|
@@ -105,7 +108,7 @@ export const createResponseSelector = (options = {}) => {
|
|
|
105
108
|
specificity,
|
|
106
109
|
});
|
|
107
110
|
// Select response (single, sequence, or stateResponse)
|
|
108
|
-
const response = selectResponseFromMock(testId, scenarioId, mockIndex, mock, sequenceTracker, stateManager);
|
|
111
|
+
const response = selectResponseFromMock(testId, scenarioId, mockIndex, mock, sequenceTracker, stateManager, logger);
|
|
109
112
|
if (!response) {
|
|
110
113
|
return {
|
|
111
114
|
success: false,
|
|
@@ -141,6 +144,9 @@ export const createResponseSelector = (options = {}) => {
|
|
|
141
144
|
// Apply afterResponse.setState to mutate state for subsequent requests
|
|
142
145
|
if (mock.afterResponse?.setState && stateManager) {
|
|
143
146
|
stateManager.merge(testId, mock.afterResponse.setState);
|
|
147
|
+
logger.debug(LogCategories.STATE, LogEvents.STATE_SET, logContext, {
|
|
148
|
+
setState: mock.afterResponse.setState,
|
|
149
|
+
});
|
|
144
150
|
}
|
|
145
151
|
return { success: true, data: finalResponse };
|
|
146
152
|
}
|
|
@@ -199,9 +205,11 @@ export const createResponseSelector = (options = {}) => {
|
|
|
199
205
|
* @param mock - The mock definition
|
|
200
206
|
* @param sequenceTracker - Optional sequence tracker for Phase 2
|
|
201
207
|
* @param stateManager - Optional state manager for stateResponse
|
|
208
|
+
* @param logger - Logger for debugging
|
|
202
209
|
* @returns ScenaristResponse or null if mock has no response type
|
|
203
210
|
*/
|
|
204
|
-
const selectResponseFromMock = (testId, scenarioId, mockIndex, mock, sequenceTracker, stateManager) => {
|
|
211
|
+
const selectResponseFromMock = (testId, scenarioId, mockIndex, mock, sequenceTracker, stateManager, logger) => {
|
|
212
|
+
const logContext = { testId, scenarioId };
|
|
205
213
|
// Phase 2: If mock has a sequence, use sequence tracker
|
|
206
214
|
if (mock.sequence) {
|
|
207
215
|
if (!sequenceTracker) {
|
|
@@ -222,7 +230,7 @@ const selectResponseFromMock = (testId, scenarioId, mockIndex, mock, sequenceTra
|
|
|
222
230
|
}
|
|
223
231
|
// State-aware response: evaluate conditions against current state
|
|
224
232
|
if (mock.stateResponse) {
|
|
225
|
-
return resolveStateResponse(testId, mock.stateResponse, stateManager);
|
|
233
|
+
return resolveStateResponse(testId, mock.stateResponse, stateManager, logger, logContext);
|
|
226
234
|
}
|
|
227
235
|
// Phase 1: Single response
|
|
228
236
|
if (mock.response) {
|
|
@@ -240,18 +248,36 @@ const selectResponseFromMock = (testId, scenarioId, mockIndex, mock, sequenceTra
|
|
|
240
248
|
* @param testId - Test ID for state isolation
|
|
241
249
|
* @param stateResponse - The stateResponse configuration
|
|
242
250
|
* @param stateManager - Optional state manager for state lookup
|
|
251
|
+
* @param logger - Logger for debugging
|
|
252
|
+
* @param logContext - Context for log messages
|
|
243
253
|
* @returns The resolved response (matching condition or default)
|
|
244
254
|
*/
|
|
245
|
-
const resolveStateResponse = (testId, stateResponse, stateManager) => {
|
|
255
|
+
const resolveStateResponse = (testId, stateResponse, stateManager, logger, logContext) => {
|
|
246
256
|
// Without stateManager, always return default
|
|
247
257
|
if (!stateManager) {
|
|
258
|
+
logger.debug(LogCategories.STATE, LogEvents.STATE_RESPONSE_RESOLVED, logContext, {
|
|
259
|
+
result: "default",
|
|
260
|
+
reason: "no_state_manager",
|
|
261
|
+
});
|
|
248
262
|
return stateResponse.default;
|
|
249
263
|
}
|
|
250
264
|
// Get current state for this test
|
|
251
265
|
const currentState = stateManager.getAll(testId);
|
|
252
266
|
// Create resolver and evaluate conditions
|
|
253
267
|
const resolver = createStateResponseResolver();
|
|
254
|
-
|
|
268
|
+
const response = resolver.resolveResponse(stateResponse, currentState);
|
|
269
|
+
// Log which response was selected and why
|
|
270
|
+
const isDefault = response === stateResponse.default;
|
|
271
|
+
const matchedCondition = isDefault
|
|
272
|
+
? null
|
|
273
|
+
: stateResponse.conditions.find((c) => resolver.resolveResponse({ default: stateResponse.default, conditions: [c] }, currentState) !== stateResponse.default);
|
|
274
|
+
logger.debug(LogCategories.STATE, LogEvents.STATE_RESPONSE_RESOLVED, logContext, {
|
|
275
|
+
result: isDefault ? "default" : "condition",
|
|
276
|
+
currentState,
|
|
277
|
+
conditionsCount: stateResponse.conditions.length,
|
|
278
|
+
matchedWhen: matchedCondition?.when ?? null,
|
|
279
|
+
});
|
|
280
|
+
return response;
|
|
255
281
|
};
|
|
256
282
|
/**
|
|
257
283
|
* Calculate specificity score for match criteria.
|
package/package.json
CHANGED