@mattermost/playwright-lib 10.6.0-0
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 +214 -0
- package/dist/asset/mattermost-icon_128x128.png +0 -0
- package/dist/browser_context.d.ts +17 -0
- package/dist/browser_context.js +71 -0
- package/dist/browser_context.js.map +1 -0
- package/dist/constant.d.ts +3 -0
- package/dist/constant.js +8 -0
- package/dist/constant.js.map +1 -0
- package/dist/file.d.ts +42 -0
- package/dist/file.js +74 -0
- package/dist/file.js.map +1 -0
- package/dist/flag.d.ts +7 -0
- package/dist/flag.js +76 -0
- package/dist/flag.js.map +1 -0
- package/dist/global_setup.d.ts +3 -0
- package/dist/global_setup.js +173 -0
- package/dist/global_setup.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/dist/mock_browser_api.d.ts +31 -0
- package/dist/mock_browser_api.js +71 -0
- package/dist/mock_browser_api.js.map +1 -0
- package/dist/server/channel.d.ts +12 -0
- package/dist/server/channel.js +25 -0
- package/dist/server/channel.js.map +1 -0
- package/dist/server/client.d.ts +16 -0
- package/dist/server/client.js +39 -0
- package/dist/server/client.js.map +1 -0
- package/dist/server/default_config.d.ts +2 -0
- package/dist/server/default_config.js +755 -0
- package/dist/server/default_config.js.map +1 -0
- package/dist/server/index.d.ts +7 -0
- package/dist/server/init.d.ts +23 -0
- package/dist/server/init.js +73 -0
- package/dist/server/init.js.map +1 -0
- package/dist/server/post.d.ts +2 -0
- package/dist/server/post.js +31 -0
- package/dist/server/post.js.map +1 -0
- package/dist/server/team.d.ts +2 -0
- package/dist/server/team.js +18 -0
- package/dist/server/team.js.map +1 -0
- package/dist/server/user.d.ts +3 -0
- package/dist/server/user.js +33 -0
- package/dist/server/user.js.map +1 -0
- package/dist/test_action.d.ts +4 -0
- package/dist/test_action.js +24 -0
- package/dist/test_action.js.map +1 -0
- package/dist/test_config.d.ts +20 -0
- package/dist/test_config.js +82 -0
- package/dist/test_config.js.map +1 -0
- package/dist/test_fixture.d.ts +72 -0
- package/dist/test_fixture.js +172 -0
- package/dist/test_fixture.js.map +1 -0
- package/dist/types.d.ts +91 -0
- package/dist/ui/components/channels/app_bar.d.ts +7 -0
- package/dist/ui/components/channels/app_bar.js +20 -0
- package/dist/ui/components/channels/app_bar.js.map +1 -0
- package/dist/ui/components/channels/center_view.d.ts +52 -0
- package/dist/ui/components/channels/center_view.js +124 -0
- package/dist/ui/components/channels/center_view.js.map +1 -0
- package/dist/ui/components/channels/delete_post_confirmation_dialog.d.ts +11 -0
- package/dist/ui/components/channels/delete_post_confirmation_dialog.js +35 -0
- package/dist/ui/components/channels/delete_post_confirmation_dialog.js.map +1 -0
- package/dist/ui/components/channels/delete_post_modal.d.ts +8 -0
- package/dist/ui/components/channels/delete_post_modal.js +26 -0
- package/dist/ui/components/channels/delete_post_modal.js.map +1 -0
- package/dist/ui/components/channels/emoji_gif_picker.d.ts +16 -0
- package/dist/ui/components/channels/emoji_gif_picker.js +50 -0
- package/dist/ui/components/channels/emoji_gif_picker.js.map +1 -0
- package/dist/ui/components/channels/find_channels_modal.d.ts +8 -0
- package/dist/ui/components/channels/find_channels_modal.js +22 -0
- package/dist/ui/components/channels/find_channels_modal.js.map +1 -0
- package/dist/ui/components/channels/generic_confirm_modal.d.ts +16 -0
- package/dist/ui/components/channels/generic_confirm_modal.js +40 -0
- package/dist/ui/components/channels/generic_confirm_modal.js.map +1 -0
- package/dist/ui/components/channels/header.d.ts +6 -0
- package/dist/ui/components/channels/header.js +18 -0
- package/dist/ui/components/channels/header.js.map +1 -0
- package/dist/ui/components/channels/message_priority.d.ts +18 -0
- package/dist/ui/components/channels/message_priority.js +66 -0
- package/dist/ui/components/channels/message_priority.js.map +1 -0
- package/dist/ui/components/channels/post.d.ts +29 -0
- package/dist/ui/components/channels/post.js +63 -0
- package/dist/ui/components/channels/post.js.map +1 -0
- package/dist/ui/components/channels/post_create.d.ts +41 -0
- package/dist/ui/components/channels/post_create.js +118 -0
- package/dist/ui/components/channels/post_create.js.map +1 -0
- package/dist/ui/components/channels/post_dot_menu.d.ts +20 -0
- package/dist/ui/components/channels/post_dot_menu.js +47 -0
- package/dist/ui/components/channels/post_dot_menu.js.map +1 -0
- package/dist/ui/components/channels/post_edit.d.ts +21 -0
- package/dist/ui/components/channels/post_edit.js +76 -0
- package/dist/ui/components/channels/post_edit.js.map +1 -0
- package/dist/ui/components/channels/post_menu.d.ts +26 -0
- package/dist/ui/components/channels/post_menu.js +54 -0
- package/dist/ui/components/channels/post_menu.js.map +1 -0
- package/dist/ui/components/channels/post_reminder_menu.d.ts +11 -0
- package/dist/ui/components/channels/post_reminder_menu.js +29 -0
- package/dist/ui/components/channels/post_reminder_menu.js.map +1 -0
- package/dist/ui/components/channels/restore_post_confirmation_dialog.d.ts +10 -0
- package/dist/ui/components/channels/restore_post_confirmation_dialog.js +30 -0
- package/dist/ui/components/channels/restore_post_confirmation_dialog.js.map +1 -0
- package/dist/ui/components/channels/scheduled_draft_menu.d.ts +8 -0
- package/dist/ui/components/channels/scheduled_draft_menu.js +23 -0
- package/dist/ui/components/channels/scheduled_draft_menu.js.map +1 -0
- package/dist/ui/components/channels/scheduled_draft_modal.d.ts +20 -0
- package/dist/ui/components/channels/scheduled_draft_modal.js +84 -0
- package/dist/ui/components/channels/scheduled_draft_modal.js.map +1 -0
- package/dist/ui/components/channels/search_popover.d.ts +15 -0
- package/dist/ui/components/channels/search_popover.js +43 -0
- package/dist/ui/components/channels/search_popover.js.map +1 -0
- package/dist/ui/components/channels/settings/notification_settings.d.ts +13 -0
- package/dist/ui/components/channels/settings/notification_settings.js +41 -0
- package/dist/ui/components/channels/settings/notification_settings.js.map +1 -0
- package/dist/ui/components/channels/settings/settings_modal.d.ts +11 -0
- package/dist/ui/components/channels/settings/settings_modal.js +32 -0
- package/dist/ui/components/channels/settings/settings_modal.js.map +1 -0
- package/dist/ui/components/channels/sidebar_left.d.ts +24 -0
- package/dist/ui/components/channels/sidebar_left.js +54 -0
- package/dist/ui/components/channels/sidebar_left.js.map +1 -0
- package/dist/ui/components/channels/sidebar_right.d.ts +38 -0
- package/dist/ui/components/channels/sidebar_right.js +87 -0
- package/dist/ui/components/channels/sidebar_right.js.map +1 -0
- package/dist/ui/components/channels/thread_footer.d.ts +11 -0
- package/dist/ui/components/channels/thread_footer.js +27 -0
- package/dist/ui/components/channels/thread_footer.js.map +1 -0
- package/dist/ui/components/channels/user_profile_popover.d.ts +7 -0
- package/dist/ui/components/channels/user_profile_popover.js +21 -0
- package/dist/ui/components/channels/user_profile_popover.js.map +1 -0
- package/dist/ui/components/footer.d.ts +11 -0
- package/dist/ui/components/footer.js +28 -0
- package/dist/ui/components/footer.js.map +1 -0
- package/dist/ui/components/global_header.d.ts +15 -0
- package/dist/ui/components/global_header.js +46 -0
- package/dist/ui/components/global_header.js.map +1 -0
- package/dist/ui/components/index.d.ts +73 -0
- package/dist/ui/components/index.js +77 -0
- package/dist/ui/components/index.js.map +1 -0
- package/dist/ui/components/main_header.d.ts +8 -0
- package/dist/ui/components/main_header.js +22 -0
- package/dist/ui/components/main_header.js.map +1 -0
- package/dist/ui/components/system_console/navbar.d.ts +6 -0
- package/dist/ui/components/system_console/navbar.js +18 -0
- package/dist/ui/components/system_console/navbar.js.map +1 -0
- package/dist/ui/components/system_console/sections/system_users/column_toggle_menu.d.ts +22 -0
- package/dist/ui/components/system_console/sections/system_users/column_toggle_menu.js +47 -0
- package/dist/ui/components/system_console/sections/system_users/column_toggle_menu.js.map +1 -0
- package/dist/ui/components/system_console/sections/system_users/feature_discovery.d.ts +10 -0
- package/dist/ui/components/system_console/sections/system_users/feature_discovery.js +24 -0
- package/dist/ui/components/system_console/sections/system_users/feature_discovery.js.map +1 -0
- package/dist/ui/components/system_console/sections/system_users/filter_menu.d.ts +21 -0
- package/dist/ui/components/system_console/sections/system_users/filter_menu.js +42 -0
- package/dist/ui/components/system_console/sections/system_users/filter_menu.js.map +1 -0
- package/dist/ui/components/system_console/sections/system_users/filter_popover.d.ts +30 -0
- package/dist/ui/components/system_console/sections/system_users/filter_popover.js +61 -0
- package/dist/ui/components/system_console/sections/system_users/filter_popover.js.map +1 -0
- package/dist/ui/components/system_console/sections/system_users/mobile_security.d.ts +23 -0
- package/dist/ui/components/system_console/sections/system_users/mobile_security.js +56 -0
- package/dist/ui/components/system_console/sections/system_users/mobile_security.js.map +1 -0
- package/dist/ui/components/system_console/sections/system_users/system_users.d.ts +58 -0
- package/dist/ui/components/system_console/sections/system_users/system_users.js +114 -0
- package/dist/ui/components/system_console/sections/system_users/system_users.js.map +1 -0
- package/dist/ui/components/system_console/sidebar.d.ts +17 -0
- package/dist/ui/components/system_console/sidebar.js +37 -0
- package/dist/ui/components/system_console/sidebar.js.map +1 -0
- package/dist/ui/pages/channels.d.ts +31 -0
- package/dist/ui/pages/channels.js +79 -0
- package/dist/ui/pages/channels.js.map +1 -0
- package/dist/ui/pages/drafts.d.ts +30 -0
- package/dist/ui/pages/drafts.js +114 -0
- package/dist/ui/pages/drafts.js.map +1 -0
- package/dist/ui/pages/index.d.ts +19 -0
- package/dist/ui/pages/index.js +34 -0
- package/dist/ui/pages/index.js.map +1 -0
- package/dist/ui/pages/landing_login.d.ts +11 -0
- package/dist/ui/pages/landing_login.js +36 -0
- package/dist/ui/pages/landing_login.js.map +1 -0
- package/dist/ui/pages/login.d.ts +25 -0
- package/dist/ui/pages/login.js +62 -0
- package/dist/ui/pages/login.js.map +1 -0
- package/dist/ui/pages/reset_password.d.ts +15 -0
- package/dist/ui/pages/reset_password.js +44 -0
- package/dist/ui/pages/reset_password.js.map +1 -0
- package/dist/ui/pages/scheduled_draft.d.ts +38 -0
- package/dist/ui/pages/scheduled_draft.js +144 -0
- package/dist/ui/pages/scheduled_draft.js.map +1 -0
- package/dist/ui/pages/signup.d.ts +31 -0
- package/dist/ui/pages/signup.js +78 -0
- package/dist/ui/pages/signup.js.map +1 -0
- package/dist/ui/pages/system_console.d.ts +26 -0
- package/dist/ui/pages/system_console.js +64 -0
- package/dist/ui/pages/system_console.js.map +1 -0
- package/dist/util.d.ts +29 -0
- package/dist/util.js +51 -0
- package/dist/util.js.map +1 -0
- package/dist/visual/index.d.ts +3 -0
- package/dist/visual/index.js +37 -0
- package/dist/visual/index.js.map +1 -0
- package/dist/visual/percy.d.ts +2 -0
- package/dist/visual/percy.js +23 -0
- package/dist/visual/percy.js.map +1 -0
- package/package.json +68 -0
package/README.md
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# @mattermost/playwright-lib
|
|
2
|
+
|
|
3
|
+
A comprehensive end-to-end testing library for Mattermost web, desktop and plugin applications using Playwright.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This library provides:
|
|
8
|
+
|
|
9
|
+
- Pre-built page objects and components for common Mattermost UI elements
|
|
10
|
+
- Server configuration and initialization utilities
|
|
11
|
+
- Test fixtures and helpers
|
|
12
|
+
- Visual testing support with Percy integration
|
|
13
|
+
- Accessibility testing support with [axe-core](https://github.com/dequelabs/axe-core)
|
|
14
|
+
- Browser notification mocking
|
|
15
|
+
- File handling utilities
|
|
16
|
+
- Common test actions and assertions
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install @mattermost/playwright-lib
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
Basic example of logging in and posting a message:
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import {test, expect} from '@mattermost/playwright-lib';
|
|
30
|
+
|
|
31
|
+
test('user can post message', async ({pw}) => {
|
|
32
|
+
// # Create and login a new user
|
|
33
|
+
const {user} = await pw.initSetup();
|
|
34
|
+
const {channelsPage} = await pw.testBrowser.login(user);
|
|
35
|
+
|
|
36
|
+
// # Navigate and post a message
|
|
37
|
+
await channelsPage.goto();
|
|
38
|
+
const message = 'Hello World!';
|
|
39
|
+
await channelsPage.postMessage(message);
|
|
40
|
+
|
|
41
|
+
// * Verify message appears
|
|
42
|
+
const lastPost = await channelsPage.getLastPost();
|
|
43
|
+
await expect(lastPost).toHaveText(message);
|
|
44
|
+
});
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Key Components
|
|
48
|
+
|
|
49
|
+
### Page Objects
|
|
50
|
+
|
|
51
|
+
Ready-to-use page objects for common Mattermost pages:
|
|
52
|
+
|
|
53
|
+
- Login
|
|
54
|
+
- Signup
|
|
55
|
+
- Channels
|
|
56
|
+
- System Console
|
|
57
|
+
- And more...
|
|
58
|
+
|
|
59
|
+
### UI Components
|
|
60
|
+
|
|
61
|
+
Reusable component objects for UI elements:
|
|
62
|
+
|
|
63
|
+
- Headers
|
|
64
|
+
- Posts
|
|
65
|
+
- Menus
|
|
66
|
+
- Modals
|
|
67
|
+
- And more...
|
|
68
|
+
|
|
69
|
+
### Test Utilities
|
|
70
|
+
|
|
71
|
+
Helper functions for common testing needs:
|
|
72
|
+
|
|
73
|
+
- Server setup and configuration
|
|
74
|
+
- User/team creation
|
|
75
|
+
- File handling
|
|
76
|
+
- Visual testing
|
|
77
|
+
- And more...
|
|
78
|
+
|
|
79
|
+
## Configuration
|
|
80
|
+
|
|
81
|
+
The library can be configured via optional environment variables:
|
|
82
|
+
|
|
83
|
+
### Environment Variables
|
|
84
|
+
|
|
85
|
+
All environment variables are optional with sensible defaults.
|
|
86
|
+
|
|
87
|
+
#### Server Configuration
|
|
88
|
+
|
|
89
|
+
| Variable | Description | Default |
|
|
90
|
+
| ----------------------------- | ------------------------------------------ | -------------------------------- |
|
|
91
|
+
| `PW_BASE_URL` | Server URL | `http://localhost:8065` |
|
|
92
|
+
| `PW_ADMIN_USERNAME` | Admin username | `sysadmin` |
|
|
93
|
+
| `PW_ADMIN_PASSWORD` | Admin password | `Sys@dmin-sample1` |
|
|
94
|
+
| `PW_ADMIN_EMAIL` | Admin email | `sysadmin@sample.mattermost.com` |
|
|
95
|
+
| `PW_ENSURE_PLUGINS_INSTALLED` | Comma-separated list of plugins to install | `[]` |
|
|
96
|
+
| `PW_RESET_BEFORE_TEST` | Reset server before test | `false` |
|
|
97
|
+
|
|
98
|
+
#### High Availability Cluster Settings
|
|
99
|
+
|
|
100
|
+
| Variable | Description | Default |
|
|
101
|
+
| -------------------------- | ----------------------- | ---------------- |
|
|
102
|
+
| `PW_HA_CLUSTER_ENABLED` | Enable HA cluster | `false` |
|
|
103
|
+
| `PW_HA_CLUSTER_NODE_COUNT` | Number of cluster nodes | `2` |
|
|
104
|
+
| `PW_HA_CLUSTER_NAME` | Cluster name | `mm_dev_cluster` |
|
|
105
|
+
|
|
106
|
+
#### Push Notifications
|
|
107
|
+
|
|
108
|
+
| Variable | Description | Default |
|
|
109
|
+
| ----------------------------- | ---------------------------- | ---------------------------------- |
|
|
110
|
+
| `PW_PUSH_NOTIFICATION_SERVER` | Push notification server URL | `https://push-test.mattermost.com` |
|
|
111
|
+
|
|
112
|
+
#### Playwright Settings
|
|
113
|
+
|
|
114
|
+
| Variable | Description | Default |
|
|
115
|
+
| ------------- | ------------------------------- | ------- |
|
|
116
|
+
| `PW_HEADLESS` | Run tests headless | `true` |
|
|
117
|
+
| `PW_SLOWMO` | Add delay between actions in ms | `0` |
|
|
118
|
+
| `PW_WORKERS` | Number of parallel workers | `1` |
|
|
119
|
+
|
|
120
|
+
#### Visual Testing
|
|
121
|
+
|
|
122
|
+
| Variable | Description | Default |
|
|
123
|
+
| -------------------- | --------------------------- | ------- |
|
|
124
|
+
| `PW_SNAPSHOT_ENABLE` | Enable snapshot testing | `false` |
|
|
125
|
+
| `PW_PERCY_ENABLE` | Enable Percy visual testing | `false` |
|
|
126
|
+
|
|
127
|
+
#### CI Settings
|
|
128
|
+
|
|
129
|
+
| Variable | Description | Default |
|
|
130
|
+
| -------- | ------------------------------------ | ------- |
|
|
131
|
+
| `CI` | Set automatically in CI environments | N/A |
|
|
132
|
+
|
|
133
|
+
## Accessibility Testing
|
|
134
|
+
|
|
135
|
+
The library includes built-in accessibility testing using [axe-core](https://github.com/dequelabs/axe-core):
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
import {test, expect} from '@mattermost/playwright-lib';
|
|
139
|
+
|
|
140
|
+
test('verify login page accessibility', async ({page, axe}) => {
|
|
141
|
+
// # Navigate to login page
|
|
142
|
+
await page.goto('/login');
|
|
143
|
+
|
|
144
|
+
// # Run accessibility scan
|
|
145
|
+
const results = await axe.builder(page).analyze();
|
|
146
|
+
|
|
147
|
+
// * Verify no accessibility violations
|
|
148
|
+
expect(results.violations).toHaveLength(0);
|
|
149
|
+
});
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
The axe-core integration:
|
|
153
|
+
|
|
154
|
+
- Runs WCAG 2.0 Level A & AA rules by default
|
|
155
|
+
- Provides detailed violation reports
|
|
156
|
+
- Supports rule customization
|
|
157
|
+
- Can be configured per-test or globally
|
|
158
|
+
|
|
159
|
+
## Visual Testing
|
|
160
|
+
|
|
161
|
+
The library supports visual testing through [Playwright's built-in visual comparisons](https://playwright.dev/docs/test-snapshots) and [Percy](https://www.browserstack.com/percy) integration:
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
import {test, expect} from '@mattermost/playwright-lib';
|
|
165
|
+
|
|
166
|
+
test('verify channel header appearance', async ({pw, browserName, viewport}, testInfo) => {
|
|
167
|
+
// # Setup and login
|
|
168
|
+
const {user} = await pw.initSetup();
|
|
169
|
+
const {page, channelsPage} = await pw.testBrowser.login(user);
|
|
170
|
+
|
|
171
|
+
// # Navigate and prepare page
|
|
172
|
+
await channelsPage.goto();
|
|
173
|
+
await expect(channelsPage.appBar.playbooksIcon).toBeVisible();
|
|
174
|
+
await pw.hideDynamicChannelsContent(page);
|
|
175
|
+
|
|
176
|
+
// * Take and verify snapshot
|
|
177
|
+
await pw.matchSnapshot(testInfo, {page, browserName, viewport});
|
|
178
|
+
});
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## Browser Notifications
|
|
182
|
+
|
|
183
|
+
Mock and verify browser notifications:
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
import {test, expect} from '@mattermost/playwright-lib';
|
|
187
|
+
|
|
188
|
+
test('verify notification on mention', async ({pw}) => {
|
|
189
|
+
// # Setup users and team
|
|
190
|
+
const {team, adminUser, user} = await pw.initSetup();
|
|
191
|
+
|
|
192
|
+
// # Setup admin browser with notifications
|
|
193
|
+
const {page: adminPage, channelsPage: adminChannelsPage} = await pw.testBrowser.login(adminUser);
|
|
194
|
+
await adminChannelsPage.goto(team.name, 'town-square');
|
|
195
|
+
await pw.stubNotification(adminPage, 'granted');
|
|
196
|
+
|
|
197
|
+
// # Setup user browser and post mention
|
|
198
|
+
const {channelsPage: userChannelsPage} = await pw.testBrowser.login(user);
|
|
199
|
+
await userChannelsPage.goto(team.name, 'off-topic');
|
|
200
|
+
await userChannelsPage.postMessage(`@ALL good morning, ${team.name}!`);
|
|
201
|
+
|
|
202
|
+
// * Verify notification received
|
|
203
|
+
const notifications = await pw.waitForNotification(adminPage);
|
|
204
|
+
expect(notifications.length).toBe(1);
|
|
205
|
+
});
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Contributing
|
|
209
|
+
|
|
210
|
+
See [CONTRIBUTING.md](../../../CONTRIBUTING.md) for development setup and guidelines.
|
|
211
|
+
|
|
212
|
+
## License
|
|
213
|
+
|
|
214
|
+
See [LICENSE.txt](../../../LICENSE.txt) for license information.
|
|
Binary file
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Browser, BrowserContext } from '@playwright/test';
|
|
2
|
+
import { UserProfile } from '@mattermost/types/users';
|
|
3
|
+
export declare class TestBrowser {
|
|
4
|
+
readonly browser: Browser;
|
|
5
|
+
context: BrowserContext | null;
|
|
6
|
+
constructor(browser: Browser);
|
|
7
|
+
login(user: UserProfile): Promise<{
|
|
8
|
+
context: BrowserContext;
|
|
9
|
+
page: import("playwright-core").Page;
|
|
10
|
+
channelsPage: import("./ui/pages").ChannelsPage;
|
|
11
|
+
systemConsolePage: import("./ui/pages").SystemConsolePage;
|
|
12
|
+
scheduledDraftPage: import("./ui/pages").ScheduledDraftPage;
|
|
13
|
+
draftPage: import("./ui/pages").DraftPage;
|
|
14
|
+
}>;
|
|
15
|
+
close(): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
export declare function loginByAPI(loginId: string, password: string, token?: string, ldapOnly?: boolean): Promise<string>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var promises = require('node:fs/promises');
|
|
4
|
+
var test = require('@playwright/test');
|
|
5
|
+
var test_config = require('./test_config.js');
|
|
6
|
+
var index = require('./ui/pages/index.js');
|
|
7
|
+
|
|
8
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
9
|
+
// See LICENSE.txt for license information.
|
|
10
|
+
class TestBrowser {
|
|
11
|
+
browser;
|
|
12
|
+
context;
|
|
13
|
+
constructor(browser) {
|
|
14
|
+
this.browser = browser;
|
|
15
|
+
this.context = null;
|
|
16
|
+
}
|
|
17
|
+
async login(user) {
|
|
18
|
+
const options = { storageState: '' };
|
|
19
|
+
if (user) {
|
|
20
|
+
// Log in via API request and save user storage
|
|
21
|
+
const storagePath = await loginByAPI(user.username, user.password);
|
|
22
|
+
options.storageState = storagePath;
|
|
23
|
+
}
|
|
24
|
+
// Sign in a user in new browser context
|
|
25
|
+
const context = await this.browser.newContext(options);
|
|
26
|
+
const page = await context.newPage();
|
|
27
|
+
const channelsPage = new index.pages.ChannelsPage(page);
|
|
28
|
+
const systemConsolePage = new index.pages.SystemConsolePage(page);
|
|
29
|
+
const scheduledDraftPage = new index.pages.ScheduledDraftPage(page);
|
|
30
|
+
const draftPage = new index.pages.DraftPage(page);
|
|
31
|
+
this.context = context;
|
|
32
|
+
return { context, page, channelsPage, systemConsolePage, scheduledDraftPage, draftPage };
|
|
33
|
+
}
|
|
34
|
+
async close() {
|
|
35
|
+
if (this.context) {
|
|
36
|
+
await this.context.close();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async function loginByAPI(loginId, password, token = '', ldapOnly = false) {
|
|
41
|
+
const requestContext = await test.request.newContext();
|
|
42
|
+
const data = {
|
|
43
|
+
login_id: loginId,
|
|
44
|
+
password,
|
|
45
|
+
token,
|
|
46
|
+
deviceId: '',
|
|
47
|
+
};
|
|
48
|
+
if (ldapOnly) {
|
|
49
|
+
data.ldap_only = 'true';
|
|
50
|
+
}
|
|
51
|
+
// Log in via API
|
|
52
|
+
await requestContext.post(`${test_config.testConfig.baseURL}/api/v4/users/login`, {
|
|
53
|
+
data,
|
|
54
|
+
headers: { 'X-Requested-With': 'XMLHttpRequest' },
|
|
55
|
+
});
|
|
56
|
+
// Save signed-in state to a folder
|
|
57
|
+
const storagePath = `storage_state/${Date.now()}_${loginId}_${password}${token ? '_' + token : ''}${ldapOnly ? '_ldap' : ''}.json`;
|
|
58
|
+
const storageState = await requestContext.storageState({ path: storagePath });
|
|
59
|
+
await requestContext.dispose();
|
|
60
|
+
// Append origins to bypass seeing landing page then write to file
|
|
61
|
+
storageState.origins.push({
|
|
62
|
+
origin: test_config.testConfig.baseURL,
|
|
63
|
+
localStorage: [{ name: '__landingPageSeen__', value: 'true' }],
|
|
64
|
+
});
|
|
65
|
+
await promises.writeFile(storagePath, JSON.stringify(storageState));
|
|
66
|
+
return storagePath;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
exports.TestBrowser = TestBrowser;
|
|
70
|
+
exports.loginByAPI = loginByAPI;
|
|
71
|
+
//# sourceMappingURL=browser_context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser_context.js","sources":["../src/browser_context.ts"],"sourcesContent":["// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.\n// See LICENSE.txt for license information.\n\nimport {writeFile} from 'node:fs/promises';\n\nimport {Browser, BrowserContext, request} from '@playwright/test';\nimport {UserProfile} from '@mattermost/types/users';\n\nimport {testConfig} from './test_config';\nimport {pages} from './ui/pages';\n\nexport class TestBrowser {\n readonly browser: Browser;\n context: BrowserContext | null;\n\n constructor(browser: Browser) {\n this.browser = browser;\n this.context = null;\n }\n\n async login(user: UserProfile) {\n const options = {storageState: ''};\n if (user) {\n // Log in via API request and save user storage\n const storagePath = await loginByAPI(user.username, user.password);\n options.storageState = storagePath;\n }\n\n // Sign in a user in new browser context\n const context = await this.browser.newContext(options);\n const page = await context.newPage();\n\n const channelsPage = new pages.ChannelsPage(page);\n const systemConsolePage = new pages.SystemConsolePage(page);\n const scheduledDraftPage = new pages.ScheduledDraftPage(page);\n const draftPage = new pages.DraftPage(page);\n\n this.context = context;\n\n return {context, page, channelsPage, systemConsolePage, scheduledDraftPage, draftPage};\n }\n\n async close() {\n if (this.context) {\n await this.context.close();\n }\n }\n}\n\nexport async function loginByAPI(loginId: string, password: string, token = '', ldapOnly = false) {\n const requestContext = await request.newContext();\n\n const data: any = {\n login_id: loginId,\n password,\n token,\n deviceId: '',\n };\n\n if (ldapOnly) {\n data.ldap_only = 'true';\n }\n\n // Log in via API\n await requestContext.post(`${testConfig.baseURL}/api/v4/users/login`, {\n data,\n headers: {'X-Requested-With': 'XMLHttpRequest'},\n });\n\n // Save signed-in state to a folder\n const storagePath = `storage_state/${Date.now()}_${loginId}_${password}${token ? '_' + token : ''}${\n ldapOnly ? '_ldap' : ''\n }.json`;\n const storageState = await requestContext.storageState({path: storagePath});\n await requestContext.dispose();\n\n // Append origins to bypass seeing landing page then write to file\n storageState.origins.push({\n origin: testConfig.baseURL,\n localStorage: [{name: '__landingPageSeen__', value: 'true'}],\n });\n await writeFile(storagePath, JSON.stringify(storageState));\n\n return storagePath;\n}\n"],"names":["pages","request","testConfig","writeFile"],"mappings":";;;;;;;AAAA;AACA;MAUa,WAAW,CAAA;AACX,IAAA,OAAO;AAChB,IAAA,OAAO;AAEP,IAAA,WAAA,CAAY,OAAgB,EAAA;AACxB,QAAA,IAAI,CAAC,OAAO,GAAG,OAAO;AACtB,QAAA,IAAI,CAAC,OAAO,GAAG,IAAI;;IAGvB,MAAM,KAAK,CAAC,IAAiB,EAAA;AACzB,QAAA,MAAM,OAAO,GAAG,EAAC,YAAY,EAAE,EAAE,EAAC;QAClC,IAAI,IAAI,EAAE;;AAEN,YAAA,MAAM,WAAW,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC;AAClE,YAAA,OAAO,CAAC,YAAY,GAAG,WAAW;;;QAItC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC;AACtD,QAAA,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE;QAEpC,MAAM,YAAY,GAAG,IAAIA,WAAK,CAAC,YAAY,CAAC,IAAI,CAAC;QACjD,MAAM,iBAAiB,GAAG,IAAIA,WAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC;QAC3D,MAAM,kBAAkB,GAAG,IAAIA,WAAK,CAAC,kBAAkB,CAAC,IAAI,CAAC;QAC7D,MAAM,SAAS,GAAG,IAAIA,WAAK,CAAC,SAAS,CAAC,IAAI,CAAC;AAE3C,QAAA,IAAI,CAAC,OAAO,GAAG,OAAO;AAEtB,QAAA,OAAO,EAAC,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,SAAS,EAAC;;AAG1F,IAAA,MAAM,KAAK,GAAA;AACP,QAAA,IAAI,IAAI,CAAC,OAAO,EAAE;AACd,YAAA,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;;;AAGrC;AAEM,eAAe,UAAU,CAAC,OAAe,EAAE,QAAgB,EAAE,KAAK,GAAG,EAAE,EAAE,QAAQ,GAAG,KAAK,EAAA;AAC5F,IAAA,MAAM,cAAc,GAAG,MAAMC,YAAO,CAAC,UAAU,EAAE;AAEjD,IAAA,MAAM,IAAI,GAAQ;AACd,QAAA,QAAQ,EAAE,OAAO;QACjB,QAAQ;QACR,KAAK;AACL,QAAA,QAAQ,EAAE,EAAE;KACf;IAED,IAAI,QAAQ,EAAE;AACV,QAAA,IAAI,CAAC,SAAS,GAAG,MAAM;;;IAI3B,MAAM,cAAc,CAAC,IAAI,CAAC,GAAGC,sBAAU,CAAC,OAAO,CAAA,mBAAA,CAAqB,EAAE;QAClE,IAAI;AACJ,QAAA,OAAO,EAAE,EAAC,kBAAkB,EAAE,gBAAgB,EAAC;AAClD,KAAA,CAAC;;AAGF,IAAA,MAAM,WAAW,GAAG,CAAiB,cAAA,EAAA,IAAI,CAAC,GAAG,EAAE,CAAI,CAAA,EAAA,OAAO,IAAI,QAAQ,CAAA,EAAG,KAAK,GAAG,GAAG,GAAG,KAAK,GAAG,EAAE,GAC7F,QAAQ,GAAG,OAAO,GAAG,EACzB,OAAO;AACP,IAAA,MAAM,YAAY,GAAG,MAAM,cAAc,CAAC,YAAY,CAAC,EAAC,IAAI,EAAE,WAAW,EAAC,CAAC;AAC3E,IAAA,MAAM,cAAc,CAAC,OAAO,EAAE;;AAG9B,IAAA,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC;QACtB,MAAM,EAAEA,sBAAU,CAAC,OAAO;QAC1B,YAAY,EAAE,CAAC,EAAC,IAAI,EAAE,qBAAqB,EAAE,KAAK,EAAE,MAAM,EAAC,CAAC;AAC/D,KAAA,CAAC;IACF,MAAMC,kBAAS,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;AAE1D,IAAA,OAAO,WAAW;AACtB;;;;;"}
|
package/dist/constant.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constant.js","sources":["../src/constant.ts"],"sourcesContent":["// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.\n// See LICENSE.txt for license information.\n\nexport const appsPluginId = 'com.mattermost.apps';\nexport const callsPluginId = 'com.mattermost.calls';\nexport const playbooksPluginId = 'playbooks';\n"],"names":[],"mappings":";;AAAA;AACA;AAGO,MAAM,aAAa,GAAG;;;;"}
|
package/dist/file.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export declare const assetPath: string;
|
|
2
|
+
declare const availableFiles: readonly ["mattermost-icon_128x128.png"];
|
|
3
|
+
type AvailableFilename = (typeof availableFiles)[number];
|
|
4
|
+
/**
|
|
5
|
+
* Reads file data and creates a File object.
|
|
6
|
+
* @param filePath - The path to the file.
|
|
7
|
+
* @returns A File object containing the file data.
|
|
8
|
+
* @throws If the file does not exist.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getFileData(filePath: string): File;
|
|
11
|
+
/**
|
|
12
|
+
* Reads file data and creates a Blob object.
|
|
13
|
+
* @param filePath - The path to the file.
|
|
14
|
+
* @returns A Blob object containing the file data.
|
|
15
|
+
* @throws If the file does not exist.
|
|
16
|
+
*/
|
|
17
|
+
export declare function getBlobData(filePath: string): Blob;
|
|
18
|
+
/**
|
|
19
|
+
* Reads file data from the "asset" directory and creates a File object.
|
|
20
|
+
* @param filename - The name of the file in the "asset" directory.
|
|
21
|
+
* @returns An object containing a File object
|
|
22
|
+
*/
|
|
23
|
+
export declare function getFileFromAsset(filename: string): File;
|
|
24
|
+
/**
|
|
25
|
+
* Reads file data from the "asset" directory and creates a Blob object.
|
|
26
|
+
* @param filename - The name of the file in the "asset" directory.
|
|
27
|
+
* @returns An object containing a Blob object
|
|
28
|
+
*/
|
|
29
|
+
export declare function getBlobFromAsset(filename: string): Blob;
|
|
30
|
+
/**
|
|
31
|
+
* Reads file data from the lib "asset" directory and creates a File object.
|
|
32
|
+
* @param filename - The name of the file in the "asset" directory.
|
|
33
|
+
* @returns An object containing a File object
|
|
34
|
+
*/
|
|
35
|
+
export declare function getFileFromCommonAsset(filename: AvailableFilename): File;
|
|
36
|
+
/**
|
|
37
|
+
* Reads file data from the lib "asset" directory and creates a Blob object.
|
|
38
|
+
* @param filename - The name of the file in the "asset" directory.
|
|
39
|
+
* @returns An object containing a Blob object
|
|
40
|
+
*/
|
|
41
|
+
export declare function getBlobFromCommonAsset(filename: AvailableFilename): Blob;
|
|
42
|
+
export {};
|
package/dist/file.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var path = require('node:path');
|
|
4
|
+
var fs = require('node:fs');
|
|
5
|
+
var mime = require('mime-types');
|
|
6
|
+
|
|
7
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
8
|
+
// See LICENSE.txt for license information.
|
|
9
|
+
const commonAssetPath = path.resolve(__dirname, 'asset');
|
|
10
|
+
const assetPath = path.resolve(process.cwd(), 'asset');
|
|
11
|
+
/**
|
|
12
|
+
* Reads file data and creates a File object.
|
|
13
|
+
* @param filePath - The path to the file.
|
|
14
|
+
* @returns A File object containing the file data.
|
|
15
|
+
* @throws If the file does not exist.
|
|
16
|
+
*/
|
|
17
|
+
function getFileData(filePath) {
|
|
18
|
+
if (!fs.existsSync(filePath)) {
|
|
19
|
+
throw new Error(`File not found at path: ${filePath}`);
|
|
20
|
+
}
|
|
21
|
+
const mimeType = mime.lookup(filePath) || undefined;
|
|
22
|
+
const fileName = path.basename(filePath);
|
|
23
|
+
const fileBuffer = fs.readFileSync(filePath);
|
|
24
|
+
return new File([fileBuffer], fileName, { type: mimeType });
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Reads file data and creates a Blob object.
|
|
28
|
+
* @param filePath - The path to the file.
|
|
29
|
+
* @returns A Blob object containing the file data.
|
|
30
|
+
* @throws If the file does not exist.
|
|
31
|
+
*/
|
|
32
|
+
function getBlobData(filePath) {
|
|
33
|
+
if (!fs.existsSync(filePath)) {
|
|
34
|
+
throw new Error(`File not found at path: ${filePath}`);
|
|
35
|
+
}
|
|
36
|
+
const mimeType = mime.lookup(filePath) || undefined;
|
|
37
|
+
const fileBuffer = fs.readFileSync(filePath);
|
|
38
|
+
return new Blob([fileBuffer], { type: mimeType });
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Reads file data from the "asset" directory and creates a File object.
|
|
42
|
+
* @param filename - The name of the file in the "asset" directory.
|
|
43
|
+
* @returns An object containing a File object
|
|
44
|
+
*/
|
|
45
|
+
function getFileFromAsset(filename) {
|
|
46
|
+
const filePath = path.join(assetPath, filename);
|
|
47
|
+
return getFileData(filePath);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Reads file data from the "asset" directory and creates a Blob object.
|
|
51
|
+
* @param filename - The name of the file in the "asset" directory.
|
|
52
|
+
* @returns An object containing a Blob object
|
|
53
|
+
*/
|
|
54
|
+
function getBlobFromAsset(filename) {
|
|
55
|
+
const filePath = path.join(assetPath, filename);
|
|
56
|
+
return getBlobData(filePath);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Reads file data from the lib "asset" directory and creates a File object.
|
|
60
|
+
* @param filename - The name of the file in the "asset" directory.
|
|
61
|
+
* @returns An object containing a File object
|
|
62
|
+
*/
|
|
63
|
+
function getFileFromCommonAsset(filename) {
|
|
64
|
+
const filePath = path.join(commonAssetPath, filename);
|
|
65
|
+
return getFileData(filePath);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
exports.assetPath = assetPath;
|
|
69
|
+
exports.getBlobData = getBlobData;
|
|
70
|
+
exports.getBlobFromAsset = getBlobFromAsset;
|
|
71
|
+
exports.getFileData = getFileData;
|
|
72
|
+
exports.getFileFromAsset = getFileFromAsset;
|
|
73
|
+
exports.getFileFromCommonAsset = getFileFromCommonAsset;
|
|
74
|
+
//# sourceMappingURL=file.js.map
|
package/dist/file.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.js","sources":["../src/file.ts"],"sourcesContent":["// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.\n// See LICENSE.txt for license information.\n\nimport path from 'node:path';\nimport fs from 'node:fs';\n\nimport mime from 'mime-types';\n\nconst commonAssetPath = path.resolve(__dirname, 'asset');\nexport const assetPath = path.resolve(process.cwd(), 'asset');\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nconst availableFiles = ['mattermost-icon_128x128.png'] as const;\ntype AvailableFilename = (typeof availableFiles)[number];\n\n/**\n * Reads file data and creates a File object.\n * @param filePath - The path to the file.\n * @returns A File object containing the file data.\n * @throws If the file does not exist.\n */\nexport function getFileData(filePath: string): File {\n if (!fs.existsSync(filePath)) {\n throw new Error(`File not found at path: ${filePath}`);\n }\n\n const mimeType = mime.lookup(filePath) || undefined;\n const fileName = path.basename(filePath);\n const fileBuffer = fs.readFileSync(filePath);\n\n return new File([fileBuffer], fileName, {type: mimeType});\n}\n\n/**\n * Reads file data and creates a Blob object.\n * @param filePath - The path to the file.\n * @returns A Blob object containing the file data.\n * @throws If the file does not exist.\n */\nexport function getBlobData(filePath: string): Blob {\n if (!fs.existsSync(filePath)) {\n throw new Error(`File not found at path: ${filePath}`);\n }\n\n const mimeType = mime.lookup(filePath) || undefined;\n const fileBuffer = fs.readFileSync(filePath);\n\n return new Blob([fileBuffer], {type: mimeType});\n}\n\n/**\n * Reads file data from the \"asset\" directory and creates a File object.\n * @param filename - The name of the file in the \"asset\" directory.\n * @returns An object containing a File object\n */\nexport function getFileFromAsset(filename: string) {\n const filePath = path.join(assetPath, filename);\n\n return getFileData(filePath);\n}\n\n/**\n * Reads file data from the \"asset\" directory and creates a Blob object.\n * @param filename - The name of the file in the \"asset\" directory.\n * @returns An object containing a Blob object\n */\nexport function getBlobFromAsset(filename: string) {\n const filePath = path.join(assetPath, filename);\n\n return getBlobData(filePath);\n}\n\n/**\n * Reads file data from the lib \"asset\" directory and creates a File object.\n * @param filename - The name of the file in the \"asset\" directory.\n * @returns An object containing a File object\n */\nexport function getFileFromCommonAsset(filename: AvailableFilename) {\n const filePath = path.join(commonAssetPath, filename);\n\n return getFileData(filePath);\n}\n\n/**\n * Reads file data from the lib \"asset\" directory and creates a Blob object.\n * @param filename - The name of the file in the \"asset\" directory.\n * @returns An object containing a Blob object\n */\nexport function getBlobFromCommonAsset(filename: AvailableFilename) {\n const filePath = path.join(commonAssetPath, filename);\n\n return getBlobData(filePath);\n}\n"],"names":[],"mappings":";;;;;;AAAA;AACA;AAOA,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC;AACjD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO;AAM5D;;;;;AAKG;AACG,SAAU,WAAW,CAAC,QAAgB,EAAA;IACxC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;AAC1B,QAAA,MAAM,IAAI,KAAK,CAAC,2BAA2B,QAAQ,CAAA,CAAE,CAAC;;IAG1D,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,SAAS;IACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;IACxC,MAAM,UAAU,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC;AAE5C,IAAA,OAAO,IAAI,IAAI,CAAC,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,EAAC,IAAI,EAAE,QAAQ,EAAC,CAAC;AAC7D;AAEA;;;;;AAKG;AACG,SAAU,WAAW,CAAC,QAAgB,EAAA;IACxC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;AAC1B,QAAA,MAAM,IAAI,KAAK,CAAC,2BAA2B,QAAQ,CAAA,CAAE,CAAC;;IAG1D,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,SAAS;IACnD,MAAM,UAAU,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC;AAE5C,IAAA,OAAO,IAAI,IAAI,CAAC,CAAC,UAAU,CAAC,EAAE,EAAC,IAAI,EAAE,QAAQ,EAAC,CAAC;AACnD;AAEA;;;;AAIG;AACG,SAAU,gBAAgB,CAAC,QAAgB,EAAA;IAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC;AAE/C,IAAA,OAAO,WAAW,CAAC,QAAQ,CAAC;AAChC;AAEA;;;;AAIG;AACG,SAAU,gBAAgB,CAAC,QAAgB,EAAA;IAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC;AAE/C,IAAA,OAAO,WAAW,CAAC,QAAQ,CAAC;AAChC;AAEA;;;;AAIG;AACG,SAAU,sBAAsB,CAAC,QAA2B,EAAA;IAC9D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,QAAQ,CAAC;AAErD,IAAA,OAAO,WAAW,CAAC,QAAQ,CAAC;AAChC;;;;;;;;;"}
|
package/dist/flag.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function shouldHaveCallsEnabled(enabled?: boolean): Promise<void>;
|
|
2
|
+
export declare function shouldHaveFeatureFlag(name: string, value: string | boolean): Promise<void>;
|
|
3
|
+
export declare function shouldRunInLinux(): Promise<void>;
|
|
4
|
+
export declare function ensureLicense(): Promise<void>;
|
|
5
|
+
export declare function requestTrialLicense(): Promise<void>;
|
|
6
|
+
export declare function skipIfNoLicense(): Promise<void>;
|
|
7
|
+
export declare function skipIfFeatureFlagNotSet(name: string, value: string | boolean): Promise<void>;
|
package/dist/flag.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var os = require('node:os');
|
|
4
|
+
var test = require('@playwright/test');
|
|
5
|
+
var constant = require('./constant.js');
|
|
6
|
+
var init = require('./server/init.js');
|
|
7
|
+
|
|
8
|
+
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
|
9
|
+
// See LICENSE.txt for license information.
|
|
10
|
+
async function shouldHaveCallsEnabled(enabled = true) {
|
|
11
|
+
const { adminClient } = await init.getAdminClient();
|
|
12
|
+
const config = await adminClient.getConfig();
|
|
13
|
+
const callsEnabled = config.PluginSettings.PluginStates[constant.callsPluginId].Enable;
|
|
14
|
+
const matched = callsEnabled === enabled;
|
|
15
|
+
test.expect(matched, matched ? '' : `Calls expect "${enabled}" but actual "${callsEnabled}"`).toBeTruthy();
|
|
16
|
+
}
|
|
17
|
+
async function shouldHaveFeatureFlag(name, value) {
|
|
18
|
+
const { adminClient } = await init.getAdminClient();
|
|
19
|
+
const config = await adminClient.getConfig();
|
|
20
|
+
const matched = config.FeatureFlags[name] === value;
|
|
21
|
+
test.expect(matched, matched ? '' : `FeatureFlags["${name}'] expect "${value}" but actual "${config.FeatureFlags[name]}"`).toBeTruthy();
|
|
22
|
+
}
|
|
23
|
+
async function shouldRunInLinux() {
|
|
24
|
+
const platform = os.platform();
|
|
25
|
+
test.expect(platform, 'Run in Linux or Playwright docker image only').toBe('linux');
|
|
26
|
+
}
|
|
27
|
+
async function ensureLicense() {
|
|
28
|
+
const { adminClient } = await init.getAdminClient();
|
|
29
|
+
let license = await adminClient.getClientLicenseOld();
|
|
30
|
+
if (license?.IsLicensed !== 'true') {
|
|
31
|
+
const config = await adminClient.getClientConfigOld();
|
|
32
|
+
test.expect(config.ServiceEnvironment === 'dev', 'The trial license request fails in the local development environment. Please manually upload the test license.').toBeFalsy();
|
|
33
|
+
await requestTrialLicense();
|
|
34
|
+
license = await adminClient.getClientLicenseOld();
|
|
35
|
+
}
|
|
36
|
+
test.expect(license?.IsLicensed === 'true', 'Ensure server has license').toBeTruthy();
|
|
37
|
+
}
|
|
38
|
+
async function requestTrialLicense() {
|
|
39
|
+
const { adminClient } = await init.getAdminClient();
|
|
40
|
+
const admin = await adminClient.getMe();
|
|
41
|
+
try {
|
|
42
|
+
await adminClient.requestTrialLicense({
|
|
43
|
+
receive_emails_accepted: true,
|
|
44
|
+
terms_accepted: true,
|
|
45
|
+
users: 100,
|
|
46
|
+
contact_name: admin.first_name + ' ' + admin.last_name,
|
|
47
|
+
contact_email: admin.email,
|
|
48
|
+
company_name: 'Mattermost Playwright E2E Tests',
|
|
49
|
+
company_size: '101-250',
|
|
50
|
+
company_country: 'United States',
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
test.expect(error, 'Failed to request trial license').toBeFalsy();
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async function skipIfNoLicense() {
|
|
59
|
+
const { adminClient } = await init.getAdminClient();
|
|
60
|
+
const license = await adminClient.getClientLicenseOld();
|
|
61
|
+
test.test.skip(license.IsLicensed === 'false', 'Skipping test - server not licensed');
|
|
62
|
+
}
|
|
63
|
+
async function skipIfFeatureFlagNotSet(name, value) {
|
|
64
|
+
const { adminClient } = await init.getAdminClient();
|
|
65
|
+
const cfg = await adminClient.getConfig();
|
|
66
|
+
test.test.skip(cfg.FeatureFlags[name] !== value, `Skipping test - Feature Flag ${name} needs to be set to ${value}`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
exports.ensureLicense = ensureLicense;
|
|
70
|
+
exports.requestTrialLicense = requestTrialLicense;
|
|
71
|
+
exports.shouldHaveCallsEnabled = shouldHaveCallsEnabled;
|
|
72
|
+
exports.shouldHaveFeatureFlag = shouldHaveFeatureFlag;
|
|
73
|
+
exports.shouldRunInLinux = shouldRunInLinux;
|
|
74
|
+
exports.skipIfFeatureFlagNotSet = skipIfFeatureFlagNotSet;
|
|
75
|
+
exports.skipIfNoLicense = skipIfNoLicense;
|
|
76
|
+
//# sourceMappingURL=flag.js.map
|
package/dist/flag.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flag.js","sources":["../src/flag.ts"],"sourcesContent":["// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.\n// See LICENSE.txt for license information.\n\nimport os from 'node:os';\n\nimport {expect, test} from '@playwright/test';\n\nimport {callsPluginId} from './constant';\nimport {getAdminClient} from './server/init';\n\nexport async function shouldHaveCallsEnabled(enabled = true) {\n const {adminClient} = await getAdminClient();\n const config = await adminClient.getConfig();\n\n const callsEnabled = config.PluginSettings.PluginStates[callsPluginId].Enable;\n\n const matched = callsEnabled === enabled;\n expect(matched, matched ? '' : `Calls expect \"${enabled}\" but actual \"${callsEnabled}\"`).toBeTruthy();\n}\n\nexport async function shouldHaveFeatureFlag(name: string, value: string | boolean) {\n const {adminClient} = await getAdminClient();\n const config = await adminClient.getConfig();\n\n const matched = config.FeatureFlags[name] === value;\n expect(\n matched,\n matched ? '' : `FeatureFlags[\"${name}'] expect \"${value}\" but actual \"${config.FeatureFlags[name]}\"`,\n ).toBeTruthy();\n}\n\nexport async function shouldRunInLinux() {\n const platform = os.platform();\n expect(platform, 'Run in Linux or Playwright docker image only').toBe('linux');\n}\n\nexport async function ensureLicense() {\n const {adminClient} = await getAdminClient();\n let license = await adminClient.getClientLicenseOld();\n\n if (license?.IsLicensed !== 'true') {\n const config = await adminClient.getClientConfigOld();\n expect(\n config.ServiceEnvironment === 'dev',\n 'The trial license request fails in the local development environment. Please manually upload the test license.',\n ).toBeFalsy();\n\n await requestTrialLicense();\n\n license = await adminClient.getClientLicenseOld();\n }\n\n expect(license?.IsLicensed === 'true', 'Ensure server has license').toBeTruthy();\n}\n\nexport async function requestTrialLicense() {\n const {adminClient} = await getAdminClient();\n const admin = await adminClient.getMe();\n try {\n await adminClient.requestTrialLicense({\n receive_emails_accepted: true,\n terms_accepted: true,\n users: 100,\n contact_name: admin.first_name + ' ' + admin.last_name,\n contact_email: admin.email,\n company_name: 'Mattermost Playwright E2E Tests',\n company_size: '101-250',\n company_country: 'United States',\n });\n } catch (error) {\n expect(error, 'Failed to request trial license').toBeFalsy();\n throw error;\n }\n}\n\nexport async function skipIfNoLicense() {\n const {adminClient} = await getAdminClient();\n const license = await adminClient.getClientLicenseOld();\n\n test.skip(license.IsLicensed === 'false', 'Skipping test - server not licensed');\n}\n\nexport async function skipIfFeatureFlagNotSet(name: string, value: string | boolean) {\n const {adminClient} = await getAdminClient();\n const cfg = await adminClient.getConfig();\n\n test.skip(cfg.FeatureFlags[name] !== value, `Skipping test - Feature Flag ${name} needs to be set to ${value}`);\n}\n"],"names":["getAdminClient","callsPluginId","expect","test"],"mappings":"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"}
|