@rimori/playwright-testing 0.2.1 → 0.2.3-next.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.
- package/README.md +151 -0
- package/dist/core/MessageChannelSimulator.d.ts +18 -82
- package/dist/core/MessageChannelSimulator.js +63 -104
- package/dist/core/RimoriTestEnvironment.d.ts +163 -25
- package/dist/core/RimoriTestEnvironment.js +383 -136
- package/dist/core/SettingsStateManager.d.ts +41 -0
- package/dist/core/SettingsStateManager.js +74 -0
- package/dist/fixtures/default-user-info.js +1 -0
- package/dist/test/translator.test.js +1 -1
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -17,6 +17,157 @@ The `@rimori/playwright-testing` package enables end-to-end testing of Rimori pl
|
|
|
17
17
|
npm install --save-dev @rimori/playwright-testing @playwright/test
|
|
18
18
|
# or
|
|
19
19
|
pnpm add -D @rimori/playwright-testing @playwright/test
|
|
20
|
+
# or
|
|
21
|
+
yarn add -D @rimori/playwright-testing @playwright/test
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Setup Steps
|
|
25
|
+
|
|
26
|
+
To initialize Playwright testing in your Rimori plugin, follow these steps:
|
|
27
|
+
|
|
28
|
+
### 1. Install Dependencies
|
|
29
|
+
|
|
30
|
+
Add the required dependencies to your `package.json`:
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@playwright/test": "^1.40.0",
|
|
36
|
+
"@rimori/playwright-testing": "^0.2.1"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Then run:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npm install
|
|
45
|
+
# or
|
|
46
|
+
yarn install
|
|
47
|
+
# or
|
|
48
|
+
pnpm install
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 2. Create Playwright Configuration
|
|
52
|
+
|
|
53
|
+
Create a `playwright.config.ts` file in your plugin root:
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { defineConfig, devices } from '@playwright/test';
|
|
57
|
+
|
|
58
|
+
export default defineConfig({
|
|
59
|
+
testDir: './test',
|
|
60
|
+
fullyParallel: true,
|
|
61
|
+
forbidOnly: !!process.env.CI,
|
|
62
|
+
retries: process.env.CI ? 2 : 0,
|
|
63
|
+
workers: process.env.CI ? 1 : undefined,
|
|
64
|
+
reporter: 'html',
|
|
65
|
+
use: {
|
|
66
|
+
trace: 'on-first-retry',
|
|
67
|
+
headless: false,
|
|
68
|
+
screenshot: 'only-on-failure',
|
|
69
|
+
},
|
|
70
|
+
timeout: 30000,
|
|
71
|
+
expect: {
|
|
72
|
+
timeout: 5000,
|
|
73
|
+
},
|
|
74
|
+
projects: [
|
|
75
|
+
{
|
|
76
|
+
name: 'chromium',
|
|
77
|
+
use: { ...devices['Desktop Chrome'] },
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### 3. Add Test Scripts
|
|
84
|
+
|
|
85
|
+
Add test scripts to your `package.json`:
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"scripts": {
|
|
90
|
+
"test": "playwright test",
|
|
91
|
+
"test:headed": "playwright test --headed",
|
|
92
|
+
"test:debug": "playwright test --debug",
|
|
93
|
+
"test:ui": "playwright test --ui",
|
|
94
|
+
"test:headed:debug": "playwright test --headed --debug"
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### 4. Create Test Directory and Files
|
|
100
|
+
|
|
101
|
+
Create a `test` directory in your plugin root and add your test files:
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// test/my-plugin.test.ts
|
|
105
|
+
import { test, expect } from '@playwright/test';
|
|
106
|
+
import { RimoriTestEnvironment } from '@rimori/playwright-testing';
|
|
107
|
+
|
|
108
|
+
const pluginId = 'pl1234567890'; // Your plugin ID from rimori.config.ts
|
|
109
|
+
const pluginUrl = 'http://localhost:3002'; // Your dev server URL
|
|
110
|
+
|
|
111
|
+
test.describe('My Plugin', () => {
|
|
112
|
+
let env: RimoriTestEnvironment;
|
|
113
|
+
|
|
114
|
+
test.beforeEach(async ({ page }) => {
|
|
115
|
+
env = new RimoriTestEnvironment({ page, pluginId });
|
|
116
|
+
|
|
117
|
+
// Set up your mocks here
|
|
118
|
+
// env.ai.mockGetObject(...);
|
|
119
|
+
// env.plugin.mockGetSettings(...);
|
|
120
|
+
|
|
121
|
+
await env.setup();
|
|
122
|
+
await page.goto(`${pluginUrl}/#/your-page`);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test('should work correctly', async ({ page }) => {
|
|
126
|
+
await expect(page.getByText('Hello')).toBeVisible();
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### 5. Get Your Plugin ID
|
|
132
|
+
|
|
133
|
+
Find your plugin ID in `rimori/rimori.config.ts`:
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
const config: RimoriPluginConfig = {
|
|
137
|
+
id: 'pl1234567890', // <-- This is your plugin ID
|
|
138
|
+
// ...
|
|
139
|
+
};
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 6. Run Tests
|
|
143
|
+
|
|
144
|
+
1. **Start your dev server** in one terminal:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
npm run dev
|
|
148
|
+
# or
|
|
149
|
+
yarn dev
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
2. **Run tests** in another terminal:
|
|
153
|
+
```bash
|
|
154
|
+
npm test
|
|
155
|
+
# or
|
|
156
|
+
yarn test
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Complete Example Setup
|
|
160
|
+
|
|
161
|
+
Here's a complete example of what your plugin structure should look like:
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
your-plugin/
|
|
165
|
+
├── package.json # With @playwright/test and test scripts
|
|
166
|
+
├── playwright.config.ts # Playwright configuration
|
|
167
|
+
├── rimori/
|
|
168
|
+
│ └── rimori.config.ts # Contains your plugin ID
|
|
169
|
+
└── test/
|
|
170
|
+
└── my-plugin.test.ts # Your test files
|
|
20
171
|
```
|
|
21
172
|
|
|
22
173
|
## Quick Start
|
|
@@ -1,92 +1,21 @@
|
|
|
1
1
|
import type { Page } from '@playwright/test';
|
|
2
|
-
|
|
3
|
-
code: string;
|
|
4
|
-
name: string;
|
|
5
|
-
native: string;
|
|
6
|
-
capitalized: string;
|
|
7
|
-
uppercase: string;
|
|
8
|
-
};
|
|
9
|
-
type StudyBuddy = {
|
|
10
|
-
id: string;
|
|
11
|
-
name: string;
|
|
12
|
-
description: string;
|
|
13
|
-
avatarUrl: string;
|
|
14
|
-
voiceId: string;
|
|
15
|
-
aiPersonality: string;
|
|
16
|
-
};
|
|
17
|
-
export type UserInfo = {
|
|
18
|
-
mother_tongue: Language;
|
|
19
|
-
target_language: Language;
|
|
20
|
-
skill_level_reading: string;
|
|
21
|
-
skill_level_writing: string;
|
|
22
|
-
skill_level_grammar: string;
|
|
23
|
-
skill_level_speaking: string;
|
|
24
|
-
skill_level_listening: string;
|
|
25
|
-
skill_level_understanding: string;
|
|
26
|
-
goal_longterm: string;
|
|
27
|
-
goal_weekly: string;
|
|
28
|
-
study_buddy: StudyBuddy;
|
|
29
|
-
story_genre: string;
|
|
30
|
-
study_duration: number;
|
|
31
|
-
motivation_type: string;
|
|
32
|
-
onboarding_completed: boolean;
|
|
33
|
-
context_menu_on_select: boolean;
|
|
34
|
-
user_name?: string;
|
|
35
|
-
target_country: string;
|
|
36
|
-
target_city?: string;
|
|
37
|
-
};
|
|
38
|
-
type RimoriGuild = {
|
|
39
|
-
id: string;
|
|
40
|
-
longTermGoalOverride: string;
|
|
41
|
-
allowUserPluginSettings: boolean;
|
|
42
|
-
};
|
|
43
|
-
type PluginInfo = {
|
|
44
|
-
id: string;
|
|
45
|
-
title: string;
|
|
46
|
-
description: string;
|
|
47
|
-
logo: string;
|
|
48
|
-
url: string;
|
|
49
|
-
};
|
|
50
|
-
type RimoriInfo = {
|
|
51
|
-
url: string;
|
|
52
|
-
key: string;
|
|
53
|
-
backendUrl: string;
|
|
54
|
-
token: string;
|
|
55
|
-
expiration: Date;
|
|
56
|
-
tablePrefix: string;
|
|
57
|
-
pluginId: string;
|
|
58
|
-
guild: RimoriGuild;
|
|
59
|
-
installedPlugins: PluginInfo[];
|
|
60
|
-
profile: UserInfo;
|
|
61
|
-
mainPanelPlugin?: PluginInfo;
|
|
62
|
-
sidePanelPlugin?: PluginInfo;
|
|
63
|
-
};
|
|
64
|
-
type EventBusMessage = {
|
|
65
|
-
timestamp: string;
|
|
66
|
-
sender: string;
|
|
67
|
-
topic: string;
|
|
68
|
-
data: unknown;
|
|
69
|
-
debug: boolean;
|
|
70
|
-
eventId?: number;
|
|
71
|
-
};
|
|
2
|
+
import { UserInfo, RimoriInfo, EventBusMessage, EventPayload } from '@rimori/client';
|
|
72
3
|
type MessageChannelSimulatorArgs = {
|
|
73
4
|
page: Page;
|
|
74
5
|
pluginId: string;
|
|
6
|
+
rimoriInfo: RimoriInfo;
|
|
75
7
|
queryParams?: Record<string, string>;
|
|
76
|
-
rimoriInfo?: RimoriInfo;
|
|
77
8
|
};
|
|
78
9
|
type EventListener = (event: EventBusMessage) => void | Promise<void>;
|
|
10
|
+
type AutoResponder = (event: EventBusMessage) => unknown | Promise<unknown>;
|
|
79
11
|
export declare class MessageChannelSimulator {
|
|
80
12
|
private readonly page;
|
|
81
13
|
private readonly pluginId;
|
|
82
14
|
private readonly queryParams;
|
|
83
|
-
private readonly
|
|
84
|
-
private readonly providedInfo?;
|
|
15
|
+
private readonly rimoriInfo;
|
|
85
16
|
private readonly listeners;
|
|
86
17
|
private readonly autoResponders;
|
|
87
18
|
private readonly pendingOutbound;
|
|
88
|
-
private currentUserInfo;
|
|
89
|
-
private currentRimoriInfo;
|
|
90
19
|
private isReady;
|
|
91
20
|
private instanceId;
|
|
92
21
|
/**
|
|
@@ -106,26 +35,33 @@ export declare class MessageChannelSimulator {
|
|
|
106
35
|
/**
|
|
107
36
|
* Sends an event into the plugin as though the Rimori parent emitted it.
|
|
108
37
|
*/
|
|
109
|
-
emit(topic: string, data:
|
|
38
|
+
emit(topic: string, data: EventPayload, sender?: string): Promise<void>;
|
|
110
39
|
/**
|
|
111
40
|
* Registers a handler for events emitted from the plugin.
|
|
112
41
|
*/
|
|
113
42
|
on(topic: string, handler: EventListener): () => void;
|
|
114
43
|
/**
|
|
115
|
-
*
|
|
44
|
+
* Registers a one-time auto-responder for a request/response topic.
|
|
45
|
+
* When a request with an eventId comes in for this topic, the responder will
|
|
46
|
+
* be called once and then automatically removed.
|
|
47
|
+
*
|
|
48
|
+
* @param topic - The event topic to respond to
|
|
49
|
+
* @param responder - A function that returns the response data, or a value to return directly
|
|
50
|
+
* @returns A function to manually remove the responder before it's used
|
|
51
|
+
*/
|
|
52
|
+
respondOnce(topic: string, responder: AutoResponder | unknown): () => void;
|
|
53
|
+
/**
|
|
54
|
+
* Overrides the user info.
|
|
116
55
|
*/
|
|
117
|
-
setUserInfo(
|
|
118
|
-
getRimoriInfo(): RimoriInfo
|
|
56
|
+
setUserInfo(userInfo: UserInfo): void;
|
|
57
|
+
getRimoriInfo(): RimoriInfo;
|
|
119
58
|
private setupMessageChannel;
|
|
120
59
|
private sendToPlugin;
|
|
121
60
|
private flushPending;
|
|
122
61
|
private handlePortMessage;
|
|
123
62
|
private dispatchEvent;
|
|
124
63
|
private maybeRespond;
|
|
125
|
-
private buildRimoriInfo;
|
|
126
|
-
private serializeRimoriInfo;
|
|
127
64
|
private cloneUserInfo;
|
|
128
|
-
private mergeUserInfo;
|
|
129
65
|
private registerAutoResponders;
|
|
130
66
|
private cloneRimoriInfo;
|
|
131
67
|
}
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MessageChannelSimulator = void 0;
|
|
4
4
|
const node_crypto_1 = require("node:crypto");
|
|
5
|
-
const default_user_info_1 = require("../fixtures/default-user-info");
|
|
6
5
|
class MessageChannelSimulator {
|
|
7
6
|
/**
|
|
8
7
|
* Creates a simulator that mimics the Rimori host for plugin tests.
|
|
@@ -15,22 +14,19 @@ class MessageChannelSimulator {
|
|
|
15
14
|
this.listeners = new Map();
|
|
16
15
|
this.autoResponders = new Map();
|
|
17
16
|
this.pendingOutbound = [];
|
|
18
|
-
this.currentRimoriInfo = null;
|
|
19
17
|
this.isReady = false;
|
|
20
18
|
this.instanceId = (0, node_crypto_1.randomUUID)();
|
|
21
19
|
this.page = page;
|
|
22
20
|
this.pluginId = pluginId;
|
|
23
21
|
this.queryParams = queryParams ?? {};
|
|
24
|
-
this.
|
|
25
|
-
this.currentUserInfo = this.cloneUserInfo(default_user_info_1.DEFAULT_USER_INFO);
|
|
26
|
-
this.providedInfo = rimoriInfo ? this.cloneRimoriInfo(rimoriInfo) : undefined;
|
|
22
|
+
this.rimoriInfo = this.cloneRimoriInfo(rimoriInfo);
|
|
27
23
|
this.registerAutoResponders();
|
|
28
24
|
}
|
|
29
25
|
get defaultUserInfo() {
|
|
30
|
-
return this.cloneUserInfo(this.
|
|
26
|
+
return this.cloneUserInfo(this.rimoriInfo.profile);
|
|
31
27
|
}
|
|
32
28
|
get userInfo() {
|
|
33
|
-
return this.cloneUserInfo(this.
|
|
29
|
+
return this.cloneUserInfo(this.rimoriInfo.profile);
|
|
34
30
|
}
|
|
35
31
|
/**
|
|
36
32
|
* Injects the handshake shims so the plugin talks to this simulator.
|
|
@@ -112,6 +108,7 @@ class MessageChannelSimulator {
|
|
|
112
108
|
const message = {
|
|
113
109
|
event: {
|
|
114
110
|
timestamp: new Date().toISOString(),
|
|
111
|
+
eventId: Math.floor(Math.random() * 1000000),
|
|
115
112
|
sender,
|
|
116
113
|
topic,
|
|
117
114
|
data,
|
|
@@ -143,25 +140,52 @@ class MessageChannelSimulator {
|
|
|
143
140
|
};
|
|
144
141
|
}
|
|
145
142
|
/**
|
|
146
|
-
*
|
|
143
|
+
* Registers a one-time auto-responder for a request/response topic.
|
|
144
|
+
* When a request with an eventId comes in for this topic, the responder will
|
|
145
|
+
* be called once and then automatically removed.
|
|
146
|
+
*
|
|
147
|
+
* @param topic - The event topic to respond to
|
|
148
|
+
* @param responder - A function that returns the response data, or a value to return directly
|
|
149
|
+
* @returns A function to manually remove the responder before it's used
|
|
147
150
|
*/
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
151
|
+
respondOnce(topic, responder) {
|
|
152
|
+
let used = false;
|
|
153
|
+
const wrappedResponder = (event) => {
|
|
154
|
+
if (used) {
|
|
155
|
+
return undefined;
|
|
156
|
+
}
|
|
157
|
+
used = true;
|
|
158
|
+
// Remove from autoResponders after first use
|
|
159
|
+
this.autoResponders.delete(topic);
|
|
160
|
+
// If responder is a function, call it with the event, otherwise return the value directly
|
|
161
|
+
if (typeof responder === 'function') {
|
|
162
|
+
return responder(event);
|
|
163
|
+
}
|
|
164
|
+
return responder;
|
|
165
|
+
};
|
|
166
|
+
this.autoResponders.set(topic, wrappedResponder);
|
|
167
|
+
// Return a function to manually remove the responder
|
|
168
|
+
return () => {
|
|
169
|
+
if (!used) {
|
|
170
|
+
this.autoResponders.delete(topic);
|
|
171
|
+
used = true;
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Overrides the user info.
|
|
177
|
+
*/
|
|
178
|
+
setUserInfo(userInfo) {
|
|
179
|
+
this.rimoriInfo.profile = userInfo;
|
|
153
180
|
}
|
|
154
181
|
getRimoriInfo() {
|
|
155
|
-
return this.
|
|
182
|
+
return this.cloneRimoriInfo(this.rimoriInfo);
|
|
156
183
|
}
|
|
157
184
|
async setupMessageChannel() {
|
|
158
185
|
if (this.isReady) {
|
|
159
186
|
return;
|
|
160
187
|
}
|
|
161
|
-
|
|
162
|
-
this.currentRimoriInfo = rimoriInfo;
|
|
163
|
-
const serialized = this.serializeRimoriInfo(rimoriInfo);
|
|
164
|
-
await this.page.evaluate(({ pluginId, queryParams, instanceId, rimoriInfo: info, }) => {
|
|
188
|
+
await this.page.evaluate(({ pluginId, queryParams, instanceId, rimoriInfo, }) => {
|
|
165
189
|
const channel = new MessageChannel();
|
|
166
190
|
channel.port1.onmessage = (event) => {
|
|
167
191
|
// @ts-expect-error binding injected via exposeBinding
|
|
@@ -176,10 +200,7 @@ class MessageChannelSimulator {
|
|
|
176
200
|
pluginId,
|
|
177
201
|
instanceId,
|
|
178
202
|
queryParams,
|
|
179
|
-
rimoriInfo
|
|
180
|
-
...info,
|
|
181
|
-
expiration: new Date(info.expiration),
|
|
182
|
-
},
|
|
203
|
+
rimoriInfo,
|
|
183
204
|
},
|
|
184
205
|
ports: [channel.port2],
|
|
185
206
|
});
|
|
@@ -188,7 +209,7 @@ class MessageChannelSimulator {
|
|
|
188
209
|
pluginId: this.pluginId,
|
|
189
210
|
queryParams: this.queryParams,
|
|
190
211
|
instanceId: this.instanceId,
|
|
191
|
-
rimoriInfo:
|
|
212
|
+
rimoriInfo: this.rimoriInfo,
|
|
192
213
|
});
|
|
193
214
|
this.isReady = true;
|
|
194
215
|
await this.flushPending();
|
|
@@ -215,21 +236,33 @@ class MessageChannelSimulator {
|
|
|
215
236
|
return;
|
|
216
237
|
}
|
|
217
238
|
if ('event' in payload && payload.event) {
|
|
218
|
-
console.log(
|
|
239
|
+
// console.log(
|
|
240
|
+
// '[MessageChannelSimulator] handlePortMessage - received event:',
|
|
241
|
+
// payload.event.topic,
|
|
242
|
+
// 'from:',
|
|
243
|
+
// payload.event.sender,
|
|
244
|
+
// );
|
|
219
245
|
await this.dispatchEvent(payload.event);
|
|
220
246
|
await this.maybeRespond(payload.event);
|
|
221
247
|
return;
|
|
222
248
|
}
|
|
223
249
|
}
|
|
224
250
|
async dispatchEvent(event) {
|
|
225
|
-
console.log(
|
|
251
|
+
// console.log(
|
|
252
|
+
// '[MessageChannelSimulator] dispatchEvent - topic:',
|
|
253
|
+
// event.topic,
|
|
254
|
+
// 'sender:',
|
|
255
|
+
// event.sender,
|
|
256
|
+
// 'listeners:',
|
|
257
|
+
// this.listeners.has(event.topic) ? this.listeners.get(event.topic)?.size : 0,
|
|
258
|
+
// );
|
|
226
259
|
const handlers = this.listeners.get(event.topic);
|
|
227
260
|
if (!handlers?.size) {
|
|
228
261
|
console.log('[MessageChannelSimulator] No handlers found for topic:', event.topic);
|
|
229
262
|
console.log('[MessageChannelSimulator] Available topics:', Array.from(this.listeners.keys()));
|
|
230
263
|
return;
|
|
231
264
|
}
|
|
232
|
-
console.log('[MessageChannelSimulator] Calling', handlers.size, 'handler(s) for topic:', event.topic);
|
|
265
|
+
// console.log('[MessageChannelSimulator] Calling', handlers.size, 'handler(s) for topic:', event.topic);
|
|
233
266
|
for (const handler of handlers) {
|
|
234
267
|
await handler(event);
|
|
235
268
|
}
|
|
@@ -252,90 +285,16 @@ class MessageChannelSimulator {
|
|
|
252
285
|
},
|
|
253
286
|
});
|
|
254
287
|
}
|
|
255
|
-
buildRimoriInfo() {
|
|
256
|
-
if (this.providedInfo) {
|
|
257
|
-
const clone = this.cloneRimoriInfo(this.providedInfo);
|
|
258
|
-
clone.profile = this.cloneUserInfo(this.currentUserInfo);
|
|
259
|
-
clone.pluginId = this.pluginId;
|
|
260
|
-
clone.tablePrefix = clone.tablePrefix || `${this.pluginId}_`;
|
|
261
|
-
return clone;
|
|
262
|
-
}
|
|
263
|
-
return {
|
|
264
|
-
url: 'http://localhost:3500',
|
|
265
|
-
key: 'rimori-sdk-key',
|
|
266
|
-
backendUrl: 'http://localhost:3501',
|
|
267
|
-
token: 'rimori-token',
|
|
268
|
-
expiration: new Date(Date.now() + 60 * 60 * 1000),
|
|
269
|
-
tablePrefix: `${this.pluginId}_`,
|
|
270
|
-
pluginId: this.pluginId,
|
|
271
|
-
guild: {
|
|
272
|
-
id: 'guild-test',
|
|
273
|
-
longTermGoalOverride: '',
|
|
274
|
-
allowUserPluginSettings: true,
|
|
275
|
-
},
|
|
276
|
-
installedPlugins: [
|
|
277
|
-
{
|
|
278
|
-
id: this.pluginId,
|
|
279
|
-
title: 'Test Plugin',
|
|
280
|
-
description: 'Playwright testing plugin',
|
|
281
|
-
logo: '',
|
|
282
|
-
url: 'https://plugins.rimori.localhost',
|
|
283
|
-
},
|
|
284
|
-
],
|
|
285
|
-
profile: this.cloneUserInfo(this.currentUserInfo),
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
serializeRimoriInfo(info) {
|
|
289
|
-
return {
|
|
290
|
-
...info,
|
|
291
|
-
expiration: info.expiration.toISOString(),
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
288
|
cloneUserInfo(input) {
|
|
295
289
|
return JSON.parse(JSON.stringify(input));
|
|
296
290
|
}
|
|
297
|
-
mergeUserInfo(current, overrides) {
|
|
298
|
-
const clone = this.cloneUserInfo(current);
|
|
299
|
-
if (overrides.mother_tongue) {
|
|
300
|
-
clone.mother_tongue = {
|
|
301
|
-
...clone.mother_tongue,
|
|
302
|
-
...overrides.mother_tongue,
|
|
303
|
-
};
|
|
304
|
-
}
|
|
305
|
-
if (overrides.target_language) {
|
|
306
|
-
clone.target_language = {
|
|
307
|
-
...clone.target_language,
|
|
308
|
-
...overrides.target_language,
|
|
309
|
-
};
|
|
310
|
-
}
|
|
311
|
-
if (overrides.study_buddy) {
|
|
312
|
-
clone.study_buddy = {
|
|
313
|
-
...clone.study_buddy,
|
|
314
|
-
...overrides.study_buddy,
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
const { mother_tongue, target_language, study_buddy, ...rest } = overrides;
|
|
318
|
-
for (const [key, value] of Object.entries(rest)) {
|
|
319
|
-
if (value === undefined) {
|
|
320
|
-
continue;
|
|
321
|
-
}
|
|
322
|
-
clone[key] = value;
|
|
323
|
-
}
|
|
324
|
-
return clone;
|
|
325
|
-
}
|
|
326
291
|
registerAutoResponders() {
|
|
327
|
-
this.autoResponders.set('global.supabase.requestAccess', () => this.
|
|
328
|
-
this.autoResponders.set('global.profile.requestUserInfo', () => this.cloneUserInfo(this.
|
|
329
|
-
this.autoResponders.set('global.profile.getUserInfo', () => this.cloneUserInfo(this.
|
|
292
|
+
this.autoResponders.set('global.supabase.requestAccess', () => this.cloneRimoriInfo(this.rimoriInfo));
|
|
293
|
+
this.autoResponders.set('global.profile.requestUserInfo', () => this.cloneUserInfo(this.rimoriInfo.profile));
|
|
294
|
+
this.autoResponders.set('global.profile.getUserInfo', () => this.cloneUserInfo(this.rimoriInfo.profile));
|
|
330
295
|
}
|
|
331
296
|
cloneRimoriInfo(info) {
|
|
332
|
-
return
|
|
333
|
-
...info,
|
|
334
|
-
expiration: new Date(info.expiration),
|
|
335
|
-
guild: { ...info.guild },
|
|
336
|
-
installedPlugins: info.installedPlugins.map((plugin) => ({ ...plugin })),
|
|
337
|
-
profile: this.cloneUserInfo(info.profile),
|
|
338
|
-
};
|
|
297
|
+
return JSON.parse(JSON.stringify(info));
|
|
339
298
|
}
|
|
340
299
|
}
|
|
341
300
|
exports.MessageChannelSimulator = MessageChannelSimulator;
|