@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
|
@@ -3165,7 +3165,7 @@ const PRIVACY_LABELS = {
|
|
|
3165
3165
|
* reach DOM that Radix renders outside the dialog subtree (popovers,
|
|
3166
3166
|
* select options, etc.).
|
|
3167
3167
|
*/
|
|
3168
|
-
function asPage$
|
|
3168
|
+
function asPage$6(scope) {
|
|
3169
3169
|
return 'page' in scope ? scope.page() : scope;
|
|
3170
3170
|
}
|
|
3171
3171
|
/**
|
|
@@ -3226,7 +3226,7 @@ async function selectPrivacyAction(scope, action) {
|
|
|
3226
3226
|
await trigger.click();
|
|
3227
3227
|
// Radix Select renders options in a portal at the document root, so we
|
|
3228
3228
|
// always look them up on the Page — never on the dialog Locator.
|
|
3229
|
-
const option = asPage$
|
|
3229
|
+
const option = asPage$6(scope).getByRole('option', {
|
|
3230
3230
|
name: PRIVACY_LABELS.actionOptions[action],
|
|
3231
3231
|
});
|
|
3232
3232
|
await test$1.expect(option).toBeVisible({ timeout: 5000 });
|
|
@@ -3338,7 +3338,7 @@ const CHAT_PRIVACY_LABELS = {
|
|
|
3338
3338
|
rowLabel: 'Allow users to control chat privacy',
|
|
3339
3339
|
},
|
|
3340
3340
|
};
|
|
3341
|
-
function asPage$
|
|
3341
|
+
function asPage$5(scope) {
|
|
3342
3342
|
return 'page' in scope ? scope.page() : scope;
|
|
3343
3343
|
}
|
|
3344
3344
|
// ──────────────────────────────────────────────────────────────────────
|
|
@@ -3410,7 +3410,7 @@ async function clickChatPrivacyToggle(scope) {
|
|
|
3410
3410
|
// ── Mid-session confirm dialog ────────────────────────────────────────
|
|
3411
3411
|
/** Locator for the AlertDialog content that the mid-session enable opens. */
|
|
3412
3412
|
function getChatPrivacyConfirmDialog(scope) {
|
|
3413
|
-
return asPage$
|
|
3413
|
+
return asPage$5(scope).getByTestId('chat-privacy-confirm-dialog');
|
|
3414
3414
|
}
|
|
3415
3415
|
async function expectChatPrivacyConfirmDialogOpen(scope, open) {
|
|
3416
3416
|
if (open) {
|
|
@@ -3429,7 +3429,7 @@ async function expectChatPrivacyConfirmDialogOpen(scope, open) {
|
|
|
3429
3429
|
*/
|
|
3430
3430
|
async function confirmEnableChatPrivacyMidSession(scope) {
|
|
3431
3431
|
await clickChatPrivacyToggle(scope);
|
|
3432
|
-
const page = asPage$
|
|
3432
|
+
const page = asPage$5(scope);
|
|
3433
3433
|
await expectChatPrivacyConfirmDialogOpen(page, true);
|
|
3434
3434
|
const action = page.getByTestId('chat-privacy-confirm-action');
|
|
3435
3435
|
await test$1.expect(action).toBeVisible({ timeout: 10000 });
|
|
@@ -3440,7 +3440,7 @@ async function confirmEnableChatPrivacyMidSession(scope) {
|
|
|
3440
3440
|
}
|
|
3441
3441
|
/** Cancel the confirm dialog without enabling. */
|
|
3442
3442
|
async function cancelEnableChatPrivacyMidSession(scope) {
|
|
3443
|
-
const page = asPage$
|
|
3443
|
+
const page = asPage$5(scope);
|
|
3444
3444
|
const cancel = page.getByTestId('chat-privacy-confirm-cancel');
|
|
3445
3445
|
await test$1.expect(cancel).toBeVisible({ timeout: 10000 });
|
|
3446
3446
|
await cancel.click();
|
|
@@ -3627,7 +3627,7 @@ const VOICE_LABELS = {
|
|
|
3627
3627
|
* reach DOM that Radix renders outside the dialog subtree (popovers,
|
|
3628
3628
|
* select options, etc.).
|
|
3629
3629
|
*/
|
|
3630
|
-
function asPage$
|
|
3630
|
+
function asPage$4(scope) {
|
|
3631
3631
|
return 'page' in scope ? scope.page() : scope;
|
|
3632
3632
|
}
|
|
3633
3633
|
// ─── Tab navigation ──────────────────────────────────────────────────────
|
|
@@ -3709,7 +3709,7 @@ async function openMentorVoicePicker(scope) {
|
|
|
3709
3709
|
const openBtn = scope.getByTestId('mentor-voice-trigger-open');
|
|
3710
3710
|
await test$1.expect(openBtn).toBeVisible({ timeout: 10000 });
|
|
3711
3711
|
await openBtn.click();
|
|
3712
|
-
await test$1.expect(asPage$
|
|
3712
|
+
await test$1.expect(asPage$4(scope).getByTestId('voice-picker-modal')).toBeVisible({
|
|
3713
3713
|
timeout: 10000,
|
|
3714
3714
|
});
|
|
3715
3715
|
}
|
|
@@ -3721,7 +3721,7 @@ async function openCallConfigVoicePicker(scope) {
|
|
|
3721
3721
|
const openBtn = scope.getByTestId('call-config-voice-trigger-open');
|
|
3722
3722
|
await test$1.expect(openBtn).toBeVisible({ timeout: 10000 });
|
|
3723
3723
|
await openBtn.click();
|
|
3724
|
-
await test$1.expect(asPage$
|
|
3724
|
+
await test$1.expect(asPage$4(scope).getByTestId('voice-picker-modal')).toBeVisible({
|
|
3725
3725
|
timeout: 10000,
|
|
3726
3726
|
});
|
|
3727
3727
|
}
|
|
@@ -3834,7 +3834,7 @@ async function selectCallMode(scope, mode) {
|
|
|
3834
3834
|
const trigger = scope.getByRole('combobox', { name: VOICE_LABELS.callConfigFields.mode });
|
|
3835
3835
|
await test$1.expect(trigger).toBeVisible({ timeout: 10000 });
|
|
3836
3836
|
await trigger.click();
|
|
3837
|
-
const option = asPage$
|
|
3837
|
+
const option = asPage$4(scope).getByRole('option', { name: VOICE_LABELS.modeOptions[mode] });
|
|
3838
3838
|
await test$1.expect(option).toBeVisible({ timeout: 5000 });
|
|
3839
3839
|
await option.click();
|
|
3840
3840
|
await test$1.expect(trigger).toHaveText(new RegExp(VOICE_LABELS.modeOptions[mode]));
|
|
@@ -3850,7 +3850,7 @@ async function selectFromCombobox(scope, triggerName, optionName) {
|
|
|
3850
3850
|
const trigger = scope.getByRole('combobox', { name: triggerName });
|
|
3851
3851
|
await test$1.expect(trigger).toBeVisible({ timeout: 10000 });
|
|
3852
3852
|
await trigger.click();
|
|
3853
|
-
const option = asPage$
|
|
3853
|
+
const option = asPage$4(scope).getByRole('option', { name: optionName });
|
|
3854
3854
|
await test$1.expect(option).toBeVisible({ timeout: 5000 });
|
|
3855
3855
|
await option.click();
|
|
3856
3856
|
}
|
|
@@ -3947,7 +3947,7 @@ const SCREENSHARE_LABELS = {
|
|
|
3947
3947
|
},
|
|
3948
3948
|
saveButton: 'Save',
|
|
3949
3949
|
};
|
|
3950
|
-
function asPage$
|
|
3950
|
+
function asPage$3(scope) {
|
|
3951
3951
|
return 'page' in scope ? scope.page() : scope;
|
|
3952
3952
|
}
|
|
3953
3953
|
/**
|
|
@@ -3987,7 +3987,7 @@ async function openScreenSharePromptEditor(scope, field) {
|
|
|
3987
3987
|
const btn = scope.getByRole('button', { name: `Edit ${label}` });
|
|
3988
3988
|
await test$1.expect(btn).toBeVisible({ timeout: 10000 });
|
|
3989
3989
|
await btn.click();
|
|
3990
|
-
await test$1.expect(asPage$
|
|
3990
|
+
await test$1.expect(asPage$3(scope).getByText(`Edit ${label}`)).toBeVisible({ timeout: 10000 });
|
|
3991
3991
|
logger.info(`Opened screen-share ${field} editor`);
|
|
3992
3992
|
}
|
|
3993
3993
|
/**
|
|
@@ -3997,7 +3997,7 @@ async function openScreenSharePromptEditor(scope, field) {
|
|
|
3997
3997
|
*/
|
|
3998
3998
|
async function setScreenSharePrompt(scope, field, text) {
|
|
3999
3999
|
await openScreenSharePromptEditor(scope, field);
|
|
4000
|
-
const page = asPage$
|
|
4000
|
+
const page = asPage$3(scope);
|
|
4001
4001
|
const editor = page.getByRole('dialog').locator('[contenteditable="true"]').first();
|
|
4002
4002
|
await test$1.expect(editor).toBeVisible({ timeout: 10000 });
|
|
4003
4003
|
await editor.click();
|
|
@@ -4006,7 +4006,10 @@ async function setScreenSharePrompt(scope, field, text) {
|
|
|
4006
4006
|
await editor.pressSequentially(text);
|
|
4007
4007
|
// The modal's Save button — scope to dialog so we don't grab the
|
|
4008
4008
|
// outer tab's Save.
|
|
4009
|
-
await page
|
|
4009
|
+
await page
|
|
4010
|
+
.getByRole('dialog')
|
|
4011
|
+
.getByRole('button', { name: /^save$/i })
|
|
4012
|
+
.click();
|
|
4010
4013
|
await test$1.expect(page.getByRole('dialog')).toBeHidden({ timeout: 10000 });
|
|
4011
4014
|
logger.info(`Set screen-share ${field}`);
|
|
4012
4015
|
}
|
|
@@ -4325,7 +4328,7 @@ const TASKS_LABELS = {
|
|
|
4325
4328
|
* reach DOM that Radix renders outside the dialog subtree (popovers,
|
|
4326
4329
|
* select options, the schedule / delete / log-details dialogs, etc.).
|
|
4327
4330
|
*/
|
|
4328
|
-
function asPage$
|
|
4331
|
+
function asPage$2(scope) {
|
|
4329
4332
|
return 'page' in scope ? scope.page() : scope;
|
|
4330
4333
|
}
|
|
4331
4334
|
// ── Tab navigation ─────────────────────────────────────────────────────
|
|
@@ -4435,7 +4438,7 @@ async function searchTasks(scope, query) {
|
|
|
4435
4438
|
* shares an accessible name with the dialog's submit button.
|
|
4436
4439
|
*/
|
|
4437
4440
|
function getScheduleTaskDialog(scope) {
|
|
4438
|
-
return asPage$
|
|
4441
|
+
return asPage$2(scope).getByRole('dialog', { name: TASKS_LABELS.scheduleDialog.dialogName });
|
|
4439
4442
|
}
|
|
4440
4443
|
/** Open the Schedule Task dialog and wait for it to be interactive. */
|
|
4441
4444
|
async function openScheduleTaskDialog(scope) {
|
|
@@ -4454,7 +4457,7 @@ async function openScheduleTaskDialog(scope) {
|
|
|
4454
4457
|
*/
|
|
4455
4458
|
async function scheduleTask(scope, opts) {
|
|
4456
4459
|
await openScheduleTaskDialog(scope);
|
|
4457
|
-
const page = asPage$
|
|
4460
|
+
const page = asPage$2(scope);
|
|
4458
4461
|
// Scope every query to the dialog: the toolbar "Schedule Task" button shares
|
|
4459
4462
|
// an accessible name with the dialog's submit button, so an unscoped
|
|
4460
4463
|
// getByRole('button', { name: 'Schedule Task' }) matches two elements.
|
|
@@ -4489,13 +4492,13 @@ async function scheduleTask(scope, opts) {
|
|
|
4489
4492
|
}
|
|
4490
4493
|
/** Asserts the in-dialog past-time error is currently shown. */
|
|
4491
4494
|
async function expectScheduleStartTimeInPastError(scope) {
|
|
4492
|
-
await test$1.expect(asPage$
|
|
4495
|
+
await test$1.expect(asPage$2(scope).getByText(TASKS_LABELS.scheduleDialog.startTimeInPast)).toBeVisible({
|
|
4493
4496
|
timeout: 5000,
|
|
4494
4497
|
});
|
|
4495
4498
|
}
|
|
4496
4499
|
// ── Delete flow ────────────────────────────────────────────────────────
|
|
4497
4500
|
function getDeleteTaskDialog(scope) {
|
|
4498
|
-
return asPage$
|
|
4501
|
+
return asPage$2(scope).locator(`[role="dialog"][aria-label="${TASKS_LABELS.deleteDialog.dialogName}"]`);
|
|
4499
4502
|
}
|
|
4500
4503
|
/**
|
|
4501
4504
|
* Click the trash icon on a task row and confirm the delete in the
|
|
@@ -4516,7 +4519,7 @@ async function deleteTask(scope, taskName) {
|
|
|
4516
4519
|
}
|
|
4517
4520
|
// ── Logs panel + log details ───────────────────────────────────────────
|
|
4518
4521
|
function getLogDetailsDialog(scope) {
|
|
4519
|
-
return asPage$
|
|
4522
|
+
return asPage$2(scope).locator(`[role="dialog"][aria-label="${TASKS_LABELS.logDetails.dialogName}"]`);
|
|
4520
4523
|
}
|
|
4521
4524
|
/**
|
|
4522
4525
|
* Wait for the logs panel to finish loading and assert that the selected
|
|
@@ -4552,6 +4555,801 @@ async function expectLogDetailsStatus(scope, status) {
|
|
|
4552
4555
|
});
|
|
4553
4556
|
}
|
|
4554
4557
|
|
|
4558
|
+
/**
|
|
4559
|
+
* Evals tab helpers — Playwright bindings for the `AgentEvaluationTab`
|
|
4560
|
+
* component from `@iblai/web-containers` (edit-mentor modal > Evals tab),
|
|
4561
|
+
* including the embedded tenant Benchmarks management dialog.
|
|
4562
|
+
*
|
|
4563
|
+
* All UI strings below mirror `AGENT_EVALUATION_TAB_LABELS` from
|
|
4564
|
+
* `@iblai/web-containers/next` plus the `benchmarks*` i18n namespaces. If a
|
|
4565
|
+
* consumer renames a label via the `labels` prop, override these constants
|
|
4566
|
+
* per spec — don't edit this file.
|
|
4567
|
+
*
|
|
4568
|
+
* Every dialog spawned by this tab carries an explicit `aria-label` on its
|
|
4569
|
+
* `DialogContent` (see `dialogName` entries). Helpers ALWAYS resolve the
|
|
4570
|
+
* dialog once via `[role="dialog"][aria-label="…"]` — the attribute selector,
|
|
4571
|
+
* not the role accessible name, because a visible `DialogTitle` makes Radix's
|
|
4572
|
+
* `aria-labelledby` win the accessible-name computation — and then resolve
|
|
4573
|
+
* every in-dialog control from that scoped locator. This matters here more
|
|
4574
|
+
* than usual:
|
|
4575
|
+
* - the toolbar "New Evaluation" / "Manage benchmarks" buttons share their
|
|
4576
|
+
* text with the dialog titles they open;
|
|
4577
|
+
* - the LLM-judge dialog's title AND submit button both read "Evaluate";
|
|
4578
|
+
* - dialogs nest three deep (Manage benchmarks → benchmark items → add
|
|
4579
|
+
* Q&A), and the add-Q&A dialog has Manual / CSV Upload sub-tabs whose
|
|
4580
|
+
* footers each have their own Cancel button.
|
|
4581
|
+
*
|
|
4582
|
+
* The helpers assume the Edit Mentor dialog is already open. Call
|
|
4583
|
+
* `switchToEvaluationTab(page)` first; from then on, every helper accepts
|
|
4584
|
+
* either the `Page` or a scoping `Locator`.
|
|
4585
|
+
*/
|
|
4586
|
+
const EVALS_LABELS = {
|
|
4587
|
+
tabName: 'Evals',
|
|
4588
|
+
header: {
|
|
4589
|
+
title: 'Evals',
|
|
4590
|
+
description: 'Run this agent against a benchmark and score the responses.',
|
|
4591
|
+
},
|
|
4592
|
+
benchmarkPicker: {
|
|
4593
|
+
placeholder: 'Select a benchmark',
|
|
4594
|
+
searchPlaceholder: 'Search benchmarks...',
|
|
4595
|
+
empty: 'No benchmarks found',
|
|
4596
|
+
/** `data-testid` on the combobox trigger button (its text is the selected benchmark, so it has no stable accessible name). */
|
|
4597
|
+
triggerTestId: 'benchmark-combobox',
|
|
4598
|
+
/** `data-testid` on the dropdown panel (rendered inline, not in a portal). */
|
|
4599
|
+
dropdownTestId: 'benchmark-combobox-dropdown',
|
|
4600
|
+
},
|
|
4601
|
+
actions: {
|
|
4602
|
+
newExperiment: 'New Evaluation',
|
|
4603
|
+
manageBenchmarks: 'Manage benchmarks',
|
|
4604
|
+
viewResults: 'View results',
|
|
4605
|
+
evaluate: 'New review',
|
|
4606
|
+
exportCsv: 'Export CSV',
|
|
4607
|
+
checkStatus: 'Check status',
|
|
4608
|
+
delete: 'Delete',
|
|
4609
|
+
},
|
|
4610
|
+
checkStatusToast: {
|
|
4611
|
+
pending: 'Evaluation is still running',
|
|
4612
|
+
completed: 'Evaluation completed',
|
|
4613
|
+
failed: 'Evaluation failed',
|
|
4614
|
+
},
|
|
4615
|
+
emptyBenchmarks: 'No benchmarks yet. Use "Manage benchmarks" above to create one.',
|
|
4616
|
+
startDialog: {
|
|
4617
|
+
/** `aria-label` on the dialog's `DialogContent` — scopes in-dialog locators. */
|
|
4618
|
+
dialogName: 'start-evaluation',
|
|
4619
|
+
experimentNameLabel: 'Evaluation name',
|
|
4620
|
+
cancel: 'Cancel',
|
|
4621
|
+
start: 'Start Evaluation',
|
|
4622
|
+
},
|
|
4623
|
+
manageBenchmarksDialog: {
|
|
4624
|
+
/** `aria-label` on the dialog's `DialogContent` — scopes in-dialog locators. */
|
|
4625
|
+
dialogName: 'manage-benchmarks',
|
|
4626
|
+
searchAriaLabel: 'Search benchmarks',
|
|
4627
|
+
newBenchmark: 'New Benchmark',
|
|
4628
|
+
empty: 'No benchmarks found',
|
|
4629
|
+
},
|
|
4630
|
+
createBenchmarkDialog: {
|
|
4631
|
+
/** `aria-label` on the dialog's `DialogContent` — scopes in-dialog locators. */
|
|
4632
|
+
dialogName: 'create-benchmark',
|
|
4633
|
+
nameLabel: 'Name',
|
|
4634
|
+
descriptionLabel: 'Description',
|
|
4635
|
+
cancel: 'Cancel',
|
|
4636
|
+
create: 'Create',
|
|
4637
|
+
},
|
|
4638
|
+
benchmarkItemsDialog: {
|
|
4639
|
+
/** `aria-label` on the dialog's `DialogContent` — scopes in-dialog locators. */
|
|
4640
|
+
dialogName: 'benchmark-items',
|
|
4641
|
+
addItems: 'Add Q&A',
|
|
4642
|
+
deleteItemAriaLabel: 'Delete Q&A',
|
|
4643
|
+
empty: 'No Q&A in this benchmark yet',
|
|
4644
|
+
},
|
|
4645
|
+
addItemsDialog: {
|
|
4646
|
+
/** `aria-label` on the dialog's `DialogContent` — scopes in-dialog locators. */
|
|
4647
|
+
dialogName: 'add-benchmark-items',
|
|
4648
|
+
manualTab: 'Manual',
|
|
4649
|
+
csvTab: 'CSV Upload',
|
|
4650
|
+
questionLabel: 'Question',
|
|
4651
|
+
answerLabel: 'Answer',
|
|
4652
|
+
addRow: 'Add row',
|
|
4653
|
+
removeRowAriaLabel: 'Remove row',
|
|
4654
|
+
add: 'Add',
|
|
4655
|
+
csvFileLabel: 'CSV file',
|
|
4656
|
+
upload: 'Upload',
|
|
4657
|
+
cancel: 'Cancel',
|
|
4658
|
+
},
|
|
4659
|
+
deleteItemDialog: {
|
|
4660
|
+
/** `aria-label` on the dialog's `DialogContent` — scopes in-dialog locators. */
|
|
4661
|
+
dialogName: 'delete-benchmark-item',
|
|
4662
|
+
delete: 'Delete',
|
|
4663
|
+
cancel: 'Cancel',
|
|
4664
|
+
},
|
|
4665
|
+
detailDialog: {
|
|
4666
|
+
/** `aria-label` on the dialog's `DialogContent` — scopes in-dialog locators. */
|
|
4667
|
+
dialogName: 'evaluation-detail',
|
|
4668
|
+
refreshAriaLabel: 'Refresh',
|
|
4669
|
+
newReview: 'New review',
|
|
4670
|
+
waitingHint: 'Waiting for the evaluation to produce traces. This page auto-refreshes.',
|
|
4671
|
+
noScoresHint: 'No scores yet',
|
|
4672
|
+
scoreNameLabel: 'Score name',
|
|
4673
|
+
scoreValueLabel: 'Value',
|
|
4674
|
+
scoreCommentLabel: 'Comment',
|
|
4675
|
+
addScore: 'Add',
|
|
4676
|
+
removeScoreAriaLabel: 'Remove score',
|
|
4677
|
+
reviewsHeading: 'Reviews',
|
|
4678
|
+
reviewDetailsAriaLabel: 'Toggle review details',
|
|
4679
|
+
reviewStatus: {
|
|
4680
|
+
pending: 'Queued',
|
|
4681
|
+
running: 'Running',
|
|
4682
|
+
completed: 'Complete',
|
|
4683
|
+
failed: 'Failed',
|
|
4684
|
+
},
|
|
4685
|
+
},
|
|
4686
|
+
judgeDialog: {
|
|
4687
|
+
/** `aria-label` on the dialog's `DialogContent` — scopes in-dialog locators. */
|
|
4688
|
+
dialogName: 'llm-judge',
|
|
4689
|
+
criteriaLabel: 'Criteria',
|
|
4690
|
+
scoreNameLabel: 'Score name',
|
|
4691
|
+
maxConcurrencyLabel: 'Max concurrency',
|
|
4692
|
+
selectorAriaLabel: 'LLM Model Selector',
|
|
4693
|
+
cancel: 'Cancel',
|
|
4694
|
+
submit: 'Evaluate',
|
|
4695
|
+
},
|
|
4696
|
+
llmPickerDialog: {
|
|
4697
|
+
/** `aria-label` on the dialog's `DialogContent` — scopes in-dialog locators. */
|
|
4698
|
+
dialogName: 'evaluate-llm-picker',
|
|
4699
|
+
searchPlaceholder: 'Search providers...',
|
|
4700
|
+
/** Title of the follow-up model-selection modal (llm-tab's `LLMProviderModal`, no aria-label of its own). */
|
|
4701
|
+
modelDialogTitle: 'LLM Selection',
|
|
4702
|
+
},
|
|
4703
|
+
deleteDialog: {
|
|
4704
|
+
/** `aria-label` on the dialog's `DialogContent` — scopes in-dialog locators. */
|
|
4705
|
+
dialogName: 'delete-evaluation',
|
|
4706
|
+
cancel: 'Cancel',
|
|
4707
|
+
confirm: 'Delete',
|
|
4708
|
+
},
|
|
4709
|
+
};
|
|
4710
|
+
/**
|
|
4711
|
+
* Resolve a Page from either a Page or a Locator. Used for DOM that Radix
|
|
4712
|
+
* renders in a portal outside the current scope (dialogs, dropdown menus,
|
|
4713
|
+
* toasts) — those queries must run on the page, never on the tab pane or a
|
|
4714
|
+
* parent dialog.
|
|
4715
|
+
*/
|
|
4716
|
+
function asPage$1(scope) {
|
|
4717
|
+
return 'page' in scope ? scope.page() : scope;
|
|
4718
|
+
}
|
|
4719
|
+
/** Escape a user-supplied string (run / benchmark names) for use in a RegExp. */
|
|
4720
|
+
function escapeRegExp(value) {
|
|
4721
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
4722
|
+
}
|
|
4723
|
+
/** Attribute-based dialog locator — immune to title renames and to Radix's `aria-labelledby` name precedence. */
|
|
4724
|
+
function dialogByName(scope, dialogName) {
|
|
4725
|
+
return asPage$1(scope).locator(`[role="dialog"][aria-label="${dialogName}"]`);
|
|
4726
|
+
}
|
|
4727
|
+
// ── Tab navigation ─────────────────────────────────────────────────────
|
|
4728
|
+
/**
|
|
4729
|
+
* Check whether the Evals tab is rendered in the Edit Mentor dialog.
|
|
4730
|
+
* Returns false instead of throwing so callers can guard permission-gated
|
|
4731
|
+
* tabs.
|
|
4732
|
+
*/
|
|
4733
|
+
async function isEvaluationTabVisible(page) {
|
|
4734
|
+
const tab = page.getByRole('tab', { name: EVALS_LABELS.tabName, exact: true });
|
|
4735
|
+
try {
|
|
4736
|
+
await test$1.expect(tab).toBeVisible({ timeout: 5000 });
|
|
4737
|
+
return true;
|
|
4738
|
+
}
|
|
4739
|
+
catch (_a) {
|
|
4740
|
+
return false;
|
|
4741
|
+
}
|
|
4742
|
+
}
|
|
4743
|
+
/**
|
|
4744
|
+
* Switch to the Evals tab. Assumes the Edit Mentor dialog is open. Waits
|
|
4745
|
+
* for the toolbar "Manage benchmarks" button (unique to this pane) before
|
|
4746
|
+
* returning, so callers can rely on the panel being interactive.
|
|
4747
|
+
*/
|
|
4748
|
+
async function switchToEvaluationTab(page) {
|
|
4749
|
+
const tab = page.getByRole('tab', { name: EVALS_LABELS.tabName, exact: true });
|
|
4750
|
+
await test$1.expect(tab).toBeVisible({ timeout: 10000 });
|
|
4751
|
+
await tab.click();
|
|
4752
|
+
await test$1.expect(page.getByRole('button', { name: EVALS_LABELS.actions.manageBenchmarks })).toBeVisible({ timeout: 10000 });
|
|
4753
|
+
logger.info('Switched to Evals tab');
|
|
4754
|
+
}
|
|
4755
|
+
// ── Toolbar: benchmark picker + action buttons ─────────────────────────
|
|
4756
|
+
/** Locator for the benchmark combobox trigger. Its text is the selected benchmark name. */
|
|
4757
|
+
function getBenchmarkCombobox(scope) {
|
|
4758
|
+
return scope.getByTestId(EVALS_LABELS.benchmarkPicker.triggerTestId);
|
|
4759
|
+
}
|
|
4760
|
+
/** Locator for the combobox dropdown panel (rendered inline under the trigger, not in a portal). */
|
|
4761
|
+
function getBenchmarkComboboxDropdown(scope) {
|
|
4762
|
+
return scope.getByTestId(EVALS_LABELS.benchmarkPicker.dropdownTestId);
|
|
4763
|
+
}
|
|
4764
|
+
/** Locator for the toolbar "New Evaluation" button (opens the start dialog). */
|
|
4765
|
+
function getNewEvaluationButton(scope) {
|
|
4766
|
+
return scope.getByRole('button', { name: EVALS_LABELS.actions.newExperiment, exact: true });
|
|
4767
|
+
}
|
|
4768
|
+
/** Locator for the toolbar "Manage benchmarks" button (opens the benchmarks dialog). */
|
|
4769
|
+
function getManageBenchmarksButton(scope) {
|
|
4770
|
+
return scope.getByRole('button', { name: EVALS_LABELS.actions.manageBenchmarks, exact: true });
|
|
4771
|
+
}
|
|
4772
|
+
/** Assert the currently selected benchmark shown on the combobox trigger. */
|
|
4773
|
+
async function expectSelectedBenchmark(scope, benchmarkName) {
|
|
4774
|
+
await test$1.expect(getBenchmarkCombobox(scope)).toContainText(benchmarkName, { timeout: 10000 });
|
|
4775
|
+
}
|
|
4776
|
+
/**
|
|
4777
|
+
* Open the benchmark combobox, optionally filter via its search input, and
|
|
4778
|
+
* pick a benchmark by exact name. Waits for the dropdown to close and the
|
|
4779
|
+
* trigger to reflect the selection.
|
|
4780
|
+
*/
|
|
4781
|
+
async function selectBenchmark(scope, benchmarkName, opts = {}) {
|
|
4782
|
+
const trigger = getBenchmarkCombobox(scope);
|
|
4783
|
+
await test$1.expect(trigger).toBeEnabled({ timeout: 10000 });
|
|
4784
|
+
await trigger.click();
|
|
4785
|
+
const dropdown = getBenchmarkComboboxDropdown(scope);
|
|
4786
|
+
await test$1.expect(dropdown).toBeVisible({ timeout: 5000 });
|
|
4787
|
+
if (opts.search) {
|
|
4788
|
+
const search = dropdown.getByPlaceholder(EVALS_LABELS.benchmarkPicker.searchPlaceholder);
|
|
4789
|
+
await search.fill(benchmarkName);
|
|
4790
|
+
await test$1.expect(search).toHaveValue(benchmarkName);
|
|
4791
|
+
}
|
|
4792
|
+
await dropdown
|
|
4793
|
+
.getByRole('button', { name: new RegExp(`^${escapeRegExp(benchmarkName)}$`) })
|
|
4794
|
+
.click();
|
|
4795
|
+
await test$1.expect(dropdown).toBeHidden({ timeout: 5000 });
|
|
4796
|
+
await expectSelectedBenchmark(scope, benchmarkName);
|
|
4797
|
+
logger.info(`Selected benchmark: ${benchmarkName}`);
|
|
4798
|
+
}
|
|
4799
|
+
/** Assert the "no benchmarks yet" empty notice is shown in the tab body. */
|
|
4800
|
+
async function expectNoBenchmarksNotice(scope) {
|
|
4801
|
+
await test$1.expect(scope.getByText(EVALS_LABELS.emptyBenchmarks)).toBeVisible({ timeout: 10000 });
|
|
4802
|
+
}
|
|
4803
|
+
// ── Runs table ─────────────────────────────────────────────────────────
|
|
4804
|
+
/**
|
|
4805
|
+
* Locator for an evaluation run's table row, matched by an exact cell so a
|
|
4806
|
+
* run whose name is a substring of another ("smoke" vs "smoke-2") can't
|
|
4807
|
+
* cross-match.
|
|
4808
|
+
*/
|
|
4809
|
+
function getRunRow(scope, runName) {
|
|
4810
|
+
return scope
|
|
4811
|
+
.getByRole('row')
|
|
4812
|
+
.filter({ has: asPage$1(scope).getByRole('cell', { name: runName, exact: true }) });
|
|
4813
|
+
}
|
|
4814
|
+
async function expectRunInTable(scope, runName) {
|
|
4815
|
+
await test$1.expect(getRunRow(scope, runName)).toBeVisible({ timeout: 15000 });
|
|
4816
|
+
}
|
|
4817
|
+
async function expectRunNotInTable(scope, runName) {
|
|
4818
|
+
await test$1.expect(getRunRow(scope, runName)).toBeHidden({ timeout: 15000 });
|
|
4819
|
+
}
|
|
4820
|
+
/** Assert the status badge on a run's row (badge text is upper-cased by the UI). */
|
|
4821
|
+
async function expectRunStatus(scope, runName, status) {
|
|
4822
|
+
await test$1.expect(getRunRow(scope, runName).getByText(status, { exact: true })).toBeVisible({
|
|
4823
|
+
timeout: 15000,
|
|
4824
|
+
});
|
|
4825
|
+
}
|
|
4826
|
+
/** Assert the empty-state row shown when the selected benchmark has no runs for this agent. */
|
|
4827
|
+
async function expectRunsTableEmpty(scope, benchmarkName) {
|
|
4828
|
+
await test$1.expect(scope.getByText(`No evaluations yet for this agent on benchmark "${benchmarkName}".`)).toBeVisible({ timeout: 15000 });
|
|
4829
|
+
}
|
|
4830
|
+
/**
|
|
4831
|
+
* Open the three-dots actions menu on a run's row. The trigger carries
|
|
4832
|
+
* `aria-label="Actions for <runName>"`, so it can't collide with other rows.
|
|
4833
|
+
* Returns the menu locator (Radix portals it outside the table — page scope).
|
|
4834
|
+
*/
|
|
4835
|
+
async function openRunActionsMenu(scope, runName) {
|
|
4836
|
+
await getRunRow(scope, runName)
|
|
4837
|
+
.getByRole('button', { name: `Actions for ${runName}`, exact: true })
|
|
4838
|
+
.click();
|
|
4839
|
+
const menu = asPage$1(scope).getByRole('menu');
|
|
4840
|
+
await test$1.expect(menu).toBeVisible({ timeout: 5000 });
|
|
4841
|
+
return menu;
|
|
4842
|
+
}
|
|
4843
|
+
/**
|
|
4844
|
+
* Row action: "View results" — opens the evaluation detail dialog.
|
|
4845
|
+
* Only enabled once the run is COMPLETED. Returns the scoped detail dialog.
|
|
4846
|
+
*/
|
|
4847
|
+
async function openRunResults(scope, runName) {
|
|
4848
|
+
const menu = await openRunActionsMenu(scope, runName);
|
|
4849
|
+
const item = menu.getByRole('menuitem', { name: EVALS_LABELS.actions.viewResults });
|
|
4850
|
+
await test$1.expect(item).toBeEnabled({ timeout: 5000 });
|
|
4851
|
+
await item.click();
|
|
4852
|
+
const dialog = getEvaluationDetailDialog(scope);
|
|
4853
|
+
await test$1.expect(dialog).toBeVisible({ timeout: 10000 });
|
|
4854
|
+
logger.info(`Opened results for run: ${runName}`);
|
|
4855
|
+
return dialog;
|
|
4856
|
+
}
|
|
4857
|
+
/**
|
|
4858
|
+
* Row action: "New review" — opens the LLM-judge dialog for the run.
|
|
4859
|
+
* Only enabled once the run is COMPLETED. Returns the scoped judge dialog.
|
|
4860
|
+
*/
|
|
4861
|
+
async function openNewReviewForRun(scope, runName) {
|
|
4862
|
+
const menu = await openRunActionsMenu(scope, runName);
|
|
4863
|
+
const item = menu.getByRole('menuitem', { name: EVALS_LABELS.actions.evaluate });
|
|
4864
|
+
await test$1.expect(item).toBeEnabled({ timeout: 5000 });
|
|
4865
|
+
await item.click();
|
|
4866
|
+
const dialog = getLlmJudgeDialog(scope);
|
|
4867
|
+
await test$1.expect(dialog).toBeVisible({ timeout: 10000 });
|
|
4868
|
+
return dialog;
|
|
4869
|
+
}
|
|
4870
|
+
/**
|
|
4871
|
+
* Row action: "Check status" — triggers a fresh status fetch and waits for
|
|
4872
|
+
* the outcome toast. Returns which toast appeared. The menu stays open by
|
|
4873
|
+
* design (the item prevents default), so we close it with Escape.
|
|
4874
|
+
*/
|
|
4875
|
+
async function checkRunStatus(scope, runName) {
|
|
4876
|
+
const page = asPage$1(scope);
|
|
4877
|
+
const menu = await openRunActionsMenu(scope, runName);
|
|
4878
|
+
await menu.getByRole('menuitem', { name: EVALS_LABELS.actions.checkStatus }).click();
|
|
4879
|
+
const toasts = EVALS_LABELS.checkStatusToast;
|
|
4880
|
+
const toast = page
|
|
4881
|
+
.getByText(new RegExp(`${toasts.pending}|${toasts.completed}|${toasts.failed}`))
|
|
4882
|
+
.first();
|
|
4883
|
+
await test$1.expect(toast).toBeVisible({ timeout: 15000 });
|
|
4884
|
+
const text = (await toast.innerText()).trim();
|
|
4885
|
+
await page.keyboard.press('Escape');
|
|
4886
|
+
await test$1.expect(menu).toBeHidden({ timeout: 5000 });
|
|
4887
|
+
if (text.includes(toasts.completed))
|
|
4888
|
+
return 'completed';
|
|
4889
|
+
if (text.includes(toasts.failed))
|
|
4890
|
+
return 'failed';
|
|
4891
|
+
return 'pending';
|
|
4892
|
+
}
|
|
4893
|
+
/**
|
|
4894
|
+
* Row action: "Export CSV" — waits for the browser download and returns its
|
|
4895
|
+
* suggested filename (`<benchmark>_<run>_results.csv`).
|
|
4896
|
+
*/
|
|
4897
|
+
async function exportRunCsv(scope, runName) {
|
|
4898
|
+
const page = asPage$1(scope);
|
|
4899
|
+
const menu = await openRunActionsMenu(scope, runName);
|
|
4900
|
+
const item = menu.getByRole('menuitem', { name: EVALS_LABELS.actions.exportCsv });
|
|
4901
|
+
await test$1.expect(item).toBeEnabled({ timeout: 5000 });
|
|
4902
|
+
const downloadPromise = page.waitForEvent('download', { timeout: 30000 });
|
|
4903
|
+
await item.click();
|
|
4904
|
+
const download = await downloadPromise;
|
|
4905
|
+
logger.info(`Exported run CSV: ${download.suggestedFilename()}`);
|
|
4906
|
+
return download.suggestedFilename();
|
|
4907
|
+
}
|
|
4908
|
+
// ── Start evaluation dialog ────────────────────────────────────────────
|
|
4909
|
+
/** Locator for the "New Evaluation" dialog. Scoped by aria-label — its title text collides with the toolbar button that opens it. */
|
|
4910
|
+
function getStartEvaluationDialog(scope) {
|
|
4911
|
+
return dialogByName(scope, EVALS_LABELS.startDialog.dialogName);
|
|
4912
|
+
}
|
|
4913
|
+
/** Open the start dialog via the toolbar button and wait for it to be interactive. */
|
|
4914
|
+
async function openStartEvaluationDialog(scope) {
|
|
4915
|
+
await getNewEvaluationButton(scope).click();
|
|
4916
|
+
const dialog = getStartEvaluationDialog(scope);
|
|
4917
|
+
await test$1.expect(dialog.getByLabel(EVALS_LABELS.startDialog.experimentNameLabel)).toBeVisible({
|
|
4918
|
+
timeout: 10000,
|
|
4919
|
+
});
|
|
4920
|
+
return dialog;
|
|
4921
|
+
}
|
|
4922
|
+
/**
|
|
4923
|
+
* End-to-end: open the "New Evaluation" dialog, optionally name the run,
|
|
4924
|
+
* submit, and wait for the dialog to close. When `name` is omitted the
|
|
4925
|
+
* backend auto-generates one.
|
|
4926
|
+
*/
|
|
4927
|
+
async function startEvaluation(scope, opts = {}) {
|
|
4928
|
+
const dialog = await openStartEvaluationDialog(scope);
|
|
4929
|
+
if (opts.name !== undefined) {
|
|
4930
|
+
await dialog.getByLabel(EVALS_LABELS.startDialog.experimentNameLabel).fill(opts.name);
|
|
4931
|
+
}
|
|
4932
|
+
// Scoped to the dialog: "Start Evaluation" is unique today, but the toolbar
|
|
4933
|
+
// "New Evaluation" trigger sits right behind the overlay — never query the page.
|
|
4934
|
+
const submit = dialog.getByRole('button', { name: EVALS_LABELS.startDialog.start });
|
|
4935
|
+
await test$1.expect(submit).toBeEnabled({ timeout: 5000 });
|
|
4936
|
+
await submit.click();
|
|
4937
|
+
await test$1.expect(dialog).toBeHidden({ timeout: 15000 });
|
|
4938
|
+
logger.info(`Started evaluation${opts.name ? `: ${opts.name}` : ''}`);
|
|
4939
|
+
}
|
|
4940
|
+
/** Cancel out of the start dialog and wait for it to close. */
|
|
4941
|
+
async function cancelStartEvaluation(scope) {
|
|
4942
|
+
const dialog = getStartEvaluationDialog(scope);
|
|
4943
|
+
await dialog.getByRole('button', { name: EVALS_LABELS.startDialog.cancel }).click();
|
|
4944
|
+
await test$1.expect(dialog).toBeHidden({ timeout: 5000 });
|
|
4945
|
+
}
|
|
4946
|
+
// ── Delete evaluation dialog ───────────────────────────────────────────
|
|
4947
|
+
/** Locator for the "Delete Evaluation" confirm dialog. */
|
|
4948
|
+
function getDeleteEvaluationDialog(scope) {
|
|
4949
|
+
return dialogByName(scope, EVALS_LABELS.deleteDialog.dialogName);
|
|
4950
|
+
}
|
|
4951
|
+
/**
|
|
4952
|
+
* Delete a run from its row actions menu and confirm in the follow-up
|
|
4953
|
+
* dialog. The confirm button ("Delete") shares its name with the menu item
|
|
4954
|
+
* that opened the dialog, so the confirm click MUST stay dialog-scoped.
|
|
4955
|
+
*/
|
|
4956
|
+
async function deleteEvaluation(scope, runName) {
|
|
4957
|
+
const menu = await openRunActionsMenu(scope, runName);
|
|
4958
|
+
await menu.getByRole('menuitem', { name: EVALS_LABELS.actions.delete }).click();
|
|
4959
|
+
const dialog = getDeleteEvaluationDialog(scope);
|
|
4960
|
+
const confirm = dialog.getByRole('button', { name: EVALS_LABELS.deleteDialog.confirm });
|
|
4961
|
+
await test$1.expect(confirm).toBeVisible({ timeout: 5000 });
|
|
4962
|
+
await confirm.click();
|
|
4963
|
+
await test$1.expect(dialog).toBeHidden({ timeout: 15000 });
|
|
4964
|
+
logger.info(`Deleted evaluation: ${runName}`);
|
|
4965
|
+
}
|
|
4966
|
+
/** Open the delete confirm from the row menu, then cancel out of it. */
|
|
4967
|
+
async function cancelDeleteEvaluation(scope, runName) {
|
|
4968
|
+
const menu = await openRunActionsMenu(scope, runName);
|
|
4969
|
+
await menu.getByRole('menuitem', { name: EVALS_LABELS.actions.delete }).click();
|
|
4970
|
+
const dialog = getDeleteEvaluationDialog(scope);
|
|
4971
|
+
await dialog.getByRole('button', { name: EVALS_LABELS.deleteDialog.cancel }).click();
|
|
4972
|
+
await test$1.expect(dialog).toBeHidden({ timeout: 5000 });
|
|
4973
|
+
}
|
|
4974
|
+
// ── LLM-judge ("Evaluate") dialog ──────────────────────────────────────
|
|
4975
|
+
/**
|
|
4976
|
+
* Locator for the LLM-judge dialog. Scoped by aria-label — its title AND its
|
|
4977
|
+
* submit button both read "Evaluate", and it can be stacked on top of the
|
|
4978
|
+
* evaluation-detail dialog.
|
|
4979
|
+
*/
|
|
4980
|
+
function getLlmJudgeDialog(scope) {
|
|
4981
|
+
return dialogByName(scope, EVALS_LABELS.judgeDialog.dialogName);
|
|
4982
|
+
}
|
|
4983
|
+
/** Locator for the judge dialog's LLM provider-picker dialog (stacked above it). */
|
|
4984
|
+
function getLlmPickerDialog(scope) {
|
|
4985
|
+
return dialogByName(scope, EVALS_LABELS.llmPickerDialog.dialogName);
|
|
4986
|
+
}
|
|
4987
|
+
/**
|
|
4988
|
+
* Inside the judge dialog: pick the judging LLM. Opens the provider picker,
|
|
4989
|
+
* optionally filters, clicks the provider card, then picks the model in the
|
|
4990
|
+
* follow-up "LLM Selection" modal (llm-tab's `LLMProviderModal`; matched by
|
|
4991
|
+
* title text since it has no aria-label). Both pickers close on selection.
|
|
4992
|
+
*/
|
|
4993
|
+
async function selectJudgeLlm(scope, providerName, modelName) {
|
|
4994
|
+
const page = asPage$1(scope);
|
|
4995
|
+
const judgeDialog = getLlmJudgeDialog(scope);
|
|
4996
|
+
await judgeDialog
|
|
4997
|
+
.getByRole('button', { name: EVALS_LABELS.judgeDialog.selectorAriaLabel })
|
|
4998
|
+
.click();
|
|
4999
|
+
const picker = getLlmPickerDialog(scope);
|
|
5000
|
+
await test$1.expect(picker).toBeVisible({ timeout: 10000 });
|
|
5001
|
+
await picker.getByPlaceholder(EVALS_LABELS.llmPickerDialog.searchPlaceholder).fill(providerName);
|
|
5002
|
+
await picker.getByRole('button', { name: new RegExp(escapeRegExp(providerName), 'i') }).click();
|
|
5003
|
+
// Model-selection modal is a separate stacked dialog outside the picker.
|
|
5004
|
+
const modelDialog = page
|
|
5005
|
+
.getByRole('dialog')
|
|
5006
|
+
.filter({ hasText: EVALS_LABELS.llmPickerDialog.modelDialogTitle });
|
|
5007
|
+
await test$1.expect(modelDialog).toBeVisible({ timeout: 10000 });
|
|
5008
|
+
await modelDialog.getByRole('button', { name: new RegExp(escapeRegExp(modelName), 'i') }).click();
|
|
5009
|
+
await test$1.expect(picker).toBeHidden({ timeout: 10000 });
|
|
5010
|
+
logger.info(`Selected judge LLM ${providerName}/${modelName}`);
|
|
5011
|
+
}
|
|
5012
|
+
/**
|
|
5013
|
+
* Fill and submit the LLM-judge dialog (assumes it is already open — see
|
|
5014
|
+
* `openNewReviewForRun` / `openNewReviewFromDetail`). Waits for the dialog
|
|
5015
|
+
* to close on success.
|
|
5016
|
+
*/
|
|
5017
|
+
async function submitLlmJudge(scope, opts) {
|
|
5018
|
+
const dialog = getLlmJudgeDialog(scope);
|
|
5019
|
+
await test$1.expect(dialog).toBeVisible({ timeout: 10000 });
|
|
5020
|
+
await dialog.getByLabel(EVALS_LABELS.judgeDialog.criteriaLabel).fill(opts.criteria);
|
|
5021
|
+
await dialog.getByLabel(EVALS_LABELS.judgeDialog.scoreNameLabel).fill(opts.scoreName);
|
|
5022
|
+
if (opts.maxConcurrency !== undefined) {
|
|
5023
|
+
await dialog
|
|
5024
|
+
.getByLabel(EVALS_LABELS.judgeDialog.maxConcurrencyLabel)
|
|
5025
|
+
.fill(String(opts.maxConcurrency));
|
|
5026
|
+
}
|
|
5027
|
+
await selectJudgeLlm(scope, opts.provider, opts.model);
|
|
5028
|
+
// Dialog-scoped on purpose: the dialog title is also "Evaluate".
|
|
5029
|
+
const submit = dialog.getByRole('button', { name: EVALS_LABELS.judgeDialog.submit, exact: true });
|
|
5030
|
+
await test$1.expect(submit).toBeEnabled({ timeout: 5000 });
|
|
5031
|
+
await submit.click();
|
|
5032
|
+
await test$1.expect(dialog).toBeHidden({ timeout: 15000 });
|
|
5033
|
+
logger.info(`Started LLM review "${opts.scoreName}"`);
|
|
5034
|
+
}
|
|
5035
|
+
/** Cancel out of the judge dialog and wait for it to close. */
|
|
5036
|
+
async function cancelLlmJudge(scope) {
|
|
5037
|
+
const dialog = getLlmJudgeDialog(scope);
|
|
5038
|
+
await dialog.getByRole('button', { name: EVALS_LABELS.judgeDialog.cancel }).click();
|
|
5039
|
+
await test$1.expect(dialog).toBeHidden({ timeout: 5000 });
|
|
5040
|
+
}
|
|
5041
|
+
// ── Evaluation detail dialog ───────────────────────────────────────────
|
|
5042
|
+
/** Locator for the evaluation-detail dialog. Its title is the run name (dynamic), hence the aria-label hook. */
|
|
5043
|
+
function getEvaluationDetailDialog(scope) {
|
|
5044
|
+
return dialogByName(scope, EVALS_LABELS.detailDialog.dialogName);
|
|
5045
|
+
}
|
|
5046
|
+
/** Click the detail dialog's refresh icon button (aria-label "Refresh"). */
|
|
5047
|
+
async function refreshEvaluationDetail(scope) {
|
|
5048
|
+
const dialog = getEvaluationDetailDialog(scope);
|
|
5049
|
+
const refresh = dialog.getByRole('button', {
|
|
5050
|
+
name: EVALS_LABELS.detailDialog.refreshAriaLabel,
|
|
5051
|
+
exact: true,
|
|
5052
|
+
});
|
|
5053
|
+
await refresh.click();
|
|
5054
|
+
await test$1.expect(refresh).toBeEnabled({ timeout: 15000 });
|
|
5055
|
+
}
|
|
5056
|
+
/** Open the LLM-judge dialog from the detail dialog's "New review" CTA. Returns the judge dialog. */
|
|
5057
|
+
async function openNewReviewFromDetail(scope) {
|
|
5058
|
+
const dialog = getEvaluationDetailDialog(scope);
|
|
5059
|
+
const cta = dialog.getByRole('button', {
|
|
5060
|
+
name: EVALS_LABELS.detailDialog.newReview,
|
|
5061
|
+
exact: true,
|
|
5062
|
+
});
|
|
5063
|
+
await test$1.expect(cta).toBeEnabled({ timeout: 10000 });
|
|
5064
|
+
await cta.click();
|
|
5065
|
+
const judgeDialog = getLlmJudgeDialog(scope);
|
|
5066
|
+
await test$1.expect(judgeDialog).toBeVisible({ timeout: 10000 });
|
|
5067
|
+
return judgeDialog;
|
|
5068
|
+
}
|
|
5069
|
+
/** Assert the detail dialog is still waiting for traces (auto-refreshing hint). */
|
|
5070
|
+
async function expectDetailWaitingForTraces(scope) {
|
|
5071
|
+
await test$1.expect(getEvaluationDetailDialog(scope).getByText(EVALS_LABELS.detailDialog.waitingHint)).toBeVisible({ timeout: 10000 });
|
|
5072
|
+
}
|
|
5073
|
+
/**
|
|
5074
|
+
* Locator for a trace's expand/collapse row inside the detail dialog,
|
|
5075
|
+
* matched by (part of) its question text.
|
|
5076
|
+
*/
|
|
5077
|
+
function getTraceRow(scope, questionText) {
|
|
5078
|
+
return getEvaluationDetailDialog(scope)
|
|
5079
|
+
.getByRole('button')
|
|
5080
|
+
.filter({ hasText: questionText })
|
|
5081
|
+
.first();
|
|
5082
|
+
}
|
|
5083
|
+
/** Expand a trace by its question text so its outputs and scores are visible. */
|
|
5084
|
+
async function expandTrace(scope, questionText) {
|
|
5085
|
+
await getTraceRow(scope, questionText).click();
|
|
5086
|
+
// The manual-score form only exists on the expanded trace.
|
|
5087
|
+
await test$1.expect(getEvaluationDetailDialog(scope).getByLabel(EVALS_LABELS.detailDialog.scoreNameLabel)).toBeVisible({ timeout: 10000 });
|
|
5088
|
+
}
|
|
5089
|
+
/**
|
|
5090
|
+
* Add a manual score to the currently expanded trace. `value` must be
|
|
5091
|
+
* between 0 and 1 (the UI rejects anything else with an error toast).
|
|
5092
|
+
*/
|
|
5093
|
+
async function addManualScore(scope, opts) {
|
|
5094
|
+
const dialog = getEvaluationDetailDialog(scope);
|
|
5095
|
+
await dialog.getByLabel(EVALS_LABELS.detailDialog.scoreNameLabel).fill(opts.name);
|
|
5096
|
+
await dialog.getByLabel(EVALS_LABELS.detailDialog.scoreValueLabel).fill(String(opts.value));
|
|
5097
|
+
if (opts.comment !== undefined) {
|
|
5098
|
+
await dialog.getByLabel(EVALS_LABELS.detailDialog.scoreCommentLabel).fill(opts.comment);
|
|
5099
|
+
}
|
|
5100
|
+
await dialog
|
|
5101
|
+
.getByRole('button', { name: EVALS_LABELS.detailDialog.addScore, exact: true })
|
|
5102
|
+
.click();
|
|
5103
|
+
await expectTraceScore(scope, opts.name);
|
|
5104
|
+
logger.info(`Added manual score: ${opts.name}=${opts.value}`);
|
|
5105
|
+
}
|
|
5106
|
+
/** Assert a score chip with the given name is visible on the expanded trace. */
|
|
5107
|
+
async function expectTraceScore(scope, scoreName) {
|
|
5108
|
+
await test$1.expect(getEvaluationDetailDialog(scope).getByText(scoreName, { exact: true }).first()).toBeVisible({ timeout: 15000 });
|
|
5109
|
+
}
|
|
5110
|
+
/**
|
|
5111
|
+
* Remove a score chip from the expanded trace. The chip's trash button
|
|
5112
|
+
* carries `aria-label="Remove score"`; we scope through the chip matched by
|
|
5113
|
+
* score name so multiple chips can't cross-match.
|
|
5114
|
+
*/
|
|
5115
|
+
async function removeTraceScore(scope, scoreName) {
|
|
5116
|
+
const dialog = getEvaluationDetailDialog(scope);
|
|
5117
|
+
const chip = dialog
|
|
5118
|
+
.locator('div')
|
|
5119
|
+
.filter({ has: asPage$1(scope).getByText(scoreName, { exact: true }) })
|
|
5120
|
+
.filter({
|
|
5121
|
+
has: asPage$1(scope).getByRole('button', {
|
|
5122
|
+
name: EVALS_LABELS.detailDialog.removeScoreAriaLabel,
|
|
5123
|
+
}),
|
|
5124
|
+
})
|
|
5125
|
+
.last();
|
|
5126
|
+
await chip
|
|
5127
|
+
.getByRole('button', { name: EVALS_LABELS.detailDialog.removeScoreAriaLabel })
|
|
5128
|
+
.first()
|
|
5129
|
+
.click();
|
|
5130
|
+
}
|
|
5131
|
+
/**
|
|
5132
|
+
* Locator for a review row's expand toggle in the detail dialog's Reviews
|
|
5133
|
+
* list. All toggles share the "Toggle review details" aria-label, so the
|
|
5134
|
+
* row is disambiguated by the score name it displays.
|
|
5135
|
+
*/
|
|
5136
|
+
function getReviewRow(scope, scoreName) {
|
|
5137
|
+
return getEvaluationDetailDialog(scope)
|
|
5138
|
+
.getByRole('button', { name: EVALS_LABELS.detailDialog.reviewDetailsAriaLabel })
|
|
5139
|
+
.filter({ hasText: scoreName })
|
|
5140
|
+
.first();
|
|
5141
|
+
}
|
|
5142
|
+
/** Assert a review with the given score name appears in the Reviews list. */
|
|
5143
|
+
async function expectReviewInList(scope, scoreName) {
|
|
5144
|
+
await test$1.expect(getReviewRow(scope, scoreName)).toBeVisible({ timeout: 15000 });
|
|
5145
|
+
}
|
|
5146
|
+
/** Assert a review row's status pill (Queued / Running / Complete / Failed). */
|
|
5147
|
+
async function expectReviewStatus(scope, scoreName, status) {
|
|
5148
|
+
await test$1.expect(getReviewRow(scope, scoreName).getByText(EVALS_LABELS.detailDialog.reviewStatus[status], {
|
|
5149
|
+
exact: true,
|
|
5150
|
+
})).toBeVisible({ timeout: 15000 });
|
|
5151
|
+
}
|
|
5152
|
+
/** Expand a review row to show its criteria and produced scores. */
|
|
5153
|
+
async function expandReview(scope, scoreName) {
|
|
5154
|
+
const row = getReviewRow(scope, scoreName);
|
|
5155
|
+
await row.click();
|
|
5156
|
+
await test$1.expect(row).toHaveAttribute('aria-expanded', 'true', { timeout: 5000 });
|
|
5157
|
+
}
|
|
5158
|
+
/** Close the detail dialog via Escape and wait for it to be gone. */
|
|
5159
|
+
async function closeEvaluationDetailDialog(scope) {
|
|
5160
|
+
const dialog = getEvaluationDetailDialog(scope);
|
|
5161
|
+
await asPage$1(scope).keyboard.press('Escape');
|
|
5162
|
+
await test$1.expect(dialog).toBeHidden({ timeout: 10000 });
|
|
5163
|
+
}
|
|
5164
|
+
// ── Manage benchmarks dialog (embedded tenant Benchmarks) ──────────────
|
|
5165
|
+
/** Locator for the "Manage benchmarks" dialog. Scoped by aria-label — its title collides with the toolbar button that opens it. */
|
|
5166
|
+
function getManageBenchmarksDialog(scope) {
|
|
5167
|
+
return dialogByName(scope, EVALS_LABELS.manageBenchmarksDialog.dialogName);
|
|
5168
|
+
}
|
|
5169
|
+
/** Open the Manage benchmarks dialog from the toolbar and wait for its table UI. Returns the scoped dialog. */
|
|
5170
|
+
async function openManageBenchmarksDialog(scope) {
|
|
5171
|
+
await getManageBenchmarksButton(scope).click();
|
|
5172
|
+
const dialog = getManageBenchmarksDialog(scope);
|
|
5173
|
+
await test$1.expect(dialog.getByRole('button', { name: EVALS_LABELS.manageBenchmarksDialog.newBenchmark })).toBeVisible({ timeout: 10000 });
|
|
5174
|
+
return dialog;
|
|
5175
|
+
}
|
|
5176
|
+
/** Type into the benchmarks search input (aria-label "Search benchmarks") inside the manage dialog. */
|
|
5177
|
+
async function searchBenchmarks(scope, query) {
|
|
5178
|
+
const input = getManageBenchmarksDialog(scope).getByLabel(EVALS_LABELS.manageBenchmarksDialog.searchAriaLabel);
|
|
5179
|
+
await input.fill(query);
|
|
5180
|
+
await test$1.expect(input).toHaveValue(query);
|
|
5181
|
+
}
|
|
5182
|
+
/** Assert a benchmark appears in the manage dialog's table. */
|
|
5183
|
+
async function expectBenchmarkListed(scope, benchmarkName) {
|
|
5184
|
+
await test$1.expect(getManageBenchmarksDialog(scope).getByText(benchmarkName, { exact: true }).first()).toBeVisible({ timeout: 15000 });
|
|
5185
|
+
}
|
|
5186
|
+
/** Locator for the "New Benchmark" dialog. Scoped by aria-label — its title collides with the button that opens it. */
|
|
5187
|
+
function getCreateBenchmarkDialog(scope) {
|
|
5188
|
+
return dialogByName(scope, EVALS_LABELS.createBenchmarkDialog.dialogName);
|
|
5189
|
+
}
|
|
5190
|
+
/**
|
|
5191
|
+
* Create a benchmark from inside the manage dialog: open "New Benchmark",
|
|
5192
|
+
* fill the form, submit, and wait for both the dialog to close and the new
|
|
5193
|
+
* row to appear.
|
|
5194
|
+
*/
|
|
5195
|
+
async function createBenchmark(scope, opts) {
|
|
5196
|
+
const manageDialog = getManageBenchmarksDialog(scope);
|
|
5197
|
+
await manageDialog
|
|
5198
|
+
.getByRole('button', { name: EVALS_LABELS.manageBenchmarksDialog.newBenchmark })
|
|
5199
|
+
.click();
|
|
5200
|
+
const dialog = getCreateBenchmarkDialog(scope);
|
|
5201
|
+
await dialog.getByLabel(EVALS_LABELS.createBenchmarkDialog.nameLabel).fill(opts.name);
|
|
5202
|
+
if (opts.description !== undefined) {
|
|
5203
|
+
await dialog
|
|
5204
|
+
.getByLabel(EVALS_LABELS.createBenchmarkDialog.descriptionLabel)
|
|
5205
|
+
.fill(opts.description);
|
|
5206
|
+
}
|
|
5207
|
+
const submit = dialog.getByRole('button', {
|
|
5208
|
+
name: EVALS_LABELS.createBenchmarkDialog.create,
|
|
5209
|
+
exact: true,
|
|
5210
|
+
});
|
|
5211
|
+
await test$1.expect(submit).toBeEnabled({ timeout: 5000 });
|
|
5212
|
+
await submit.click();
|
|
5213
|
+
await test$1.expect(dialog).toBeHidden({ timeout: 15000 });
|
|
5214
|
+
await expectBenchmarkListed(scope, opts.name);
|
|
5215
|
+
logger.info(`Created benchmark: ${opts.name}`);
|
|
5216
|
+
}
|
|
5217
|
+
/** Locator for a benchmark's items dialog (Q&A list). Its title is the benchmark name (dynamic), hence the aria-label hook. */
|
|
5218
|
+
function getBenchmarkItemsDialog(scope) {
|
|
5219
|
+
return dialogByName(scope, EVALS_LABELS.benchmarkItemsDialog.dialogName);
|
|
5220
|
+
}
|
|
5221
|
+
/**
|
|
5222
|
+
* Open a benchmark's Q&A items dialog from its row's eye button
|
|
5223
|
+
* (`aria-label="View items in <name>"`). Returns the scoped items dialog.
|
|
5224
|
+
*/
|
|
5225
|
+
async function openBenchmarkItems(scope, benchmarkName) {
|
|
5226
|
+
await getManageBenchmarksDialog(scope)
|
|
5227
|
+
.getByRole('button', { name: `View items in ${benchmarkName}`, exact: true })
|
|
5228
|
+
.click();
|
|
5229
|
+
const dialog = getBenchmarkItemsDialog(scope);
|
|
5230
|
+
await test$1.expect(dialog.getByRole('button', { name: EVALS_LABELS.benchmarkItemsDialog.addItems })).toBeVisible({ timeout: 10000 });
|
|
5231
|
+
return dialog;
|
|
5232
|
+
}
|
|
5233
|
+
/** Assert a Q&A item (matched by its question text) is listed in the items dialog. */
|
|
5234
|
+
async function expectQaItemListed(scope, questionText) {
|
|
5235
|
+
await test$1.expect(getBenchmarkItemsDialog(scope).getByText(questionText, { exact: false }).first()).toBeVisible({ timeout: 15000 });
|
|
5236
|
+
}
|
|
5237
|
+
/** Locator for the "Add Q&A" dialog (Manual / CSV Upload sub-tabs). */
|
|
5238
|
+
function getAddItemsDialog(scope) {
|
|
5239
|
+
return dialogByName(scope, EVALS_LABELS.addItemsDialog.dialogName);
|
|
5240
|
+
}
|
|
5241
|
+
/** Open the "Add Q&A" dialog from the items dialog. Returns the scoped add dialog. */
|
|
5242
|
+
async function openAddItemsDialog(scope) {
|
|
5243
|
+
await getBenchmarkItemsDialog(scope)
|
|
5244
|
+
.getByRole('button', { name: EVALS_LABELS.benchmarkItemsDialog.addItems })
|
|
5245
|
+
.click();
|
|
5246
|
+
const dialog = getAddItemsDialog(scope);
|
|
5247
|
+
// Both sub-tab triggers are unique to this dialog — a reliable ready signal.
|
|
5248
|
+
await test$1.expect(dialog.getByRole('tab', { name: EVALS_LABELS.addItemsDialog.manualTab, exact: true })).toBeVisible({ timeout: 10000 });
|
|
5249
|
+
return dialog;
|
|
5250
|
+
}
|
|
5251
|
+
/**
|
|
5252
|
+
* Switch to a sub-tab INSIDE the Add Q&A dialog. The tab query must stay
|
|
5253
|
+
* dialog-scoped: the edit-mentor modal behind it has its own `role="tab"`
|
|
5254
|
+
* strip, and an unscoped `getByRole('tab')` can cross-match. Returns the
|
|
5255
|
+
* active tabpanel so callers interact only with that sub-tab's controls
|
|
5256
|
+
* (each panel has its own footer with its own Cancel/submit buttons).
|
|
5257
|
+
*/
|
|
5258
|
+
async function switchToAddItemsSubTab(scope, subTab) {
|
|
5259
|
+
const dialog = getAddItemsDialog(scope);
|
|
5260
|
+
const tabName = subTab === 'manual'
|
|
5261
|
+
? EVALS_LABELS.addItemsDialog.manualTab
|
|
5262
|
+
: EVALS_LABELS.addItemsDialog.csvTab;
|
|
5263
|
+
const tab = dialog.getByRole('tab', { name: tabName, exact: true });
|
|
5264
|
+
await tab.click();
|
|
5265
|
+
await test$1.expect(tab).toHaveAttribute('data-state', 'active', { timeout: 5000 });
|
|
5266
|
+
const panel = dialog.getByRole('tabpanel');
|
|
5267
|
+
await test$1.expect(panel).toBeVisible({ timeout: 5000 });
|
|
5268
|
+
return panel;
|
|
5269
|
+
}
|
|
5270
|
+
/**
|
|
5271
|
+
* Add Q&A pairs via the Manual sub-tab. Fills one row per pair (clicking
|
|
5272
|
+
* "Add row" as needed), submits, and waits for the dialog to close. Row
|
|
5273
|
+
* inputs are matched by label WITHIN each row container so the Question /
|
|
5274
|
+
* Answer labels of sibling rows can't collide.
|
|
5275
|
+
*/
|
|
5276
|
+
async function addQaPairsManually(scope, pairs) {
|
|
5277
|
+
const dialog = getAddItemsDialog(scope);
|
|
5278
|
+
const panel = await switchToAddItemsSubTab(scope, 'manual');
|
|
5279
|
+
for (let i = 0; i < pairs.length; i++) {
|
|
5280
|
+
if (i > 0) {
|
|
5281
|
+
await panel
|
|
5282
|
+
.getByRole('button', { name: EVALS_LABELS.addItemsDialog.addRow, exact: true })
|
|
5283
|
+
.click();
|
|
5284
|
+
}
|
|
5285
|
+
const question = panel.getByLabel(EVALS_LABELS.addItemsDialog.questionLabel).nth(i);
|
|
5286
|
+
await test$1.expect(question).toBeVisible({ timeout: 5000 });
|
|
5287
|
+
await question.fill(pairs[i].question);
|
|
5288
|
+
if (pairs[i].answer !== undefined) {
|
|
5289
|
+
await panel
|
|
5290
|
+
.getByLabel(EVALS_LABELS.addItemsDialog.answerLabel)
|
|
5291
|
+
.nth(i)
|
|
5292
|
+
.fill(pairs[i].answer);
|
|
5293
|
+
}
|
|
5294
|
+
}
|
|
5295
|
+
await panel.getByRole('button', { name: EVALS_LABELS.addItemsDialog.add, exact: true }).click();
|
|
5296
|
+
await test$1.expect(dialog).toBeHidden({ timeout: 15000 });
|
|
5297
|
+
logger.info(`Added ${pairs.length} Q&A pair(s) manually`);
|
|
5298
|
+
}
|
|
5299
|
+
/**
|
|
5300
|
+
* Upload Q&A pairs via the CSV Upload sub-tab. `csvPath` is a path on the
|
|
5301
|
+
* test machine; the file needs `input` (required) and `expected_output`
|
|
5302
|
+
* (optional) columns. Waits for the dialog to close on success.
|
|
5303
|
+
*/
|
|
5304
|
+
async function uploadQaCsv(scope, csvPath) {
|
|
5305
|
+
const dialog = getAddItemsDialog(scope);
|
|
5306
|
+
const panel = await switchToAddItemsSubTab(scope, 'csv');
|
|
5307
|
+
await panel.getByLabel(EVALS_LABELS.addItemsDialog.csvFileLabel).setInputFiles(csvPath);
|
|
5308
|
+
await panel
|
|
5309
|
+
.getByRole('button', { name: EVALS_LABELS.addItemsDialog.upload, exact: true })
|
|
5310
|
+
.click();
|
|
5311
|
+
await test$1.expect(dialog).toBeHidden({ timeout: 30000 });
|
|
5312
|
+
logger.info(`Uploaded Q&A CSV: ${csvPath}`);
|
|
5313
|
+
}
|
|
5314
|
+
/** Locator for the Q&A delete-confirm dialog. */
|
|
5315
|
+
function getDeleteQaItemDialog(scope) {
|
|
5316
|
+
return dialogByName(scope, EVALS_LABELS.deleteItemDialog.dialogName);
|
|
5317
|
+
}
|
|
5318
|
+
/**
|
|
5319
|
+
* Delete a Q&A item by its question text: click the row's trash button
|
|
5320
|
+
* (`aria-label="Delete Q&A"`) and confirm. The confirm "Delete" button must
|
|
5321
|
+
* stay scoped to the confirm dialog — the items dialog's rows keep their
|
|
5322
|
+
* own delete buttons mounted behind it.
|
|
5323
|
+
*/
|
|
5324
|
+
async function deleteQaItem(scope, questionText) {
|
|
5325
|
+
const itemsDialog = getBenchmarkItemsDialog(scope);
|
|
5326
|
+
const row = itemsDialog.getByRole('row').filter({ hasText: questionText }).first();
|
|
5327
|
+
await row
|
|
5328
|
+
.getByRole('button', { name: EVALS_LABELS.benchmarkItemsDialog.deleteItemAriaLabel })
|
|
5329
|
+
.click();
|
|
5330
|
+
const confirmDialog = getDeleteQaItemDialog(scope);
|
|
5331
|
+
const confirm = confirmDialog.getByRole('button', {
|
|
5332
|
+
name: EVALS_LABELS.deleteItemDialog.delete,
|
|
5333
|
+
exact: true,
|
|
5334
|
+
});
|
|
5335
|
+
await test$1.expect(confirm).toBeVisible({ timeout: 5000 });
|
|
5336
|
+
await confirm.click();
|
|
5337
|
+
await test$1.expect(confirmDialog).toBeHidden({ timeout: 15000 });
|
|
5338
|
+
logger.info(`Deleted Q&A item: ${questionText}`);
|
|
5339
|
+
}
|
|
5340
|
+
/** Close the benchmark items dialog via Escape and wait for it to be gone. */
|
|
5341
|
+
async function closeBenchmarkItemsDialog(scope) {
|
|
5342
|
+
const dialog = getBenchmarkItemsDialog(scope);
|
|
5343
|
+
await asPage$1(scope).keyboard.press('Escape');
|
|
5344
|
+
await test$1.expect(dialog).toBeHidden({ timeout: 10000 });
|
|
5345
|
+
}
|
|
5346
|
+
/** Close the Manage benchmarks dialog via Escape and wait for it to be gone. */
|
|
5347
|
+
async function closeManageBenchmarksDialog(scope) {
|
|
5348
|
+
const dialog = getManageBenchmarksDialog(scope);
|
|
5349
|
+
await asPage$1(scope).keyboard.press('Escape');
|
|
5350
|
+
await test$1.expect(dialog).toBeHidden({ timeout: 10000 });
|
|
5351
|
+
}
|
|
5352
|
+
|
|
4555
5353
|
/**
|
|
4556
5354
|
* LTI tab helpers — Playwright bindings for the `AgentLtiTab` component from
|
|
4557
5355
|
* `@iblai/web-containers`.
|
|
@@ -5214,6 +6012,7 @@ Object.defineProperty(exports, "expect", {
|
|
|
5214
6012
|
exports.AuthFlowBuilder = AuthFlowBuilder;
|
|
5215
6013
|
exports.CHAT_PRIVACY_LABELS = CHAT_PRIVACY_LABELS;
|
|
5216
6014
|
exports.CustomReporter = CustomReporter;
|
|
6015
|
+
exports.EVALS_LABELS = EVALS_LABELS;
|
|
5217
6016
|
exports.LTI_LABELS = LTI_LABELS;
|
|
5218
6017
|
exports.LTI_TEST_IDS = LTI_TEST_IDS;
|
|
5219
6018
|
exports.MailsacClient = MailsacClient;
|
|
@@ -5221,7 +6020,9 @@ exports.PRIVACY_LABELS = PRIVACY_LABELS;
|
|
|
5221
6020
|
exports.SCREENSHARE_LABELS = SCREENSHARE_LABELS;
|
|
5222
6021
|
exports.TASKS_LABELS = TASKS_LABELS;
|
|
5223
6022
|
exports.VOICE_LABELS = VOICE_LABELS;
|
|
6023
|
+
exports.addManualScore = addManualScore;
|
|
5224
6024
|
exports.addMemory = addMemory;
|
|
6025
|
+
exports.addQaPairsManually = addQaPairsManually;
|
|
5225
6026
|
exports.archiveFirstMemory = archiveFirstMemory;
|
|
5226
6027
|
exports.archiveMemoryByContent = archiveMemoryByContent;
|
|
5227
6028
|
exports.billingAutoRechargeSection = billingAutoRechargeSection;
|
|
@@ -5229,13 +6030,17 @@ exports.billingCreditsSection = billingCreditsSection;
|
|
|
5229
6030
|
exports.billingPlanSection = billingPlanSection;
|
|
5230
6031
|
exports.buildReportUrl = buildReportUrl;
|
|
5231
6032
|
exports.canChatWithEmbedMentor = canChatWithEmbedMentor;
|
|
6033
|
+
exports.cancelDeleteEvaluation = cancelDeleteEvaluation;
|
|
5232
6034
|
exports.cancelDeleteInstance = cancelDeleteInstance;
|
|
5233
6035
|
exports.cancelDeleteSkill = cancelDeleteSkill;
|
|
5234
6036
|
exports.cancelDisconnectInstance = cancelDisconnectInstance;
|
|
5235
6037
|
exports.cancelEnableChatPrivacyMidSession = cancelEnableChatPrivacyMidSession;
|
|
5236
6038
|
exports.cancelKeyDelete = cancelKeyDelete;
|
|
6039
|
+
exports.cancelLlmJudge = cancelLlmJudge;
|
|
5237
6040
|
exports.cancelNewInstanceDialog = cancelNewInstanceDialog;
|
|
6041
|
+
exports.cancelStartEvaluation = cancelStartEvaluation;
|
|
5238
6042
|
exports.checkAdminStatus = checkAdminStatus;
|
|
6043
|
+
exports.checkRunStatus = checkRunStatus;
|
|
5239
6044
|
exports.clearDateRangeFilter = clearDateRangeFilter;
|
|
5240
6045
|
exports.clearInstanceSearch = clearInstanceSearch;
|
|
5241
6046
|
exports.clickBackHome = clickBackHome;
|
|
@@ -5246,14 +6051,18 @@ exports.clickBillingUpgrade = clickBillingUpgrade;
|
|
|
5246
6051
|
exports.clickChatPrivacyToggle = clickChatPrivacyToggle;
|
|
5247
6052
|
exports.clickDownloadAgain = clickDownloadAgain;
|
|
5248
6053
|
exports.clickManualDownloadLink = clickManualDownloadLink;
|
|
6054
|
+
exports.closeBenchmarkItemsDialog = closeBenchmarkItemsDialog;
|
|
5249
6055
|
exports.closeCreditBalanceDropdown = closeCreditBalanceDropdown;
|
|
6056
|
+
exports.closeEvaluationDetailDialog = closeEvaluationDetailDialog;
|
|
5250
6057
|
exports.closeKeyDetail = closeKeyDetail;
|
|
6058
|
+
exports.closeManageBenchmarksDialog = closeManageBenchmarksDialog;
|
|
5251
6059
|
exports.closeWithEsc = closeWithEsc;
|
|
5252
6060
|
exports.confirmEnableChatPrivacyMidSession = confirmEnableChatPrivacyMidSession;
|
|
5253
6061
|
exports.confirmKeyDelete = confirmKeyDelete;
|
|
5254
6062
|
exports.connectToInstance = connectToInstance;
|
|
5255
6063
|
exports.copyEndpoint = copyEndpoint;
|
|
5256
6064
|
exports.createAuthSetup = createAuthSetup;
|
|
6065
|
+
exports.createBenchmark = createBenchmark;
|
|
5257
6066
|
exports.createEnvConfig = createEnvConfig;
|
|
5258
6067
|
exports.createInstance = createInstance;
|
|
5259
6068
|
exports.createKey = createKey;
|
|
@@ -5264,10 +6073,12 @@ exports.createTool = createTool;
|
|
|
5264
6073
|
exports.creditBalancePanel = creditBalancePanel;
|
|
5265
6074
|
exports.creditBalancePlanBadge = creditBalancePlanBadge;
|
|
5266
6075
|
exports.creditBalanceTrigger = creditBalanceTrigger;
|
|
6076
|
+
exports.deleteEvaluation = deleteEvaluation;
|
|
5267
6077
|
exports.deleteFirstMemory = deleteFirstMemory;
|
|
5268
6078
|
exports.deleteInstance = deleteInstance;
|
|
5269
6079
|
exports.deleteKey = deleteKey;
|
|
5270
6080
|
exports.deleteMemoryByContent = deleteMemoryByContent;
|
|
6081
|
+
exports.deleteQaItem = deleteQaItem;
|
|
5271
6082
|
exports.deleteSkill = deleteSkill;
|
|
5272
6083
|
exports.deleteTask = deleteTask;
|
|
5273
6084
|
exports.disableSkill = disableSkill;
|
|
@@ -5278,7 +6089,10 @@ exports.editLink = editLink;
|
|
|
5278
6089
|
exports.editSkill = editSkill;
|
|
5279
6090
|
exports.editTool = editTool;
|
|
5280
6091
|
exports.enableSkill = enableSkill;
|
|
6092
|
+
exports.expandReview = expandReview;
|
|
6093
|
+
exports.expandTrace = expandTrace;
|
|
5281
6094
|
exports.expectAllEndpointsVisible = expectAllEndpointsVisible;
|
|
6095
|
+
exports.expectBenchmarkListed = expectBenchmarkListed;
|
|
5282
6096
|
exports.expectBillingAutoRechargeSection = expectBillingAutoRechargeSection;
|
|
5283
6097
|
exports.expectBillingCreditsSection = expectBillingCreditsSection;
|
|
5284
6098
|
exports.expectBillingPlanSection = expectBillingPlanSection;
|
|
@@ -5299,6 +6113,7 @@ exports.expectCreditBalancePanelForFreePlan = expectCreditBalancePanelForFreePla
|
|
|
5299
6113
|
exports.expectCreditBalancePanelForPremiumPlan = expectCreditBalancePanelForPremiumPlan;
|
|
5300
6114
|
exports.expectCreditBalancePanelForTrialPlan = expectCreditBalancePanelForTrialPlan;
|
|
5301
6115
|
exports.expectCreditBalanceVisibilityForTenant = expectCreditBalanceVisibilityForTenant;
|
|
6116
|
+
exports.expectDetailWaitingForTraces = expectDetailWaitingForTraces;
|
|
5302
6117
|
exports.expectEndpointUrl = expectEndpointUrl;
|
|
5303
6118
|
exports.expectEntitySelected = expectEntitySelected;
|
|
5304
6119
|
exports.expectFailedTasks = expectFailedTasks;
|
|
@@ -5316,14 +6131,23 @@ exports.expectLtiHeader = expectLtiHeader;
|
|
|
5316
6131
|
exports.expectMentorVoiceTriggerShows = expectMentorVoiceTriggerShows;
|
|
5317
6132
|
exports.expectNoAccessibilityViolations = expectNoAccessibilityViolations;
|
|
5318
6133
|
exports.expectNoAccessibilityViolationsOnDialogs = expectNoAccessibilityViolationsOnDialogs;
|
|
6134
|
+
exports.expectNoBenchmarksNotice = expectNoBenchmarksNotice;
|
|
5319
6135
|
exports.expectNoLogsForSelectedTask = expectNoLogsForSelectedTask;
|
|
5320
6136
|
exports.expectOutputFilterEnabled = expectOutputFilterEnabled;
|
|
5321
6137
|
exports.expectPrivacyFieldsHidden = expectPrivacyFieldsHidden;
|
|
5322
6138
|
exports.expectPrivacyFieldsVisible = expectPrivacyFieldsVisible;
|
|
5323
6139
|
exports.expectPrivateModeSelected = expectPrivateModeSelected;
|
|
5324
6140
|
exports.expectPrivateModeTabReady = expectPrivateModeTabReady;
|
|
6141
|
+
exports.expectQaItemListed = expectQaItemListed;
|
|
6142
|
+
exports.expectReviewInList = expectReviewInList;
|
|
6143
|
+
exports.expectReviewStatus = expectReviewStatus;
|
|
6144
|
+
exports.expectRunInTable = expectRunInTable;
|
|
6145
|
+
exports.expectRunNotInTable = expectRunNotInTable;
|
|
6146
|
+
exports.expectRunStatus = expectRunStatus;
|
|
6147
|
+
exports.expectRunsTableEmpty = expectRunsTableEmpty;
|
|
5325
6148
|
exports.expectScheduleStartTimeInPastError = expectScheduleStartTimeInPastError;
|
|
5326
6149
|
exports.expectScreenShareDisabledHint = expectScreenShareDisabledHint;
|
|
6150
|
+
exports.expectSelectedBenchmark = expectSelectedBenchmark;
|
|
5327
6151
|
exports.expectSttSelectDisabled = expectSttSelectDisabled;
|
|
5328
6152
|
exports.expectTaskInList = expectTaskInList;
|
|
5329
6153
|
exports.expectTaskNotInList = expectTaskNotInList;
|
|
@@ -5335,9 +6159,11 @@ exports.expectToolInList = expectToolInList;
|
|
|
5335
6159
|
exports.expectToolNotInList = expectToolNotInList;
|
|
5336
6160
|
exports.expectToolsEmpty = expectToolsEmpty;
|
|
5337
6161
|
exports.expectTotalTasks = expectTotalTasks;
|
|
6162
|
+
exports.expectTraceScore = expectTraceScore;
|
|
5338
6163
|
exports.expectTtsSelectDisabled = expectTtsSelectDisabled;
|
|
5339
6164
|
exports.expectVoiceProviderSelected = expectVoiceProviderSelected;
|
|
5340
6165
|
exports.expectVoiceVisible = expectVoiceVisible;
|
|
6166
|
+
exports.exportRunCsv = exportRunCsv;
|
|
5341
6167
|
exports.fillLinkName = fillLinkName;
|
|
5342
6168
|
exports.fillToolForm = fillToolForm;
|
|
5343
6169
|
exports.filterByAction = filterByAction;
|
|
@@ -5347,14 +6173,19 @@ exports.filterByActorAndVerify = filterByActorAndVerify;
|
|
|
5347
6173
|
exports.filterByDateRange = filterByDateRange;
|
|
5348
6174
|
exports.generateBrowserSetupProjects = generateBrowserSetupProjects;
|
|
5349
6175
|
exports.generateProjectConfig = generateProjectConfig;
|
|
6176
|
+
exports.getAddItemsDialog = getAddItemsDialog;
|
|
5350
6177
|
exports.getAuditLogRowCount = getAuditLogRowCount;
|
|
5351
6178
|
exports.getAvailableActors = getAvailableActors;
|
|
6179
|
+
exports.getBenchmarkCombobox = getBenchmarkCombobox;
|
|
6180
|
+
exports.getBenchmarkComboboxDropdown = getBenchmarkComboboxDropdown;
|
|
6181
|
+
exports.getBenchmarkItemsDialog = getBenchmarkItemsDialog;
|
|
5352
6182
|
exports.getBillingAutoRechargeStatus = getBillingAutoRechargeStatus;
|
|
5353
6183
|
exports.getBillingPlanLabel = getBillingPlanLabel;
|
|
5354
6184
|
exports.getBrowserKey = getBrowserKey;
|
|
5355
6185
|
exports.getCallConfigForm = getCallConfigForm;
|
|
5356
6186
|
exports.getChatPrivacyConfirmDialog = getChatPrivacyConfirmDialog;
|
|
5357
6187
|
exports.getChatPrivacyToggle = getChatPrivacyToggle;
|
|
6188
|
+
exports.getCreateBenchmarkDialog = getCreateBenchmarkDialog;
|
|
5358
6189
|
exports.getCreateKeyButton = getCreateKeyButton;
|
|
5359
6190
|
exports.getCreateLinkButton = getCreateLinkButton;
|
|
5360
6191
|
exports.getCreateToolButton = getCreateToolButton;
|
|
@@ -5362,10 +6193,13 @@ exports.getCreditBalancePlanLabel = getCreditBalancePlanLabel;
|
|
|
5362
6193
|
exports.getCreditBalanceRemaining = getCreditBalanceRemaining;
|
|
5363
6194
|
exports.getCurrentModel = getCurrentModel;
|
|
5364
6195
|
exports.getCurrentTenantShowPaywall = getCurrentTenantShowPaywall;
|
|
6196
|
+
exports.getDeleteEvaluationDialog = getDeleteEvaluationDialog;
|
|
6197
|
+
exports.getDeleteQaItemDialog = getDeleteQaItemDialog;
|
|
5365
6198
|
exports.getEndpoint = getEndpoint;
|
|
5366
6199
|
exports.getEndpointCopyButton = getEndpointCopyButton;
|
|
5367
6200
|
exports.getEndpointUrl = getEndpointUrl;
|
|
5368
6201
|
exports.getEntityChip = getEntityChip;
|
|
6202
|
+
exports.getEvaluationDetailDialog = getEvaluationDetailDialog;
|
|
5369
6203
|
exports.getInstanceHealthLabel = getInstanceHealthLabel;
|
|
5370
6204
|
exports.getInstanceRowCount = getInstanceRowCount;
|
|
5371
6205
|
exports.getInstanceStatusLabel = getInstanceStatusLabel;
|
|
@@ -5387,15 +6221,23 @@ exports.getLinkNameInput = getLinkNameInput;
|
|
|
5387
6221
|
exports.getLinkRow = getLinkRow;
|
|
5388
6222
|
exports.getLinksEmptyState = getLinksEmptyState;
|
|
5389
6223
|
exports.getLinksSection = getLinksSection;
|
|
6224
|
+
exports.getLlmJudgeDialog = getLlmJudgeDialog;
|
|
6225
|
+
exports.getLlmPickerDialog = getLlmPickerDialog;
|
|
5390
6226
|
exports.getLtiSubTab = getLtiSubTab;
|
|
6227
|
+
exports.getManageBenchmarksButton = getManageBenchmarksButton;
|
|
6228
|
+
exports.getManageBenchmarksDialog = getManageBenchmarksDialog;
|
|
5391
6229
|
exports.getMemoryCount = getMemoryCount;
|
|
5392
6230
|
exports.getMentorIdFromUrl = getMentorIdFromUrl;
|
|
6231
|
+
exports.getNewEvaluationButton = getNewEvaluationButton;
|
|
5393
6232
|
exports.getOutputFilterSwitch = getOutputFilterSwitch;
|
|
5394
6233
|
exports.getPaginationInfo = getPaginationInfo;
|
|
5395
6234
|
exports.getPrivateModeCard = getPrivateModeCard;
|
|
6235
|
+
exports.getReviewRow = getReviewRow;
|
|
6236
|
+
exports.getRunRow = getRunRow;
|
|
5396
6237
|
exports.getScheduleTaskButton = getScheduleTaskButton;
|
|
5397
6238
|
exports.getSearchInput = getSearchInput;
|
|
5398
6239
|
exports.getSkillRowCount = getSkillRowCount;
|
|
6240
|
+
exports.getStartEvaluationDialog = getStartEvaluationDialog;
|
|
5399
6241
|
exports.getTaskRow = getTaskRow;
|
|
5400
6242
|
exports.getTenantChatPrivacyRow = getTenantChatPrivacyRow;
|
|
5401
6243
|
exports.getTenantChatPrivacySwitch = getTenantChatPrivacySwitch;
|
|
@@ -5405,6 +6247,7 @@ exports.getToolModal = getToolModal;
|
|
|
5405
6247
|
exports.getToolRow = getToolRow;
|
|
5406
6248
|
exports.getToolsEmptyState = getToolsEmptyState;
|
|
5407
6249
|
exports.getToolsSection = getToolsSection;
|
|
6250
|
+
exports.getTraceRow = getTraceRow;
|
|
5408
6251
|
exports.getVoiceProviderCard = getVoiceProviderCard;
|
|
5409
6252
|
exports.getVoiceRow = getVoiceRow;
|
|
5410
6253
|
exports.goToFirstPage = goToFirstPage;
|
|
@@ -5413,6 +6256,7 @@ exports.goToNextPage = goToNextPage;
|
|
|
5413
6256
|
exports.goToPage = goToPage;
|
|
5414
6257
|
exports.goToPreviousPage = goToPreviousPage;
|
|
5415
6258
|
exports.inviteUserTest = inviteUserTest;
|
|
6259
|
+
exports.isEvaluationTabVisible = isEvaluationTabVisible;
|
|
5416
6260
|
exports.isFirefox = isFirefox;
|
|
5417
6261
|
exports.isJSON = isJSON;
|
|
5418
6262
|
exports.isLtiTabVisible = isLtiTabVisible;
|
|
@@ -5434,8 +6278,10 @@ exports.navigateToAuditLog = navigateToAuditLog;
|
|
|
5434
6278
|
exports.navigateToAuditLogAndWaitForData = navigateToAuditLogAndWaitForData;
|
|
5435
6279
|
exports.navigateToDataReports = navigateToDataReports;
|
|
5436
6280
|
exports.navigateToReportDownload = navigateToReportDownload;
|
|
6281
|
+
exports.openAddItemsDialog = openAddItemsDialog;
|
|
5437
6282
|
exports.openAddMemoryDialog = openAddMemoryDialog;
|
|
5438
6283
|
exports.openAgentPromptEditModal = openAgentPromptEditModal;
|
|
6284
|
+
exports.openBenchmarkItems = openBenchmarkItems;
|
|
5439
6285
|
exports.openCallConfigVoicePicker = openCallConfigVoicePicker;
|
|
5440
6286
|
exports.openCreateKeyModal = openCreateKeyModal;
|
|
5441
6287
|
exports.openCreateLinkModal = openCreateLinkModal;
|
|
@@ -5451,12 +6297,18 @@ exports.openKeyActionsMenu = openKeyActionsMenu;
|
|
|
5451
6297
|
exports.openKeyDelete = openKeyDelete;
|
|
5452
6298
|
exports.openKeyDetail = openKeyDetail;
|
|
5453
6299
|
exports.openLLMProviderPicker = openLLMProviderPicker;
|
|
6300
|
+
exports.openManageBenchmarksDialog = openManageBenchmarksDialog;
|
|
5454
6301
|
exports.openMentorVoicePicker = openMentorVoicePicker;
|
|
5455
6302
|
exports.openNewInstanceDialog = openNewInstanceDialog;
|
|
6303
|
+
exports.openNewReviewForRun = openNewReviewForRun;
|
|
6304
|
+
exports.openNewReviewFromDetail = openNewReviewFromDetail;
|
|
5456
6305
|
exports.openNewSkillDialog = openNewSkillDialog;
|
|
6306
|
+
exports.openRunActionsMenu = openRunActionsMenu;
|
|
6307
|
+
exports.openRunResults = openRunResults;
|
|
5457
6308
|
exports.openScheduleTaskDialog = openScheduleTaskDialog;
|
|
5458
6309
|
exports.openScreenSharePromptEditor = openScreenSharePromptEditor;
|
|
5459
6310
|
exports.openSkillActionsMenu = openSkillActionsMenu;
|
|
6311
|
+
exports.openStartEvaluationDialog = openStartEvaluationDialog;
|
|
5460
6312
|
exports.parseReportUrlParams = parseReportUrlParams;
|
|
5461
6313
|
exports.previewCallConfigVoiceInline = previewCallConfigVoiceInline;
|
|
5462
6314
|
exports.previewMentorVoiceInline = previewMentorVoiceInline;
|
|
@@ -5465,8 +6317,10 @@ exports.pushConfiguration = pushConfiguration;
|
|
|
5465
6317
|
exports.readEndpointUrl = readEndpointUrl;
|
|
5466
6318
|
exports.readKeyPublicJwk = readKeyPublicJwk;
|
|
5467
6319
|
exports.readKeyPublicKey = readKeyPublicKey;
|
|
6320
|
+
exports.refreshEvaluationDetail = refreshEvaluationDetail;
|
|
5468
6321
|
exports.reliableClick = reliableClick;
|
|
5469
6322
|
exports.reliableFill = reliableFill;
|
|
6323
|
+
exports.removeTraceScore = removeTraceScore;
|
|
5470
6324
|
exports.renameKey = renameKey;
|
|
5471
6325
|
exports.resetCallConfig = resetCallConfig;
|
|
5472
6326
|
exports.retry = retry;
|
|
@@ -5477,11 +6331,14 @@ exports.saveCallConfig = saveCallConfig;
|
|
|
5477
6331
|
exports.saveScreenSharePrompts = saveScreenSharePrompts;
|
|
5478
6332
|
exports.saveVoiceSettings = saveVoiceSettings;
|
|
5479
6333
|
exports.scheduleTask = scheduleTask;
|
|
6334
|
+
exports.searchBenchmarks = searchBenchmarks;
|
|
5480
6335
|
exports.searchInstances = searchInstances;
|
|
5481
6336
|
exports.searchTasks = searchTasks;
|
|
5482
6337
|
exports.searchVoices = searchVoices;
|
|
6338
|
+
exports.selectBenchmark = selectBenchmark;
|
|
5483
6339
|
exports.selectCallMode = selectCallMode;
|
|
5484
6340
|
exports.selectDateFromCalendar = selectDateFromCalendar;
|
|
6341
|
+
exports.selectJudgeLlm = selectJudgeLlm;
|
|
5485
6342
|
exports.selectLLMModel = selectLLMModel;
|
|
5486
6343
|
exports.selectLlmProvider = selectLlmProvider;
|
|
5487
6344
|
exports.selectPrivacyAction = selectPrivacyAction;
|
|
@@ -5519,8 +6376,12 @@ exports.shouldSaveEditedCSVAndTriggerDownload = shouldSaveEditedCSVAndTriggerDow
|
|
|
5519
6376
|
exports.shouldShowCombiningReportsDialog = shouldShowCombiningReportsDialog;
|
|
5520
6377
|
exports.shouldVerifyCSVEditorDialogAccessibility = shouldVerifyCSVEditorDialogAccessibility;
|
|
5521
6378
|
exports.signUpWithEmailAndPassword = signUpWithEmailAndPassword;
|
|
6379
|
+
exports.startEvaluation = startEvaluation;
|
|
5522
6380
|
exports.submitLinkModal = submitLinkModal;
|
|
6381
|
+
exports.submitLlmJudge = submitLlmJudge;
|
|
5523
6382
|
exports.submitToolModal = submitToolModal;
|
|
6383
|
+
exports.switchToAddItemsSubTab = switchToAddItemsSubTab;
|
|
6384
|
+
exports.switchToEvaluationTab = switchToEvaluationTab;
|
|
5524
6385
|
exports.switchToLtiSubTab = switchToLtiSubTab;
|
|
5525
6386
|
exports.switchToLtiTab = switchToLtiTab;
|
|
5526
6387
|
exports.switchToMemoryTab = switchToMemoryTab;
|
|
@@ -5538,6 +6399,7 @@ exports.toggleAutoPush = toggleAutoPush;
|
|
|
5538
6399
|
exports.toggleMemorySwitch = toggleMemorySwitch;
|
|
5539
6400
|
exports.toggleSkill = toggleSkill;
|
|
5540
6401
|
exports.toolFields = toolFields;
|
|
6402
|
+
exports.uploadQaCsv = uploadQaCsv;
|
|
5541
6403
|
exports.verifyAgentConfigPromptsVisible = verifyAgentConfigPromptsVisible;
|
|
5542
6404
|
exports.verifyAuditLogEmptyState = verifyAuditLogEmptyState;
|
|
5543
6405
|
exports.verifyAuditLogEntryStructure = verifyAuditLogEntryStructure;
|