Files
bifrost/tests/e2e/features/virtual-keys/virtual-keys.spec.ts
Beyhan Oğur 880f412e2c first commit
2026-04-26 21:52:23 +03:00

558 lines
19 KiB
TypeScript

import { expect, test } from '../../core/fixtures/base.fixture'
import {
createVirtualKeyData,
createVirtualKeyWithBudget,
createVirtualKeyWithMultipleProviders,
createVirtualKeyWithProvider,
createVirtualKeyWithRateLimit,
SAMPLE_BUDGETS,
SAMPLE_RATE_LIMITS,
} from './virtual-keys.data'
// Track created VKs for cleanup
const createdVKs: string[] = []
test.describe('Virtual Keys', () => {
test.beforeEach(async ({ virtualKeysPage }) => {
await virtualKeysPage.goto()
})
test.afterEach(async ({ virtualKeysPage }) => {
// Close any open sheets first
await virtualKeysPage.closeSheet()
// Clean up all tracked VKs
if (createdVKs.length > 0) {
await virtualKeysPage.cleanupVirtualKeys([...createdVKs])
createdVKs.length = 0 // Clear the array
}
})
test.describe('Virtual Key Creation', () => {
test('should display create virtual key button', async ({ virtualKeysPage }) => {
await expect(virtualKeysPage.createBtn).toBeVisible()
})
test('should open virtual key creation sheet', async ({ virtualKeysPage }) => {
await virtualKeysPage.createBtn.click()
// Verify sheet is visible
await expect(virtualKeysPage.sheet).toBeVisible()
// Verify form fields are present
await expect(virtualKeysPage.nameInput).toBeVisible()
await expect(virtualKeysPage.descriptionInput).toBeVisible()
})
test('should create a basic virtual key', async ({ virtualKeysPage }) => {
const vkData = createVirtualKeyData({
name: `Basic VK ${Date.now()}`,
description: 'A basic virtual key for testing',
})
createdVKs.push(vkData.name)
await virtualKeysPage.createVirtualKey(vkData)
// Verify virtual key appears in table
const vkExists = await virtualKeysPage.virtualKeyExists(vkData.name)
expect(vkExists).toBe(true)
})
test('should create virtual key with single provider', async ({ virtualKeysPage }) => {
const vkData = createVirtualKeyWithProvider('openai', {
name: `OpenAI VK ${Date.now()}`,
})
createdVKs.push(vkData.name)
await virtualKeysPage.createVirtualKey(vkData)
const vkExists = await virtualKeysPage.virtualKeyExists(vkData.name)
expect(vkExists).toBe(true)
})
test('should create inactive virtual key', async ({ virtualKeysPage }) => {
const vkData = createVirtualKeyData({
name: `Inactive VK ${Date.now()}`,
isActive: false,
})
createdVKs.push(vkData.name)
await virtualKeysPage.createVirtualKey(vkData)
const vkExists = await virtualKeysPage.virtualKeyExists(vkData.name)
expect(vkExists).toBe(true)
})
test('should cancel virtual key creation', async ({ virtualKeysPage }) => {
await virtualKeysPage.createBtn.click()
await expect(virtualKeysPage.sheet).toBeVisible()
// Fill some data
const testName = `Cancelled VK ${Date.now()}`
await virtualKeysPage.nameInput.fill(testName)
// Cancel
await virtualKeysPage.cancelBtn.click()
// Sheet should close
await expect(virtualKeysPage.sheet).not.toBeVisible()
// Virtual key should not exist
const vkExists = await virtualKeysPage.virtualKeyExists(testName)
expect(vkExists).toBe(false)
})
})
test.describe('Virtual Key with Budget', () => {
test('should create virtual key with small budget', async ({ virtualKeysPage }) => {
const vkData = createVirtualKeyWithBudget(SAMPLE_BUDGETS.small, {
name: `Small Budget VK ${Date.now()}`,
})
createdVKs.push(vkData.name)
await virtualKeysPage.createVirtualKey(vkData)
const vkExists = await virtualKeysPage.virtualKeyExists(vkData.name)
expect(vkExists).toBe(true)
// Verify budget was saved correctly
await virtualKeysPage.viewVirtualKey(vkData.name)
await virtualKeysPage.waitForSheetAnimation()
const budgetInput = virtualKeysPage.page.locator('#budgetMaxLimit')
await expect(budgetInput).toHaveValue(String(SAMPLE_BUDGETS.small.maxLimit))
await virtualKeysPage.closeSheet()
})
test('should create virtual key with medium budget', async ({ virtualKeysPage }) => {
const vkData = createVirtualKeyWithBudget(SAMPLE_BUDGETS.medium, {
name: `Medium Budget VK ${Date.now()}`,
})
createdVKs.push(vkData.name)
await virtualKeysPage.createVirtualKey(vkData)
const vkExists = await virtualKeysPage.virtualKeyExists(vkData.name)
expect(vkExists).toBe(true)
})
test('should create virtual key with daily budget', async ({ virtualKeysPage }) => {
const vkData = createVirtualKeyWithBudget(SAMPLE_BUDGETS.daily, {
name: `Daily Budget VK ${Date.now()}`,
})
createdVKs.push(vkData.name)
await virtualKeysPage.createVirtualKey(vkData)
const vkExists = await virtualKeysPage.virtualKeyExists(vkData.name)
expect(vkExists).toBe(true)
})
})
test.describe('Virtual Key with Rate Limits', () => {
test('should create virtual key with token rate limit', async ({ virtualKeysPage }) => {
const vkData = createVirtualKeyWithRateLimit(SAMPLE_RATE_LIMITS.tokenOnly, {
name: `Token Limit VK ${Date.now()}`,
})
createdVKs.push(vkData.name)
await virtualKeysPage.createVirtualKey(vkData)
const vkExists = await virtualKeysPage.virtualKeyExists(vkData.name)
expect(vkExists).toBe(true)
// Verify rate limit was saved correctly
await virtualKeysPage.viewVirtualKey(vkData.name)
await virtualKeysPage.waitForSheetAnimation()
const tokenLimitInput = virtualKeysPage.page.locator('#tokenMaxLimit')
await expect(tokenLimitInput).toHaveValue(String(SAMPLE_RATE_LIMITS.tokenOnly.tokenMaxLimit))
await virtualKeysPage.closeSheet()
})
test('should create virtual key with request rate limit', async ({ virtualKeysPage }) => {
const vkData = createVirtualKeyWithRateLimit(SAMPLE_RATE_LIMITS.requestOnly, {
name: `Request Limit VK ${Date.now()}`,
})
createdVKs.push(vkData.name)
await virtualKeysPage.createVirtualKey(vkData)
const vkExists = await virtualKeysPage.virtualKeyExists(vkData.name)
expect(vkExists).toBe(true)
})
test('should create virtual key with combined rate limits', async ({ virtualKeysPage }) => {
const vkData = createVirtualKeyWithRateLimit(SAMPLE_RATE_LIMITS.conservative, {
name: `Combined Limits VK ${Date.now()}`,
})
createdVKs.push(vkData.name)
await virtualKeysPage.createVirtualKey(vkData)
const vkExists = await virtualKeysPage.virtualKeyExists(vkData.name)
expect(vkExists).toBe(true)
})
})
test.describe('Virtual Key with Multiple Providers', () => {
test('should create virtual key with two providers', async ({ virtualKeysPage }) => {
const vkData = createVirtualKeyWithMultipleProviders(['openai', 'anthropic'], {
name: `Multi Provider VK ${Date.now()}`,
})
createdVKs.push(vkData.name)
await virtualKeysPage.createVirtualKey(vkData)
const vkExists = await virtualKeysPage.virtualKeyExists(vkData.name)
expect(vkExists).toBe(true)
})
})
test.describe('Virtual Key with Budget and Rate Limits', () => {
test('should create virtual key with budget and rate limits', async ({ virtualKeysPage }) => {
const vkData = createVirtualKeyData({
name: `Full Config VK ${Date.now()}`,
description: 'Virtual key with all configurations',
isActive: true,
budget: SAMPLE_BUDGETS.medium,
rateLimit: SAMPLE_RATE_LIMITS.moderate,
})
createdVKs.push(vkData.name)
await virtualKeysPage.createVirtualKey(vkData)
const vkExists = await virtualKeysPage.virtualKeyExists(vkData.name)
expect(vkExists).toBe(true)
})
})
})
// Track created VKs for management tests
const managementVKs: string[] = []
test.describe('Virtual Key Management', () => {
test.beforeEach(async ({ virtualKeysPage }) => {
await virtualKeysPage.goto()
})
test.afterEach(async ({ virtualKeysPage }) => {
// Close any open sheets first
await virtualKeysPage.closeSheet()
// Clean up all tracked VKs
if (managementVKs.length > 0) {
await virtualKeysPage.cleanupVirtualKeys([...managementVKs])
managementVKs.length = 0
}
})
test('should edit virtual key name', async ({ virtualKeysPage }) => {
// First create a virtual key
const originalName = `Edit Test VK ${Date.now()}`
const vkData = createVirtualKeyData({ name: originalName })
await virtualKeysPage.createVirtualKey(vkData)
// Now edit it
const updatedName = `${originalName} Updated`
managementVKs.push(updatedName) // Track the updated name for cleanup
await virtualKeysPage.editVirtualKey(originalName, {
name: updatedName,
})
// Verify updated name exists
const vkExists = await virtualKeysPage.virtualKeyExists(updatedName)
expect(vkExists).toBe(true)
})
test('should edit virtual key description', async ({ virtualKeysPage }) => {
const vkName = `Desc Edit VK ${Date.now()}`
const vkData = createVirtualKeyData({
name: vkName,
description: 'Original description',
})
managementVKs.push(vkName)
await virtualKeysPage.createVirtualKey(vkData)
await virtualKeysPage.editVirtualKey(vkName, {
description: 'Updated description for testing',
})
// Virtual key should still exist
const vkExists = await virtualKeysPage.virtualKeyExists(vkName)
expect(vkExists).toBe(true)
})
test('should toggle virtual key active state', async ({ virtualKeysPage }) => {
const vkName = `Toggle Active VK ${Date.now()}`
const vkData = createVirtualKeyData({
name: vkName,
isActive: true,
})
managementVKs.push(vkName)
await virtualKeysPage.createVirtualKey(vkData)
// Toggle to inactive
await virtualKeysPage.editVirtualKey(vkName, {
isActive: false,
})
const vkExists = await virtualKeysPage.virtualKeyExists(vkName)
expect(vkExists).toBe(true)
})
test('should delete virtual key', async ({ virtualKeysPage }) => {
const vkName = `Delete Test VK ${Date.now()}`
const vkData = createVirtualKeyData({ name: vkName })
await virtualKeysPage.createVirtualKey(vkData)
// Verify it exists
let vkExists = await virtualKeysPage.virtualKeyExists(vkName)
expect(vkExists).toBe(true)
// Delete it (this is the test - no need to track for cleanup)
await virtualKeysPage.deleteVirtualKey(vkName)
// Verify it's gone
vkExists = await virtualKeysPage.virtualKeyExists(vkName)
expect(vkExists).toBe(false)
})
test('should view virtual key details', async ({ virtualKeysPage }) => {
const vkName = `View Details VK ${Date.now()}`
const vkData = createVirtualKeyData({
name: vkName,
description: 'Detailed description for viewing',
})
managementVKs.push(vkName)
await virtualKeysPage.createVirtualKey(vkData)
// Click to view details
await virtualKeysPage.viewVirtualKey(vkName)
// Detail sheet should be visible with correct content
await expect(virtualKeysPage.sheet).toBeVisible()
await expect(virtualKeysPage.nameInput).toHaveValue(vkName)
await expect(virtualKeysPage.descriptionInput).toHaveValue('Detailed description for viewing')
// Close the sheet (will be handled by afterEach if not)
await virtualKeysPage.closeSheet()
})
test('should copy virtual key value', async ({ virtualKeysPage }) => {
const vkName = `Copy Value VK ${Date.now()}`
const vkData = createVirtualKeyData({ name: vkName })
managementVKs.push(vkName)
await virtualKeysPage.createVirtualKey(vkData)
// Copy the key value - method waits for success toast
await virtualKeysPage.copyVirtualKeyValue(vkName)
// Verify copy succeeded: row still exists and key is intact
const vkExists = await virtualKeysPage.virtualKeyExists(vkName)
expect(vkExists).toBe(true)
})
test('should toggle key visibility', async ({ virtualKeysPage }) => {
const vkName = `Toggle Visibility VK ${Date.now()}`
const vkData = createVirtualKeyData({ name: vkName })
managementVKs.push(vkName)
await virtualKeysPage.createVirtualKey(vkData)
// Initially key is masked
let isRevealed = await virtualKeysPage.isKeyRevealed(vkName)
expect(isRevealed).toBe(false)
// Toggle visibility (show key)
await virtualKeysPage.toggleKeyVisibility(vkName)
isRevealed = await virtualKeysPage.isKeyRevealed(vkName)
expect(isRevealed).toBe(true)
// Toggle again (hide key)
await virtualKeysPage.toggleKeyVisibility(vkName)
isRevealed = await virtualKeysPage.isKeyRevealed(vkName)
expect(isRevealed).toBe(false)
})
})
// Track VKs created in Virtual Keys Table tests for cleanup
const tableTestVKs: string[] = []
test.describe('Virtual Keys Table', () => {
test.beforeEach(async ({ virtualKeysPage }) => {
await virtualKeysPage.goto()
})
test.afterEach(async ({ virtualKeysPage }) => {
await virtualKeysPage.closeSheet()
if (tableTestVKs.length > 0) {
await virtualKeysPage.cleanupVirtualKeys([...tableTestVKs])
tableTestVKs.length = 0
}
})
test('should display virtual keys table', async ({ virtualKeysPage }) => {
await virtualKeysPage.page.getByRole('heading', { name: /Virtual Keys/i }).or(virtualKeysPage.emptyState).first().waitFor({ state: 'visible', timeout: 10000 })
const hadTable = await virtualKeysPage.table.isVisible().catch(() => false)
if (!hadTable) {
await expect(virtualKeysPage.emptyState).toBeVisible({ timeout: 10000 })
} else {
await expect(virtualKeysPage.table).toBeVisible({ timeout: 10000 })
}
const vkData = createVirtualKeyData({ name: `Table test VK ${Date.now()}`, description: 'For table display test' })
tableTestVKs.push(vkData.name)
await virtualKeysPage.createVirtualKey(vkData)
await expect(virtualKeysPage.table).toBeVisible({ timeout: 10000 })
await expect(virtualKeysPage.table.locator('th', { hasText: 'Name' })).toBeVisible()
await expect(virtualKeysPage.table.locator('th', { hasText: 'Key' })).toBeVisible()
})
test('should show empty state when no virtual keys', async ({ virtualKeysPage }) => {
await virtualKeysPage.page.getByRole('heading', { name: /Virtual Keys/i }).or(virtualKeysPage.emptyState).first().waitFor({ state: 'visible', timeout: 10000 })
const tableVisible = await virtualKeysPage.table.isVisible().catch(() => false)
if (tableVisible) {
test.skip(true, 'Pre-existing virtual keys found; empty-state assertion requires isolated data.')
return
}
await expect(virtualKeysPage.emptyState).toBeVisible({ timeout: 10000 })
})
})
test.describe('Form Validation', () => {
test.beforeEach(async ({ virtualKeysPage }) => {
await virtualKeysPage.goto()
})
test.afterEach(async ({ virtualKeysPage }) => {
// Close any open sheets
await virtualKeysPage.closeSheet()
})
test('should require name for virtual key', async ({ virtualKeysPage }) => {
await virtualKeysPage.dismissToasts()
await virtualKeysPage.createBtn.click()
await expect(virtualKeysPage.sheet).toBeVisible()
// Wait for sheet animation to complete
await virtualKeysPage.waitForSheetAnimation()
// Save button should be disabled when name is empty
await expect(virtualKeysPage.saveBtn).toBeDisabled()
})
test('should accept valid budget values', async ({ virtualKeysPage }) => {
await virtualKeysPage.dismissToasts()
await virtualKeysPage.createBtn.click()
await expect(virtualKeysPage.sheet).toBeVisible()
// Wait for sheet animation to complete
await virtualKeysPage.waitForSheetAnimation()
// Fill name (required field)
await virtualKeysPage.nameInput.fill(`Valid Budget Test ${Date.now()}`)
// Fill budget
const budgetInput = virtualKeysPage.page.locator('#budgetMaxLimit')
await expect(budgetInput).toBeVisible({ timeout: 5000 })
await budgetInput.fill('100')
// Save button should be enabled if form is valid
await expect(virtualKeysPage.saveBtn).toBeEnabled()
})
})
// Track created VKs for provider tests
const providerVKs: string[] = []
test.describe('Provider Management', () => {
test.beforeEach(async ({ virtualKeysPage }) => {
await virtualKeysPage.goto()
})
test.afterEach(async ({ virtualKeysPage }) => {
// Close any open sheets first
await virtualKeysPage.closeSheet()
// Clean up all tracked VKs
if (providerVKs.length > 0) {
await virtualKeysPage.cleanupVirtualKeys([...providerVKs])
providerVKs.length = 0
}
})
test('should add provider to existing virtual key', async ({ virtualKeysPage }) => {
// Create a virtual key first
const vkName = `Add Provider VK ${Date.now()}`
const vkData = createVirtualKeyWithProvider('openai', { name: vkName })
providerVKs.push(vkName)
await virtualKeysPage.createVirtualKey(vkData)
// View the virtual key
await virtualKeysPage.viewVirtualKey(vkName)
// Check if we can see provider configuration
const providerSection = virtualKeysPage.page.getByText(/Providers|Provider/i).first()
const isVisible = await providerSection.isVisible().catch(() => false)
if (isVisible) {
// Provider section is available
expect(isVisible).toBe(true)
}
// Close sheet (handled by afterEach as well)
await virtualKeysPage.closeSheet()
})
test('should remove provider from virtual key', async ({ virtualKeysPage }) => {
// Create a virtual key with multiple providers
const vkName = `Remove Provider VK ${Date.now()}`
const vkData = createVirtualKeyWithMultipleProviders(['openai', 'anthropic'], { name: vkName })
providerVKs.push(vkName)
await virtualKeysPage.createVirtualKey(vkData)
// View the virtual key
await virtualKeysPage.viewVirtualKey(vkName)
// Check if we can see and interact with providers
const removeProviderBtn = virtualKeysPage.page.locator('button').filter({
has: virtualKeysPage.page.locator('svg.lucide-trash, svg.lucide-x, svg.lucide-trash-2')
}).first()
const isVisible = await removeProviderBtn.isVisible().catch(() => false)
if (isVisible) {
// Remove provider is available - this is expected behavior
expect(isVisible).toBe(true)
}
// Close sheet (handled by afterEach as well)
await virtualKeysPage.closeSheet()
})
test('should update provider-specific budget', async ({ virtualKeysPage }) => {
// Create a virtual key with budget
const vkName = `Provider Budget VK ${Date.now()}`
const vkData = createVirtualKeyWithProvider('openai', {
name: vkName,
budget: SAMPLE_BUDGETS.small,
})
providerVKs.push(vkName)
await virtualKeysPage.createVirtualKey(vkData)
// Edit the virtual key
await virtualKeysPage.editVirtualKey(vkName, {
budget: SAMPLE_BUDGETS.large,
})
// Verify it still exists
const vkExists = await virtualKeysPage.virtualKeyExists(vkName)
expect(vkExists).toBe(true)
})
})