@iblai/iblai-js 1.20.16 → 1.20.18

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.
@@ -33,5 +33,6 @@ export { billingPlanSection, billingCreditsSection, billingAutoRechargeSection,
33
33
  export type { BillingAutoRechargeStatus } from './billing-tab-helpers';
34
34
  export { TASKS_LABELS, isTasksTabVisible, switchToTasksTab, getScheduleTaskButton, getSearchInput, getTaskRow, expectTotalTasks, expectCompletedTasks, expectFailedTasks, expectTasksEmpty, expectTaskInList, expectTaskNotInList, selectTaskInList, expectTaskStatus, searchTasks, openScheduleTaskDialog, scheduleTask, expectScheduleStartTimeInPastError, deleteTask, expectLogsForTask, expectNoLogsForSelectedTask, openFirstLogDetails, expectLogDetailsStatus, } from './tasks-tab-helpers';
35
35
  export type { TaskRepeat, TaskStatus } from './tasks-tab-helpers';
36
+ export * from './lti-tab-helpers';
36
37
  export { createPlaywrightConfig, generateProjectConfig, generateBrowserSetupProjects, getBrowserKey, } from './playwright-config';
37
38
  export type { PlatformConfig, CreatePlaywrightConfigOptions } from './playwright-config';
@@ -0,0 +1,270 @@
1
+ import { Locator, Page } from '@playwright/test';
2
+ /**
3
+ * LTI tab helpers — Playwright bindings for the `AgentLtiTab` component from
4
+ * `@iblai/web-containers`.
5
+ *
6
+ * The LTI tab is a peer top-level tab in the Edit Mentor (Agent) dialog with
7
+ * four sub-tabs: Links, Keys, Tools, and Tool Endpoints. It only renders when
8
+ * the agent is LTI-accessible (`is_lti_accessible`), so navigation helpers
9
+ * return `false` rather than throwing when the tab is absent.
10
+ *
11
+ * SELECTOR POLICY: every locator below resolves via a stable `data-testid`,
12
+ * an `aria-label`, or an accessible role+name (tab / button / menuitem /
13
+ * heading text). No CSS class or structural selectors are used, so these
14
+ * helpers survive styling changes.
15
+ *
16
+ * The helpers assume the Edit Mentor dialog is already open. Call
17
+ * `switchToLtiTab(page)` first; most helpers accept either the `Page` or the
18
+ * dialog `Locator` as `scope`.
19
+ */
20
+ export declare const LTI_LABELS: {
21
+ /** Left-sidebar tab name. */
22
+ readonly tabName: "LTI";
23
+ readonly header: {
24
+ readonly title: "LTI";
25
+ readonly description: "Manage LTI agent links, signing keys, tools, and platform endpoints.";
26
+ };
27
+ readonly subTabs: {
28
+ readonly agentLinks: "Links";
29
+ readonly keys: "Keys";
30
+ readonly tools: "Tools";
31
+ readonly toolEndpoints: "Tool Endpoints";
32
+ };
33
+ readonly modals: {
34
+ readonly createLink: "Create LTI Link";
35
+ readonly editLink: "Edit LTI Link";
36
+ readonly createKey: "Create LTI Key";
37
+ readonly keyDetail: "LTI Key";
38
+ readonly deleteKey: "Delete LTI Key";
39
+ readonly createTool: "Create LTI Tool";
40
+ readonly editTool: "Edit LTI Tool";
41
+ };
42
+ readonly buttons: {
43
+ readonly createLink: "Create LTI Link";
44
+ readonly createKey: "Create LTI Key";
45
+ readonly createTool: "Create LTI Tool";
46
+ /** Confirm button inside the delete-key modal. */
47
+ readonly deleteKey: "Delete";
48
+ readonly edit: "Edit";
49
+ readonly delete: "Delete";
50
+ readonly cancel: "Cancel";
51
+ readonly close: "Close";
52
+ readonly save: "Save";
53
+ readonly create: "Create";
54
+ };
55
+ readonly empty: {
56
+ readonly links: "No LTI link yet for this agent.";
57
+ readonly keys: "No LTI keys yet.";
58
+ readonly tools: "No LTI tools yet.";
59
+ };
60
+ };
61
+ /** data-testid values rendered by the LTI components. */
62
+ export declare const LTI_TEST_IDS: {
63
+ readonly tabBody: "lti-tab-body";
64
+ readonly subTabs: "lti-sub-tabs";
65
+ readonly subTab: {
66
+ readonly agentLinks: "lti-sub-tab-agent-links";
67
+ readonly keys: "lti-sub-tab-keys";
68
+ readonly tools: "lti-sub-tab-tools";
69
+ readonly toolEndpoints: "lti-sub-tab-tool-endpoints";
70
+ };
71
+ readonly links: {
72
+ readonly section: "lti-links-section";
73
+ readonly createButton: "lti-link-create-button";
74
+ readonly empty: "lti-links-empty";
75
+ readonly row: "lti-link-row";
76
+ readonly modal: "lti-link-modal";
77
+ readonly nameInput: "lti-link-name-input";
78
+ };
79
+ readonly keys: {
80
+ readonly section: "lti-keys-section";
81
+ readonly createButton: "lti-key-create-button";
82
+ readonly empty: "lti-keys-empty";
83
+ readonly row: "lti-key-row";
84
+ readonly createModal: "lti-key-create-modal";
85
+ readonly createNameInput: "lti-key-name-input";
86
+ readonly detailModal: "lti-key-detail-modal";
87
+ readonly detailNameInput: "lti-key-detail-name-input";
88
+ readonly publicKey: "lti-key-public-key";
89
+ readonly publicJwk: "lti-key-public-jwk";
90
+ readonly deleteModal: "lti-key-delete-modal";
91
+ };
92
+ readonly tools: {
93
+ readonly section: "lti-tools-section";
94
+ readonly createButton: "lti-tool-create-button";
95
+ readonly empty: "lti-tools-empty";
96
+ readonly row: "lti-tool-row";
97
+ readonly modal: "lti-tool-modal";
98
+ readonly titleInput: "lti-tool-title-input";
99
+ readonly issuerInput: "lti-tool-issuer-input";
100
+ readonly clientIdInput: "lti-tool-client-id-input";
101
+ readonly authLoginInput: "lti-tool-auth-login-input";
102
+ readonly authTokenInput: "lti-tool-auth-token-input";
103
+ readonly authAudienceInput: "lti-tool-auth-audience-input";
104
+ readonly keySetModeUrl: "lti-tool-keyset-mode-url";
105
+ readonly keySetModeRaw: "lti-tool-keyset-mode-raw";
106
+ readonly jwksUrlInput: "lti-tool-jwks-url-input";
107
+ readonly jwksJsonInput: "lti-tool-jwks-json-input";
108
+ readonly keySelect: "lti-tool-key-select";
109
+ readonly deploymentIdsInput: "lti-tool-deployment-ids-input";
110
+ };
111
+ readonly endpoints: {
112
+ readonly redirectUri: "lti-endpoint-redirect-uri";
113
+ readonly login: "lti-endpoint-login";
114
+ readonly deepLinking: "lti-endpoint-deep-linking";
115
+ readonly jwks: "lti-endpoint-jwks";
116
+ readonly url: "lti-endpoint-url";
117
+ };
118
+ };
119
+ export type LtiSubTab = keyof typeof LTI_TEST_IDS.subTab;
120
+ export type LtiEndpoint = 'redirectUri' | 'login' | 'deepLinking' | 'jwks';
121
+ export type LtiKeySetMode = 'url' | 'raw';
122
+ /** Fields accepted by `createTool` / `editTool`. */
123
+ export interface LtiToolFormData {
124
+ title: string;
125
+ issuer: string;
126
+ clientId: string;
127
+ authLoginUrl: string;
128
+ authTokenUrl: string;
129
+ authAudience?: string;
130
+ /** Defaults to 'url'. */
131
+ keySetMode?: LtiKeySetMode;
132
+ /** Required when keySetMode === 'url'. */
133
+ jwksUrl?: string;
134
+ /** Required when keySetMode === 'raw' (raw JWKS JSON string). */
135
+ jwksJson?: string;
136
+ /** Name of the signing key to pick from the dropdown. */
137
+ signingKeyName: string;
138
+ /** Deployment ids; joined with newlines into the textarea. */
139
+ deploymentIds?: string[];
140
+ }
141
+ /**
142
+ * Whether the LTI tab is currently available in the Edit Mentor dialog.
143
+ * Returns `false` instead of throwing (the tab is hidden unless the agent is
144
+ * LTI-accessible).
145
+ */
146
+ export declare function isLtiTabVisible(page: Page): Promise<boolean>;
147
+ /**
148
+ * Switch to the LTI tab. Assumes the Edit Mentor dialog is open. Waits for the
149
+ * sub-tab bar to be interactive before returning.
150
+ */
151
+ export declare function switchToLtiTab(page: Page): Promise<void>;
152
+ /** Locator for a sub-tab trigger. */
153
+ export declare function getLtiSubTab(scope: Page | Locator, subTab: LtiSubTab): Locator;
154
+ /** Switch to one of the four LTI sub-tabs and wait for it to become active. */
155
+ export declare function switchToLtiSubTab(page: Page, subTab: LtiSubTab): Promise<void>;
156
+ export declare function expectLtiHeader(scope: Page | Locator): Promise<void>;
157
+ export declare function getLinksSection(scope: Page | Locator): Locator;
158
+ /** The "Create LTI Link" button (only shown when no link exists yet). */
159
+ export declare function getCreateLinkButton(scope: Page | Locator): Locator;
160
+ export declare function getLinksEmptyState(scope: Page | Locator): Locator;
161
+ /** A link row located by its visible name. */
162
+ export declare function getLinkRow(scope: Page | Locator, name: string): Locator;
163
+ /** The per-row "Edit <name>" pencil button. */
164
+ export declare function getLinkEditButton(scope: Page | Locator, name: string): Locator;
165
+ /** The "Copy target link URI" button shown in a link row. */
166
+ export declare function getLinkCopyTargetUriButton(scope: Page | Locator): Locator;
167
+ export declare function getLinkModal(scope: Page | Locator): Locator;
168
+ export declare function getLinkNameInput(scope: Page | Locator): Locator;
169
+ export declare function openCreateLinkModal(scope: Page | Locator): Promise<void>;
170
+ export declare function openEditLinkModal(scope: Page | Locator, name: string): Promise<void>;
171
+ /** Type a name into the (already-open) link modal. */
172
+ export declare function fillLinkName(scope: Page | Locator, name: string): Promise<void>;
173
+ export declare function submitLinkModal(scope: Page | Locator): Promise<void>;
174
+ /** Full create-link flow. */
175
+ export declare function createLink(scope: Page | Locator, name: string): Promise<void>;
176
+ /** Full rename-link flow (opens via the row's edit pencil). */
177
+ export declare function editLink(scope: Page | Locator, currentName: string, newName: string): Promise<void>;
178
+ export declare function expectLinksEmpty(scope: Page | Locator): Promise<void>;
179
+ export declare function expectLinkInList(scope: Page | Locator, name: string): Promise<void>;
180
+ export declare function expectLinkNotInList(scope: Page | Locator, name: string): Promise<void>;
181
+ export declare function expectLinkTargetUri(scope: Page | Locator, name: string, targetUri: string): Promise<void>;
182
+ export declare function getKeysSection(scope: Page | Locator): Locator;
183
+ export declare function getCreateKeyButton(scope: Page | Locator): Locator;
184
+ export declare function getKeysEmptyState(scope: Page | Locator): Locator;
185
+ export declare function getKeyRow(scope: Page | Locator, name: string): Locator;
186
+ /** The per-row three-dots "Actions for <name>" menu trigger. */
187
+ export declare function getKeyActionsTrigger(scope: Page | Locator, name: string): Locator;
188
+ /** Open a key's three-dots menu and return the open menu (portal-rendered). */
189
+ export declare function openKeyActionsMenu(scope: Page | Locator, name: string): Promise<Locator>;
190
+ export declare function getKeyCreateModal(scope: Page | Locator): Locator;
191
+ export declare function getKeyCreateNameInput(scope: Page | Locator): Locator;
192
+ export declare function openCreateKeyModal(scope: Page | Locator): Promise<void>;
193
+ export declare function createKey(scope: Page | Locator, name: string): Promise<void>;
194
+ export declare function getKeyDetailModal(scope: Page | Locator): Locator;
195
+ export declare function getKeyDetailNameInput(scope: Page | Locator): Locator;
196
+ export declare function getKeyPublicKeyField(scope: Page | Locator): Locator;
197
+ export declare function getKeyPublicJwkField(scope: Page | Locator): Locator;
198
+ /** Open the detail (edit) modal for a key via its actions menu → Edit. */
199
+ export declare function openKeyDetail(scope: Page | Locator, name: string): Promise<void>;
200
+ /** Read the displayed public key (PEM) value. */
201
+ export declare function readKeyPublicKey(scope: Page | Locator): Promise<string>;
202
+ /** Read the displayed public JWK value. */
203
+ export declare function readKeyPublicJwk(scope: Page | Locator): Promise<string>;
204
+ /** Rename a key via the detail modal (opens the menu → Edit, then Save). */
205
+ export declare function renameKey(scope: Page | Locator, name: string, newName: string): Promise<void>;
206
+ export declare function closeKeyDetail(scope: Page | Locator): Promise<void>;
207
+ export declare function getKeyDeleteModal(scope: Page | Locator): Locator;
208
+ /** Open the delete confirmation for a key via its actions menu → Delete. */
209
+ export declare function openKeyDelete(scope: Page | Locator, name: string): Promise<void>;
210
+ export declare function confirmKeyDelete(scope: Page | Locator): Promise<void>;
211
+ export declare function cancelKeyDelete(scope: Page | Locator): Promise<void>;
212
+ /** Full delete-key flow (menu → Delete → confirm), expects the modal to close. */
213
+ export declare function deleteKey(scope: Page | Locator, name: string): Promise<void>;
214
+ /**
215
+ * Assert the delete error (e.g. "key is associated with tool X"). The backend
216
+ * returns 400/409 and the message is surfaced as a toast (matching the app's
217
+ * delete-modal convention); the modal stays open so the user can cancel.
218
+ */
219
+ export declare function expectKeyDeleteError(scope: Page | Locator, message: string): Promise<void>;
220
+ export declare function expectKeysEmpty(scope: Page | Locator): Promise<void>;
221
+ export declare function expectKeyInList(scope: Page | Locator, name: string): Promise<void>;
222
+ export declare function expectKeyNotInList(scope: Page | Locator, name: string): Promise<void>;
223
+ export declare function getToolsSection(scope: Page | Locator): Locator;
224
+ export declare function getCreateToolButton(scope: Page | Locator): Locator;
225
+ export declare function getToolsEmptyState(scope: Page | Locator): Locator;
226
+ export declare function getToolRow(scope: Page | Locator, name: string): Locator;
227
+ export declare function getToolEditButton(scope: Page | Locator, name: string): Locator;
228
+ export declare function getToolModal(scope: Page | Locator): Locator;
229
+ /** Field locators inside the (open) tool modal. */
230
+ export declare const toolFields: {
231
+ title: (scope: Page | Locator) => Locator;
232
+ issuer: (scope: Page | Locator) => Locator;
233
+ clientId: (scope: Page | Locator) => Locator;
234
+ authLoginUrl: (scope: Page | Locator) => Locator;
235
+ authTokenUrl: (scope: Page | Locator) => Locator;
236
+ authAudience: (scope: Page | Locator) => Locator;
237
+ jwksUrl: (scope: Page | Locator) => Locator;
238
+ jwksJson: (scope: Page | Locator) => Locator;
239
+ deploymentIds: (scope: Page | Locator) => Locator;
240
+ };
241
+ export declare function getToolKeySelect(scope: Page | Locator): Locator;
242
+ export declare function openCreateToolModal(scope: Page | Locator): Promise<void>;
243
+ export declare function openEditToolModal(scope: Page | Locator, name: string): Promise<void>;
244
+ /** Pick the JWKS source (URL or raw JSON) in the open tool modal. */
245
+ export declare function selectToolKeySetMode(scope: Page | Locator, mode: LtiKeySetMode): Promise<void>;
246
+ /** Pick a signing key by name from the Radix select in the open tool modal. */
247
+ export declare function selectToolSigningKey(scope: Page | Locator, name: string): Promise<void>;
248
+ /** Fill every field of the open tool modal from `data`. */
249
+ export declare function fillToolForm(scope: Page | Locator, data: LtiToolFormData): Promise<void>;
250
+ export declare function submitToolModal(scope: Page | Locator): Promise<void>;
251
+ /** Full create-tool flow. */
252
+ export declare function createTool(scope: Page | Locator, data: LtiToolFormData): Promise<void>;
253
+ /** Full edit-tool flow (opens via the row's edit pencil, applies overrides). */
254
+ export declare function editTool(scope: Page | Locator, name: string, data: LtiToolFormData): Promise<void>;
255
+ export declare function expectToolsEmpty(scope: Page | Locator): Promise<void>;
256
+ export declare function expectToolInList(scope: Page | Locator, name: string): Promise<void>;
257
+ export declare function expectToolNotInList(scope: Page | Locator, name: string): Promise<void>;
258
+ /** Container for a single platform endpoint row. */
259
+ export declare function getEndpoint(scope: Page | Locator, endpoint: LtiEndpoint): Locator;
260
+ /** The `<code>` element holding an endpoint's URL. */
261
+ export declare function getEndpointUrl(scope: Page | Locator, endpoint: LtiEndpoint): Locator;
262
+ /** The per-endpoint "Copy URL" button. */
263
+ export declare function getEndpointCopyButton(scope: Page | Locator, endpoint: LtiEndpoint): Locator;
264
+ /** Read an endpoint URL string. */
265
+ export declare function readEndpointUrl(scope: Page | Locator, endpoint: LtiEndpoint): Promise<string>;
266
+ /** Click an endpoint's copy button; the button label flips to "Copied". */
267
+ export declare function copyEndpoint(scope: Page | Locator, endpoint: LtiEndpoint): Promise<void>;
268
+ export declare function expectEndpointUrl(scope: Page | Locator, endpoint: LtiEndpoint, url: string): Promise<void>;
269
+ /** Assert all four endpoints render with non-empty URLs. */
270
+ export declare function expectAllEndpointsVisible(scope: Page | Locator): Promise<void>;