You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

113 lines
4.1 KiB

  1. import type { APIRequestContext, Locator, Page } from '@playwright/test';
  2. import { expect, rootStorageStatePath, test } from './fixtures/cluster';
  3. type ModelPricingConfig = {
  4. success: boolean;
  5. data: {
  6. schema_version: number;
  7. scope: string;
  8. dimensions: Array<{ key: string }>;
  9. table: unknown[];
  10. };
  11. };
  12. const modelName = () =>
  13. `e2e-video-pricing-model-${Date.now()}-${Math.floor(Math.random() * 1000)}`;
  14. async function fillControl(locator: Locator, value: string) {
  15. const input = locator.locator('input');
  16. if ((await input.count()) > 0) {
  17. await input.first().fill(value);
  18. return;
  19. }
  20. await locator.fill(value);
  21. }
  22. async function fillByTestId(page: Page, testId: string, value: string) {
  23. await fillControl(page.getByTestId(testId), value);
  24. }
  25. async function countGeneratorRatioRows(page: Page) {
  26. return await page.getByTestId(/^generator-ratio-value-/).count();
  27. }
  28. async function fetchModelPricing(
  29. request: APIRequestContext,
  30. model: string,
  31. ): Promise<ModelPricingConfig> {
  32. const response = await request.get(
  33. `/api/option/model_pricing/${encodeURIComponent(model)}`,
  34. );
  35. expect(response.ok()).toBeTruthy();
  36. return (await response.json()) as ModelPricingConfig;
  37. }
  38. test.describe.serial('Model Pricing E2E', () => {
  39. test.use({ storageState: rootStorageStatePath });
  40. test('root can save and reload a generated model pricing config', async ({
  41. page,
  42. request,
  43. }) => {
  44. const model = modelName();
  45. await page.goto('/console/setting?tab=ratio');
  46. await page.getByTestId('model-pricing-tab').click();
  47. await expect(page.getByTestId('model-pricing-page')).toBeVisible();
  48. await page.getByTestId('model-pricing-add-model').click();
  49. await expect(page.getByTestId('model-pricing-editor')).toBeVisible();
  50. await fillByTestId(page, 'model-pricing-model-name', model);
  51. await fillByTestId(page, 'dimension-key-0', 'duration');
  52. await fillByTestId(page, 'dimension-source-path-0', 'duration');
  53. await page.getByTestId('dimension-add').click();
  54. await fillByTestId(page, 'dimension-key-1', 'quality');
  55. await fillByTestId(page, 'dimension-source-path-1', 'quality');
  56. await page.getByTestId('model-pricing-open-generator').click();
  57. await expect(page.getByTestId('model-pricing-generator')).toBeVisible();
  58. await fillByTestId(page, 'generator-base-price', '0.2');
  59. const generator = page.getByTestId('model-pricing-generator');
  60. await generator.locator('input[value="replace_all"]').check({ force: true });
  61. const qualityRowIndex = (await countGeneratorRatioRows(page)) - 1;
  62. await fillByTestId(page, `generator-ratio-value-${qualityRowIndex}`, 'standard');
  63. await fillByTestId(page, `generator-ratio-ratio-${qualityRowIndex}`, '1.5');
  64. await expect(page.getByTestId('generator-apply')).toBeEnabled();
  65. await page.getByTestId('generator-apply').click();
  66. const saveResponsePromise = page.waitForResponse(
  67. (response) =>
  68. response.request().method() === 'PUT' &&
  69. response
  70. .url()
  71. .includes(`/api/option/model_pricing/${encodeURIComponent(model)}`),
  72. );
  73. await page.getByTestId('model-pricing-save').click();
  74. const saveResponse = await saveResponsePromise;
  75. expect(saveResponse.ok()).toBeTruthy();
  76. const saveBody = await saveResponse.json();
  77. expect(saveBody.success).toBe(true);
  78. await page.reload();
  79. await page.getByTestId('model-pricing-tab').click();
  80. await expect(page.getByTestId('model-pricing-page')).toBeVisible();
  81. await fillByTestId(page, 'model-pricing-search', model);
  82. await expect(page.getByTestId('model-pricing-table')).toContainText(model);
  83. await page.getByTestId(`model-pricing-edit-${model}`).click();
  84. await expect(page.getByTestId('model-pricing-editor')).toBeVisible();
  85. const data = await fetchModelPricing(request, model);
  86. expect(data.success).toBe(true);
  87. expect(data.data.schema_version).toBe(1);
  88. expect(data.data.scope).toBe('model');
  89. expect(data.data.dimensions.map((dimension) => dimension.key)).toEqual([
  90. 'duration',
  91. 'quality',
  92. ]);
  93. expect(data.data.table.length).toBeGreaterThan(0);
  94. });
  95. });