From 12d42e5ed51d67dfe93cf2e8fbd3caa014791d92 Mon Sep 17 00:00:00 2001 From: Valentin Kirilov Date: Wed, 3 Sep 2025 13:49:14 +0300 Subject: [PATCH 1/8] refactor(ui): split vector search index preset data into multiple files - necessary due to some odd issues with the imports, failing when running the playwright tests re #RI-7275 --- .../create-index/steps/AddDataStep.spec.tsx | 2 +- .../steps/CreateIndexStep.spec.tsx | 2 +- .../create-index/steps/CreateIndexStep.tsx | 2 +- .../create-index/steps/config.tsx | 104 +----------------- .../vector-search/create-index/steps/data.ts | 100 +++++++++++++++++ .../vector-search/create-index/steps/index.ts | 1 + 6 files changed, 105 insertions(+), 106 deletions(-) create mode 100644 redisinsight/ui/src/pages/vector-search/create-index/steps/data.ts diff --git a/redisinsight/ui/src/pages/vector-search/create-index/steps/AddDataStep.spec.tsx b/redisinsight/ui/src/pages/vector-search/create-index/steps/AddDataStep.spec.tsx index ff9d1ce4ed..d464634024 100644 --- a/redisinsight/ui/src/pages/vector-search/create-index/steps/AddDataStep.spec.tsx +++ b/redisinsight/ui/src/pages/vector-search/create-index/steps/AddDataStep.spec.tsx @@ -2,7 +2,7 @@ import React from 'react' import { render, screen, fireEvent } from 'uiSrc/utils/test-utils' import { AddDataStep } from './AddDataStep' -import { selectedBikesIndexFields } from './config' +import { selectedBikesIndexFields } from './data' import { SearchIndexType, SampleDataType, diff --git a/redisinsight/ui/src/pages/vector-search/create-index/steps/CreateIndexStep.spec.tsx b/redisinsight/ui/src/pages/vector-search/create-index/steps/CreateIndexStep.spec.tsx index 7eb481d17e..769ab9a105 100644 --- a/redisinsight/ui/src/pages/vector-search/create-index/steps/CreateIndexStep.spec.tsx +++ b/redisinsight/ui/src/pages/vector-search/create-index/steps/CreateIndexStep.spec.tsx @@ -3,7 +3,6 @@ import { fireEvent, render, screen } from 'uiSrc/utils/test-utils' import { sendEventTelemetry, TelemetryEvent } from 'uiSrc/telemetry' import { CreateIndexStep } from './CreateIndexStep' -import { bikesIndexFieldsBoxes, selectedBikesIndexFields } from './config' import { SearchIndexType, SampleDataType, @@ -11,6 +10,7 @@ import { PresetDataType, StepComponentProps, } from '../types' +import { bikesIndexFieldsBoxes, selectedBikesIndexFields } from './data' // Mock the telemetry module, so we don't send actual telemetry data during tests jest.mock('uiSrc/telemetry', () => ({ diff --git a/redisinsight/ui/src/pages/vector-search/create-index/steps/CreateIndexStep.tsx b/redisinsight/ui/src/pages/vector-search/create-index/steps/CreateIndexStep.tsx index 2e9cee9aee..82f6d4a1d6 100644 --- a/redisinsight/ui/src/pages/vector-search/create-index/steps/CreateIndexStep.tsx +++ b/redisinsight/ui/src/pages/vector-search/create-index/steps/CreateIndexStep.tsx @@ -15,7 +15,7 @@ import { TextInput } from 'uiSrc/components/base/inputs' import { sendEventTelemetry, TelemetryEvent } from 'uiSrc/telemetry' import { PlayFilledIcon } from 'uiSrc/components/base/icons' -import { bikesIndexFieldsBoxes, moviesIndexFieldsBoxes } from './config' +import { bikesIndexFieldsBoxes, moviesIndexFieldsBoxes } from './data' import { CreateIndexStepScreenWrapper, SearchInputWrapper } from './styles' import { PreviewCommandDrawer } from './PreviewCommandDrawer' import { IStepComponent, SampleDataContent, StepComponentProps } from '../types' diff --git a/redisinsight/ui/src/pages/vector-search/create-index/steps/config.tsx b/redisinsight/ui/src/pages/vector-search/create-index/steps/config.tsx index c2f8110a0b..6efa4f9142 100644 --- a/redisinsight/ui/src/pages/vector-search/create-index/steps/config.tsx +++ b/redisinsight/ui/src/pages/vector-search/create-index/steps/config.tsx @@ -1,6 +1,3 @@ -import React from 'react' -import { FieldTypes } from 'uiSrc/pages/browser/components/create-redisearch-index/constants' -import { VectorSearchBox } from 'uiSrc/components/new-index/create-index-step/field-box/types' import { BoxSelectionOption } from 'uiSrc/components/new-index/selection-box/SelectionBox' import { BikeIcon, @@ -12,6 +9,7 @@ import { import { SearchIndexType, SampleDataType, SampleDataContent } from '../types' import { RiBadge } from 'uiSrc/components/base/display/badge/RiBadge' import { Row } from 'uiSrc/components/base/layout/flex' +import React from 'react' // ** Add data step */ @@ -63,103 +61,3 @@ export const indexDataContent: BoxSelectionOption[] = [ icon: PopcornIcon, }, ] - -// ** Create index step */ - -export const bikesIndexFieldsBoxes: VectorSearchBox[] = [ - { - value: 'model', - label: 'model', - text: 'Product model', - tag: FieldTypes.TEXT, - disabled: true, - }, - { - value: 'brand', - label: 'brand', - text: 'Product brand', - tag: FieldTypes.TEXT, - disabled: true, - }, - { - value: 'price', - label: 'price', - text: 'Product price', - tag: FieldTypes.NUMERIC, - disabled: true, - }, - { - value: 'type', - label: 'type', - text: 'Product type', - tag: FieldTypes.TAG, - disabled: true, - }, - { - value: 'material', - label: 'material', - text: 'Product material', - tag: FieldTypes.TAG, - disabled: true, - }, - { - value: 'weight', - label: 'weight', - text: 'Product weight', - tag: FieldTypes.NUMERIC, - disabled: true, - }, - { - value: 'description_embeddings', - label: 'description_embeddings', - text: 'Product embedding vector', - tag: FieldTypes.VECTOR, - disabled: true, - }, -] - -export const moviesIndexFieldsBoxes: VectorSearchBox[] = [ - { - value: 'title', - label: 'title', - text: 'Movie title', - tag: FieldTypes.TEXT, - disabled: true, - }, - { - value: 'genres', - label: 'genres', - text: 'Movie genre', - tag: FieldTypes.TAG, - disabled: true, - }, - { - value: 'plot', - label: 'plot', - text: 'Movie plot', - tag: FieldTypes.TEXT, - disabled: true, - }, - { - value: 'year', - label: 'year', - text: 'Movie year', - tag: FieldTypes.NUMERIC, - disabled: true, - }, - { - value: 'embedding', - label: 'embedding', - text: 'Movie embedding vector', - tag: FieldTypes.VECTOR, - disabled: true, - }, -] - -export const selectedBikesIndexFields = bikesIndexFieldsBoxes.map( - (field) => field.value, -) - -export const selectedMoviesIndexFields = moviesIndexFieldsBoxes.map( - (field) => field.value, -) diff --git a/redisinsight/ui/src/pages/vector-search/create-index/steps/data.ts b/redisinsight/ui/src/pages/vector-search/create-index/steps/data.ts new file mode 100644 index 0000000000..b7e85649dd --- /dev/null +++ b/redisinsight/ui/src/pages/vector-search/create-index/steps/data.ts @@ -0,0 +1,100 @@ +import { FieldTypes } from 'uiSrc/pages/browser/components/create-redisearch-index/constants' +import { VectorSearchBox } from 'uiSrc/components/new-index/create-index-step/field-box/types' + +export const bikesIndexFieldsBoxes: VectorSearchBox[] = [ + { + value: 'model', + label: 'model', + text: 'Product model', + tag: FieldTypes.TEXT, + disabled: true, + }, + { + value: 'brand', + label: 'brand', + text: 'Product brand', + tag: FieldTypes.TEXT, + disabled: true, + }, + { + value: 'price', + label: 'price', + text: 'Product price', + tag: FieldTypes.NUMERIC, + disabled: true, + }, + { + value: 'type', + label: 'type', + text: 'Product type', + tag: FieldTypes.TAG, + disabled: true, + }, + { + value: 'material', + label: 'material', + text: 'Product material', + tag: FieldTypes.TAG, + disabled: true, + }, + { + value: 'weight', + label: 'weight', + text: 'Product weight', + tag: FieldTypes.NUMERIC, + disabled: true, + }, + { + value: 'description_embeddings', + label: 'description_embeddings', + text: 'Product embedding vector', + tag: FieldTypes.VECTOR, + disabled: true, + }, +] + +export const selectedBikesIndexFields = bikesIndexFieldsBoxes.map( + (field) => field.value, +) + +export const moviesIndexFieldsBoxes: VectorSearchBox[] = [ + { + value: 'title', + label: 'title', + text: 'Movie title', + tag: FieldTypes.TEXT, + disabled: true, + }, + { + value: 'genres', + label: 'genres', + text: 'Movie genre', + tag: FieldTypes.TAG, + disabled: true, + }, + { + value: 'plot', + label: 'plot', + text: 'Movie plot', + tag: FieldTypes.TEXT, + disabled: true, + }, + { + value: 'year', + label: 'year', + text: 'Movie year', + tag: FieldTypes.NUMERIC, + disabled: true, + }, + { + value: 'embedding', + label: 'embedding', + text: 'Movie embedding vector', + tag: FieldTypes.VECTOR, + disabled: true, + }, +] + +export const selectedMoviesIndexFields = moviesIndexFieldsBoxes.map( + (field) => field.value, +) diff --git a/redisinsight/ui/src/pages/vector-search/create-index/steps/index.ts b/redisinsight/ui/src/pages/vector-search/create-index/steps/index.ts index 149f776442..df6bd7f140 100644 --- a/redisinsight/ui/src/pages/vector-search/create-index/steps/index.ts +++ b/redisinsight/ui/src/pages/vector-search/create-index/steps/index.ts @@ -3,4 +3,5 @@ import { AddDataStep } from './AddDataStep' import { CreateIndexStep } from './CreateIndexStep' export * from './config' +export * from './data' export const stepContents = [SelectDatabaseStep, AddDataStep, CreateIndexStep] From 04d908c0d81a4bd9853f769cdf2f778015787758 Mon Sep 17 00:00:00 2001 From: Valentin Kirilov Date: Wed, 3 Sep 2025 13:51:18 +0300 Subject: [PATCH 2/8] test(e2e): added mocks for the playwright tests re #RI-7275 --- tests/playwright/playwright.config.ts | 1 + tests/playwright/setup/module-mocks.ts | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 tests/playwright/setup/module-mocks.ts diff --git a/tests/playwright/playwright.config.ts b/tests/playwright/playwright.config.ts index cbf77fa969..125365a15a 100644 --- a/tests/playwright/playwright.config.ts +++ b/tests/playwright/playwright.config.ts @@ -2,6 +2,7 @@ import { defineConfig, devices } from '@playwright/test' import { Status } from 'allure-js-commons' import dotenv from 'dotenv' import * as os from 'os' +import './setup/module-mocks' dotenv.config({ path: process.env.envPath ?? 'env/.local-web.env', diff --git a/tests/playwright/setup/module-mocks.ts b/tests/playwright/setup/module-mocks.ts new file mode 100644 index 0000000000..62267ae2da --- /dev/null +++ b/tests/playwright/setup/module-mocks.ts @@ -0,0 +1,22 @@ +// Module mocks for Node.js environment to handle UI imports + +const Module = require('module') +const originalRequire = Module.prototype.require + +Module.prototype.require = function (id: string) { + // Mock SVG imports with Vite's ?react syntax + if (id.endsWith('.svg?react')) { + return function SvgMock() { + return null + } + } + + // Mock missing UI dependencies + if (id === '@redislabsdev/redis-ui-styles') { + return {} + } + + return originalRequire.apply(this, arguments) +} + +export {} From 3fee9df572a4e849a53e5d5fe1b0b0d5e8a1bf5a Mon Sep 17 00:00:00 2001 From: Valentin Kirilov Date: Wed, 3 Sep 2025 13:56:21 +0300 Subject: [PATCH 3/8] test(e2e): added playwright tests for the "create index" flow re #RI-7275 --- .../create-index/steps/AddDataStep.tsx | 9 +- .../create-index/steps/config.tsx | 6 +- .../pages/vector-search/create-index-page.ts | 158 +++++++++++++++++- .../tests/vector-search/create-index.spec.ts | 56 +++++++ 4 files changed, 218 insertions(+), 11 deletions(-) create mode 100644 tests/playwright/tests/vector-search/create-index.spec.ts diff --git a/redisinsight/ui/src/pages/vector-search/create-index/steps/AddDataStep.tsx b/redisinsight/ui/src/pages/vector-search/create-index/steps/AddDataStep.tsx index ef4c0f4811..9a3c97f411 100644 --- a/redisinsight/ui/src/pages/vector-search/create-index/steps/AddDataStep.tsx +++ b/redisinsight/ui/src/pages/vector-search/create-index/steps/AddDataStep.tsx @@ -10,13 +10,8 @@ import { SmallSelectionBox, StyledBoxSelectionGroup, } from './styles' -import { - indexDataContent, - indexType, - sampleDatasetOptions, - selectedBikesIndexFields, - selectedMoviesIndexFields, -} from './config' +import { indexDataContent, indexType, sampleDatasetOptions } from './config' +import { selectedBikesIndexFields, selectedMoviesIndexFields } from './data' import { IStepComponent, PresetDataType, diff --git a/redisinsight/ui/src/pages/vector-search/create-index/steps/config.tsx b/redisinsight/ui/src/pages/vector-search/create-index/steps/config.tsx index 6efa4f9142..1eaeed2244 100644 --- a/redisinsight/ui/src/pages/vector-search/create-index/steps/config.tsx +++ b/redisinsight/ui/src/pages/vector-search/create-index/steps/config.tsx @@ -1,3 +1,4 @@ +import React from 'react' import { BoxSelectionOption } from 'uiSrc/components/new-index/selection-box/SelectionBox' import { BikeIcon, @@ -5,11 +6,10 @@ import { VectorSearchIcon, WandIcon, } from 'uiSrc/components/base/icons' - -import { SearchIndexType, SampleDataType, SampleDataContent } from '../types' import { RiBadge } from 'uiSrc/components/base/display/badge/RiBadge' import { Row } from 'uiSrc/components/base/layout/flex' -import React from 'react' + +import { SearchIndexType, SampleDataType, SampleDataContent } from '../types' // ** Add data step */ diff --git a/tests/playwright/pageObjects/pages/vector-search/create-index-page.ts b/tests/playwright/pageObjects/pages/vector-search/create-index-page.ts index 283c083091..188cb02d58 100644 --- a/tests/playwright/pageObjects/pages/vector-search/create-index-page.ts +++ b/tests/playwright/pageObjects/pages/vector-search/create-index-page.ts @@ -1,17 +1,45 @@ /* eslint-disable @typescript-eslint/lines-between-class-members */ -import { Locator, Page } from '@playwright/test' +import { expect, Locator, Page } from '@playwright/test' +import { + SampleDataContent, + SampleDataType, + SearchIndexType, +} from 'uiSrc/pages/vector-search/create-index/types' +import { + indexDataContent, + indexType as indexTypesData, + sampleDatasetOptions, +} from 'uiSrc/pages/vector-search/create-index/steps/config' import { BasePage } from '../../base-page' +import { Toast } from '../../components/common/toast' export class CreateIndexPage extends BasePage { + private toast: Toast + // CONTAINERS public readonly vectorSearchPage: Locator public readonly createIndexPage: Locator public readonly wizardTitle: Locator + // STEP 1 CONTAINERS + public readonly step1Container: Locator + public readonly step1IndexTypeContainer: Locator + public readonly step1SampleDatasetContainer: Locator + public readonly step1DataContentContainer: Locator + public readonly step1NextButton: Locator + + // STEP 2 CONTAINERS + public readonly step2Container: Locator + public readonly step2CommandPreviewDrawer: Locator + public readonly step2OpenCommandPreviewButton: Locator + public readonly step2CloseCommandPreviewButton: Locator + public readonly step2CreateIndexButton: Locator + constructor(page: Page) { super(page) this.page = page + this.toast = new Toast(page) // CONTAINERS this.vectorSearchPage = page.getByTestId('vector-search-page') @@ -19,10 +47,138 @@ export class CreateIndexPage extends BasePage { 'vector-search--create-index-page', ) this.wizardTitle = page.getByText('New vector search') + + // STEP 1 CONTAINERS + this.step1Container = page.getByTestId('create-index-step1') + this.step1IndexTypeContainer = page.getByTestId('step-data--index-type') + this.step1SampleDatasetContainer = page.getByTestId( + 'step-data--sample-dataset', + ) + this.step1DataContentContainer = page.getByTestId( + 'step-data--data-content', + ) + this.step1NextButton = page.getByText('Proceed to index') + + // STEP 2 CONTAINERS + this.step2Container = page.getByTestId('create-index-step2') + this.step2OpenCommandPreviewButton = page.getByText('Command preview') + this.step2CommandPreviewDrawer = page.getByTestId( + 'preview-command-drawer', + ) + this.step2CloseCommandPreviewButton = + this.step2CommandPreviewDrawer.getByText('Close') + this.step2CreateIndexButton = page.getByRole('button', { + name: 'Create index', + }) } async verifyCreateIndexPageLoaded(): Promise { await this.waitForLocatorVisible(this.createIndexPage) await this.waitForLocatorVisible(this.wizardTitle) + await this.waitForLocatorVisible(this.step1Container) + } + + async step1SelectIndexType(indexType: SearchIndexType): Promise { + await this.waitForLocatorVisible(this.step1IndexTypeContainer) + + const indexTypeData = indexTypesData.find( + (type) => type.value === indexType, + ) + if (!indexTypeData) { + throw new Error(`Index type ${indexType} not found`) + } + + const indexTypeElement = this.step1IndexTypeContainer.getByText( + indexTypeData.label!, + ) + + await this.waitForLocatorVisible(indexTypeElement) + await indexTypeElement.click() + } + + async step1SelectSampleDataset( + sampleDataset: SampleDataType, + ): Promise { + await this.waitForLocatorVisible(this.step1SampleDatasetContainer) + + const sampleDatasetData = sampleDatasetOptions.find( + (dataset) => dataset.value === sampleDataset, + ) + if (!sampleDatasetData) { + throw new Error(`Sample dataset ${sampleDataset} not found`) + } + + const sampleDatasetElement = this.step1SampleDatasetContainer.getByText( + sampleDatasetData.label!, + ) + + await this.waitForLocatorVisible(sampleDatasetElement) + await sampleDatasetElement.click() + } + + async step1SelectDataContent( + dataContent: SampleDataContent, + ): Promise { + await this.waitForLocatorVisible(this.step1DataContentContainer) + + const dataContentData = indexDataContent.find( + (data) => data.value === dataContent, + ) + if (!dataContentData) { + throw new Error(`Data content ${dataContent} not found`) + } + + const dataContentElement = this.step1DataContentContainer.getByText( + dataContentData.label!, + ) + + await this.waitForLocatorVisible(dataContentElement) + await dataContentElement.click() + } + + async step1ClickNextButton(): Promise { + await this.waitForLocatorVisible(this.step1NextButton) + await this.step1NextButton.click() + + await this.waitForLocatorVisible(this.step2Container) + } + + async step2ClickCommandPreviewButton(): Promise { + await this.waitForLocatorVisible(this.step2OpenCommandPreviewButton) + await this.step2OpenCommandPreviewButton.click() + + await this.waitForLocatorVisible(this.step2CommandPreviewDrawer) + } + + async step2ClickCloseCommandPreviewButton(): Promise { + await this.waitForLocatorVisible(this.step2CloseCommandPreviewButton) + await this.step2CloseCommandPreviewButton.click() + + await this.waitForLocatorVisible(this.step2Container) + } + + async step2ClickCreateIndexButton(): Promise { + await this.waitForLocatorVisible(this.step2CreateIndexButton) + await this.step2CreateIndexButton.click() + + // Verify we're back on the vector search page + await this.waitForLocatorVisible(this.vectorSearchPage) + + // Check for success toast + await this.verifySuccessToast('Index has been created') + } + + async verifySuccessToast( + expectedMessage: string, + timeout = 2000, + ): Promise { + try { + await this.waitForLocatorVisible(this.toast.toastSuccess, timeout) + await expect(this.toast.toastBody).toContainText(expectedMessage) + await this.toast.closeToast() + } catch { + // No toast appeared - this is acceptable for some actions + // Success is typically verified by other means (navigation, etc.) + } } } diff --git a/tests/playwright/tests/vector-search/create-index.spec.ts b/tests/playwright/tests/vector-search/create-index.spec.ts new file mode 100644 index 0000000000..a3a3342902 --- /dev/null +++ b/tests/playwright/tests/vector-search/create-index.spec.ts @@ -0,0 +1,56 @@ +import { + SampleDataContent, + SampleDataType, + SearchIndexType, +} from 'uiSrc/pages/vector-search/create-index/types' +import { VectorSearchPage } from '../../pageObjects/pages/vector-search/vector-search-page' +import { test } from '../../fixtures/test' +import { + addStandaloneInstanceAndNavigateToIt, + navigateToStandaloneInstance, +} from '../../helpers/utils' +import { CreateIndexPage } from '../../pageObjects/pages/vector-search/create-index-page' + +test.describe('Vector Search - Create Index', () => { + let searchPage: VectorSearchPage + let createIndexPage: CreateIndexPage + let cleanupInstance: () => Promise + + test.beforeEach(async ({ page, api: { databaseService } }) => { + searchPage = new VectorSearchPage(page) + createIndexPage = new CreateIndexPage(page) + cleanupInstance = await addStandaloneInstanceAndNavigateToIt( + page, + databaseService, + ) + + await navigateToStandaloneInstance(page) + await searchPage.navigateToVectorSearchPage() + await searchPage.navigateToCreateIndexPage() + }) + + test.afterEach(async () => { + await cleanupInstance() + }) + + test('should create a vector search index', async () => { + // Step 1 + await createIndexPage.step1SelectIndexType( + SearchIndexType.REDIS_QUERY_ENGINE, + ) + await createIndexPage.step1SelectSampleDataset( + SampleDataType.PRESET_DATA, + ) + await createIndexPage.step1SelectDataContent( + SampleDataContent.E_COMMERCE_DISCOVERY, + ) + await createIndexPage.step1ClickNextButton() + + // Step 2 + await createIndexPage.step2ClickCommandPreviewButton() + await createIndexPage.step2ClickCloseCommandPreviewButton() + await createIndexPage.step2ClickCreateIndexButton() + + await createIndexPage.verifySuccessToast('Index has been created') + }) +}) From 0996b21096d5f8c931fde7a2f91912d744e6c68d Mon Sep 17 00:00:00 2001 From: Valentin Kirilov Date: Thu, 11 Sep 2025 08:45:00 +0300 Subject: [PATCH 4/8] test(e2e): fix redi-ui dependency path alias --- tests/playwright/package.json | 7 +++++++ tests/playwright/setup/module-mocks.ts | 7 ++----- tests/playwright/yarn.lock | 5 +++++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/tests/playwright/package.json b/tests/playwright/package.json index d345d45157..beedae6805 100644 --- a/tests/playwright/package.json +++ b/tests/playwright/package.json @@ -39,7 +39,14 @@ "dotenv": "^16.4.7", "dotenv-cli": "^8.0.0", "fs-extra": "^11.3.0", + "module-alias": "^2.2.3", "node-color-log": "^12.0.1", "sqlite3": "^5.1.7" + }, + "_moduleAliases": { + "@redislabsdev/redis-ui-icons": "../../node_modules/@redis-ui/icons", + "@redislabsdev/redis-ui-styles": "../../node_modules/@redis-ui/styles", + "@redislabsdev/redis-ui-components": "../../node_modules/@redis-ui/components", + "@redislabsdev/redis-ui-table": "../../node_modules/@redis-ui/table" } } diff --git a/tests/playwright/setup/module-mocks.ts b/tests/playwright/setup/module-mocks.ts index 62267ae2da..c31375e966 100644 --- a/tests/playwright/setup/module-mocks.ts +++ b/tests/playwright/setup/module-mocks.ts @@ -1,5 +1,7 @@ // Module mocks for Node.js environment to handle UI imports +require('module-alias/register') + const Module = require('module') const originalRequire = Module.prototype.require @@ -11,11 +13,6 @@ Module.prototype.require = function (id: string) { } } - // Mock missing UI dependencies - if (id === '@redislabsdev/redis-ui-styles') { - return {} - } - return originalRequire.apply(this, arguments) } diff --git a/tests/playwright/yarn.lock b/tests/playwright/yarn.lock index cd405a051f..dcb510c1cd 100644 --- a/tests/playwright/yarn.lock +++ b/tests/playwright/yarn.lock @@ -1324,6 +1324,11 @@ mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +module-alias@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/module-alias/-/module-alias-2.2.3.tgz#ec2e85c68973bda6ab71ce7c93b763ec96053221" + integrity sha512-23g5BFj4zdQL/b6tor7Ji+QY4pEfNH784BMslY9Qb0UnJWRAt+lQGLYmRaM0KDBwIG23ffEBELhZDP2rhi9f/Q== + ms@^2.0.0, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" From e4c74c00e6c0cf56dde3b2af3bc6de8914e40782 Mon Sep 17 00:00:00 2001 From: Valentin Kirilov Date: Thu, 11 Sep 2025 09:17:20 +0300 Subject: [PATCH 5/8] test(e2e): add test to verify the cancel wizard button re #RI-7275 --- .../pages/vector-search/create-index-page.ts | 15 +++++++++++++++ .../tests/vector-search/create-index.spec.ts | 17 +++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/tests/playwright/pageObjects/pages/vector-search/create-index-page.ts b/tests/playwright/pageObjects/pages/vector-search/create-index-page.ts index 188cb02d58..894625a985 100644 --- a/tests/playwright/pageObjects/pages/vector-search/create-index-page.ts +++ b/tests/playwright/pageObjects/pages/vector-search/create-index-page.ts @@ -36,6 +36,9 @@ export class CreateIndexPage extends BasePage { public readonly step2CloseCommandPreviewButton: Locator public readonly step2CreateIndexButton: Locator + // BUTTONS + public readonly cancelButton: Locator + constructor(page: Page) { super(page) this.page = page @@ -70,6 +73,11 @@ export class CreateIndexPage extends BasePage { this.step2CreateIndexButton = page.getByRole('button', { name: 'Create index', }) + + // BUTTONS + this.cancelButton = page.getByRole('button', { + name: 'Cancel', + }) } async verifyCreateIndexPageLoaded(): Promise { @@ -181,4 +189,11 @@ export class CreateIndexPage extends BasePage { // Success is typically verified by other means (navigation, etc.) } } + + async clickCancelButton(): Promise { + await this.waitForLocatorVisible(this.cancelButton) + await this.cancelButton.click() + + await this.waitForLocatorVisible(this.vectorSearchPage) + } } diff --git a/tests/playwright/tests/vector-search/create-index.spec.ts b/tests/playwright/tests/vector-search/create-index.spec.ts index a3a3342902..14314b74c4 100644 --- a/tests/playwright/tests/vector-search/create-index.spec.ts +++ b/tests/playwright/tests/vector-search/create-index.spec.ts @@ -53,4 +53,21 @@ test.describe('Vector Search - Create Index', () => { await createIndexPage.verifySuccessToast('Index has been created') }) + + test('should cancel the create index wizard', async () => { + // Fill in step 1 + await createIndexPage.step1SelectIndexType( + SearchIndexType.REDIS_QUERY_ENGINE, + ) + await createIndexPage.step1SelectSampleDataset( + SampleDataType.PRESET_DATA, + ) + await createIndexPage.step1SelectDataContent( + SampleDataContent.E_COMMERCE_DISCOVERY, + ) + await createIndexPage.step1ClickNextButton() + + // Cancel the wizard + await createIndexPage.clickCancelButton() + }) }) From 7877ec1e39377bbb5efda5bd6d95f75c7865317c Mon Sep 17 00:00:00 2001 From: Valentin Kirilov Date: Wed, 10 Sep 2025 16:31:23 +0300 Subject: [PATCH 6/8] test(e2e): refactor the toast notification helper --- .../pageObjects/components/common/toast.ts | 19 ++++++++++++++++++- tests/playwright/selectors/toast-selectors.ts | 8 ++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/tests/playwright/pageObjects/components/common/toast.ts b/tests/playwright/pageObjects/components/common/toast.ts index d90e5731a4..65df2d9669 100644 --- a/tests/playwright/pageObjects/components/common/toast.ts +++ b/tests/playwright/pageObjects/components/common/toast.ts @@ -3,6 +3,8 @@ import { BasePage } from '../../base-page' import { ToastSelectors } from '../../../selectors' export class Toast extends BasePage { + // Deprecated - use new toast selectors below + // TODO: Remove deprecated selectors and usages after migrating all toasts public readonly toastHeader: Locator public readonly toastBody: Locator @@ -17,6 +19,15 @@ export class Toast extends BasePage { public readonly toastCancelBtn: Locator + // New toast selectors + public readonly toastContainer: Locator + + public readonly toastMessage: Locator + + public readonly toastDescription: Locator + + public readonly toastActionButton: Locator + constructor(page: Page) { super(page) this.toastHeader = page.locator(ToastSelectors.toastHeader) @@ -26,6 +37,12 @@ export class Toast extends BasePage { this.toastCloseButton = page.locator(ToastSelectors.toastCloseButton) this.toastSubmitBtn = page.getByTestId(ToastSelectors.toastSubmitBtn) this.toastCancelBtn = page.getByTestId(ToastSelectors.toastCancelBtn) + + // New toast selectors + this.toastContainer = page.locator(ToastSelectors.toastContainer) + this.toastMessage = page.locator(ToastSelectors.toastMessage) + this.toastDescription = page.locator(ToastSelectors.toastDescription) + this.toastActionButton = page.locator(ToastSelectors.toastActionButton) } async isCloseButtonVisible(): Promise { @@ -33,6 +50,6 @@ export class Toast extends BasePage { } async closeToast(): Promise { - await this.toastCloseButton.click() + await this.toastActionButton.click() } } diff --git a/tests/playwright/selectors/toast-selectors.ts b/tests/playwright/selectors/toast-selectors.ts index 8d60edd874..6de445b50b 100644 --- a/tests/playwright/selectors/toast-selectors.ts +++ b/tests/playwright/selectors/toast-selectors.ts @@ -1,4 +1,6 @@ export const ToastSelectors = { + // Deprecated - use new toast selectors below + // TODO: Remove deprecated selectors and usages after migrating all toasts toastHeader: '[data-test-subj=euiToastHeader]', toastBody: '[class*=euiToastBody]', toastSuccess: '[class*=euiToast--success]', @@ -6,4 +8,10 @@ export const ToastSelectors = { toastCloseButton: '[data-test-subj=toastCloseButton]', toastSubmitBtn: 'submit-tooltip-btn', toastCancelBtn: 'toast-cancel-btn', + + // New selectors - use these for new toasts + toastContainer: '[data-testid="redisui-toast"]', + toastMessage: '[data-testid="redisui-toast-message"]', + toastDescription: '[data-testid="redisui-toast-description"]', + toastActionButton: '[data-testid="redisui-toast-action-button"]', } From 105ee22e29e00348e2863d3937e57b39f564a76b Mon Sep 17 00:00:00 2001 From: Valentin Kirilov Date: Thu, 11 Sep 2025 09:20:27 +0300 Subject: [PATCH 7/8] test(e2e): update the toast verification helper --- .../pages/vector-search/create-index-page.ts | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/tests/playwright/pageObjects/pages/vector-search/create-index-page.ts b/tests/playwright/pageObjects/pages/vector-search/create-index-page.ts index 894625a985..99fd285744 100644 --- a/tests/playwright/pageObjects/pages/vector-search/create-index-page.ts +++ b/tests/playwright/pageObjects/pages/vector-search/create-index-page.ts @@ -180,14 +180,9 @@ export class CreateIndexPage extends BasePage { expectedMessage: string, timeout = 2000, ): Promise { - try { - await this.waitForLocatorVisible(this.toast.toastSuccess, timeout) - await expect(this.toast.toastBody).toContainText(expectedMessage) - await this.toast.closeToast() - } catch { - // No toast appeared - this is acceptable for some actions - // Success is typically verified by other means (navigation, etc.) - } + await this.waitForLocatorVisible(this.toast.toastContainer, timeout) + await expect(this.toast.toastMessage).toContainText(expectedMessage) + await this.toast.closeToast() } async clickCancelButton(): Promise { From 9c179fe294436cd2dbac4756093119402f4b5c75 Mon Sep 17 00:00:00 2001 From: Valentin Kirilov Date: Thu, 11 Sep 2025 09:25:54 +0300 Subject: [PATCH 8/8] test(e2e): update the database instance for the create index tests --- tests/playwright/tests/vector-search/create-index.spec.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/playwright/tests/vector-search/create-index.spec.ts b/tests/playwright/tests/vector-search/create-index.spec.ts index 14314b74c4..a641767956 100644 --- a/tests/playwright/tests/vector-search/create-index.spec.ts +++ b/tests/playwright/tests/vector-search/create-index.spec.ts @@ -10,6 +10,7 @@ import { navigateToStandaloneInstance, } from '../../helpers/utils' import { CreateIndexPage } from '../../pageObjects/pages/vector-search/create-index-page' +import { ossStandaloneV6Config } from '../../helpers/conf' test.describe('Vector Search - Create Index', () => { let searchPage: VectorSearchPage @@ -22,9 +23,10 @@ test.describe('Vector Search - Create Index', () => { cleanupInstance = await addStandaloneInstanceAndNavigateToIt( page, databaseService, + ossStandaloneV6Config, ) - await navigateToStandaloneInstance(page) + await navigateToStandaloneInstance(page, ossStandaloneV6Config) await searchPage.navigateToVectorSearchPage() await searchPage.navigateToCreateIndexPage() })