test: Add e2e test for IME input (#2267)

* test: Add e2e test for IME input

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>

* fix: Unify translation for label and placeholder

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>

---------

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
This commit is contained in:
Ferdinand Thiessen 2024-08-06 23:00:06 +02:00 коммит произвёл GitHub
Родитель f18c6f3f7e
Коммит b7d9f79015
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
6 изменённых файлов: 133 добавлений и 3 удалений

Просмотреть файл

@ -0,0 +1,77 @@
import { expect, mergeTests } from '@playwright/test'
import { test as randomUserTest } from '../support/fixtures/random-user'
import { test as appNavigationTest } from '../support/fixtures/navigation'
import { test as formTest } from '../support/fixtures/form'
import { QuestionType } from '../support/sections/QuestionType'
const test = mergeTests(randomUserTest, appNavigationTest, formTest)
test.beforeEach(async ({ page }) => {
await page.goto('apps/forms')
await page.waitForURL(/apps\/forms$/)
})
test(
'IME input does not trigger new option',
{
annotation: {
type: 'issue',
description: 'https://github.com/nextcloud/forms/issues/2220',
},
},
async ({ browserName, appNavigation, page, form }) => {
test.skip(
browserName !== 'chromium',
'IME testing is currently only implemented in Chromium API',
)
// Now get the developer tools API
const client = await page.context().newCDPSession(page)
// Create a new form
await appNavigation.clickNewForm()
await form.fillTitle('Example')
// Create a new Drop down question
await form.addQuestion(QuestionType.Dropdown)
const question = (await form.getQuestions()).at(-1)!
// expect there is question
expect(question).not.toBe(undefined)
// Add the title
await question.fillTitle('IME input')
// no answers yet
await expect(question.answerInputs).toHaveCount(0)
// Start composing a new name by focussing the input and composing
await question.newAnswerInput.focus()
await client.send('Input.imeSetComposition', {
selectionStart: -1,
selectionEnd: -1,
text: '',
})
await expect(question.newAnswerInput).toHaveValue('')
await expect(question.answerInputs).toHaveCount(0) // not committed yet
await client.send('Input.imeSetComposition', {
selectionStart: 0,
selectionEnd: 1,
text: 's',
})
await expect(question.newAnswerInput).toHaveValue('s')
await expect(question.answerInputs).toHaveCount(0) // not committed yet
await client.send('Input.imeSetComposition', {
selectionStart: 0,
selectionEnd: 2,
text: 'sa',
})
await expect(question.newAnswerInput).toHaveValue('sa')
await expect(question.answerInputs).toHaveCount(0) // not committed yet
await client.send('Input.insertText', {
text: 'さ',
})
// so there were 4 inputs but those should only result in one new option
await expect(question.answerInputs).toHaveCount(1)
await expect(question.answerInputs).toHaveValue('さ')
},
)

Просмотреть файл

@ -29,6 +29,7 @@ export class AppNavigationSection {
public async clickNewForm(): Promise<void> {
await this.newFormLocator.click()
await this.page.waitForURL(/apps\/forms\/.+/)
}
public async openArchivedForms(): Promise<void> {

Просмотреть файл

@ -4,14 +4,20 @@
*/
import type { Locator, Page } from '@playwright/test'
import type { QuestionType } from './QuestionType'
import { QuestionSection } from './QuestionSection'
export class FormSection {
public readonly mainContent: Locator
public readonly titleField: Locator
public readonly newQuestionButton: Locator
// eslint-disable-next-line no-useless-constructor
constructor(public readonly page: Page) {
this.mainContent = this.page.getByRole('main')
this.newQuestionButton = this.page.getByRole('button', {
name: 'Add a question',
})
this.titleField = this.mainContent.getByRole('textbox', {
name: 'Form title',
})
@ -20,4 +26,18 @@ export class FormSection {
public async fillTitle(text: string): Promise<void> {
await this.titleField.fill(text)
}
public async addQuestion(type: QuestionType): Promise<void> {
await this.newQuestionButton.click()
await this.page.getByRole('menuitem', { name: type }).click()
}
public async getQuestions(): Promise<QuestionSection[]> {
return this.page
.locator('main section')
.all()
.then((sections) =>
sections.map((section) => new QuestionSection(this.page, section)),
)
}
}

Просмотреть файл

@ -0,0 +1,30 @@
/**
* SPDX-FileCopyrightText: 2024 Ferdinand Thiessen <opensource@fthiessen.de>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import type { Locator, Page } from '@playwright/test'
export class QuestionSection {
public readonly titleInput: Locator
public readonly newAnswerInput: Locator
public readonly answerInputs: Locator
// eslint-disable-next-line no-useless-constructor
constructor(
public readonly page: Page,
public readonly section: Locator,
) {
this.titleInput = this.section.getByRole('textbox', { name: /title of/i })
this.newAnswerInput = this.section.getByRole('textbox', {
name: 'Add a new answer',
})
this.answerInputs = this.section.getByRole('textbox', {
name: /Answer number \d+/i,
})
}
async fillTitle(title: string): Promise<void> {
await this.titleInput.fill(title)
}
}

Просмотреть файл

@ -0,0 +1,4 @@
export enum QuestionType {
Checkboxes = 'Checkboxes',
Dropdown = 'Dropdown',
}

Просмотреть файл

@ -6,9 +6,7 @@
class="question__item__pseudoInput" />
<input
ref="input"
:aria-label="
t('forms', 'An answer for the {index} option', { index: index + 1 })
"
:aria-label="t('forms', 'Answer number {index}', { index: index + 1 })"
:placeholder="t('forms', 'Answer number {index}', { index: index + 1 })"
:value="answer.text"
class="question__input"