@rimori/playwright-testing 0.3.7 → 0.3.8-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/dist/core/RimoriE2ETestEnvironment.d.ts +1 -6
- package/dist/core/RimoriE2ETestEnvironment.js +2 -2
- package/dist/core/RimoriTestEnvironment.d.ts +5 -5
- package/dist/core/RimoriTestEnvironment.js +1 -1
- package/dist/fixtures/default-user-info.js +2 -4
- package/dist/helpers/e2e/onboarding.d.ts +19 -1
- package/dist/helpers/e2e/onboarding.js +38 -28
- package/dist/test/translator.test.js +0 -6
- package/package.json +3 -3
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Browser, Page } from '@playwright/test';
|
|
2
|
+
import { Onboarding } from '../helpers/e2e/onboarding';
|
|
2
3
|
interface RimoriE2ETestEnvironmentOptions {
|
|
3
4
|
browser: Browser;
|
|
4
5
|
pluginId: string;
|
|
@@ -10,12 +11,6 @@ interface Exercise {
|
|
|
10
11
|
actionKey: string;
|
|
11
12
|
parameters?: Record<string, unknown>;
|
|
12
13
|
}
|
|
13
|
-
export interface Onboarding {
|
|
14
|
-
motivation_type?: string;
|
|
15
|
-
preferred_genre?: string;
|
|
16
|
-
target_country?: string;
|
|
17
|
-
target_city?: string;
|
|
18
|
-
}
|
|
19
14
|
interface SetupOptions {
|
|
20
15
|
onboarding?: Onboarding;
|
|
21
16
|
exercises?: Array<Exercise>;
|
|
@@ -23,10 +23,10 @@ class RimoriE2ETestEnvironment {
|
|
|
23
23
|
}
|
|
24
24
|
async setup({ onboarding, exercises, studyPlan } = {}) {
|
|
25
25
|
const onboardingData = {
|
|
26
|
-
|
|
27
|
-
preferred_genre: onboarding?.preferred_genre ?? 'comedy',
|
|
26
|
+
learning_reason: onboarding?.learning_reason ?? 'work',
|
|
28
27
|
target_country: onboarding?.target_country ?? 'SE',
|
|
29
28
|
target_city: onboarding?.target_city ?? 'Malmö',
|
|
29
|
+
interests: onboarding?.interests ?? 'Travel, cooking, and music',
|
|
30
30
|
};
|
|
31
31
|
// Step 1: Create both test users (temp + persist) via API
|
|
32
32
|
const { temp, persist } = await this.createTestUserViaApi();
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Page, Request } from '@playwright/test';
|
|
2
|
-
import { UserInfo } from '@rimori/client
|
|
3
|
-
import { MainPanelAction, Plugin } from '@rimori/client
|
|
2
|
+
import { UserInfo } from '@rimori/client';
|
|
3
|
+
import { MainPanelAction, Plugin, SidebarAction } from '@rimori/client';
|
|
4
4
|
import { PluginSettings } from './SettingsStateManager';
|
|
5
|
-
import { EventPayload } from '@rimori/client
|
|
5
|
+
import { EventPayload } from '@rimori/client';
|
|
6
6
|
import { LanguageLevel } from '@rimori/client';
|
|
7
7
|
interface RimoriTestEnvironmentOptions {
|
|
8
8
|
page: Page;
|
|
@@ -215,9 +215,9 @@ export declare class RimoriTestEnvironment {
|
|
|
215
215
|
/**
|
|
216
216
|
* Triggers a side panel action event as the parent application would.
|
|
217
217
|
* This simulates how rimori-main's SidebarPluginHandler responds to plugin's 'action.requestSidebar' events.
|
|
218
|
-
* @param payload - The action payload containing
|
|
218
|
+
* @param payload - The action payload containing text, action key, and optional args
|
|
219
219
|
*/
|
|
220
|
-
triggerOnSidePanelAction: (payload:
|
|
220
|
+
triggerOnSidePanelAction: (payload: SidebarAction) => Promise<void>;
|
|
221
221
|
/**
|
|
222
222
|
* Triggers a main panel action event as the parent application would.
|
|
223
223
|
* This simulates how rimori-main's MainPluginHandler uses EventBus.respond to respond
|
|
@@ -160,7 +160,7 @@ class RimoriTestEnvironment {
|
|
|
160
160
|
/**
|
|
161
161
|
* Triggers a side panel action event as the parent application would.
|
|
162
162
|
* This simulates how rimori-main's SidebarPluginHandler responds to plugin's 'action.requestSidebar' events.
|
|
163
|
-
* @param payload - The action payload containing
|
|
163
|
+
* @param payload - The action payload containing text, action key, and optional args
|
|
164
164
|
*/
|
|
165
165
|
triggerOnSidePanelAction: async (payload) => {
|
|
166
166
|
if (!this.messageChannelSimulator) {
|
|
@@ -23,8 +23,8 @@ exports.DEFAULT_USER_INFO = {
|
|
|
23
23
|
skill_level_speaking: 'Pre-A1',
|
|
24
24
|
skill_level_listening: 'Pre-A1',
|
|
25
25
|
skill_level_understanding: 'Pre-A1',
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
learning_reason: 'growth',
|
|
27
|
+
personal_interests: 'Travel and cooking',
|
|
28
28
|
study_buddy: {
|
|
29
29
|
id: 'buddy-1',
|
|
30
30
|
name: 'Test Buddy',
|
|
@@ -33,9 +33,7 @@ exports.DEFAULT_USER_INFO = {
|
|
|
33
33
|
voiceId: 'alloy',
|
|
34
34
|
aiPersonality: 'friendly',
|
|
35
35
|
},
|
|
36
|
-
story_genre: 'fiction',
|
|
37
36
|
study_duration: 30,
|
|
38
|
-
motivation_type: 'career',
|
|
39
37
|
onboarding_completed: true,
|
|
40
38
|
context_menu_on_select: true,
|
|
41
39
|
user_name: 'Test User',
|
|
@@ -1,3 +1,21 @@
|
|
|
1
1
|
import { Page } from "@playwright/test";
|
|
2
|
-
|
|
2
|
+
export interface Onboarding {
|
|
3
|
+
learning_reason?: keyof typeof learningReasonMap;
|
|
4
|
+
target_country?: string;
|
|
5
|
+
target_city?: string;
|
|
6
|
+
interests?: string;
|
|
7
|
+
}
|
|
8
|
+
declare const learningReasonMap: {
|
|
9
|
+
work: string;
|
|
10
|
+
relationship: string;
|
|
11
|
+
friends_family: string;
|
|
12
|
+
education: string;
|
|
13
|
+
moving: string;
|
|
14
|
+
culture_travel: string;
|
|
15
|
+
self_improvement: string;
|
|
16
|
+
citizenship: string;
|
|
17
|
+
other: string;
|
|
18
|
+
speaking: string;
|
|
19
|
+
};
|
|
3
20
|
export declare function completeOnboarding(page: Page, onboarding: Required<Onboarding>, e2ePluginId?: string): Promise<void>;
|
|
21
|
+
export {};
|
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.completeOnboarding = completeOnboarding;
|
|
4
4
|
const test_1 = require("@playwright/test");
|
|
5
|
+
const learningReasonMap = {
|
|
6
|
+
work: 'For my job',
|
|
7
|
+
relationship: 'For my relationship',
|
|
8
|
+
friends_family: 'For friends and family',
|
|
9
|
+
education: 'For education',
|
|
10
|
+
moving: 'Moving or living abroad',
|
|
11
|
+
culture_travel: 'For culture and travel',
|
|
12
|
+
self_improvement: 'Self-improvement',
|
|
13
|
+
citizenship: 'For citizenship or residency',
|
|
14
|
+
other: 'Other reason',
|
|
15
|
+
speaking: 'What is your main motivation to learn Swedish?',
|
|
16
|
+
};
|
|
5
17
|
async function completeOnboarding(page, onboarding, e2ePluginId) {
|
|
6
18
|
console.log(`[E2E] Onboarding user`);
|
|
7
19
|
console.log(`[E2E] E2E plugin ID: ${e2ePluginId}`);
|
|
@@ -12,46 +24,44 @@ async function completeOnboarding(page, onboarding, e2ePluginId) {
|
|
|
12
24
|
page.setDefaultNavigationTimeout(60000);
|
|
13
25
|
// Ensure we're on onboarding page
|
|
14
26
|
await (0, test_1.expect)(page).toHaveURL(/\/onboarding/);
|
|
15
|
-
// Step 1:
|
|
16
|
-
const
|
|
17
|
-
await
|
|
18
|
-
await
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
await
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
await (0, test_1.expect)(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
await motivationOption.click();
|
|
30
|
-
// Step 3: Genre preference (auto-advances after selection)
|
|
31
|
-
// Wait for the genre step heading to appear
|
|
32
|
-
const genreHeading = page.getByText('What kind of stories do you like most?');
|
|
33
|
-
await (0, test_1.expect)(genreHeading).toBeVisible({ timeout: 10000 });
|
|
34
|
-
const genreOption = page.locator('label').filter({ hasText: 'Comedy' });
|
|
35
|
-
await (0, test_1.expect)(genreOption).toBeVisible({ timeout: 10000 });
|
|
36
|
-
await genreOption.click();
|
|
37
|
-
// Step 4: Location
|
|
38
|
-
// Wait for the location step to appear
|
|
27
|
+
// Step 1: Learning Reason (radio select, auto-advances after selection)
|
|
28
|
+
const learningReasonOption = page.getByText(learningReasonMap[onboarding.learning_reason]);
|
|
29
|
+
await (0, test_1.expect)(learningReasonOption).toBeVisible({ timeout: 10000 });
|
|
30
|
+
await learningReasonOption.click();
|
|
31
|
+
// Step 2: Interests (textarea with continue button)
|
|
32
|
+
await page.waitForTimeout(1000);
|
|
33
|
+
const interestsTextarea = page.locator('textarea');
|
|
34
|
+
await (0, test_1.expect)(interestsTextarea).toBeVisible({ timeout: 10000 });
|
|
35
|
+
await interestsTextarea.click();
|
|
36
|
+
await interestsTextarea.fill(onboarding.interests);
|
|
37
|
+
const interestsContinue = page.getByRole('button', { name: /continue/i });
|
|
38
|
+
await (0, test_1.expect)(interestsContinue).toBeEnabled({ timeout: 10000 });
|
|
39
|
+
await interestsContinue.click();
|
|
40
|
+
// Step 3: Location
|
|
39
41
|
const countrySelect = page.getByLabel('Country');
|
|
40
42
|
await (0, test_1.expect)(countrySelect).toBeVisible({ timeout: 10000 });
|
|
41
|
-
await countrySelect.selectOption(
|
|
42
|
-
await page.getByLabel('City (optional)').selectOption(
|
|
43
|
+
await countrySelect.selectOption(onboarding.target_country);
|
|
44
|
+
await page.getByLabel('City (optional)').selectOption(onboarding.target_city);
|
|
43
45
|
await page.getByRole('button', { name: 'Continue' }).click();
|
|
46
|
+
// Step 4: Study Buddy (card select, auto-advances after selection)
|
|
47
|
+
// Wait for study buddy step and click the first buddy card
|
|
48
|
+
await page.waitForTimeout(1000);
|
|
49
|
+
const buddyCard = page
|
|
50
|
+
.locator('button')
|
|
51
|
+
.filter({ has: page.locator('img') })
|
|
52
|
+
.first();
|
|
53
|
+
await (0, test_1.expect)(buddyCard).toBeVisible({ timeout: 10000 });
|
|
54
|
+
await buddyCard.click();
|
|
44
55
|
// Step 5: Wait for setup completion
|
|
45
56
|
await (0, test_1.expect)(page.getByRole('heading', { name: 'Almost there!' })).toBeVisible({ timeout: 10000 });
|
|
46
57
|
await page.waitForURL('**/dashboard', { timeout: 120000 });
|
|
47
|
-
// await page.screenshot({ path: path.join(process.cwd(), 'playwright/dashboard.png') });
|
|
48
58
|
await (0, test_1.expect)(page.getByRole('heading', { name: "Today's Mission" })).toBeVisible({ timeout: 30000 });
|
|
49
59
|
await (0, test_1.expect)(page.getByRole('button', { name: 'Grammar', exact: true })).toBeVisible({ timeout: 60000 });
|
|
50
60
|
await (0, test_1.expect)(page.getByRole('heading', { name: 'Getting Started: Create your first study plan' })).toBeVisible({
|
|
51
61
|
timeout: 60000,
|
|
52
62
|
});
|
|
53
63
|
await (0, test_1.expect)(page.getByText('Train your first flashcard deck', { exact: true })).toBeVisible({ timeout: 200000 });
|
|
54
|
-
await (0, test_1.expect)(page.locator('iframe').contentFrame().
|
|
64
|
+
await (0, test_1.expect)(page.locator('iframe').contentFrame().getByText('Getting Started', { exact: true })).toBeVisible({
|
|
55
65
|
timeout: 250000,
|
|
56
66
|
});
|
|
57
67
|
}
|
|
@@ -67,8 +67,6 @@ test_1.test.describe('Demo Plugin', () => {
|
|
|
67
67
|
(0, test_1.test)('translates via side panel action event', async ({ page }) => {
|
|
68
68
|
// Set up the listener BEFORE navigating so it's ready when the plugin calls onSidePanelAction
|
|
69
69
|
await env.event.triggerOnSidePanelAction({
|
|
70
|
-
plugin_id: pluginId,
|
|
71
|
-
action_key: 'translate',
|
|
72
70
|
action: 'translate',
|
|
73
71
|
text: 'tree',
|
|
74
72
|
});
|
|
@@ -82,8 +80,6 @@ test_1.test.describe('Demo Plugin', () => {
|
|
|
82
80
|
(0, test_1.test)('translates and resets the translator', async ({ page }) => {
|
|
83
81
|
// Set up the listener BEFORE navigating so it's ready when the plugin calls onSidePanelAction
|
|
84
82
|
await env.event.triggerOnSidePanelAction({
|
|
85
|
-
plugin_id: pluginId,
|
|
86
|
-
action_key: 'translate',
|
|
87
83
|
action: 'translate',
|
|
88
84
|
text: 'tree',
|
|
89
85
|
});
|
|
@@ -105,8 +101,6 @@ test_1.test.describe('Demo Plugin', () => {
|
|
|
105
101
|
await env.ai.mockGetSteamedText('This is a tree in Swedish: träd. It is an ett word.');
|
|
106
102
|
// Set up the listener BEFORE navigating so it's ready when the plugin calls onSidePanelAction
|
|
107
103
|
await env.event.triggerOnSidePanelAction({
|
|
108
|
-
plugin_id: pluginId,
|
|
109
|
-
action_key: 'translate',
|
|
110
104
|
action: 'translate',
|
|
111
105
|
text: 'tree',
|
|
112
106
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rimori/playwright-testing",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.8-next.1",
|
|
4
4
|
"description": "Playwright testing utilities for Rimori plugins and workers",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"@playwright/test": "^1.40.0",
|
|
29
|
-
"@rimori/client": "
|
|
29
|
+
"@rimori/client": "2.5.17-next.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@playwright/test": "^1.40.0",
|
|
33
|
-
"@rimori/client": "
|
|
33
|
+
"@rimori/client": "2.5.17-next.0",
|
|
34
34
|
"@types/node": "^20.12.7",
|
|
35
35
|
"rimraf": "^5.0.7",
|
|
36
36
|
"typescript": "^5.7.2"
|