@rimori/playwright-testing 0.3.5-next.2 → 0.3.5-next.3
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.
|
@@ -79,6 +79,19 @@ export declare class RimoriTestEnvironment {
|
|
|
79
79
|
* Removes a one-time mock from the mocks array after it's been used.
|
|
80
80
|
*/
|
|
81
81
|
private removeOneTimeMock;
|
|
82
|
+
/**
|
|
83
|
+
* Creates a wrapper around the Playwright Request object that provides backwards compatibility
|
|
84
|
+
* for matchers. The new rimori-client sends `messages` array instead of `instructions`,
|
|
85
|
+
* so this wrapper extracts the prompts from messages and provides them as `instructions`.
|
|
86
|
+
*
|
|
87
|
+
* The old API had a single `instructions` field which typically contained the user's specific
|
|
88
|
+
* instruction (what the AI should do). The new API splits this into:
|
|
89
|
+
* - systemPrompt (messages[0] with role='system'): High-level behavior instructions
|
|
90
|
+
* - userPrompt (messages[1] with role='user'): Specific task instruction
|
|
91
|
+
*
|
|
92
|
+
* For backwards compatibility, we concatenate all message contents into `instructions`.
|
|
93
|
+
*/
|
|
94
|
+
private createBackwardsCompatibleRequest;
|
|
82
95
|
private handleRoute;
|
|
83
96
|
/**
|
|
84
97
|
* Adds a supabase route to the supabase routes object.
|
|
@@ -216,21 +229,44 @@ export declare class RimoriTestEnvironment {
|
|
|
216
229
|
triggerOnMainPanelAction: (payload: MainPanelAction) => Promise<void>;
|
|
217
230
|
};
|
|
218
231
|
readonly ai: {
|
|
232
|
+
/**
|
|
233
|
+
* Mocks a text response from the LLM endpoint.
|
|
234
|
+
* Since getText now uses streamObject internally with a { result: string } schema,
|
|
235
|
+
* the mock value should be the full response object.
|
|
236
|
+
*
|
|
237
|
+
* @param values - The response object to return. Should include { result: string } for getText calls.
|
|
238
|
+
* @param options - Optional mock options.
|
|
239
|
+
*/
|
|
219
240
|
mockGetText: (values: unknown, options?: MockOptions) => void;
|
|
220
241
|
/**
|
|
221
242
|
* Mocks a streaming text response from the LLM endpoint.
|
|
222
|
-
* The
|
|
243
|
+
* The new rimori-client's getSteamedText uses streamObject internally with { result: string } schema,
|
|
244
|
+
* so the text is wrapped in a result object.
|
|
223
245
|
*
|
|
224
246
|
* **Note**: Due to Playwright's route.fulfill() requiring a complete response body,
|
|
225
247
|
* all SSE chunks are sent at once (no delays). The client will still parse it as SSE correctly.
|
|
226
248
|
*
|
|
227
|
-
* @param text - The text to stream. Will be formatted as SSE
|
|
249
|
+
* @param text - The text to stream. Will be wrapped as { result: text } and formatted as SSE.
|
|
228
250
|
* @param options - Optional mock options.
|
|
229
251
|
*/
|
|
230
252
|
mockGetSteamedText: (text: string, options?: MockOptions) => void;
|
|
231
253
|
mockGetVoice: (values: Buffer, options?: MockOptions) => void;
|
|
232
254
|
mockGetTextFromVoice: (text: string, options?: MockOptions) => void;
|
|
255
|
+
/**
|
|
256
|
+
* Mocks an object response from the LLM endpoint.
|
|
257
|
+
* Since getObject now uses streamObject internally, this is a streaming response.
|
|
258
|
+
*
|
|
259
|
+
* @param value - The object to return from the LLM.
|
|
260
|
+
* @param options - Optional mock options.
|
|
261
|
+
*/
|
|
233
262
|
mockGetObject: (value: Record<string, unknown>, options?: MockOptions) => void;
|
|
263
|
+
/**
|
|
264
|
+
* Mocks a streaming object response from the LLM endpoint.
|
|
265
|
+
* Returns the object via SSE format with data: prefix.
|
|
266
|
+
*
|
|
267
|
+
* @param value - The object to stream from the LLM.
|
|
268
|
+
* @param options - Optional mock options.
|
|
269
|
+
*/
|
|
234
270
|
mockGetStreamedObject: (value: Record<string, unknown>, options?: MockOptions) => void;
|
|
235
271
|
};
|
|
236
272
|
/**
|
|
@@ -197,23 +197,31 @@ class RimoriTestEnvironment {
|
|
|
197
197
|
},
|
|
198
198
|
};
|
|
199
199
|
this.ai = {
|
|
200
|
+
/**
|
|
201
|
+
* Mocks a text response from the LLM endpoint.
|
|
202
|
+
* Since getText now uses streamObject internally with a { result: string } schema,
|
|
203
|
+
* the mock value should be the full response object.
|
|
204
|
+
*
|
|
205
|
+
* @param values - The response object to return. Should include { result: string } for getText calls.
|
|
206
|
+
* @param options - Optional mock options.
|
|
207
|
+
*/
|
|
200
208
|
mockGetText: (values, options) => {
|
|
201
|
-
|
|
202
|
-
console.warn('mockGetText is not tested');
|
|
203
|
-
this.addBackendRoute('/llm-text', values, options);
|
|
209
|
+
this.addBackendRoute('/ai/llm', values, { ...options, isStreaming: true });
|
|
204
210
|
},
|
|
205
211
|
/**
|
|
206
212
|
* Mocks a streaming text response from the LLM endpoint.
|
|
207
|
-
* The
|
|
213
|
+
* The new rimori-client's getSteamedText uses streamObject internally with { result: string } schema,
|
|
214
|
+
* so the text is wrapped in a result object.
|
|
208
215
|
*
|
|
209
216
|
* **Note**: Due to Playwright's route.fulfill() requiring a complete response body,
|
|
210
217
|
* all SSE chunks are sent at once (no delays). The client will still parse it as SSE correctly.
|
|
211
218
|
*
|
|
212
|
-
* @param text - The text to stream. Will be formatted as SSE
|
|
219
|
+
* @param text - The text to stream. Will be wrapped as { result: text } and formatted as SSE.
|
|
213
220
|
* @param options - Optional mock options.
|
|
214
221
|
*/
|
|
215
222
|
mockGetSteamedText: (text, options) => {
|
|
216
|
-
|
|
223
|
+
// Wrap text in result object as the new client expects { result: string }
|
|
224
|
+
this.addBackendRoute('/ai/llm', { result: text }, { ...options, isStreaming: true });
|
|
217
225
|
},
|
|
218
226
|
mockGetVoice: (values, options) => {
|
|
219
227
|
this.addBackendRoute('/voice/tts', values, options);
|
|
@@ -221,11 +229,25 @@ class RimoriTestEnvironment {
|
|
|
221
229
|
mockGetTextFromVoice: (text, options) => {
|
|
222
230
|
this.addBackendRoute('/voice/stt', text, options);
|
|
223
231
|
},
|
|
232
|
+
/**
|
|
233
|
+
* Mocks an object response from the LLM endpoint.
|
|
234
|
+
* Since getObject now uses streamObject internally, this is a streaming response.
|
|
235
|
+
*
|
|
236
|
+
* @param value - The object to return from the LLM.
|
|
237
|
+
* @param options - Optional mock options.
|
|
238
|
+
*/
|
|
224
239
|
mockGetObject: (value, options) => {
|
|
225
|
-
this.addBackendRoute('/ai/llm
|
|
240
|
+
this.addBackendRoute('/ai/llm', value, { ...options, isStreaming: true });
|
|
226
241
|
},
|
|
242
|
+
/**
|
|
243
|
+
* Mocks a streaming object response from the LLM endpoint.
|
|
244
|
+
* Returns the object via SSE format with data: prefix.
|
|
245
|
+
*
|
|
246
|
+
* @param value - The object to stream from the LLM.
|
|
247
|
+
* @param options - Optional mock options.
|
|
248
|
+
*/
|
|
227
249
|
mockGetStreamedObject: (value, options) => {
|
|
228
|
-
this.addBackendRoute('/ai/llm
|
|
250
|
+
this.addBackendRoute('/ai/llm', value, { ...options, isStreaming: true });
|
|
229
251
|
},
|
|
230
252
|
};
|
|
231
253
|
/**
|
|
@@ -776,6 +798,53 @@ class RimoriTestEnvironment {
|
|
|
776
798
|
mocks.splice(index, 1);
|
|
777
799
|
}
|
|
778
800
|
}
|
|
801
|
+
/**
|
|
802
|
+
* Creates a wrapper around the Playwright Request object that provides backwards compatibility
|
|
803
|
+
* for matchers. The new rimori-client sends `messages` array instead of `instructions`,
|
|
804
|
+
* so this wrapper extracts the prompts from messages and provides them as `instructions`.
|
|
805
|
+
*
|
|
806
|
+
* The old API had a single `instructions` field which typically contained the user's specific
|
|
807
|
+
* instruction (what the AI should do). The new API splits this into:
|
|
808
|
+
* - systemPrompt (messages[0] with role='system'): High-level behavior instructions
|
|
809
|
+
* - userPrompt (messages[1] with role='user'): Specific task instruction
|
|
810
|
+
*
|
|
811
|
+
* For backwards compatibility, we concatenate all message contents into `instructions`.
|
|
812
|
+
*/
|
|
813
|
+
createBackwardsCompatibleRequest(originalRequest) {
|
|
814
|
+
// Create a proxy that intercepts postDataJSON calls
|
|
815
|
+
return new Proxy(originalRequest, {
|
|
816
|
+
get(target, prop) {
|
|
817
|
+
if (prop === 'postDataJSON') {
|
|
818
|
+
return () => {
|
|
819
|
+
try {
|
|
820
|
+
const body = target.postDataJSON();
|
|
821
|
+
if (body && body.messages && Array.isArray(body.messages) && !body.instructions) {
|
|
822
|
+
// Concatenate all message contents for backwards compatibility
|
|
823
|
+
// This allows matchers to check for text that might be in either system or user prompts
|
|
824
|
+
const allContent = body.messages
|
|
825
|
+
.map((m) => m.content || '')
|
|
826
|
+
.filter((content) => content.length > 0)
|
|
827
|
+
.join('\n');
|
|
828
|
+
if (allContent) {
|
|
829
|
+
return { ...body, instructions: allContent };
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
return body;
|
|
833
|
+
}
|
|
834
|
+
catch {
|
|
835
|
+
return null;
|
|
836
|
+
}
|
|
837
|
+
};
|
|
838
|
+
}
|
|
839
|
+
// For all other properties, return the original value bound to the target
|
|
840
|
+
const value = target[prop];
|
|
841
|
+
if (typeof value === 'function') {
|
|
842
|
+
return value.bind(target);
|
|
843
|
+
}
|
|
844
|
+
return value;
|
|
845
|
+
},
|
|
846
|
+
});
|
|
847
|
+
}
|
|
779
848
|
async handleRoute(route, routes) {
|
|
780
849
|
const request = route.request();
|
|
781
850
|
const requestUrl = request.url();
|
|
@@ -789,6 +858,8 @@ class RimoriTestEnvironment {
|
|
|
789
858
|
route.abort('not_found');
|
|
790
859
|
return;
|
|
791
860
|
}
|
|
861
|
+
// Create backwards-compatible request wrapper for matchers
|
|
862
|
+
const compatRequest = this.createBackwardsCompatibleRequest(request);
|
|
792
863
|
// Find the first matching mock based on matcher function
|
|
793
864
|
// Priority: mocks with matchers that match > mocks without matchers (as fallback)
|
|
794
865
|
let matchingMock;
|
|
@@ -796,7 +867,8 @@ class RimoriTestEnvironment {
|
|
|
796
867
|
for (const mock of mocks) {
|
|
797
868
|
if (mock.options?.matcher) {
|
|
798
869
|
try {
|
|
799
|
-
|
|
870
|
+
// Use the backwards-compatible request wrapper for matchers
|
|
871
|
+
if (mock.options.matcher(compatRequest)) {
|
|
800
872
|
matchingMock = mock;
|
|
801
873
|
break;
|
|
802
874
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rimori/playwright-testing",
|
|
3
|
-
"version": "0.3.5-next.
|
|
3
|
+
"version": "0.3.5-next.3",
|
|
4
4
|
"description": "Playwright testing utilities for Rimori plugins and workers",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -23,11 +23,11 @@
|
|
|
23
23
|
},
|
|
24
24
|
"peerDependencies": {
|
|
25
25
|
"@playwright/test": "^1.40.0",
|
|
26
|
-
"@rimori/client": "2.5.
|
|
26
|
+
"@rimori/client": "2.5.11-next.1"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@playwright/test": "^1.40.0",
|
|
30
|
-
"@rimori/client": "2.5.
|
|
30
|
+
"@rimori/client": "2.5.11-next.1",
|
|
31
31
|
"@types/node": "^20.12.7",
|
|
32
32
|
"rimraf": "^5.0.7",
|
|
33
33
|
"typescript": "^5.7.2"
|