@iblai/iblai-js 1.26.2 → 1.26.4
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/data-layer/playwright/evaluation-tab-helpers.d.ts +396 -0
- package/dist/data-layer/playwright/index.d.ts +1 -0
- package/dist/playwright/index.cjs +883 -21
- package/dist/playwright/index.cjs.map +1 -1
- package/dist/playwright/index.d.ts +398 -2
- package/dist/playwright/index.esm.js +820 -22
- package/dist/playwright/index.esm.js.map +1 -1
- package/dist/playwright/playwright/evaluation-tab-helpers.d.ts +396 -0
- package/dist/playwright/playwright/index.d.ts +1 -0
- package/dist/web-containers/playwright/evaluation-tab-helpers.d.ts +396 -0
- package/dist/web-containers/playwright/index.d.ts +1 -0
- package/dist/web-containers/source/index.esm.js +892 -4
- package/dist/web-containers/source/next/index.esm.js +2142 -38
- package/dist/web-utils/playwright/evaluation-tab-helpers.d.ts +396 -0
- package/dist/web-utils/playwright/index.d.ts +1 -0
- package/package.json +5 -5
|
@@ -3164,7 +3164,7 @@ const PRIVACY_LABELS = {
|
|
|
3164
3164
|
* reach DOM that Radix renders outside the dialog subtree (popovers,
|
|
3165
3165
|
* select options, etc.).
|
|
3166
3166
|
*/
|
|
3167
|
-
function asPage$
|
|
3167
|
+
function asPage$6(scope) {
|
|
3168
3168
|
return 'page' in scope ? scope.page() : scope;
|
|
3169
3169
|
}
|
|
3170
3170
|
/**
|
|
@@ -3225,7 +3225,7 @@ async function selectPrivacyAction(scope, action) {
|
|
|
3225
3225
|
await trigger.click();
|
|
3226
3226
|
// Radix Select renders options in a portal at the document root, so we
|
|
3227
3227
|
// always look them up on the Page — never on the dialog Locator.
|
|
3228
|
-
const option = asPage$
|
|
3228
|
+
const option = asPage$6(scope).getByRole('option', {
|
|
3229
3229
|
name: PRIVACY_LABELS.actionOptions[action],
|
|
3230
3230
|
});
|
|
3231
3231
|
await expect(option).toBeVisible({ timeout: 5000 });
|
|
@@ -3337,7 +3337,7 @@ const CHAT_PRIVACY_LABELS = {
|
|
|
3337
3337
|
rowLabel: 'Allow users to control chat privacy',
|
|
3338
3338
|
},
|
|
3339
3339
|
};
|
|
3340
|
-
function asPage$
|
|
3340
|
+
function asPage$5(scope) {
|
|
3341
3341
|
return 'page' in scope ? scope.page() : scope;
|
|
3342
3342
|
}
|
|
3343
3343
|
// ──────────────────────────────────────────────────────────────────────
|
|
@@ -3409,7 +3409,7 @@ async function clickChatPrivacyToggle(scope) {
|
|
|
3409
3409
|
// ── Mid-session confirm dialog ────────────────────────────────────────
|
|
3410
3410
|
/** Locator for the AlertDialog content that the mid-session enable opens. */
|
|
3411
3411
|
function getChatPrivacyConfirmDialog(scope) {
|
|
3412
|
-
return asPage$
|
|
3412
|
+
return asPage$5(scope).getByTestId('chat-privacy-confirm-dialog');
|
|
3413
3413
|
}
|
|
3414
3414
|
async function expectChatPrivacyConfirmDialogOpen(scope, open) {
|
|
3415
3415
|
if (open) {
|
|
@@ -3428,7 +3428,7 @@ async function expectChatPrivacyConfirmDialogOpen(scope, open) {
|
|
|
3428
3428
|
*/
|
|
3429
3429
|
async function confirmEnableChatPrivacyMidSession(scope) {
|
|
3430
3430
|
await clickChatPrivacyToggle(scope);
|
|
3431
|
-
const page = asPage$
|
|
3431
|
+
const page = asPage$5(scope);
|
|
3432
3432
|
await expectChatPrivacyConfirmDialogOpen(page, true);
|
|
3433
3433
|
const action = page.getByTestId('chat-privacy-confirm-action');
|
|
3434
3434
|
await expect(action).toBeVisible({ timeout: 10000 });
|
|
@@ -3439,7 +3439,7 @@ async function confirmEnableChatPrivacyMidSession(scope) {
|
|
|
3439
3439
|
}
|
|
3440
3440
|
/** Cancel the confirm dialog without enabling. */
|
|
3441
3441
|
async function cancelEnableChatPrivacyMidSession(scope) {
|
|
3442
|
-
const page = asPage$
|
|
3442
|
+
const page = asPage$5(scope);
|
|
3443
3443
|
const cancel = page.getByTestId('chat-privacy-confirm-cancel');
|
|
3444
3444
|
await expect(cancel).toBeVisible({ timeout: 10000 });
|
|
3445
3445
|
await cancel.click();
|
|
@@ -3626,7 +3626,7 @@ const VOICE_LABELS = {
|
|
|
3626
3626
|
* reach DOM that Radix renders outside the dialog subtree (popovers,
|
|
3627
3627
|
* select options, etc.).
|
|
3628
3628
|
*/
|
|
3629
|
-
function asPage$
|
|
3629
|
+
function asPage$4(scope) {
|
|
3630
3630
|
return 'page' in scope ? scope.page() : scope;
|
|
3631
3631
|
}
|
|
3632
3632
|
// ─── Tab navigation ──────────────────────────────────────────────────────
|
|
@@ -3708,7 +3708,7 @@ async function openMentorVoicePicker(scope) {
|
|
|
3708
3708
|
const openBtn = scope.getByTestId('mentor-voice-trigger-open');
|
|
3709
3709
|
await expect(openBtn).toBeVisible({ timeout: 10000 });
|
|
3710
3710
|
await openBtn.click();
|
|
3711
|
-
await expect(asPage$
|
|
3711
|
+
await expect(asPage$4(scope).getByTestId('voice-picker-modal')).toBeVisible({
|
|
3712
3712
|
timeout: 10000,
|
|
3713
3713
|
});
|
|
3714
3714
|
}
|
|
@@ -3720,7 +3720,7 @@ async function openCallConfigVoicePicker(scope) {
|
|
|
3720
3720
|
const openBtn = scope.getByTestId('call-config-voice-trigger-open');
|
|
3721
3721
|
await expect(openBtn).toBeVisible({ timeout: 10000 });
|
|
3722
3722
|
await openBtn.click();
|
|
3723
|
-
await expect(asPage$
|
|
3723
|
+
await expect(asPage$4(scope).getByTestId('voice-picker-modal')).toBeVisible({
|
|
3724
3724
|
timeout: 10000,
|
|
3725
3725
|
});
|
|
3726
3726
|
}
|
|
@@ -3833,7 +3833,7 @@ async function selectCallMode(scope, mode) {
|
|
|
3833
3833
|
const trigger = scope.getByRole('combobox', { name: VOICE_LABELS.callConfigFields.mode });
|
|
3834
3834
|
await expect(trigger).toBeVisible({ timeout: 10000 });
|
|
3835
3835
|
await trigger.click();
|
|
3836
|
-
const option = asPage$
|
|
3836
|
+
const option = asPage$4(scope).getByRole('option', { name: VOICE_LABELS.modeOptions[mode] });
|
|
3837
3837
|
await expect(option).toBeVisible({ timeout: 5000 });
|
|
3838
3838
|
await option.click();
|
|
3839
3839
|
await expect(trigger).toHaveText(new RegExp(VOICE_LABELS.modeOptions[mode]));
|
|
@@ -3849,7 +3849,7 @@ async function selectFromCombobox(scope, triggerName, optionName) {
|
|
|
3849
3849
|
const trigger = scope.getByRole('combobox', { name: triggerName });
|
|
3850
3850
|
await expect(trigger).toBeVisible({ timeout: 10000 });
|
|
3851
3851
|
await trigger.click();
|
|
3852
|
-
const option = asPage$
|
|
3852
|
+
const option = asPage$4(scope).getByRole('option', { name: optionName });
|
|
3853
3853
|
await expect(option).toBeVisible({ timeout: 5000 });
|
|
3854
3854
|
await option.click();
|
|
3855
3855
|
}
|
|
@@ -3946,7 +3946,7 @@ const SCREENSHARE_LABELS = {
|
|
|
3946
3946
|
},
|
|
3947
3947
|
saveButton: 'Save',
|
|
3948
3948
|
};
|
|
3949
|
-
function asPage$
|
|
3949
|
+
function asPage$3(scope) {
|
|
3950
3950
|
return 'page' in scope ? scope.page() : scope;
|
|
3951
3951
|
}
|
|
3952
3952
|
/**
|
|
@@ -3986,7 +3986,7 @@ async function openScreenSharePromptEditor(scope, field) {
|
|
|
3986
3986
|
const btn = scope.getByRole('button', { name: `Edit ${label}` });
|
|
3987
3987
|
await expect(btn).toBeVisible({ timeout: 10000 });
|
|
3988
3988
|
await btn.click();
|
|
3989
|
-
await expect(asPage$
|
|
3989
|
+
await expect(asPage$3(scope).getByText(`Edit ${label}`)).toBeVisible({ timeout: 10000 });
|
|
3990
3990
|
logger.info(`Opened screen-share ${field} editor`);
|
|
3991
3991
|
}
|
|
3992
3992
|
/**
|
|
@@ -3996,7 +3996,7 @@ async function openScreenSharePromptEditor(scope, field) {
|
|
|
3996
3996
|
*/
|
|
3997
3997
|
async function setScreenSharePrompt(scope, field, text) {
|
|
3998
3998
|
await openScreenSharePromptEditor(scope, field);
|
|
3999
|
-
const page = asPage$
|
|
3999
|
+
const page = asPage$3(scope);
|
|
4000
4000
|
const editor = page.getByRole('dialog').locator('[contenteditable="true"]').first();
|
|
4001
4001
|
await expect(editor).toBeVisible({ timeout: 10000 });
|
|
4002
4002
|
await editor.click();
|
|
@@ -4005,7 +4005,10 @@ async function setScreenSharePrompt(scope, field, text) {
|
|
|
4005
4005
|
await editor.pressSequentially(text);
|
|
4006
4006
|
// The modal's Save button — scope to dialog so we don't grab the
|
|
4007
4007
|
// outer tab's Save.
|
|
4008
|
-
await page
|
|
4008
|
+
await page
|
|
4009
|
+
.getByRole('dialog')
|
|
4010
|
+
.getByRole('button', { name: /^save$/i })
|
|
4011
|
+
.click();
|
|
4009
4012
|
await expect(page.getByRole('dialog')).toBeHidden({ timeout: 10000 });
|
|
4010
4013
|
logger.info(`Set screen-share ${field}`);
|
|
4011
4014
|
}
|
|
@@ -4324,7 +4327,7 @@ const TASKS_LABELS = {
|
|
|
4324
4327
|
* reach DOM that Radix renders outside the dialog subtree (popovers,
|
|
4325
4328
|
* select options, the schedule / delete / log-details dialogs, etc.).
|
|
4326
4329
|
*/
|
|
4327
|
-
function asPage$
|
|
4330
|
+
function asPage$2(scope) {
|
|
4328
4331
|
return 'page' in scope ? scope.page() : scope;
|
|
4329
4332
|
}
|
|
4330
4333
|
// ── Tab navigation ─────────────────────────────────────────────────────
|
|
@@ -4434,7 +4437,7 @@ async function searchTasks(scope, query) {
|
|
|
4434
4437
|
* shares an accessible name with the dialog's submit button.
|
|
4435
4438
|
*/
|
|
4436
4439
|
function getScheduleTaskDialog(scope) {
|
|
4437
|
-
return asPage$
|
|
4440
|
+
return asPage$2(scope).getByRole('dialog', { name: TASKS_LABELS.scheduleDialog.dialogName });
|
|
4438
4441
|
}
|
|
4439
4442
|
/** Open the Schedule Task dialog and wait for it to be interactive. */
|
|
4440
4443
|
async function openScheduleTaskDialog(scope) {
|
|
@@ -4453,7 +4456,7 @@ async function openScheduleTaskDialog(scope) {
|
|
|
4453
4456
|
*/
|
|
4454
4457
|
async function scheduleTask(scope, opts) {
|
|
4455
4458
|
await openScheduleTaskDialog(scope);
|
|
4456
|
-
const page = asPage$
|
|
4459
|
+
const page = asPage$2(scope);
|
|
4457
4460
|
// Scope every query to the dialog: the toolbar "Schedule Task" button shares
|
|
4458
4461
|
// an accessible name with the dialog's submit button, so an unscoped
|
|
4459
4462
|
// getByRole('button', { name: 'Schedule Task' }) matches two elements.
|
|
@@ -4488,13 +4491,13 @@ async function scheduleTask(scope, opts) {
|
|
|
4488
4491
|
}
|
|
4489
4492
|
/** Asserts the in-dialog past-time error is currently shown. */
|
|
4490
4493
|
async function expectScheduleStartTimeInPastError(scope) {
|
|
4491
|
-
await expect(asPage$
|
|
4494
|
+
await expect(asPage$2(scope).getByText(TASKS_LABELS.scheduleDialog.startTimeInPast)).toBeVisible({
|
|
4492
4495
|
timeout: 5000,
|
|
4493
4496
|
});
|
|
4494
4497
|
}
|
|
4495
4498
|
// ── Delete flow ────────────────────────────────────────────────────────
|
|
4496
4499
|
function getDeleteTaskDialog(scope) {
|
|
4497
|
-
return asPage$
|
|
4500
|
+
return asPage$2(scope).locator(`[role="dialog"][aria-label="${TASKS_LABELS.deleteDialog.dialogName}"]`);
|
|
4498
4501
|
}
|
|
4499
4502
|
/**
|
|
4500
4503
|
* Click the trash icon on a task row and confirm the delete in the
|
|
@@ -4515,7 +4518,7 @@ async function deleteTask(scope, taskName) {
|
|
|
4515
4518
|
}
|
|
4516
4519
|
// ── Logs panel + log details ───────────────────────────────────────────
|
|
4517
4520
|
function getLogDetailsDialog(scope) {
|
|
4518
|
-
return asPage$
|
|
4521
|
+
return asPage$2(scope).locator(`[role="dialog"][aria-label="${TASKS_LABELS.logDetails.dialogName}"]`);
|
|
4519
4522
|
}
|
|
4520
4523
|
/**
|
|
4521
4524
|
* Wait for the logs panel to finish loading and assert that the selected
|
|
@@ -4551,6 +4554,801 @@ async function expectLogDetailsStatus(scope, status) {
|
|
|
4551
4554
|
});
|
|
4552
4555
|
}
|
|
4553
4556
|
|
|
4557
|
+
/**
|
|
4558
|
+
* Evals tab helpers — Playwright bindings for the `AgentEvaluationTab`
|
|
4559
|
+
* component from `@iblai/web-containers` (edit-mentor modal > Evals tab),
|
|
4560
|
+
* including the embedded tenant Benchmarks management dialog.
|
|
4561
|
+
*
|
|
4562
|
+
* All UI strings below mirror `AGENT_EVALUATION_TAB_LABELS` from
|
|
4563
|
+
* `@iblai/web-containers/next` plus the `benchmarks*` i18n namespaces. If a
|
|
4564
|
+
* consumer renames a label via the `labels` prop, override these constants
|
|
4565
|
+
* per spec — don't edit this file.
|
|
4566
|
+
*
|
|
4567
|
+
* Every dialog spawned by this tab carries an explicit `aria-label` on its
|
|
4568
|
+
* `DialogContent` (see `dialogName` entries). Helpers ALWAYS resolve the
|
|
4569
|
+
* dialog once via `[role="dialog"][aria-label="…"]` — the attribute selector,
|
|
4570
|
+
* not the role accessible name, because a visible `DialogTitle` makes Radix's
|
|
4571
|
+
* `aria-labelledby` win the accessible-name computation — and then resolve
|
|
4572
|
+
* every in-dialog control from that scoped locator. This matters here more
|
|
4573
|
+
* than usual:
|
|
4574
|
+
* - the toolbar "New Evaluation" / "Manage benchmarks" buttons share their
|
|
4575
|
+
* text with the dialog titles they open;
|
|
4576
|
+
* - the LLM-judge dialog's title AND submit button both read "Evaluate";
|
|
4577
|
+
* - dialogs nest three deep (Manage benchmarks → benchmark items → add
|
|
4578
|
+
* Q&A), and the add-Q&A dialog has Manual / CSV Upload sub-tabs whose
|
|
4579
|
+
* footers each have their own Cancel button.
|
|
4580
|
+
*
|
|
4581
|
+
* The helpers assume the Edit Mentor dialog is already open. Call
|
|
4582
|
+
* `switchToEvaluationTab(page)` first; from then on, every helper accepts
|
|
4583
|
+
* either the `Page` or a scoping `Locator`.
|
|
4584
|
+
*/
|
|
4585
|
+
const EVALS_LABELS = {
|
|
4586
|
+
tabName: 'Evals',
|
|
4587
|
+
header: {
|
|
4588
|
+
title: 'Evals',
|
|
4589
|
+
description: 'Run this agent against a benchmark and score the responses.',
|
|
4590
|
+
},
|
|
4591
|
+
benchmarkPicker: {
|
|
4592
|
+
placeholder: 'Select a benchmark',
|
|
4593
|
+
searchPlaceholder: 'Search benchmarks...',
|
|
4594
|
+
empty: 'No benchmarks found',
|
|
4595
|
+
/** `data-testid` on the combobox trigger button (its text is the selected benchmark, so it has no stable accessible name). */
|
|
4596
|
+
triggerTestId: 'benchmark-combobox',
|
|
4597
|
+
/** `data-testid` on the dropdown panel (rendered inline, not in a portal). */
|
|
4598
|
+
dropdownTestId: 'benchmark-combobox-dropdown',
|
|
4599
|
+
},
|
|
4600
|
+
actions: {
|
|
4601
|
+
newExperiment: 'New Evaluation',
|
|
4602
|
+
manageBenchmarks: 'Manage benchmarks',
|
|
4603
|
+
viewResults: 'View results',
|
|
4604
|
+
evaluate: 'New review',
|
|
4605
|
+
exportCsv: 'Export CSV',
|
|
4606
|
+
checkStatus: 'Check status',
|
|
4607
|
+
delete: 'Delete',
|
|
4608
|
+
},
|
|
4609
|
+
checkStatusToast: {
|
|
4610
|
+
pending: 'Evaluation is still running',
|
|
4611
|
+
completed: 'Evaluation completed',
|
|
4612
|
+
failed: 'Evaluation failed',
|
|
4613
|
+
},
|
|
4614
|
+
emptyBenchmarks: 'No benchmarks yet. Use "Manage benchmarks" above to create one.',
|
|
4615
|
+
startDialog: {
|
|
4616
|
+
/** `aria-label` on the dialog's `DialogContent` — scopes in-dialog locators. */
|
|
4617
|
+
dialogName: 'start-evaluation',
|
|
4618
|
+
experimentNameLabel: 'Evaluation name',
|
|
4619
|
+
cancel: 'Cancel',
|
|
4620
|
+
start: 'Start Evaluation',
|
|
4621
|
+
},
|
|
4622
|
+
manageBenchmarksDialog: {
|
|
4623
|
+
/** `aria-label` on the dialog's `DialogContent` — scopes in-dialog locators. */
|
|
4624
|
+
dialogName: 'manage-benchmarks',
|
|
4625
|
+
searchAriaLabel: 'Search benchmarks',
|
|
4626
|
+
newBenchmark: 'New Benchmark',
|
|
4627
|
+
empty: 'No benchmarks found',
|
|
4628
|
+
},
|
|
4629
|
+
createBenchmarkDialog: {
|
|
4630
|
+
/** `aria-label` on the dialog's `DialogContent` — scopes in-dialog locators. */
|
|
4631
|
+
dialogName: 'create-benchmark',
|
|
4632
|
+
nameLabel: 'Name',
|
|
4633
|
+
descriptionLabel: 'Description',
|
|
4634
|
+
cancel: 'Cancel',
|
|
4635
|
+
create: 'Create',
|
|
4636
|
+
},
|
|
4637
|
+
benchmarkItemsDialog: {
|
|
4638
|
+
/** `aria-label` on the dialog's `DialogContent` — scopes in-dialog locators. */
|
|
4639
|
+
dialogName: 'benchmark-items',
|
|
4640
|
+
addItems: 'Add Q&A',
|
|
4641
|
+
deleteItemAriaLabel: 'Delete Q&A',
|
|
4642
|
+
empty: 'No Q&A in this benchmark yet',
|
|
4643
|
+
},
|
|
4644
|
+
addItemsDialog: {
|
|
4645
|
+
/** `aria-label` on the dialog's `DialogContent` — scopes in-dialog locators. */
|
|
4646
|
+
dialogName: 'add-benchmark-items',
|
|
4647
|
+
manualTab: 'Manual',
|
|
4648
|
+
csvTab: 'CSV Upload',
|
|
4649
|
+
questionLabel: 'Question',
|
|
4650
|
+
answerLabel: 'Answer',
|
|
4651
|
+
addRow: 'Add row',
|
|
4652
|
+
removeRowAriaLabel: 'Remove row',
|
|
4653
|
+
add: 'Add',
|
|
4654
|
+
csvFileLabel: 'CSV file',
|
|
4655
|
+
upload: 'Upload',
|
|
4656
|
+
cancel: 'Cancel',
|
|
4657
|
+
},
|
|
4658
|
+
deleteItemDialog: {
|
|
4659
|
+
/** `aria-label` on the dialog's `DialogContent` — scopes in-dialog locators. */
|
|
4660
|
+
dialogName: 'delete-benchmark-item',
|
|
4661
|
+
delete: 'Delete',
|
|
4662
|
+
cancel: 'Cancel',
|
|
4663
|
+
},
|
|
4664
|
+
detailDialog: {
|
|
4665
|
+
/** `aria-label` on the dialog's `DialogContent` — scopes in-dialog locators. */
|
|
4666
|
+
dialogName: 'evaluation-detail',
|
|
4667
|
+
refreshAriaLabel: 'Refresh',
|
|
4668
|
+
newReview: 'New review',
|
|
4669
|
+
waitingHint: 'Waiting for the evaluation to produce traces. This page auto-refreshes.',
|
|
4670
|
+
noScoresHint: 'No scores yet',
|
|
4671
|
+
scoreNameLabel: 'Score name',
|
|
4672
|
+
scoreValueLabel: 'Value',
|
|
4673
|
+
scoreCommentLabel: 'Comment',
|
|
4674
|
+
addScore: 'Add',
|
|
4675
|
+
removeScoreAriaLabel: 'Remove score',
|
|
4676
|
+
reviewsHeading: 'Reviews',
|
|
4677
|
+
reviewDetailsAriaLabel: 'Toggle review details',
|
|
4678
|
+
reviewStatus: {
|
|
4679
|
+
pending: 'Queued',
|
|
4680
|
+
running: 'Running',
|
|
4681
|
+
completed: 'Complete',
|
|
4682
|
+
failed: 'Failed',
|
|
4683
|
+
},
|
|
4684
|
+
},
|
|
4685
|
+
judgeDialog: {
|
|
4686
|
+
/** `aria-label` on the dialog's `DialogContent` — scopes in-dialog locators. */
|
|
4687
|
+
dialogName: 'llm-judge',
|
|
4688
|
+
criteriaLabel: 'Criteria',
|
|
4689
|
+
scoreNameLabel: 'Score name',
|
|
4690
|
+
maxConcurrencyLabel: 'Max concurrency',
|
|
4691
|
+
selectorAriaLabel: 'LLM Model Selector',
|
|
4692
|
+
cancel: 'Cancel',
|
|
4693
|
+
submit: 'Evaluate',
|
|
4694
|
+
},
|
|
4695
|
+
llmPickerDialog: {
|
|
4696
|
+
/** `aria-label` on the dialog's `DialogContent` — scopes in-dialog locators. */
|
|
4697
|
+
dialogName: 'evaluate-llm-picker',
|
|
4698
|
+
searchPlaceholder: 'Search providers...',
|
|
4699
|
+
/** Title of the follow-up model-selection modal (llm-tab's `LLMProviderModal`, no aria-label of its own). */
|
|
4700
|
+
modelDialogTitle: 'LLM Selection',
|
|
4701
|
+
},
|
|
4702
|
+
deleteDialog: {
|
|
4703
|
+
/** `aria-label` on the dialog's `DialogContent` — scopes in-dialog locators. */
|
|
4704
|
+
dialogName: 'delete-evaluation',
|
|
4705
|
+
cancel: 'Cancel',
|
|
4706
|
+
confirm: 'Delete',
|
|
4707
|
+
},
|
|
4708
|
+
};
|
|
4709
|
+
/**
|
|
4710
|
+
* Resolve a Page from either a Page or a Locator. Used for DOM that Radix
|
|
4711
|
+
* renders in a portal outside the current scope (dialogs, dropdown menus,
|
|
4712
|
+
* toasts) — those queries must run on the page, never on the tab pane or a
|
|
4713
|
+
* parent dialog.
|
|
4714
|
+
*/
|
|
4715
|
+
function asPage$1(scope) {
|
|
4716
|
+
return 'page' in scope ? scope.page() : scope;
|
|
4717
|
+
}
|
|
4718
|
+
/** Escape a user-supplied string (run / benchmark names) for use in a RegExp. */
|
|
4719
|
+
function escapeRegExp(value) {
|
|
4720
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
4721
|
+
}
|
|
4722
|
+
/** Attribute-based dialog locator — immune to title renames and to Radix's `aria-labelledby` name precedence. */
|
|
4723
|
+
function dialogByName(scope, dialogName) {
|
|
4724
|
+
return asPage$1(scope).locator(`[role="dialog"][aria-label="${dialogName}"]`);
|
|
4725
|
+
}
|
|
4726
|
+
// ── Tab navigation ─────────────────────────────────────────────────────
|
|
4727
|
+
/**
|
|
4728
|
+
* Check whether the Evals tab is rendered in the Edit Mentor dialog.
|
|
4729
|
+
* Returns false instead of throwing so callers can guard permission-gated
|
|
4730
|
+
* tabs.
|
|
4731
|
+
*/
|
|
4732
|
+
async function isEvaluationTabVisible(page) {
|
|
4733
|
+
const tab = page.getByRole('tab', { name: EVALS_LABELS.tabName, exact: true });
|
|
4734
|
+
try {
|
|
4735
|
+
await expect(tab).toBeVisible({ timeout: 5000 });
|
|
4736
|
+
return true;
|
|
4737
|
+
}
|
|
4738
|
+
catch (_a) {
|
|
4739
|
+
return false;
|
|
4740
|
+
}
|
|
4741
|
+
}
|
|
4742
|
+
/**
|
|
4743
|
+
* Switch to the Evals tab. Assumes the Edit Mentor dialog is open. Waits
|
|
4744
|
+
* for the toolbar "Manage benchmarks" button (unique to this pane) before
|
|
4745
|
+
* returning, so callers can rely on the panel being interactive.
|
|
4746
|
+
*/
|
|
4747
|
+
async function switchToEvaluationTab(page) {
|
|
4748
|
+
const tab = page.getByRole('tab', { name: EVALS_LABELS.tabName, exact: true });
|
|
4749
|
+
await expect(tab).toBeVisible({ timeout: 10000 });
|
|
4750
|
+
await tab.click();
|
|
4751
|
+
await expect(page.getByRole('button', { name: EVALS_LABELS.actions.manageBenchmarks })).toBeVisible({ timeout: 10000 });
|
|
4752
|
+
logger.info('Switched to Evals tab');
|
|
4753
|
+
}
|
|
4754
|
+
// ── Toolbar: benchmark picker + action buttons ─────────────────────────
|
|
4755
|
+
/** Locator for the benchmark combobox trigger. Its text is the selected benchmark name. */
|
|
4756
|
+
function getBenchmarkCombobox(scope) {
|
|
4757
|
+
return scope.getByTestId(EVALS_LABELS.benchmarkPicker.triggerTestId);
|
|
4758
|
+
}
|
|
4759
|
+
/** Locator for the combobox dropdown panel (rendered inline under the trigger, not in a portal). */
|
|
4760
|
+
function getBenchmarkComboboxDropdown(scope) {
|
|
4761
|
+
return scope.getByTestId(EVALS_LABELS.benchmarkPicker.dropdownTestId);
|
|
4762
|
+
}
|
|
4763
|
+
/** Locator for the toolbar "New Evaluation" button (opens the start dialog). */
|
|
4764
|
+
function getNewEvaluationButton(scope) {
|
|
4765
|
+
return scope.getByRole('button', { name: EVALS_LABELS.actions.newExperiment, exact: true });
|
|
4766
|
+
}
|
|
4767
|
+
/** Locator for the toolbar "Manage benchmarks" button (opens the benchmarks dialog). */
|
|
4768
|
+
function getManageBenchmarksButton(scope) {
|
|
4769
|
+
return scope.getByRole('button', { name: EVALS_LABELS.actions.manageBenchmarks, exact: true });
|
|
4770
|
+
}
|
|
4771
|
+
/** Assert the currently selected benchmark shown on the combobox trigger. */
|
|
4772
|
+
async function expectSelectedBenchmark(scope, benchmarkName) {
|
|
4773
|
+
await expect(getBenchmarkCombobox(scope)).toContainText(benchmarkName, { timeout: 10000 });
|
|
4774
|
+
}
|
|
4775
|
+
/**
|
|
4776
|
+
* Open the benchmark combobox, optionally filter via its search input, and
|
|
4777
|
+
* pick a benchmark by exact name. Waits for the dropdown to close and the
|
|
4778
|
+
* trigger to reflect the selection.
|
|
4779
|
+
*/
|
|
4780
|
+
async function selectBenchmark(scope, benchmarkName, opts = {}) {
|
|
4781
|
+
const trigger = getBenchmarkCombobox(scope);
|
|
4782
|
+
await expect(trigger).toBeEnabled({ timeout: 10000 });
|
|
4783
|
+
await trigger.click();
|
|
4784
|
+
const dropdown = getBenchmarkComboboxDropdown(scope);
|
|
4785
|
+
await expect(dropdown).toBeVisible({ timeout: 5000 });
|
|
4786
|
+
if (opts.search) {
|
|
4787
|
+
const search = dropdown.getByPlaceholder(EVALS_LABELS.benchmarkPicker.searchPlaceholder);
|
|
4788
|
+
await search.fill(benchmarkName);
|
|
4789
|
+
await expect(search).toHaveValue(benchmarkName);
|
|
4790
|
+
}
|
|
4791
|
+
await dropdown
|
|
4792
|
+
.getByRole('button', { name: new RegExp(`^${escapeRegExp(benchmarkName)}$`) })
|
|
4793
|
+
.click();
|
|
4794
|
+
await expect(dropdown).toBeHidden({ timeout: 5000 });
|
|
4795
|
+
await expectSelectedBenchmark(scope, benchmarkName);
|
|
4796
|
+
logger.info(`Selected benchmark: ${benchmarkName}`);
|
|
4797
|
+
}
|
|
4798
|
+
/** Assert the "no benchmarks yet" empty notice is shown in the tab body. */
|
|
4799
|
+
async function expectNoBenchmarksNotice(scope) {
|
|
4800
|
+
await expect(scope.getByText(EVALS_LABELS.emptyBenchmarks)).toBeVisible({ timeout: 10000 });
|
|
4801
|
+
}
|
|
4802
|
+
// ── Runs table ─────────────────────────────────────────────────────────
|
|
4803
|
+
/**
|
|
4804
|
+
* Locator for an evaluation run's table row, matched by an exact cell so a
|
|
4805
|
+
* run whose name is a substring of another ("smoke" vs "smoke-2") can't
|
|
4806
|
+
* cross-match.
|
|
4807
|
+
*/
|
|
4808
|
+
function getRunRow(scope, runName) {
|
|
4809
|
+
return scope
|
|
4810
|
+
.getByRole('row')
|
|
4811
|
+
.filter({ has: asPage$1(scope).getByRole('cell', { name: runName, exact: true }) });
|
|
4812
|
+
}
|
|
4813
|
+
async function expectRunInTable(scope, runName) {
|
|
4814
|
+
await expect(getRunRow(scope, runName)).toBeVisible({ timeout: 15000 });
|
|
4815
|
+
}
|
|
4816
|
+
async function expectRunNotInTable(scope, runName) {
|
|
4817
|
+
await expect(getRunRow(scope, runName)).toBeHidden({ timeout: 15000 });
|
|
4818
|
+
}
|
|
4819
|
+
/** Assert the status badge on a run's row (badge text is upper-cased by the UI). */
|
|
4820
|
+
async function expectRunStatus(scope, runName, status) {
|
|
4821
|
+
await expect(getRunRow(scope, runName).getByText(status, { exact: true })).toBeVisible({
|
|
4822
|
+
timeout: 15000,
|
|
4823
|
+
});
|
|
4824
|
+
}
|
|
4825
|
+
/** Assert the empty-state row shown when the selected benchmark has no runs for this agent. */
|
|
4826
|
+
async function expectRunsTableEmpty(scope, benchmarkName) {
|
|
4827
|
+
await expect(scope.getByText(`No evaluations yet for this agent on benchmark "${benchmarkName}".`)).toBeVisible({ timeout: 15000 });
|
|
4828
|
+
}
|
|
4829
|
+
/**
|
|
4830
|
+
* Open the three-dots actions menu on a run's row. The trigger carries
|
|
4831
|
+
* `aria-label="Actions for <runName>"`, so it can't collide with other rows.
|
|
4832
|
+
* Returns the menu locator (Radix portals it outside the table — page scope).
|
|
4833
|
+
*/
|
|
4834
|
+
async function openRunActionsMenu(scope, runName) {
|
|
4835
|
+
await getRunRow(scope, runName)
|
|
4836
|
+
.getByRole('button', { name: `Actions for ${runName}`, exact: true })
|
|
4837
|
+
.click();
|
|
4838
|
+
const menu = asPage$1(scope).getByRole('menu');
|
|
4839
|
+
await expect(menu).toBeVisible({ timeout: 5000 });
|
|
4840
|
+
return menu;
|
|
4841
|
+
}
|
|
4842
|
+
/**
|
|
4843
|
+
* Row action: "View results" — opens the evaluation detail dialog.
|
|
4844
|
+
* Only enabled once the run is COMPLETED. Returns the scoped detail dialog.
|
|
4845
|
+
*/
|
|
4846
|
+
async function openRunResults(scope, runName) {
|
|
4847
|
+
const menu = await openRunActionsMenu(scope, runName);
|
|
4848
|
+
const item = menu.getByRole('menuitem', { name: EVALS_LABELS.actions.viewResults });
|
|
4849
|
+
await expect(item).toBeEnabled({ timeout: 5000 });
|
|
4850
|
+
await item.click();
|
|
4851
|
+
const dialog = getEvaluationDetailDialog(scope);
|
|
4852
|
+
await expect(dialog).toBeVisible({ timeout: 10000 });
|
|
4853
|
+
logger.info(`Opened results for run: ${runName}`);
|
|
4854
|
+
return dialog;
|
|
4855
|
+
}
|
|
4856
|
+
/**
|
|
4857
|
+
* Row action: "New review" — opens the LLM-judge dialog for the run.
|
|
4858
|
+
* Only enabled once the run is COMPLETED. Returns the scoped judge dialog.
|
|
4859
|
+
*/
|
|
4860
|
+
async function openNewReviewForRun(scope, runName) {
|
|
4861
|
+
const menu = await openRunActionsMenu(scope, runName);
|
|
4862
|
+
const item = menu.getByRole('menuitem', { name: EVALS_LABELS.actions.evaluate });
|
|
4863
|
+
await expect(item).toBeEnabled({ timeout: 5000 });
|
|
4864
|
+
await item.click();
|
|
4865
|
+
const dialog = getLlmJudgeDialog(scope);
|
|
4866
|
+
await expect(dialog).toBeVisible({ timeout: 10000 });
|
|
4867
|
+
return dialog;
|
|
4868
|
+
}
|
|
4869
|
+
/**
|
|
4870
|
+
* Row action: "Check status" — triggers a fresh status fetch and waits for
|
|
4871
|
+
* the outcome toast. Returns which toast appeared. The menu stays open by
|
|
4872
|
+
* design (the item prevents default), so we close it with Escape.
|
|
4873
|
+
*/
|
|
4874
|
+
async function checkRunStatus(scope, runName) {
|
|
4875
|
+
const page = asPage$1(scope);
|
|
4876
|
+
const menu = await openRunActionsMenu(scope, runName);
|
|
4877
|
+
await menu.getByRole('menuitem', { name: EVALS_LABELS.actions.checkStatus }).click();
|
|
4878
|
+
const toasts = EVALS_LABELS.checkStatusToast;
|
|
4879
|
+
const toast = page
|
|
4880
|
+
.getByText(new RegExp(`${toasts.pending}|${toasts.completed}|${toasts.failed}`))
|
|
4881
|
+
.first();
|
|
4882
|
+
await expect(toast).toBeVisible({ timeout: 15000 });
|
|
4883
|
+
const text = (await toast.innerText()).trim();
|
|
4884
|
+
await page.keyboard.press('Escape');
|
|
4885
|
+
await expect(menu).toBeHidden({ timeout: 5000 });
|
|
4886
|
+
if (text.includes(toasts.completed))
|
|
4887
|
+
return 'completed';
|
|
4888
|
+
if (text.includes(toasts.failed))
|
|
4889
|
+
return 'failed';
|
|
4890
|
+
return 'pending';
|
|
4891
|
+
}
|
|
4892
|
+
/**
|
|
4893
|
+
* Row action: "Export CSV" — waits for the browser download and returns its
|
|
4894
|
+
* suggested filename (`<benchmark>_<run>_results.csv`).
|
|
4895
|
+
*/
|
|
4896
|
+
async function exportRunCsv(scope, runName) {
|
|
4897
|
+
const page = asPage$1(scope);
|
|
4898
|
+
const menu = await openRunActionsMenu(scope, runName);
|
|
4899
|
+
const item = menu.getByRole('menuitem', { name: EVALS_LABELS.actions.exportCsv });
|
|
4900
|
+
await expect(item).toBeEnabled({ timeout: 5000 });
|
|
4901
|
+
const downloadPromise = page.waitForEvent('download', { timeout: 30000 });
|
|
4902
|
+
await item.click();
|
|
4903
|
+
const download = await downloadPromise;
|
|
4904
|
+
logger.info(`Exported run CSV: ${download.suggestedFilename()}`);
|
|
4905
|
+
return download.suggestedFilename();
|
|
4906
|
+
}
|
|
4907
|
+
// ── Start evaluation dialog ────────────────────────────────────────────
|
|
4908
|
+
/** Locator for the "New Evaluation" dialog. Scoped by aria-label — its title text collides with the toolbar button that opens it. */
|
|
4909
|
+
function getStartEvaluationDialog(scope) {
|
|
4910
|
+
return dialogByName(scope, EVALS_LABELS.startDialog.dialogName);
|
|
4911
|
+
}
|
|
4912
|
+
/** Open the start dialog via the toolbar button and wait for it to be interactive. */
|
|
4913
|
+
async function openStartEvaluationDialog(scope) {
|
|
4914
|
+
await getNewEvaluationButton(scope).click();
|
|
4915
|
+
const dialog = getStartEvaluationDialog(scope);
|
|
4916
|
+
await expect(dialog.getByLabel(EVALS_LABELS.startDialog.experimentNameLabel)).toBeVisible({
|
|
4917
|
+
timeout: 10000,
|
|
4918
|
+
});
|
|
4919
|
+
return dialog;
|
|
4920
|
+
}
|
|
4921
|
+
/**
|
|
4922
|
+
* End-to-end: open the "New Evaluation" dialog, optionally name the run,
|
|
4923
|
+
* submit, and wait for the dialog to close. When `name` is omitted the
|
|
4924
|
+
* backend auto-generates one.
|
|
4925
|
+
*/
|
|
4926
|
+
async function startEvaluation(scope, opts = {}) {
|
|
4927
|
+
const dialog = await openStartEvaluationDialog(scope);
|
|
4928
|
+
if (opts.name !== undefined) {
|
|
4929
|
+
await dialog.getByLabel(EVALS_LABELS.startDialog.experimentNameLabel).fill(opts.name);
|
|
4930
|
+
}
|
|
4931
|
+
// Scoped to the dialog: "Start Evaluation" is unique today, but the toolbar
|
|
4932
|
+
// "New Evaluation" trigger sits right behind the overlay — never query the page.
|
|
4933
|
+
const submit = dialog.getByRole('button', { name: EVALS_LABELS.startDialog.start });
|
|
4934
|
+
await expect(submit).toBeEnabled({ timeout: 5000 });
|
|
4935
|
+
await submit.click();
|
|
4936
|
+
await expect(dialog).toBeHidden({ timeout: 15000 });
|
|
4937
|
+
logger.info(`Started evaluation${opts.name ? `: ${opts.name}` : ''}`);
|
|
4938
|
+
}
|
|
4939
|
+
/** Cancel out of the start dialog and wait for it to close. */
|
|
4940
|
+
async function cancelStartEvaluation(scope) {
|
|
4941
|
+
const dialog = getStartEvaluationDialog(scope);
|
|
4942
|
+
await dialog.getByRole('button', { name: EVALS_LABELS.startDialog.cancel }).click();
|
|
4943
|
+
await expect(dialog).toBeHidden({ timeout: 5000 });
|
|
4944
|
+
}
|
|
4945
|
+
// ── Delete evaluation dialog ───────────────────────────────────────────
|
|
4946
|
+
/** Locator for the "Delete Evaluation" confirm dialog. */
|
|
4947
|
+
function getDeleteEvaluationDialog(scope) {
|
|
4948
|
+
return dialogByName(scope, EVALS_LABELS.deleteDialog.dialogName);
|
|
4949
|
+
}
|
|
4950
|
+
/**
|
|
4951
|
+
* Delete a run from its row actions menu and confirm in the follow-up
|
|
4952
|
+
* dialog. The confirm button ("Delete") shares its name with the menu item
|
|
4953
|
+
* that opened the dialog, so the confirm click MUST stay dialog-scoped.
|
|
4954
|
+
*/
|
|
4955
|
+
async function deleteEvaluation(scope, runName) {
|
|
4956
|
+
const menu = await openRunActionsMenu(scope, runName);
|
|
4957
|
+
await menu.getByRole('menuitem', { name: EVALS_LABELS.actions.delete }).click();
|
|
4958
|
+
const dialog = getDeleteEvaluationDialog(scope);
|
|
4959
|
+
const confirm = dialog.getByRole('button', { name: EVALS_LABELS.deleteDialog.confirm });
|
|
4960
|
+
await expect(confirm).toBeVisible({ timeout: 5000 });
|
|
4961
|
+
await confirm.click();
|
|
4962
|
+
await expect(dialog).toBeHidden({ timeout: 15000 });
|
|
4963
|
+
logger.info(`Deleted evaluation: ${runName}`);
|
|
4964
|
+
}
|
|
4965
|
+
/** Open the delete confirm from the row menu, then cancel out of it. */
|
|
4966
|
+
async function cancelDeleteEvaluation(scope, runName) {
|
|
4967
|
+
const menu = await openRunActionsMenu(scope, runName);
|
|
4968
|
+
await menu.getByRole('menuitem', { name: EVALS_LABELS.actions.delete }).click();
|
|
4969
|
+
const dialog = getDeleteEvaluationDialog(scope);
|
|
4970
|
+
await dialog.getByRole('button', { name: EVALS_LABELS.deleteDialog.cancel }).click();
|
|
4971
|
+
await expect(dialog).toBeHidden({ timeout: 5000 });
|
|
4972
|
+
}
|
|
4973
|
+
// ── LLM-judge ("Evaluate") dialog ──────────────────────────────────────
|
|
4974
|
+
/**
|
|
4975
|
+
* Locator for the LLM-judge dialog. Scoped by aria-label — its title AND its
|
|
4976
|
+
* submit button both read "Evaluate", and it can be stacked on top of the
|
|
4977
|
+
* evaluation-detail dialog.
|
|
4978
|
+
*/
|
|
4979
|
+
function getLlmJudgeDialog(scope) {
|
|
4980
|
+
return dialogByName(scope, EVALS_LABELS.judgeDialog.dialogName);
|
|
4981
|
+
}
|
|
4982
|
+
/** Locator for the judge dialog's LLM provider-picker dialog (stacked above it). */
|
|
4983
|
+
function getLlmPickerDialog(scope) {
|
|
4984
|
+
return dialogByName(scope, EVALS_LABELS.llmPickerDialog.dialogName);
|
|
4985
|
+
}
|
|
4986
|
+
/**
|
|
4987
|
+
* Inside the judge dialog: pick the judging LLM. Opens the provider picker,
|
|
4988
|
+
* optionally filters, clicks the provider card, then picks the model in the
|
|
4989
|
+
* follow-up "LLM Selection" modal (llm-tab's `LLMProviderModal`; matched by
|
|
4990
|
+
* title text since it has no aria-label). Both pickers close on selection.
|
|
4991
|
+
*/
|
|
4992
|
+
async function selectJudgeLlm(scope, providerName, modelName) {
|
|
4993
|
+
const page = asPage$1(scope);
|
|
4994
|
+
const judgeDialog = getLlmJudgeDialog(scope);
|
|
4995
|
+
await judgeDialog
|
|
4996
|
+
.getByRole('button', { name: EVALS_LABELS.judgeDialog.selectorAriaLabel })
|
|
4997
|
+
.click();
|
|
4998
|
+
const picker = getLlmPickerDialog(scope);
|
|
4999
|
+
await expect(picker).toBeVisible({ timeout: 10000 });
|
|
5000
|
+
await picker.getByPlaceholder(EVALS_LABELS.llmPickerDialog.searchPlaceholder).fill(providerName);
|
|
5001
|
+
await picker.getByRole('button', { name: new RegExp(escapeRegExp(providerName), 'i') }).click();
|
|
5002
|
+
// Model-selection modal is a separate stacked dialog outside the picker.
|
|
5003
|
+
const modelDialog = page
|
|
5004
|
+
.getByRole('dialog')
|
|
5005
|
+
.filter({ hasText: EVALS_LABELS.llmPickerDialog.modelDialogTitle });
|
|
5006
|
+
await expect(modelDialog).toBeVisible({ timeout: 10000 });
|
|
5007
|
+
await modelDialog.getByRole('button', { name: new RegExp(escapeRegExp(modelName), 'i') }).click();
|
|
5008
|
+
await expect(picker).toBeHidden({ timeout: 10000 });
|
|
5009
|
+
logger.info(`Selected judge LLM ${providerName}/${modelName}`);
|
|
5010
|
+
}
|
|
5011
|
+
/**
|
|
5012
|
+
* Fill and submit the LLM-judge dialog (assumes it is already open — see
|
|
5013
|
+
* `openNewReviewForRun` / `openNewReviewFromDetail`). Waits for the dialog
|
|
5014
|
+
* to close on success.
|
|
5015
|
+
*/
|
|
5016
|
+
async function submitLlmJudge(scope, opts) {
|
|
5017
|
+
const dialog = getLlmJudgeDialog(scope);
|
|
5018
|
+
await expect(dialog).toBeVisible({ timeout: 10000 });
|
|
5019
|
+
await dialog.getByLabel(EVALS_LABELS.judgeDialog.criteriaLabel).fill(opts.criteria);
|
|
5020
|
+
await dialog.getByLabel(EVALS_LABELS.judgeDialog.scoreNameLabel).fill(opts.scoreName);
|
|
5021
|
+
if (opts.maxConcurrency !== undefined) {
|
|
5022
|
+
await dialog
|
|
5023
|
+
.getByLabel(EVALS_LABELS.judgeDialog.maxConcurrencyLabel)
|
|
5024
|
+
.fill(String(opts.maxConcurrency));
|
|
5025
|
+
}
|
|
5026
|
+
await selectJudgeLlm(scope, opts.provider, opts.model);
|
|
5027
|
+
// Dialog-scoped on purpose: the dialog title is also "Evaluate".
|
|
5028
|
+
const submit = dialog.getByRole('button', { name: EVALS_LABELS.judgeDialog.submit, exact: true });
|
|
5029
|
+
await expect(submit).toBeEnabled({ timeout: 5000 });
|
|
5030
|
+
await submit.click();
|
|
5031
|
+
await expect(dialog).toBeHidden({ timeout: 15000 });
|
|
5032
|
+
logger.info(`Started LLM review "${opts.scoreName}"`);
|
|
5033
|
+
}
|
|
5034
|
+
/** Cancel out of the judge dialog and wait for it to close. */
|
|
5035
|
+
async function cancelLlmJudge(scope) {
|
|
5036
|
+
const dialog = getLlmJudgeDialog(scope);
|
|
5037
|
+
await dialog.getByRole('button', { name: EVALS_LABELS.judgeDialog.cancel }).click();
|
|
5038
|
+
await expect(dialog).toBeHidden({ timeout: 5000 });
|
|
5039
|
+
}
|
|
5040
|
+
// ── Evaluation detail dialog ───────────────────────────────────────────
|
|
5041
|
+
/** Locator for the evaluation-detail dialog. Its title is the run name (dynamic), hence the aria-label hook. */
|
|
5042
|
+
function getEvaluationDetailDialog(scope) {
|
|
5043
|
+
return dialogByName(scope, EVALS_LABELS.detailDialog.dialogName);
|
|
5044
|
+
}
|
|
5045
|
+
/** Click the detail dialog's refresh icon button (aria-label "Refresh"). */
|
|
5046
|
+
async function refreshEvaluationDetail(scope) {
|
|
5047
|
+
const dialog = getEvaluationDetailDialog(scope);
|
|
5048
|
+
const refresh = dialog.getByRole('button', {
|
|
5049
|
+
name: EVALS_LABELS.detailDialog.refreshAriaLabel,
|
|
5050
|
+
exact: true,
|
|
5051
|
+
});
|
|
5052
|
+
await refresh.click();
|
|
5053
|
+
await expect(refresh).toBeEnabled({ timeout: 15000 });
|
|
5054
|
+
}
|
|
5055
|
+
/** Open the LLM-judge dialog from the detail dialog's "New review" CTA. Returns the judge dialog. */
|
|
5056
|
+
async function openNewReviewFromDetail(scope) {
|
|
5057
|
+
const dialog = getEvaluationDetailDialog(scope);
|
|
5058
|
+
const cta = dialog.getByRole('button', {
|
|
5059
|
+
name: EVALS_LABELS.detailDialog.newReview,
|
|
5060
|
+
exact: true,
|
|
5061
|
+
});
|
|
5062
|
+
await expect(cta).toBeEnabled({ timeout: 10000 });
|
|
5063
|
+
await cta.click();
|
|
5064
|
+
const judgeDialog = getLlmJudgeDialog(scope);
|
|
5065
|
+
await expect(judgeDialog).toBeVisible({ timeout: 10000 });
|
|
5066
|
+
return judgeDialog;
|
|
5067
|
+
}
|
|
5068
|
+
/** Assert the detail dialog is still waiting for traces (auto-refreshing hint). */
|
|
5069
|
+
async function expectDetailWaitingForTraces(scope) {
|
|
5070
|
+
await expect(getEvaluationDetailDialog(scope).getByText(EVALS_LABELS.detailDialog.waitingHint)).toBeVisible({ timeout: 10000 });
|
|
5071
|
+
}
|
|
5072
|
+
/**
|
|
5073
|
+
* Locator for a trace's expand/collapse row inside the detail dialog,
|
|
5074
|
+
* matched by (part of) its question text.
|
|
5075
|
+
*/
|
|
5076
|
+
function getTraceRow(scope, questionText) {
|
|
5077
|
+
return getEvaluationDetailDialog(scope)
|
|
5078
|
+
.getByRole('button')
|
|
5079
|
+
.filter({ hasText: questionText })
|
|
5080
|
+
.first();
|
|
5081
|
+
}
|
|
5082
|
+
/** Expand a trace by its question text so its outputs and scores are visible. */
|
|
5083
|
+
async function expandTrace(scope, questionText) {
|
|
5084
|
+
await getTraceRow(scope, questionText).click();
|
|
5085
|
+
// The manual-score form only exists on the expanded trace.
|
|
5086
|
+
await expect(getEvaluationDetailDialog(scope).getByLabel(EVALS_LABELS.detailDialog.scoreNameLabel)).toBeVisible({ timeout: 10000 });
|
|
5087
|
+
}
|
|
5088
|
+
/**
|
|
5089
|
+
* Add a manual score to the currently expanded trace. `value` must be
|
|
5090
|
+
* between 0 and 1 (the UI rejects anything else with an error toast).
|
|
5091
|
+
*/
|
|
5092
|
+
async function addManualScore(scope, opts) {
|
|
5093
|
+
const dialog = getEvaluationDetailDialog(scope);
|
|
5094
|
+
await dialog.getByLabel(EVALS_LABELS.detailDialog.scoreNameLabel).fill(opts.name);
|
|
5095
|
+
await dialog.getByLabel(EVALS_LABELS.detailDialog.scoreValueLabel).fill(String(opts.value));
|
|
5096
|
+
if (opts.comment !== undefined) {
|
|
5097
|
+
await dialog.getByLabel(EVALS_LABELS.detailDialog.scoreCommentLabel).fill(opts.comment);
|
|
5098
|
+
}
|
|
5099
|
+
await dialog
|
|
5100
|
+
.getByRole('button', { name: EVALS_LABELS.detailDialog.addScore, exact: true })
|
|
5101
|
+
.click();
|
|
5102
|
+
await expectTraceScore(scope, opts.name);
|
|
5103
|
+
logger.info(`Added manual score: ${opts.name}=${opts.value}`);
|
|
5104
|
+
}
|
|
5105
|
+
/** Assert a score chip with the given name is visible on the expanded trace. */
|
|
5106
|
+
async function expectTraceScore(scope, scoreName) {
|
|
5107
|
+
await expect(getEvaluationDetailDialog(scope).getByText(scoreName, { exact: true }).first()).toBeVisible({ timeout: 15000 });
|
|
5108
|
+
}
|
|
5109
|
+
/**
|
|
5110
|
+
* Remove a score chip from the expanded trace. The chip's trash button
|
|
5111
|
+
* carries `aria-label="Remove score"`; we scope through the chip matched by
|
|
5112
|
+
* score name so multiple chips can't cross-match.
|
|
5113
|
+
*/
|
|
5114
|
+
async function removeTraceScore(scope, scoreName) {
|
|
5115
|
+
const dialog = getEvaluationDetailDialog(scope);
|
|
5116
|
+
const chip = dialog
|
|
5117
|
+
.locator('div')
|
|
5118
|
+
.filter({ has: asPage$1(scope).getByText(scoreName, { exact: true }) })
|
|
5119
|
+
.filter({
|
|
5120
|
+
has: asPage$1(scope).getByRole('button', {
|
|
5121
|
+
name: EVALS_LABELS.detailDialog.removeScoreAriaLabel,
|
|
5122
|
+
}),
|
|
5123
|
+
})
|
|
5124
|
+
.last();
|
|
5125
|
+
await chip
|
|
5126
|
+
.getByRole('button', { name: EVALS_LABELS.detailDialog.removeScoreAriaLabel })
|
|
5127
|
+
.first()
|
|
5128
|
+
.click();
|
|
5129
|
+
}
|
|
5130
|
+
/**
|
|
5131
|
+
* Locator for a review row's expand toggle in the detail dialog's Reviews
|
|
5132
|
+
* list. All toggles share the "Toggle review details" aria-label, so the
|
|
5133
|
+
* row is disambiguated by the score name it displays.
|
|
5134
|
+
*/
|
|
5135
|
+
function getReviewRow(scope, scoreName) {
|
|
5136
|
+
return getEvaluationDetailDialog(scope)
|
|
5137
|
+
.getByRole('button', { name: EVALS_LABELS.detailDialog.reviewDetailsAriaLabel })
|
|
5138
|
+
.filter({ hasText: scoreName })
|
|
5139
|
+
.first();
|
|
5140
|
+
}
|
|
5141
|
+
/** Assert a review with the given score name appears in the Reviews list. */
|
|
5142
|
+
async function expectReviewInList(scope, scoreName) {
|
|
5143
|
+
await expect(getReviewRow(scope, scoreName)).toBeVisible({ timeout: 15000 });
|
|
5144
|
+
}
|
|
5145
|
+
/** Assert a review row's status pill (Queued / Running / Complete / Failed). */
|
|
5146
|
+
async function expectReviewStatus(scope, scoreName, status) {
|
|
5147
|
+
await expect(getReviewRow(scope, scoreName).getByText(EVALS_LABELS.detailDialog.reviewStatus[status], {
|
|
5148
|
+
exact: true,
|
|
5149
|
+
})).toBeVisible({ timeout: 15000 });
|
|
5150
|
+
}
|
|
5151
|
+
/** Expand a review row to show its criteria and produced scores. */
|
|
5152
|
+
async function expandReview(scope, scoreName) {
|
|
5153
|
+
const row = getReviewRow(scope, scoreName);
|
|
5154
|
+
await row.click();
|
|
5155
|
+
await expect(row).toHaveAttribute('aria-expanded', 'true', { timeout: 5000 });
|
|
5156
|
+
}
|
|
5157
|
+
/** Close the detail dialog via Escape and wait for it to be gone. */
|
|
5158
|
+
async function closeEvaluationDetailDialog(scope) {
|
|
5159
|
+
const dialog = getEvaluationDetailDialog(scope);
|
|
5160
|
+
await asPage$1(scope).keyboard.press('Escape');
|
|
5161
|
+
await expect(dialog).toBeHidden({ timeout: 10000 });
|
|
5162
|
+
}
|
|
5163
|
+
// ── Manage benchmarks dialog (embedded tenant Benchmarks) ──────────────
|
|
5164
|
+
/** Locator for the "Manage benchmarks" dialog. Scoped by aria-label — its title collides with the toolbar button that opens it. */
|
|
5165
|
+
function getManageBenchmarksDialog(scope) {
|
|
5166
|
+
return dialogByName(scope, EVALS_LABELS.manageBenchmarksDialog.dialogName);
|
|
5167
|
+
}
|
|
5168
|
+
/** Open the Manage benchmarks dialog from the toolbar and wait for its table UI. Returns the scoped dialog. */
|
|
5169
|
+
async function openManageBenchmarksDialog(scope) {
|
|
5170
|
+
await getManageBenchmarksButton(scope).click();
|
|
5171
|
+
const dialog = getManageBenchmarksDialog(scope);
|
|
5172
|
+
await expect(dialog.getByRole('button', { name: EVALS_LABELS.manageBenchmarksDialog.newBenchmark })).toBeVisible({ timeout: 10000 });
|
|
5173
|
+
return dialog;
|
|
5174
|
+
}
|
|
5175
|
+
/** Type into the benchmarks search input (aria-label "Search benchmarks") inside the manage dialog. */
|
|
5176
|
+
async function searchBenchmarks(scope, query) {
|
|
5177
|
+
const input = getManageBenchmarksDialog(scope).getByLabel(EVALS_LABELS.manageBenchmarksDialog.searchAriaLabel);
|
|
5178
|
+
await input.fill(query);
|
|
5179
|
+
await expect(input).toHaveValue(query);
|
|
5180
|
+
}
|
|
5181
|
+
/** Assert a benchmark appears in the manage dialog's table. */
|
|
5182
|
+
async function expectBenchmarkListed(scope, benchmarkName) {
|
|
5183
|
+
await expect(getManageBenchmarksDialog(scope).getByText(benchmarkName, { exact: true }).first()).toBeVisible({ timeout: 15000 });
|
|
5184
|
+
}
|
|
5185
|
+
/** Locator for the "New Benchmark" dialog. Scoped by aria-label — its title collides with the button that opens it. */
|
|
5186
|
+
function getCreateBenchmarkDialog(scope) {
|
|
5187
|
+
return dialogByName(scope, EVALS_LABELS.createBenchmarkDialog.dialogName);
|
|
5188
|
+
}
|
|
5189
|
+
/**
|
|
5190
|
+
* Create a benchmark from inside the manage dialog: open "New Benchmark",
|
|
5191
|
+
* fill the form, submit, and wait for both the dialog to close and the new
|
|
5192
|
+
* row to appear.
|
|
5193
|
+
*/
|
|
5194
|
+
async function createBenchmark(scope, opts) {
|
|
5195
|
+
const manageDialog = getManageBenchmarksDialog(scope);
|
|
5196
|
+
await manageDialog
|
|
5197
|
+
.getByRole('button', { name: EVALS_LABELS.manageBenchmarksDialog.newBenchmark })
|
|
5198
|
+
.click();
|
|
5199
|
+
const dialog = getCreateBenchmarkDialog(scope);
|
|
5200
|
+
await dialog.getByLabel(EVALS_LABELS.createBenchmarkDialog.nameLabel).fill(opts.name);
|
|
5201
|
+
if (opts.description !== undefined) {
|
|
5202
|
+
await dialog
|
|
5203
|
+
.getByLabel(EVALS_LABELS.createBenchmarkDialog.descriptionLabel)
|
|
5204
|
+
.fill(opts.description);
|
|
5205
|
+
}
|
|
5206
|
+
const submit = dialog.getByRole('button', {
|
|
5207
|
+
name: EVALS_LABELS.createBenchmarkDialog.create,
|
|
5208
|
+
exact: true,
|
|
5209
|
+
});
|
|
5210
|
+
await expect(submit).toBeEnabled({ timeout: 5000 });
|
|
5211
|
+
await submit.click();
|
|
5212
|
+
await expect(dialog).toBeHidden({ timeout: 15000 });
|
|
5213
|
+
await expectBenchmarkListed(scope, opts.name);
|
|
5214
|
+
logger.info(`Created benchmark: ${opts.name}`);
|
|
5215
|
+
}
|
|
5216
|
+
/** Locator for a benchmark's items dialog (Q&A list). Its title is the benchmark name (dynamic), hence the aria-label hook. */
|
|
5217
|
+
function getBenchmarkItemsDialog(scope) {
|
|
5218
|
+
return dialogByName(scope, EVALS_LABELS.benchmarkItemsDialog.dialogName);
|
|
5219
|
+
}
|
|
5220
|
+
/**
|
|
5221
|
+
* Open a benchmark's Q&A items dialog from its row's eye button
|
|
5222
|
+
* (`aria-label="View items in <name>"`). Returns the scoped items dialog.
|
|
5223
|
+
*/
|
|
5224
|
+
async function openBenchmarkItems(scope, benchmarkName) {
|
|
5225
|
+
await getManageBenchmarksDialog(scope)
|
|
5226
|
+
.getByRole('button', { name: `View items in ${benchmarkName}`, exact: true })
|
|
5227
|
+
.click();
|
|
5228
|
+
const dialog = getBenchmarkItemsDialog(scope);
|
|
5229
|
+
await expect(dialog.getByRole('button', { name: EVALS_LABELS.benchmarkItemsDialog.addItems })).toBeVisible({ timeout: 10000 });
|
|
5230
|
+
return dialog;
|
|
5231
|
+
}
|
|
5232
|
+
/** Assert a Q&A item (matched by its question text) is listed in the items dialog. */
|
|
5233
|
+
async function expectQaItemListed(scope, questionText) {
|
|
5234
|
+
await expect(getBenchmarkItemsDialog(scope).getByText(questionText, { exact: false }).first()).toBeVisible({ timeout: 15000 });
|
|
5235
|
+
}
|
|
5236
|
+
/** Locator for the "Add Q&A" dialog (Manual / CSV Upload sub-tabs). */
|
|
5237
|
+
function getAddItemsDialog(scope) {
|
|
5238
|
+
return dialogByName(scope, EVALS_LABELS.addItemsDialog.dialogName);
|
|
5239
|
+
}
|
|
5240
|
+
/** Open the "Add Q&A" dialog from the items dialog. Returns the scoped add dialog. */
|
|
5241
|
+
async function openAddItemsDialog(scope) {
|
|
5242
|
+
await getBenchmarkItemsDialog(scope)
|
|
5243
|
+
.getByRole('button', { name: EVALS_LABELS.benchmarkItemsDialog.addItems })
|
|
5244
|
+
.click();
|
|
5245
|
+
const dialog = getAddItemsDialog(scope);
|
|
5246
|
+
// Both sub-tab triggers are unique to this dialog — a reliable ready signal.
|
|
5247
|
+
await expect(dialog.getByRole('tab', { name: EVALS_LABELS.addItemsDialog.manualTab, exact: true })).toBeVisible({ timeout: 10000 });
|
|
5248
|
+
return dialog;
|
|
5249
|
+
}
|
|
5250
|
+
/**
|
|
5251
|
+
* Switch to a sub-tab INSIDE the Add Q&A dialog. The tab query must stay
|
|
5252
|
+
* dialog-scoped: the edit-mentor modal behind it has its own `role="tab"`
|
|
5253
|
+
* strip, and an unscoped `getByRole('tab')` can cross-match. Returns the
|
|
5254
|
+
* active tabpanel so callers interact only with that sub-tab's controls
|
|
5255
|
+
* (each panel has its own footer with its own Cancel/submit buttons).
|
|
5256
|
+
*/
|
|
5257
|
+
async function switchToAddItemsSubTab(scope, subTab) {
|
|
5258
|
+
const dialog = getAddItemsDialog(scope);
|
|
5259
|
+
const tabName = subTab === 'manual'
|
|
5260
|
+
? EVALS_LABELS.addItemsDialog.manualTab
|
|
5261
|
+
: EVALS_LABELS.addItemsDialog.csvTab;
|
|
5262
|
+
const tab = dialog.getByRole('tab', { name: tabName, exact: true });
|
|
5263
|
+
await tab.click();
|
|
5264
|
+
await expect(tab).toHaveAttribute('data-state', 'active', { timeout: 5000 });
|
|
5265
|
+
const panel = dialog.getByRole('tabpanel');
|
|
5266
|
+
await expect(panel).toBeVisible({ timeout: 5000 });
|
|
5267
|
+
return panel;
|
|
5268
|
+
}
|
|
5269
|
+
/**
|
|
5270
|
+
* Add Q&A pairs via the Manual sub-tab. Fills one row per pair (clicking
|
|
5271
|
+
* "Add row" as needed), submits, and waits for the dialog to close. Row
|
|
5272
|
+
* inputs are matched by label WITHIN each row container so the Question /
|
|
5273
|
+
* Answer labels of sibling rows can't collide.
|
|
5274
|
+
*/
|
|
5275
|
+
async function addQaPairsManually(scope, pairs) {
|
|
5276
|
+
const dialog = getAddItemsDialog(scope);
|
|
5277
|
+
const panel = await switchToAddItemsSubTab(scope, 'manual');
|
|
5278
|
+
for (let i = 0; i < pairs.length; i++) {
|
|
5279
|
+
if (i > 0) {
|
|
5280
|
+
await panel
|
|
5281
|
+
.getByRole('button', { name: EVALS_LABELS.addItemsDialog.addRow, exact: true })
|
|
5282
|
+
.click();
|
|
5283
|
+
}
|
|
5284
|
+
const question = panel.getByLabel(EVALS_LABELS.addItemsDialog.questionLabel).nth(i);
|
|
5285
|
+
await expect(question).toBeVisible({ timeout: 5000 });
|
|
5286
|
+
await question.fill(pairs[i].question);
|
|
5287
|
+
if (pairs[i].answer !== undefined) {
|
|
5288
|
+
await panel
|
|
5289
|
+
.getByLabel(EVALS_LABELS.addItemsDialog.answerLabel)
|
|
5290
|
+
.nth(i)
|
|
5291
|
+
.fill(pairs[i].answer);
|
|
5292
|
+
}
|
|
5293
|
+
}
|
|
5294
|
+
await panel.getByRole('button', { name: EVALS_LABELS.addItemsDialog.add, exact: true }).click();
|
|
5295
|
+
await expect(dialog).toBeHidden({ timeout: 15000 });
|
|
5296
|
+
logger.info(`Added ${pairs.length} Q&A pair(s) manually`);
|
|
5297
|
+
}
|
|
5298
|
+
/**
|
|
5299
|
+
* Upload Q&A pairs via the CSV Upload sub-tab. `csvPath` is a path on the
|
|
5300
|
+
* test machine; the file needs `input` (required) and `expected_output`
|
|
5301
|
+
* (optional) columns. Waits for the dialog to close on success.
|
|
5302
|
+
*/
|
|
5303
|
+
async function uploadQaCsv(scope, csvPath) {
|
|
5304
|
+
const dialog = getAddItemsDialog(scope);
|
|
5305
|
+
const panel = await switchToAddItemsSubTab(scope, 'csv');
|
|
5306
|
+
await panel.getByLabel(EVALS_LABELS.addItemsDialog.csvFileLabel).setInputFiles(csvPath);
|
|
5307
|
+
await panel
|
|
5308
|
+
.getByRole('button', { name: EVALS_LABELS.addItemsDialog.upload, exact: true })
|
|
5309
|
+
.click();
|
|
5310
|
+
await expect(dialog).toBeHidden({ timeout: 30000 });
|
|
5311
|
+
logger.info(`Uploaded Q&A CSV: ${csvPath}`);
|
|
5312
|
+
}
|
|
5313
|
+
/** Locator for the Q&A delete-confirm dialog. */
|
|
5314
|
+
function getDeleteQaItemDialog(scope) {
|
|
5315
|
+
return dialogByName(scope, EVALS_LABELS.deleteItemDialog.dialogName);
|
|
5316
|
+
}
|
|
5317
|
+
/**
|
|
5318
|
+
* Delete a Q&A item by its question text: click the row's trash button
|
|
5319
|
+
* (`aria-label="Delete Q&A"`) and confirm. The confirm "Delete" button must
|
|
5320
|
+
* stay scoped to the confirm dialog — the items dialog's rows keep their
|
|
5321
|
+
* own delete buttons mounted behind it.
|
|
5322
|
+
*/
|
|
5323
|
+
async function deleteQaItem(scope, questionText) {
|
|
5324
|
+
const itemsDialog = getBenchmarkItemsDialog(scope);
|
|
5325
|
+
const row = itemsDialog.getByRole('row').filter({ hasText: questionText }).first();
|
|
5326
|
+
await row
|
|
5327
|
+
.getByRole('button', { name: EVALS_LABELS.benchmarkItemsDialog.deleteItemAriaLabel })
|
|
5328
|
+
.click();
|
|
5329
|
+
const confirmDialog = getDeleteQaItemDialog(scope);
|
|
5330
|
+
const confirm = confirmDialog.getByRole('button', {
|
|
5331
|
+
name: EVALS_LABELS.deleteItemDialog.delete,
|
|
5332
|
+
exact: true,
|
|
5333
|
+
});
|
|
5334
|
+
await expect(confirm).toBeVisible({ timeout: 5000 });
|
|
5335
|
+
await confirm.click();
|
|
5336
|
+
await expect(confirmDialog).toBeHidden({ timeout: 15000 });
|
|
5337
|
+
logger.info(`Deleted Q&A item: ${questionText}`);
|
|
5338
|
+
}
|
|
5339
|
+
/** Close the benchmark items dialog via Escape and wait for it to be gone. */
|
|
5340
|
+
async function closeBenchmarkItemsDialog(scope) {
|
|
5341
|
+
const dialog = getBenchmarkItemsDialog(scope);
|
|
5342
|
+
await asPage$1(scope).keyboard.press('Escape');
|
|
5343
|
+
await expect(dialog).toBeHidden({ timeout: 10000 });
|
|
5344
|
+
}
|
|
5345
|
+
/** Close the Manage benchmarks dialog via Escape and wait for it to be gone. */
|
|
5346
|
+
async function closeManageBenchmarksDialog(scope) {
|
|
5347
|
+
const dialog = getManageBenchmarksDialog(scope);
|
|
5348
|
+
await asPage$1(scope).keyboard.press('Escape');
|
|
5349
|
+
await expect(dialog).toBeHidden({ timeout: 10000 });
|
|
5350
|
+
}
|
|
5351
|
+
|
|
4554
5352
|
/**
|
|
4555
5353
|
* LTI tab helpers — Playwright bindings for the `AgentLtiTab` component from
|
|
4556
5354
|
* `@iblai/web-containers`.
|
|
@@ -5206,5 +6004,5 @@ function createPlaywrightConfig(options) {
|
|
|
5206
6004
|
});
|
|
5207
6005
|
}
|
|
5208
6006
|
|
|
5209
|
-
export { AuthFlowBuilder, CHAT_PRIVACY_LABELS, CustomReporter, LTI_LABELS, LTI_TEST_IDS, MailsacClient, PRIVACY_LABELS, SCREENSHARE_LABELS, TASKS_LABELS, VOICE_LABELS, addMemory, archiveFirstMemory, archiveMemoryByContent, billingAutoRechargeSection, billingCreditsSection, billingPlanSection, buildReportUrl, canChatWithEmbedMentor, cancelDeleteInstance, cancelDeleteSkill, cancelDisconnectInstance, cancelEnableChatPrivacyMidSession, cancelKeyDelete, cancelNewInstanceDialog, checkAdminStatus, clearDateRangeFilter, clearInstanceSearch, clickBackHome, clickBillingAddCredits, clickBillingManageBilling, clickBillingManageUsage, clickBillingUpgrade, clickChatPrivacyToggle, clickDownloadAgain, clickManualDownloadLink, closeCreditBalanceDropdown, closeKeyDetail, closeWithEsc, confirmEnableChatPrivacyMidSession, confirmKeyDelete, connectToInstance, copyEndpoint, createAuthSetup, createEnvConfig, createInstance, createKey, createLink, createPlaywrightConfig, createSkill, createTool, creditBalancePanel, creditBalancePlanBadge, creditBalanceTrigger, deleteFirstMemory, deleteInstance, deleteKey, deleteMemoryByContent, deleteSkill, deleteTask, disableSkill, disconnectInstance, editAgentPrompt, editInstance, editLink, editSkill, editTool, enableSkill, expectAllEndpointsVisible, expectBillingAutoRechargeSection, expectBillingCreditsSection, expectBillingPlanSection, expectBillingTabForCurrentPlan, expectBillingTabForFreePlan, expectBillingTabForPremiumPlan, expectBillingTabForTrialPlan, expectCallConfigVisible, expectCallConfigVoiceTriggerShows, expectChatPrivacyConfirmDialogOpen, expectChatPrivacyLocked, expectChatPrivacySource, expectChatPrivacyState, expectChatPrivacyToggleVisible, expectCompletedTasks, expectCreditBalanceForCurrentPlan, expectCreditBalancePanelForFreePlan, expectCreditBalancePanelForPremiumPlan, expectCreditBalancePanelForTrialPlan, expectCreditBalanceVisibilityForTenant, expectEndpointUrl, expectEntitySelected, expectFailedTasks, expectKeyDeleteError, expectKeyInList, expectKeyNotInList, expectKeysEmpty, expectLinkInList, expectLinkNotInList, expectLinkTargetUri, expectLinksEmpty, expectLogDetailsStatus, expectLogsForTask, expectLtiHeader, expectMentorVoiceTriggerShows, expectNoAccessibilityViolations, expectNoAccessibilityViolationsOnDialogs, expectNoLogsForSelectedTask, expectOutputFilterEnabled, expectPrivacyFieldsHidden, expectPrivacyFieldsVisible, expectPrivateModeSelected, expectPrivateModeTabReady, expectScheduleStartTimeInPastError, expectScreenShareDisabledHint, expectSttSelectDisabled, expectTaskInList, expectTaskNotInList, expectTaskStatus, expectTasksEmpty, expectTenantChatPrivacyEnabled, expectTenantChatPrivacyVisible, expectToolInList, expectToolNotInList, expectToolsEmpty, expectTotalTasks, expectTtsSelectDisabled, expectVoiceProviderSelected, expectVoiceVisible, fillLinkName, fillToolForm, filterByAction, filterByActionAndVerify, filterByActor, filterByActorAndVerify, filterByDateRange, generateBrowserSetupProjects, generateProjectConfig, getAuditLogRowCount, getAvailableActors, getBillingAutoRechargeStatus, getBillingPlanLabel, getBrowserKey, getCallConfigForm, getChatPrivacyConfirmDialog, getChatPrivacyToggle, getCreateKeyButton, getCreateLinkButton, getCreateToolButton, getCreditBalancePlanLabel, getCreditBalanceRemaining, getCurrentModel, getCurrentTenantShowPaywall, getEndpoint, getEndpointCopyButton, getEndpointUrl, getEntityChip, getInstanceHealthLabel, getInstanceRowCount, getInstanceStatusLabel, getKeyActionsTrigger, getKeyCreateModal, getKeyCreateNameInput, getKeyDeleteModal, getKeyDetailModal, getKeyDetailNameInput, getKeyPublicJwkField, getKeyPublicKeyField, getKeyRow, getKeysEmptyState, getKeysSection, getLinkCopyTargetUriButton, getLinkEditButton, getLinkModal, getLinkNameInput, getLinkRow, getLinksEmptyState, getLinksSection, getLtiSubTab, getMemoryCount, getMentorIdFromUrl, getOutputFilterSwitch, getPaginationInfo, getPrivateModeCard, getScheduleTaskButton, getSearchInput, getSkillRowCount, getTaskRow, getTenantChatPrivacyRow, getTenantChatPrivacySwitch, getToolEditButton, getToolKeySelect, getToolModal, getToolRow, getToolsEmptyState, getToolsSection, getVoiceProviderCard, getVoiceRow, goToFirstPage, goToLastPage, goToNextPage, goToPage, goToPreviousPage, inviteUserTest, isFirefox, isJSON, isLtiTabVisible, isMemoryTabVisible, isOnFirstPage, isOnLastPage, isPrivacyTabVisible, isPrivateModeTabVisible, isSandboxTabVisible, isScreenShareTabVisible, isSkillEnabled, isTasksTabVisible, isVoiceTabVisible, logger, loginWithEmailAndPassword, loginWithMicrosoftIdp, navigateToAccountComponent, navigateToAuditLog, navigateToAuditLogAndWaitForData, navigateToDataReports, navigateToReportDownload, openAddMemoryDialog, openAgentPromptEditModal, openCallConfigVoicePicker, openCreateKeyModal, openCreateLinkModal, openCreateToolModal, openCreditBalanceDropdown, openEditInstanceDialog, openEditLinkModal, openEditSkillDialog, openEditToolModal, openFirstLogDetails, openInstanceActionsMenu, openKeyActionsMenu, openKeyDelete, openKeyDetail, openLLMProviderPicker, openMentorVoicePicker, openNewInstanceDialog, openNewSkillDialog, openScheduleTaskDialog, openScreenSharePromptEditor, openSkillActionsMenu, parseReportUrlParams, previewCallConfigVoiceInline, previewMentorVoiceInline, previewVoice, pushConfiguration, readEndpointUrl, readKeyPublicJwk, readKeyPublicKey, reliableClick, reliableFill, renameKey, resetCallConfig, retry, runConnectedInstanceChecks, runInstanceChecks, safeWaitForURL, saveCallConfig, saveScreenSharePrompts, saveVoiceSettings, scheduleTask, searchInstances, searchTasks, searchVoices, selectCallMode, selectDateFromCalendar, selectLLMModel, selectLlmProvider, selectPrivacyAction, selectPrivateMode, selectSttProvider, selectTaskInList, selectToolKeySetMode, selectToolSigningKey, selectTtsProvider, selectVoice, selectVoiceProvider, setBlockMessage, setCallLanguage, setEnableVideo, setEntitySelected, setOutputFilterEnabled, setScreenSharePrompt, setTenantChatPrivacyEnabled, setUseFunctionCallingEnabled, setupSandboxInstance, shouldAddNewRowWhenClickingAddRowButton, shouldAllowEditingCellValuesInCSVEditor, shouldCancelCombiningReports, shouldCloseCSVEditorWhenClickingCloseButton, shouldCloseCSVEditorWithoutSavingWhenClickingCancel, shouldCombineRecommendationReports, shouldDirectlyDownloadChatHistoryReportWithoutCSVEditor, shouldDisableOtherDownloadButtonsWhileGeneratingReport, shouldDisplayCSVInEditableTableFormat, shouldDisplayReportCards, shouldHaveCombinedReportDataTestIds, shouldOpenCSVEditorDialog, shouldOpenCSVEditorForUserMetadataReport, shouldSaveEditedCSVAndTriggerDownload, shouldShowCombiningReportsDialog, shouldVerifyCSVEditorDialogAccessibility, signUpWithEmailAndPassword, submitLinkModal, submitToolModal, switchToLtiSubTab, switchToLtiTab, switchToMemoryTab, switchToPrivacyTab, switchToPrivateModeTab, switchToSandboxTab, switchToScreenShareTab, switchToSkillsTab, switchToTasksTab, switchToVoiceSubTab, switchToVoiceTab, teardownSandboxInstance, test, toggleAutoPush, toggleMemorySwitch, toggleSkill, toolFields, verifyAgentConfigPromptsVisible, verifyAuditLogEmptyState, verifyAuditLogEntryStructure, verifyAuditLogGenericError, verifyAuditLogLoading, verifyAuditLogPermissionError, verifyAuditLogTableVisible, verifyConnectDisabledForUnhealthy, verifyConnectedInstanceCard, verifyCurrentPage, verifyDonePhase, verifyDownloadingPhase, verifyErrorPhase, verifyInstanceTableEmpty, verifyInstanceTableVisible, verifyMemoryExists, verifyMemoryNotExists, verifyMemoryTabMemoriesList, verifyMemoryTabSettings, verifyPreparingPhase, verifySkillVisible, verifySkillsEmptyState, verifySkillsTabVisible, waitForAuditLogDataLoaded, waitForBillingTabReady, waitForCreditBalanceLoaded, waitForDialogReady, waitForElementStable, waitForPageLoad, waitForPageReady, waitForReportDownload };
|
|
6007
|
+
export { AuthFlowBuilder, CHAT_PRIVACY_LABELS, CustomReporter, EVALS_LABELS, LTI_LABELS, LTI_TEST_IDS, MailsacClient, PRIVACY_LABELS, SCREENSHARE_LABELS, TASKS_LABELS, VOICE_LABELS, addManualScore, addMemory, addQaPairsManually, archiveFirstMemory, archiveMemoryByContent, billingAutoRechargeSection, billingCreditsSection, billingPlanSection, buildReportUrl, canChatWithEmbedMentor, cancelDeleteEvaluation, cancelDeleteInstance, cancelDeleteSkill, cancelDisconnectInstance, cancelEnableChatPrivacyMidSession, cancelKeyDelete, cancelLlmJudge, cancelNewInstanceDialog, cancelStartEvaluation, checkAdminStatus, checkRunStatus, clearDateRangeFilter, clearInstanceSearch, clickBackHome, clickBillingAddCredits, clickBillingManageBilling, clickBillingManageUsage, clickBillingUpgrade, clickChatPrivacyToggle, clickDownloadAgain, clickManualDownloadLink, closeBenchmarkItemsDialog, closeCreditBalanceDropdown, closeEvaluationDetailDialog, closeKeyDetail, closeManageBenchmarksDialog, closeWithEsc, confirmEnableChatPrivacyMidSession, confirmKeyDelete, connectToInstance, copyEndpoint, createAuthSetup, createBenchmark, createEnvConfig, createInstance, createKey, createLink, createPlaywrightConfig, createSkill, createTool, creditBalancePanel, creditBalancePlanBadge, creditBalanceTrigger, deleteEvaluation, deleteFirstMemory, deleteInstance, deleteKey, deleteMemoryByContent, deleteQaItem, deleteSkill, deleteTask, disableSkill, disconnectInstance, editAgentPrompt, editInstance, editLink, editSkill, editTool, enableSkill, expandReview, expandTrace, expectAllEndpointsVisible, expectBenchmarkListed, expectBillingAutoRechargeSection, expectBillingCreditsSection, expectBillingPlanSection, expectBillingTabForCurrentPlan, expectBillingTabForFreePlan, expectBillingTabForPremiumPlan, expectBillingTabForTrialPlan, expectCallConfigVisible, expectCallConfigVoiceTriggerShows, expectChatPrivacyConfirmDialogOpen, expectChatPrivacyLocked, expectChatPrivacySource, expectChatPrivacyState, expectChatPrivacyToggleVisible, expectCompletedTasks, expectCreditBalanceForCurrentPlan, expectCreditBalancePanelForFreePlan, expectCreditBalancePanelForPremiumPlan, expectCreditBalancePanelForTrialPlan, expectCreditBalanceVisibilityForTenant, expectDetailWaitingForTraces, expectEndpointUrl, expectEntitySelected, expectFailedTasks, expectKeyDeleteError, expectKeyInList, expectKeyNotInList, expectKeysEmpty, expectLinkInList, expectLinkNotInList, expectLinkTargetUri, expectLinksEmpty, expectLogDetailsStatus, expectLogsForTask, expectLtiHeader, expectMentorVoiceTriggerShows, expectNoAccessibilityViolations, expectNoAccessibilityViolationsOnDialogs, expectNoBenchmarksNotice, expectNoLogsForSelectedTask, expectOutputFilterEnabled, expectPrivacyFieldsHidden, expectPrivacyFieldsVisible, expectPrivateModeSelected, expectPrivateModeTabReady, expectQaItemListed, expectReviewInList, expectReviewStatus, expectRunInTable, expectRunNotInTable, expectRunStatus, expectRunsTableEmpty, expectScheduleStartTimeInPastError, expectScreenShareDisabledHint, expectSelectedBenchmark, expectSttSelectDisabled, expectTaskInList, expectTaskNotInList, expectTaskStatus, expectTasksEmpty, expectTenantChatPrivacyEnabled, expectTenantChatPrivacyVisible, expectToolInList, expectToolNotInList, expectToolsEmpty, expectTotalTasks, expectTraceScore, expectTtsSelectDisabled, expectVoiceProviderSelected, expectVoiceVisible, exportRunCsv, fillLinkName, fillToolForm, filterByAction, filterByActionAndVerify, filterByActor, filterByActorAndVerify, filterByDateRange, generateBrowserSetupProjects, generateProjectConfig, getAddItemsDialog, getAuditLogRowCount, getAvailableActors, getBenchmarkCombobox, getBenchmarkComboboxDropdown, getBenchmarkItemsDialog, getBillingAutoRechargeStatus, getBillingPlanLabel, getBrowserKey, getCallConfigForm, getChatPrivacyConfirmDialog, getChatPrivacyToggle, getCreateBenchmarkDialog, getCreateKeyButton, getCreateLinkButton, getCreateToolButton, getCreditBalancePlanLabel, getCreditBalanceRemaining, getCurrentModel, getCurrentTenantShowPaywall, getDeleteEvaluationDialog, getDeleteQaItemDialog, getEndpoint, getEndpointCopyButton, getEndpointUrl, getEntityChip, getEvaluationDetailDialog, getInstanceHealthLabel, getInstanceRowCount, getInstanceStatusLabel, getKeyActionsTrigger, getKeyCreateModal, getKeyCreateNameInput, getKeyDeleteModal, getKeyDetailModal, getKeyDetailNameInput, getKeyPublicJwkField, getKeyPublicKeyField, getKeyRow, getKeysEmptyState, getKeysSection, getLinkCopyTargetUriButton, getLinkEditButton, getLinkModal, getLinkNameInput, getLinkRow, getLinksEmptyState, getLinksSection, getLlmJudgeDialog, getLlmPickerDialog, getLtiSubTab, getManageBenchmarksButton, getManageBenchmarksDialog, getMemoryCount, getMentorIdFromUrl, getNewEvaluationButton, getOutputFilterSwitch, getPaginationInfo, getPrivateModeCard, getReviewRow, getRunRow, getScheduleTaskButton, getSearchInput, getSkillRowCount, getStartEvaluationDialog, getTaskRow, getTenantChatPrivacyRow, getTenantChatPrivacySwitch, getToolEditButton, getToolKeySelect, getToolModal, getToolRow, getToolsEmptyState, getToolsSection, getTraceRow, getVoiceProviderCard, getVoiceRow, goToFirstPage, goToLastPage, goToNextPage, goToPage, goToPreviousPage, inviteUserTest, isEvaluationTabVisible, isFirefox, isJSON, isLtiTabVisible, isMemoryTabVisible, isOnFirstPage, isOnLastPage, isPrivacyTabVisible, isPrivateModeTabVisible, isSandboxTabVisible, isScreenShareTabVisible, isSkillEnabled, isTasksTabVisible, isVoiceTabVisible, logger, loginWithEmailAndPassword, loginWithMicrosoftIdp, navigateToAccountComponent, navigateToAuditLog, navigateToAuditLogAndWaitForData, navigateToDataReports, navigateToReportDownload, openAddItemsDialog, openAddMemoryDialog, openAgentPromptEditModal, openBenchmarkItems, openCallConfigVoicePicker, openCreateKeyModal, openCreateLinkModal, openCreateToolModal, openCreditBalanceDropdown, openEditInstanceDialog, openEditLinkModal, openEditSkillDialog, openEditToolModal, openFirstLogDetails, openInstanceActionsMenu, openKeyActionsMenu, openKeyDelete, openKeyDetail, openLLMProviderPicker, openManageBenchmarksDialog, openMentorVoicePicker, openNewInstanceDialog, openNewReviewForRun, openNewReviewFromDetail, openNewSkillDialog, openRunActionsMenu, openRunResults, openScheduleTaskDialog, openScreenSharePromptEditor, openSkillActionsMenu, openStartEvaluationDialog, parseReportUrlParams, previewCallConfigVoiceInline, previewMentorVoiceInline, previewVoice, pushConfiguration, readEndpointUrl, readKeyPublicJwk, readKeyPublicKey, refreshEvaluationDetail, reliableClick, reliableFill, removeTraceScore, renameKey, resetCallConfig, retry, runConnectedInstanceChecks, runInstanceChecks, safeWaitForURL, saveCallConfig, saveScreenSharePrompts, saveVoiceSettings, scheduleTask, searchBenchmarks, searchInstances, searchTasks, searchVoices, selectBenchmark, selectCallMode, selectDateFromCalendar, selectJudgeLlm, selectLLMModel, selectLlmProvider, selectPrivacyAction, selectPrivateMode, selectSttProvider, selectTaskInList, selectToolKeySetMode, selectToolSigningKey, selectTtsProvider, selectVoice, selectVoiceProvider, setBlockMessage, setCallLanguage, setEnableVideo, setEntitySelected, setOutputFilterEnabled, setScreenSharePrompt, setTenantChatPrivacyEnabled, setUseFunctionCallingEnabled, setupSandboxInstance, shouldAddNewRowWhenClickingAddRowButton, shouldAllowEditingCellValuesInCSVEditor, shouldCancelCombiningReports, shouldCloseCSVEditorWhenClickingCloseButton, shouldCloseCSVEditorWithoutSavingWhenClickingCancel, shouldCombineRecommendationReports, shouldDirectlyDownloadChatHistoryReportWithoutCSVEditor, shouldDisableOtherDownloadButtonsWhileGeneratingReport, shouldDisplayCSVInEditableTableFormat, shouldDisplayReportCards, shouldHaveCombinedReportDataTestIds, shouldOpenCSVEditorDialog, shouldOpenCSVEditorForUserMetadataReport, shouldSaveEditedCSVAndTriggerDownload, shouldShowCombiningReportsDialog, shouldVerifyCSVEditorDialogAccessibility, signUpWithEmailAndPassword, startEvaluation, submitLinkModal, submitLlmJudge, submitToolModal, switchToAddItemsSubTab, switchToEvaluationTab, switchToLtiSubTab, switchToLtiTab, switchToMemoryTab, switchToPrivacyTab, switchToPrivateModeTab, switchToSandboxTab, switchToScreenShareTab, switchToSkillsTab, switchToTasksTab, switchToVoiceSubTab, switchToVoiceTab, teardownSandboxInstance, test, toggleAutoPush, toggleMemorySwitch, toggleSkill, toolFields, uploadQaCsv, verifyAgentConfigPromptsVisible, verifyAuditLogEmptyState, verifyAuditLogEntryStructure, verifyAuditLogGenericError, verifyAuditLogLoading, verifyAuditLogPermissionError, verifyAuditLogTableVisible, verifyConnectDisabledForUnhealthy, verifyConnectedInstanceCard, verifyCurrentPage, verifyDonePhase, verifyDownloadingPhase, verifyErrorPhase, verifyInstanceTableEmpty, verifyInstanceTableVisible, verifyMemoryExists, verifyMemoryNotExists, verifyMemoryTabMemoriesList, verifyMemoryTabSettings, verifyPreparingPhase, verifySkillVisible, verifySkillsEmptyState, verifySkillsTabVisible, waitForAuditLogDataLoaded, waitForBillingTabReady, waitForCreditBalanceLoaded, waitForDialogReady, waitForElementStable, waitForPageLoad, waitForPageReady, waitForReportDownload };
|
|
5210
6008
|
//# sourceMappingURL=index.esm.js.map
|