Skip to content

RI-6570 Verify edit list key operations for in the browsers module #4732

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 114 additions & 2 deletions tests/playwright/pageObjects/browser-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,9 @@ export class BrowserPage extends BasePage {
this.hashFieldNameInput = page.getByTestId('field-name')
this.hashFieldValueEditor = page.getByTestId('hash_value-editor')
this.hashTtlFieldInput = page.getByTestId('hash-ttl')
this.listKeyElementEditorInput = page.getByTestId('list_value-editor-')
this.listKeyElementEditorInput = page.locator(
'[data-testid^="list_value-editor-"]',
)
this.stringKeyValueInput = page.getByTestId('string-value')
this.jsonKeyValueInput = page.locator('div[data-mode-id=json] textarea')
this.jsonUploadInput = page.getByTestId('upload-input-file')
Expand Down Expand Up @@ -1019,7 +1021,11 @@ export class BrowserPage extends BasePage {
async editListKeyValue(value: string): Promise<void> {
await this.listElementsList.hover()
await this.editListButton.click()
await this.listKeyElementEditorInput.fill(value, {

// Wait for any list editor to appear - this is a legacy method
const editorInput = this.listKeyElementEditorInput.first()
await expect(editorInput).toBeVisible()
await editorInput.fill(value, {
timeout: 0,
noWaitAfter: false,
})
Expand Down Expand Up @@ -1718,4 +1724,110 @@ export class BrowserPage extends BasePage {
})
.toContain(expectedValue)
}
async editListElementValue(newValue: string): Promise<void> {
await this.listElementsList.first().hover()
await this.editListButton.first().click()

// Wait for any list editor to appear - don't assume specific index
const editorInput = this.listKeyElementEditorInput.first()
await expect(editorInput).toBeVisible()
await editorInput.fill(newValue, {
timeout: 0,
noWaitAfter: false,
})
await this.applyButton.click()

// Wait for the editor to close and changes to be applied
await expect(editorInput).not.toBeVisible()

// Wait for the new value to appear in the first list element
await expect(this.listElementsList.first()).toContainText(newValue)
}

async cancelListElementEdit(newValue: string): Promise<void> {
await this.listElementsList.first().hover()
await this.editListButton.first().click()

// Wait for any list editor to appear - don't assume specific index
const editorInput = this.listKeyElementEditorInput.first()
await expect(editorInput).toBeVisible()
await editorInput.fill(newValue, {
timeout: 0,
noWaitAfter: false,
})

// Cancel using Escape key
await this.page.keyboard.press('Escape')

// Wait for the editor to close
await expect(editorInput).not.toBeVisible()
}

async addElementsToList(
elements: string[],
position: AddElementInList = AddElementInList.Tail,
): Promise<void> {
if (await this.toast.isCloseButtonVisible()) {
await this.toast.closeToast()
}
await this.addKeyValueItemsButton.click()

if (position === AddElementInList.Head) {
await this.removeElementFromListSelect.click()
await this.removeFromHeadSelection.click()
await expect(this.removeFromHeadSelection).not.toBeVisible()
}

for (let i = 0; i < elements.length; i += 1) {
await this.getListElementInput(i).click()
await this.getListElementInput(i).fill(elements[i])
if (elements.length > 1 && i < elements.length - 1) {
await this.addAdditionalElement.click()
}
}
await this.saveElementButton.click()
}

async removeListElementsFromTail(count: number): Promise<void> {
await this.removeElementFromListIconButton.click()
await this.countInput.fill(count.toString())
await this.removeElementFromListButton.click()
await this.confirmRemoveListElementButton.click()
}

async removeListElementsFromHead(count: number): Promise<void> {
await this.removeElementFromListIconButton.click()
await this.countInput.fill(count.toString())
await this.removeElementFromListSelect.click()
await this.removeFromHeadSelection.click()
await this.removeElementFromListButton.click()
await this.confirmRemoveListElementButton.click()
}

async verifyListContainsElements(
expectedElements: string[],
): Promise<void> {
const displayedElements = await this.getAllListElements()
expectedElements.forEach((expectedElement) => {
expect(displayedElements).toContain(expectedElement)
})
}

async verifyListDoesNotContainElements(
unwantedElements: string[],
): Promise<void> {
const displayedElements = await this.getAllListElements()
unwantedElements.forEach((unwantedElement) => {
expect(displayedElements).not.toContain(unwantedElement)
})
}

async waitForListLengthToUpdate(expectedLength: number): Promise<void> {
await expect
.poll(async () => {
const keyLength = await this.getKeyLength()
return parseInt(keyLength, 10)
})
.toBe(expectedLength)
}
}
248 changes: 248 additions & 0 deletions tests/playwright/tests/browser/keys-edit/edit-list-key.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
import { faker } from '@faker-js/faker'

import { BrowserPage } from '../../../pageObjects/browser-page'
import { test, expect } from '../../../fixtures/test'
import { ossStandaloneConfig } from '../../../helpers/conf'
import { AddElementInList } from '../../../helpers/constants'
import {
addStandaloneInstanceAndNavigateToIt,
navigateToStandaloneInstance,
} from '../../../helpers/utils'

test.describe('Browser - Edit Key Operations - List Key Editing', () => {
let browserPage: BrowserPage
let keyName: string
let cleanupInstance: () => Promise<void>

test.beforeEach(async ({ page, api: { databaseService } }) => {
browserPage = new BrowserPage(page)
keyName = faker.string.alphanumeric(10)
cleanupInstance = await addStandaloneInstanceAndNavigateToIt(
page,
databaseService,
)

await navigateToStandaloneInstance(page)
})

test.afterEach(async ({ api: { keyService } }) => {
// Clean up: delete the key if it exists
try {
await keyService.deleteKeyByNameApi(
keyName,
ossStandaloneConfig.databaseName,
)
} catch (error) {
// Key might already be deleted in test, ignore error
}

await cleanupInstance()
})

test('should edit list element value successfully', async ({
api: { keyService },
}) => {
// Arrange: Create a list key with multiple elements
const listElements = [
faker.lorem.word(),
faker.lorem.word(),
faker.lorem.word(),
]
const newElementValue = faker.lorem.word()

await keyService.addListKeyApi(
{ keyName, elements: listElements },
ossStandaloneConfig,
)

// Open key details and verify initial content
await browserPage.openKeyDetailsAndVerify(keyName)
await browserPage.verifyListContainsElements(listElements)
await browserPage.verifyKeyLength(listElements.length.toString())

// Edit the first element value
await browserPage.editListElementValue(newElementValue)

// Verify the element was updated
await browserPage.verifyListContainsElements([newElementValue])
await browserPage.verifyListDoesNotContainElements([listElements[0]])
await browserPage.verifyKeyLength(listElements.length.toString()) // Length should remain the same
})

test('should cancel list element edit successfully', async ({
api: { keyService },
}) => {
// Arrange: Create a list key
const listElements = [faker.lorem.word(), faker.lorem.word()]
const attemptedValue = faker.lorem.word()

await keyService.addListKeyApi(
{ keyName, elements: listElements },
ossStandaloneConfig,
)

// Open key details and start edit but cancel
await browserPage.openKeyDetailsAndVerify(keyName)
await browserPage.verifyListContainsElements(listElements)

// Start edit but cancel
await browserPage.cancelListElementEdit(attemptedValue)

// Verify original content is preserved
await browserPage.verifyListContainsElements(listElements)
await browserPage.verifyListDoesNotContainElements([attemptedValue])
})

test('should add elements to list tail successfully', async ({
api: { keyService },
}) => {
// Arrange: Create a list key with initial elements
const initialElements = [faker.lorem.word(), faker.lorem.word()]
const newElements = [faker.lorem.word(), faker.lorem.word()]

await keyService.addListKeyApi(
{ keyName, elements: initialElements },
ossStandaloneConfig,
)

// Open key details and add elements to tail
await browserPage.openKeyDetailsAndVerify(keyName)
await browserPage.verifyListContainsElements(initialElements)

await browserPage.addElementsToList(newElements, AddElementInList.Tail)

// Verify all elements are present and length is updated
const expectedLength = initialElements.length + newElements.length
await browserPage.waitForListLengthToUpdate(expectedLength)
await browserPage.verifyListContainsElements([
...initialElements,
...newElements,
])
})

test('should add elements to list head successfully', async ({
api: { keyService },
}) => {
// Arrange: Create a list key with initial elements
const initialElements = [faker.lorem.word(), faker.lorem.word()]
const newElements = [faker.lorem.word()]

await keyService.addListKeyApi(
{ keyName, elements: initialElements },
ossStandaloneConfig,
)

// Open key details and add elements to head
await browserPage.openKeyDetailsAndVerify(keyName)
await browserPage.verifyListContainsElements(initialElements)

await browserPage.addElementsToList(newElements, AddElementInList.Head)

// Verify all elements are present and length is updated
const expectedLength = initialElements.length + newElements.length
await browserPage.waitForListLengthToUpdate(expectedLength)
await browserPage.verifyListContainsElements([
...newElements,
...initialElements,
])
})

test('should remove elements from list tail successfully', async ({
api: { keyService },
}) => {
// Arrange: Create a list key with multiple elements
const listElements = [
faker.lorem.word(),
faker.lorem.word(),
faker.lorem.word(),
faker.lorem.word(),
]
const removeCount = 2

await keyService.addListKeyApi(
{ keyName, elements: listElements },
ossStandaloneConfig,
)

// Open key details and remove elements from tail
await browserPage.openKeyDetailsAndVerify(keyName)
await browserPage.verifyListContainsElements(listElements)

await browserPage.removeListElementsFromTail(removeCount)

// Verify length is updated (Redis lists remove from the right/tail)
const expectedLength = listElements.length - removeCount
await browserPage.waitForListLengthToUpdate(expectedLength)
await browserPage.verifyKeyLength(expectedLength.toString())

// Verify the correct elements were removed (last 2 elements should be gone)
const remainingElements = listElements.slice(0, -removeCount) // Keep all but last 2
const removedElements = listElements.slice(-removeCount) // Last 2 elements
await browserPage.verifyListContainsElements(remainingElements)
await browserPage.verifyListDoesNotContainElements(removedElements)
})

test('should remove elements from list head successfully', async ({
api: { keyService },
}) => {
// Arrange: Create a list key with multiple elements
const listElements = [
faker.lorem.word(),
faker.lorem.word(),
faker.lorem.word(),
faker.lorem.word(),
]
const removeCount = 1

await keyService.addListKeyApi(
{ keyName, elements: listElements },
ossStandaloneConfig,
)

// Open key details and remove elements from head
await browserPage.openKeyDetailsAndVerify(keyName)
await browserPage.verifyListContainsElements(listElements)

await browserPage.removeListElementsFromHead(removeCount)

// Verify length is updated (Redis lists remove from the left/head)
const expectedLength = listElements.length - removeCount
await browserPage.waitForListLengthToUpdate(expectedLength)
await browserPage.verifyKeyLength(expectedLength.toString())

// Verify the correct elements were removed (first element should be gone)
const remainingElements = listElements.slice(removeCount) // Skip first element
const removedElements = listElements.slice(0, removeCount) // First element
await browserPage.verifyListContainsElements(remainingElements)
await browserPage.verifyListDoesNotContainElements(removedElements)
})

test('should handle removing all elements from list', async ({
api: { keyService },
}) => {
// Arrange: Create a list key with a few elements
const listElements = [faker.lorem.word(), faker.lorem.word()]

await keyService.addListKeyApi(
{ keyName, elements: listElements },
ossStandaloneConfig,
)

// Open key details and remove all elements
await browserPage.openKeyDetailsAndVerify(keyName)
await browserPage.verifyListContainsElements(listElements)

await browserPage.removeListElementsFromTail(listElements.length)

// Verify list is empty (key should be removed when list becomes empty)
await expect
.poll(async () => {
try {
return await browserPage.isKeyDetailsOpen(keyName)
} catch {
return false
}
})
.toBe(false)
})
})
Loading