From ef2959e16506343e96fc6fd06a60914e6907682c Mon Sep 17 00:00:00 2001 From: BharathKShetty Date: Fri, 15 Aug 2025 20:31:51 +0530 Subject: [PATCH 01/10] Workflow 1: Basic Translation Builder Display --- e2e/pages/form-builder-page.ts | 14 ++++ .../translation-builder-workflows.spec.ts | 66 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 e2e/specs/translation-builder-workflows.spec.ts diff --git a/e2e/pages/form-builder-page.ts b/e2e/pages/form-builder-page.ts index d39ba95f3..474a92029 100644 --- a/e2e/pages/form-builder-page.ts +++ b/e2e/pages/form-builder-page.ts @@ -71,6 +71,20 @@ export class FormBuilderPage { readonly questionIdInput = () => this.page.getByRole('textbox', { name: /question id/i }); readonly questionCreatedMessage = () => this.page.getByText(/new question created/i); + readonly translationBuilderTab = () => this.page.getByRole('tab', { name: /translation builder/i }); + readonly languageDropdown = () => this.page.getByRole('combobox', { name: 'target-language' }); + readonly downloadTranslationButton = () => this.page.getByRole('button', { name: /download translation/i }); + readonly uploadTranslationButton = () => this.page.getByRole('button', { name: /upload translation/i }); + readonly translationSearchInput = () => this.page.getByPlaceholder(/search translation keys/i); + readonly allTranslationsTab = () => this.page.getByRole('tab', { name: 'All' }); + readonly translatedTab = () => this.page.getByRole('tab', { name: 'Translated' }); + readonly untranslatedTab = () => this.page.getByRole('tab', { name: 'Untranslated' }); + readonly editTranslationButton = (index: number = 0) => + this.page.locator('[data-testid="edit-translation-button"]').nth(index); + readonly translationModal = () => this.page.getByRole('dialog'); + readonly translationValueInput = () => this.page.getByLabel(/translation value/i); + readonly saveTranslationButton = () => this.page.getByRole('button', { name: /save/i }); + async gotoFormBuilder() { await this.page.goto('form-builder'); } diff --git a/e2e/specs/translation-builder-workflows.spec.ts b/e2e/specs/translation-builder-workflows.spec.ts new file mode 100644 index 000000000..2b49e7f66 --- /dev/null +++ b/e2e/specs/translation-builder-workflows.spec.ts @@ -0,0 +1,66 @@ +/* eslint-disable testing-library/prefer-screen-queries */ +import { test } from '../core'; +import { expect } from '@playwright/test'; +import { deleteForm, createForm, createValueReference, addFormResources } from '../commands/form-operations'; +import { FormBuilderPage } from '../pages'; + +let formUuid = ''; + +const formDetails = { + name: 'Covid-19 Screening', + description: 'A test form for recording COVID-19 screening information', + version: '1.0', + published: true, +}; + +test.describe('Translation Builder Workflows', () => { + test.beforeEach(async ({ api }) => { + const form = await createForm(api, false, formDetails); + formUuid = form.uuid; + + const valueReference = await createValueReference(api); + await addFormResources(api, valueReference, formUuid); + }); + + test.afterEach(async ({ api }) => { + if (formUuid) { + await deleteForm(api, formUuid); + } + }); + + test('Workflow 1: Basic Translation Builder Display', async ({ page }) => { + const formBuilderPage = new FormBuilderPage(page); + + await test.step('Navigate to form builder', async () => { + await formBuilderPage.gotoFormBuilder(); + }); + + await test.step('Search and open the test form', async () => { + await formBuilderPage.searchForForm(formDetails.name); + await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); + }); + + await test.step('Open translation builder tab', async () => { + await formBuilderPage.translationBuilderTab().click(); + }); + + await test.step('Verify translation builder components are displayed', async () => { + const translationPanel = formBuilderPage.page + .getByRole('tabpanel') + .filter({ has: formBuilderPage.page.getByRole('button', { name: /upload translation/i }) }); + + await expect(translationPanel).toBeVisible(); + await expect(translationPanel.getByRole('button', { name: /download translation/i })).toBeVisible(); + await expect(translationPanel.getByRole('button', { name: /upload translation/i })).toBeVisible(); + const tabList = translationPanel.getByRole('tablist', { name: 'Translation filter' }); + await expect(tabList).toBeVisible(); + + const tabs = tabList.getByRole('tab'); + await expect(tabs).toHaveCount(3); + await expect(tabs.nth(0)).toContainText(/all/i); + await expect(tabs.nth(1)).toContainText(/translated/i); + await expect(tabs.nth(2)).toContainText(/untranslated/i); + await expect(translationPanel.getByPlaceholder(/search translation keys/i)).toBeVisible(); + }); + }); +}); From f6514ea5f9c016c6c420f32ac160c8fe78b29e3c Mon Sep 17 00:00:00 2001 From: BharathKShetty Date: Fri, 15 Aug 2025 21:26:58 +0530 Subject: [PATCH 02/10] Workflow 2: Language Selection and Switching --- e2e/pages/form-builder-page.ts | 4 ++- .../translation-builder-workflows.spec.ts | 32 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/e2e/pages/form-builder-page.ts b/e2e/pages/form-builder-page.ts index 474a92029..50ff28304 100644 --- a/e2e/pages/form-builder-page.ts +++ b/e2e/pages/form-builder-page.ts @@ -72,7 +72,9 @@ export class FormBuilderPage { readonly questionCreatedMessage = () => this.page.getByText(/new question created/i); readonly translationBuilderTab = () => this.page.getByRole('tab', { name: /translation builder/i }); - readonly languageDropdown = () => this.page.getByRole('combobox', { name: 'target-language' }); + readonly translationBuilderPanel = () => + this.page.getByRole('tabpanel').filter({ has: this.page.getByRole('button', { name: /upload translation/i }) }); + readonly languageDropdown = () => this.translationBuilderPanel().locator('#target-language'); readonly downloadTranslationButton = () => this.page.getByRole('button', { name: /download translation/i }); readonly uploadTranslationButton = () => this.page.getByRole('button', { name: /upload translation/i }); readonly translationSearchInput = () => this.page.getByPlaceholder(/search translation keys/i); diff --git a/e2e/specs/translation-builder-workflows.spec.ts b/e2e/specs/translation-builder-workflows.spec.ts index 2b49e7f66..421c7cd05 100644 --- a/e2e/specs/translation-builder-workflows.spec.ts +++ b/e2e/specs/translation-builder-workflows.spec.ts @@ -63,4 +63,36 @@ test.describe('Translation Builder Workflows', () => { await expect(translationPanel.getByPlaceholder(/search translation keys/i)).toBeVisible(); }); }); + + test('Workflow 2: Language Selection and Switching', async ({ page }) => { + const formBuilderPage = new FormBuilderPage(page); + + await test.step('Navigate to form builder and open translation builder', async () => { + await formBuilderPage.gotoFormBuilder(); + await formBuilderPage.searchForForm(formDetails.name); + await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); + await formBuilderPage.translationBuilderTab().click(); + await expect(formBuilderPage.downloadTranslationButton()).toBeVisible(); + }); + + await test.step('Verify language dropdown is present and functional', async () => { + const languageDropdown = formBuilderPage.languageDropdown(); + await expect(languageDropdown).toBeVisible(); + await expect(languageDropdown).toBeEnabled(); + }); + + await test.step('Open language dropdown and verify available languages', async () => { + await formBuilderPage.languageDropdown().click(); + + const dropdownMenu = formBuilderPage.translationBuilderPanel().locator('.cds--list-box__menu'); + await expect(dropdownMenu).toBeVisible(); + + const languageOptions = dropdownMenu.getByRole('option'); + const optionCount = await languageOptions.count(); + expect(optionCount).toBeGreaterThan(0); + + await expect(dropdownMenu.getByRole('option', { name: 'English (en)' })).toBeVisible(); + await expect(languageOptions.nth(1)).toBeVisible(); + }); + }); }); From 2bec8c3179d3c61f4e05f92c2ab9e41c69c08528 Mon Sep 17 00:00:00 2001 From: BharathKShetty Date: Thu, 21 Aug 2025 17:30:37 +0530 Subject: [PATCH 03/10] Added remaining e2e tests to Translation Builder --- e2e/pages/form-builder-page.ts | 26 +- .../translation-builder-workflows.spec.ts | 353 +++++++++++++++++- .../edit-translation.modal.tsx | 1 + .../translation-builder.component.tsx | 16 +- 4 files changed, 377 insertions(+), 19 deletions(-) diff --git a/e2e/pages/form-builder-page.ts b/e2e/pages/form-builder-page.ts index 50ff28304..668d098a3 100644 --- a/e2e/pages/form-builder-page.ts +++ b/e2e/pages/form-builder-page.ts @@ -73,20 +73,28 @@ export class FormBuilderPage { readonly translationBuilderTab = () => this.page.getByRole('tab', { name: /translation builder/i }); readonly translationBuilderPanel = () => - this.page.getByRole('tabpanel').filter({ has: this.page.getByRole('button', { name: /upload translation/i }) }); + this.page + .getByRole('tabpanel') + .filter({ has: this.page.getByRole('button', { name: /upload translation/i }) }) + .first(); readonly languageDropdown = () => this.translationBuilderPanel().locator('#target-language'); - readonly downloadTranslationButton = () => this.page.getByRole('button', { name: /download translation/i }); - readonly uploadTranslationButton = () => this.page.getByRole('button', { name: /upload translation/i }); + readonly downloadTranslationButton = () => + this.translationBuilderPanel().getByRole('button', { name: /download translation/i }); + readonly uploadTranslationButton = () => + this.translationBuilderPanel().getByRole('button', { name: /upload translation/i }); readonly translationSearchInput = () => this.page.getByPlaceholder(/search translation keys/i); - readonly allTranslationsTab = () => this.page.getByRole('tab', { name: 'All' }); - readonly translatedTab = () => this.page.getByRole('tab', { name: 'Translated' }); - readonly untranslatedTab = () => this.page.getByRole('tab', { name: 'Untranslated' }); + readonly translationTabsList = () => + this.translationBuilderPanel().getByRole('tablist', { name: 'Translation filter' }); + readonly allTranslationsTab = () => this.translationTabsList().getByRole('tab', { name: 'All', exact: true }); + readonly translatedTab = () => this.translationTabsList().getByRole('tab', { name: 'Translated', exact: true }); + readonly untranslatedTab = () => this.translationTabsList().getByRole('tab', { name: 'Untranslated', exact: true }); readonly editTranslationButton = (index: number = 0) => this.page.locator('[data-testid="edit-translation-button"]').nth(index); readonly translationModal = () => this.page.getByRole('dialog'); - readonly translationValueInput = () => this.page.getByLabel(/translation value/i); - readonly saveTranslationButton = () => this.page.getByRole('button', { name: /save/i }); - + translationValueInput() { + return this.page.getByTestId('translation-value-input'); + } + readonly saveTranslationButton = () => this.translationModal().getByRole('button', { name: 'Save' }); async gotoFormBuilder() { await this.page.goto('form-builder'); } diff --git a/e2e/specs/translation-builder-workflows.spec.ts b/e2e/specs/translation-builder-workflows.spec.ts index 421c7cd05..a66db18ad 100644 --- a/e2e/specs/translation-builder-workflows.spec.ts +++ b/e2e/specs/translation-builder-workflows.spec.ts @@ -1,4 +1,5 @@ /* eslint-disable testing-library/prefer-screen-queries */ + import { test } from '../core'; import { expect } from '@playwright/test'; import { deleteForm, createForm, createValueReference, addFormResources } from '../commands/form-operations'; @@ -31,20 +32,20 @@ test.describe('Translation Builder Workflows', () => { test('Workflow 1: Basic Translation Builder Display', async ({ page }) => { const formBuilderPage = new FormBuilderPage(page); - await test.step('Navigate to form builder', async () => { + await test.step('When I visit the form builder', async () => { await formBuilderPage.gotoFormBuilder(); }); - await test.step('Search and open the test form', async () => { + await test.step('And I search for the form and open it for editing', async () => { await formBuilderPage.searchForForm(formDetails.name); await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); }); - await test.step('Open translation builder tab', async () => { + await test.step('And I open the Translation builder tab', async () => { await formBuilderPage.translationBuilderTab().click(); }); - await test.step('Verify translation builder components are displayed', async () => { + await test.step('Then I should see the translation builder components (Download/Upload buttons, Translation filter tabs: All/Translated/Untranslated, and the search input)', async () => { const translationPanel = formBuilderPage.page .getByRole('tabpanel') .filter({ has: formBuilderPage.page.getByRole('button', { name: /upload translation/i }) }); @@ -67,21 +68,30 @@ test.describe('Translation Builder Workflows', () => { test('Workflow 2: Language Selection and Switching', async ({ page }) => { const formBuilderPage = new FormBuilderPage(page); - await test.step('Navigate to form builder and open translation builder', async () => { + await test.step('When I visit the form builder', async () => { await formBuilderPage.gotoFormBuilder(); + }); + + await test.step('And I search for the form and open it for editing', async () => { await formBuilderPage.searchForForm(formDetails.name); await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); + }); + + await test.step('And I open the Translation builder tab', async () => { await formBuilderPage.translationBuilderTab().click(); + }); + + await test.step('Then I should see the translation builder components (Download/Upload buttons, Translation filter tabs: All/Translated/Untranslated, and the search input)', async () => { await expect(formBuilderPage.downloadTranslationButton()).toBeVisible(); }); - await test.step('Verify language dropdown is present and functional', async () => { + await test.step('And the language dropdown is present and functional', async () => { const languageDropdown = formBuilderPage.languageDropdown(); await expect(languageDropdown).toBeVisible(); await expect(languageDropdown).toBeEnabled(); }); - await test.step('Open language dropdown and verify available languages', async () => { + await test.step('When I open the language dropdown and view available languages', async () => { await formBuilderPage.languageDropdown().click(); const dropdownMenu = formBuilderPage.translationBuilderPanel().locator('.cds--list-box__menu'); @@ -95,4 +105,333 @@ test.describe('Translation Builder Workflows', () => { await expect(languageOptions.nth(1)).toBeVisible(); }); }); + + test('Workflow 3: Translation Filtering by Tabs', async ({ page }) => { + const formBuilderPage = new FormBuilderPage(page); + + await test.step('When I visit the form builder', async () => { + await formBuilderPage.gotoFormBuilder(); + }); + + await test.step('And I search for the form and open it for editing', async () => { + await formBuilderPage.searchForForm(formDetails.name); + await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); + }); + + await test.step('And I open the Translation builder tab', async () => { + await formBuilderPage.translationBuilderTab().click(); + }); + + await test.step('Then I should see the translation builder actions', async () => { + await expect(formBuilderPage.downloadTranslationButton()).toBeVisible(); + }); + const allEntries = page.locator('[data-testid="translation-entry"]'); + const totalEntries = await allEntries.count(); + + await test.step('When I click on the All translations tab', async () => { + await formBuilderPage.allTranslationsTab().click(); + await expect(formBuilderPage.allTranslationsTab()).toHaveAttribute('aria-selected', 'true'); + }); + + await test.step('Then I should see all translation entries', async () => { + const entries = formBuilderPage.page.locator('[data-testid="translation-entry"]'); + await expect(entries.first()).toBeVisible(); + }); + + await test.step('When I click on the Translated tab', async () => { + await formBuilderPage.translatedTab().click(); + const translatedEntries = page.locator('[data-status="translated"]'); + await expect(translatedEntries).toHaveCount(0); + }); + + await test.step('When I click on the Untranslated tab', async () => { + await formBuilderPage.untranslatedTab().click(); + await expect(formBuilderPage.untranslatedTab()).toHaveAttribute('aria-selected', 'true'); + + const untranslatedEntries = page.locator('[data-status="untranslated"]'); + await expect(untranslatedEntries.first()).toBeVisible(); + + const totalEntries = await page.locator('[data-testid="translation-entry"]').count(); + + await expect(untranslatedEntries).toHaveCount(totalEntries); + }); + }); + + test('Workflow 4: Translation Search Functionality', async ({ page }) => { + const formBuilderPage = new FormBuilderPage(page); + + await test.step('When I visit the form builder', async () => { + await formBuilderPage.gotoFormBuilder(); + }); + + await test.step('And I search for the form and open it for editing', async () => { + await formBuilderPage.searchForForm(formDetails.name); + await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); + }); + + await test.step('And I open the Translation builder tab', async () => { + await formBuilderPage.translationBuilderTab().click(); + }); + + await test.step('Then I should see the translation builder actions', async () => { + await expect(formBuilderPage.downloadTranslationButton()).toBeVisible(); + }); + + await test.step('And the search input is present and functional', async () => { + const searchInput = formBuilderPage.translationSearchInput(); + await expect(searchInput).toBeVisible(); + await expect(searchInput).toBeEnabled(); + }); + + await test.step('When I type in the search input', async () => { + const searchInput = formBuilderPage.translationSearchInput(); + + await searchInput.fill('test'); + await expect(searchInput).toHaveValue('test'); + }); + + await test.step('Then the search input should contain the typed text', async () => { + const searchInput = formBuilderPage.translationSearchInput(); + await expect(searchInput).toHaveValue('test'); + }); + + await test.step('When I clear the search input', async () => { + const searchInput = formBuilderPage.translationSearchInput(); + await searchInput.clear(); + }); + + await test.step('Then the search input should be empty', async () => { + const searchInput = formBuilderPage.translationSearchInput(); + await expect(searchInput).toHaveValue(''); + }); + + await test.step('When I search for a common term that should exist', async () => { + const searchInput = formBuilderPage.translationSearchInput(); + + await searchInput.fill('Visit Details'); + await expect(searchInput).toHaveValue('Visit Details'); + }); + + await test.step('Then I should see filtered search results', async () => { + const translationEntries = formBuilderPage.page.locator('[data-testid="translation-entry"]'); + await expect(translationEntries).not.toHaveCount(0); + await expect(translationEntries.first()).toBeVisible(); + }); + }); + + test('Workflow 5: Edit Individual Translation', async ({ page }) => { + const formBuilderPage = new FormBuilderPage(page); + + await test.step('When I visit the form builder', async () => { + await formBuilderPage.gotoFormBuilder(); + }); + + await test.step('And I search for the form and open it for editing', async () => { + await formBuilderPage.searchForForm(formDetails.name); + await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); + }); + + await test.step('And I open the Translation builder tab', async () => { + await formBuilderPage.translationBuilderTab().click(); + }); + + await test.step('Then I should see the translation builder actions', async () => { + await expect(formBuilderPage.downloadTranslationButton()).toBeVisible(); + }); + + await test.step('When I click the edit button on a translation entry', async () => { + const editButton = formBuilderPage.editTranslationButton(0); + await expect(editButton).toBeVisible(); + await editButton.click(); + }); + + await test.step('Then the translation modal should open', async () => { + await expect(formBuilderPage.translationModal()).toBeVisible(); + await expect(formBuilderPage.translationValueInput()).toBeVisible(); + await expect(formBuilderPage.saveTranslationButton()).toBeVisible(); + }); + + await test.step('When I edit the translation value', async () => { + const translationInput = formBuilderPage.translationValueInput(); + const originalValue = await translationInput.inputValue(); + + await translationInput.fill('Test Translation Updated'); + await expect(translationInput).toHaveValue('Test Translation Updated'); + }); + + await test.step('And I save the translation', async () => { + await formBuilderPage.saveTranslationButton().click(); + }); + + await test.step('Then the modal should close', async () => { + await expect(formBuilderPage.translationModal()).toBeHidden(); + }); + + await test.step('And the translation should be updated', async () => { + const editButton = formBuilderPage.editTranslationButton(0); + await expect(editButton).toBeEnabled(); + }); + }); + + test('Workflow 6: Download Translation File', async ({ page }) => { + const formBuilderPage = new FormBuilderPage(page); + + await test.step('When I visit the form builder', async () => { + await formBuilderPage.gotoFormBuilder(); + }); + + await test.step('And I search for the form and open it for editing', async () => { + await formBuilderPage.searchForForm(formDetails.name); + await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); + }); + + await test.step('And I open the Translation builder tab', async () => { + await formBuilderPage.translationBuilderTab().click(); + }); + + await test.step('Then I should see the translation builder components (Download/Upload buttons, Translation filter tabs: All/Translated/Untranslated, and the search input)', async () => { + await expect(formBuilderPage.downloadTranslationButton()).toBeVisible(); + }); + + await test.step('And the download translation button is functional', async () => { + const downloadButton = formBuilderPage.downloadTranslationButton(); + + await expect(downloadButton).toBeVisible({ timeout: 10000 }); + await expect(downloadButton).toBeEnabled({ timeout: 10000 }); + }); + + await test.step('When I click the download translation button', async () => { + const downloadButton = formBuilderPage.downloadTranslationButton(); + + const [download] = await Promise.all([ + formBuilderPage.page.waitForEvent('download', { timeout: 15000 }), + downloadButton.click(), + ]); + + expect(download.suggestedFilename()).toMatch(/\.json$/); + }); + await test.step('Then a translation file should be downloaded', async () => { + await expect(formBuilderPage.downloadTranslationButton()).toBeEnabled(); + }); + + await test.step('And the download button should remain functional', async () => { + const downloadButton = formBuilderPage.downloadTranslationButton(); + await expect(downloadButton).toBeEnabled(); + + await expect(downloadButton).toBeVisible(); + }); + }); + + test('Workflow 7: Upload Translation File', async ({ page }) => { + const formBuilderPage = new FormBuilderPage(page); + + await test.step('When I visit the form builder', async () => { + await formBuilderPage.gotoFormBuilder(); + }); + + await test.step('And I search for the form and open it for editing', async () => { + await formBuilderPage.searchForForm(formDetails.name); + await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); + }); + + await test.step('And I open the Translation builder tab', async () => { + await formBuilderPage.translationBuilderTab().click(); + }); + + await test.step('Then I should see the translation builder components (Download/Upload buttons, Translation filter tabs: All/Translated/Untranslated, and the search input)', async () => { + await expect(formBuilderPage.uploadTranslationButton()).toBeVisible(); + }); + + await test.step('And the upload translation button is functional', async () => { + const uploadButton = formBuilderPage.uploadTranslationButton(); + + await expect(uploadButton).toBeVisible({ timeout: 10000 }); + await expect(uploadButton).toBeEnabled({ timeout: 10000 }); + }); + + await test.step('When I click the upload translation button', async () => { + const uploadButton = formBuilderPage.uploadTranslationButton(); + + await uploadButton.click(); + + await expect(uploadButton).toBeEnabled(); + }); + + await test.step('Then the upload functionality should be triggered', async () => { + const uploadButton = formBuilderPage.uploadTranslationButton(); + await expect(uploadButton).toBeVisible(); + await expect(uploadButton).toBeEnabled(); + }); + + await test.step('And the upload button should remain functional for subsequent uploads', async () => { + const uploadButton = formBuilderPage.uploadTranslationButton(); + + await expect(uploadButton).toBeEnabled(); + await expect(uploadButton).toBeVisible(); + + await uploadButton.click(); + await expect(uploadButton).toBeEnabled(); + }); + }); + + test('Workflow 8: Translation State Management', async ({ page }) => { + const formBuilderPage = new FormBuilderPage(page); + + await test.step('When I visit the form builder', async () => { + await formBuilderPage.gotoFormBuilder(); + }); + + await test.step('And I search for the form and open it for editing', async () => { + await formBuilderPage.searchForForm(formDetails.name); + await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); + }); + + await test.step('And I open the Translation builder tab', async () => { + await formBuilderPage.translationBuilderTab().click(); + }); + + await test.step('Then I should see the translation builder components (Download/Upload buttons, Translation filter tabs: All/Translated/Untranslated, and the search input)', async () => { + await expect(formBuilderPage.downloadTranslationButton()).toBeVisible(); + }); + + await test.step('And translation entries are displayed correctly', async () => { + const translationEntries = formBuilderPage.page.locator('[data-testid="translation-entry"]'); + await expect(translationEntries).not.toHaveCount(0); + + const firstEntry = translationEntries.first(); + await expect(firstEntry).toBeVisible(); + await expect(firstEntry.locator('[data-testid="translation-key"]')).toBeVisible(); + await expect(firstEntry.locator('[data-testid="translation-value"]')).toBeVisible(); + await expect(firstEntry.locator('[data-testid="edit-translation-button"]')).toBeVisible(); + }); + + await test.step('When I interact with translation entries', async () => { + const translationEntries = formBuilderPage.page.locator('[data-testid="translation-entry"]'); + await expect(translationEntries).not.toHaveCount(0); + + const firstEntry = translationEntries.first(); + await firstEntry.hover(); + await firstEntry.click(); + await expect(firstEntry).toBeVisible(); + }); + + await test.step('Then the translation entries should maintain their state', async () => { + const translationEntries = formBuilderPage.page.locator('[data-testid="translation-entry"]'); + await expect(translationEntries).not.toHaveCount(0); + + const editButton = formBuilderPage.editTranslationButton(0); + await expect(editButton).toBeVisible(); + await expect(editButton).toBeEnabled(); + }); + + await test.step('And the translation builder should remain stable', async () => { + await expect(formBuilderPage.downloadTranslationButton()).toBeVisible(); + await expect(formBuilderPage.uploadTranslationButton()).toBeVisible(); + await expect(formBuilderPage.translationSearchInput()).toBeVisible(); + + await expect(formBuilderPage.allTranslationsTab()).toBeVisible(); + await expect(formBuilderPage.translatedTab()).toBeVisible(); + await expect(formBuilderPage.untranslatedTab()).toBeVisible(); + }); + }); }); diff --git a/src/components/translation-builder/edit-translation.modal.tsx b/src/components/translation-builder/edit-translation.modal.tsx index ec6c57b93..a8bd8c63e 100644 --- a/src/components/translation-builder/edit-translation.modal.tsx +++ b/src/components/translation-builder/edit-translation.modal.tsx @@ -25,6 +25,7 @@ const EditTranslationModal: React.FC = ({ onClose, or labelText={t('translationValue', 'Translated Value')} value={newValue} onChange={(e) => setNewValue(e.target.value)} + data-testid="translation-value-input" /> diff --git a/src/components/translation-builder/translation-builder.component.tsx b/src/components/translation-builder/translation-builder.component.tsx index 198857a2a..6f441d110 100644 --- a/src/components/translation-builder/translation-builder.component.tsx +++ b/src/components/translation-builder/translation-builder.component.tsx @@ -287,9 +287,18 @@ const TranslationBuilder: React.FC = ({ formSchema, onU
{filteredTranslations.length > 0 ? ( filteredTranslations.map(([key, value]) => ( -
-
{key}
-
{value}
+
+
+ {key} +
+
+ {value} +
= ({ formSchema, onU onClick={() => handleEditClick(key)} size="md" className={styles.deleteButton} + data-testid="edit-translation-button" > From 95d0bd9225dfa52b933049b81fa35026bbf007c9 Mon Sep 17 00:00:00 2001 From: BharathKShetty Date: Sat, 23 Aug 2025 20:37:45 +0530 Subject: [PATCH 04/10] Refined the e2e test workflows --- .../translation-builder-workflows.spec.ts | 384 +----------------- 1 file changed, 19 insertions(+), 365 deletions(-) diff --git a/e2e/specs/translation-builder-workflows.spec.ts b/e2e/specs/translation-builder-workflows.spec.ts index a66db18ad..c3c4c0890 100644 --- a/e2e/specs/translation-builder-workflows.spec.ts +++ b/e2e/specs/translation-builder-workflows.spec.ts @@ -23,415 +23,69 @@ test.describe('Translation Builder Workflows', () => { await addFormResources(api, valueReference, formUuid); }); - test.afterEach(async ({ api }) => { - if (formUuid) { - await deleteForm(api, formUuid); - } - }); - - test('Workflow 1: Basic Translation Builder Display', async ({ page }) => { - const formBuilderPage = new FormBuilderPage(page); - - await test.step('When I visit the form builder', async () => { - await formBuilderPage.gotoFormBuilder(); - }); - - await test.step('And I search for the form and open it for editing', async () => { - await formBuilderPage.searchForForm(formDetails.name); - await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); - }); - - await test.step('And I open the Translation builder tab', async () => { - await formBuilderPage.translationBuilderTab().click(); - }); - - await test.step('Then I should see the translation builder components (Download/Upload buttons, Translation filter tabs: All/Translated/Untranslated, and the search input)', async () => { - const translationPanel = formBuilderPage.page - .getByRole('tabpanel') - .filter({ has: formBuilderPage.page.getByRole('button', { name: /upload translation/i }) }); - - await expect(translationPanel).toBeVisible(); - await expect(translationPanel.getByRole('button', { name: /download translation/i })).toBeVisible(); - await expect(translationPanel.getByRole('button', { name: /upload translation/i })).toBeVisible(); - const tabList = translationPanel.getByRole('tablist', { name: 'Translation filter' }); - await expect(tabList).toBeVisible(); - - const tabs = tabList.getByRole('tab'); - await expect(tabs).toHaveCount(3); - await expect(tabs.nth(0)).toContainText(/all/i); - await expect(tabs.nth(1)).toContainText(/translated/i); - await expect(tabs.nth(2)).toContainText(/untranslated/i); - await expect(translationPanel.getByPlaceholder(/search translation keys/i)).toBeVisible(); - }); - }); - - test('Workflow 2: Language Selection and Switching', async ({ page }) => { + test('Manage translations: switch languages, filter, and search', async ({ page }) => { const formBuilderPage = new FormBuilderPage(page); - await test.step('When I visit the form builder', async () => { + await test.step('Open a form in the translation builder', async () => { await formBuilderPage.gotoFormBuilder(); - }); - - await test.step('And I search for the form and open it for editing', async () => { await formBuilderPage.searchForForm(formDetails.name); await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); - }); - - await test.step('And I open the Translation builder tab', async () => { await formBuilderPage.translationBuilderTab().click(); }); - await test.step('Then I should see the translation builder components (Download/Upload buttons, Translation filter tabs: All/Translated/Untranslated, and the search input)', async () => { - await expect(formBuilderPage.downloadTranslationButton()).toBeVisible(); - }); - - await test.step('And the language dropdown is present and functional', async () => { - const languageDropdown = formBuilderPage.languageDropdown(); - await expect(languageDropdown).toBeVisible(); - await expect(languageDropdown).toBeEnabled(); - }); - - await test.step('When I open the language dropdown and view available languages', async () => { + await test.step('Switch between languages', async () => { await formBuilderPage.languageDropdown().click(); - const dropdownMenu = formBuilderPage.translationBuilderPanel().locator('.cds--list-box__menu'); await expect(dropdownMenu).toBeVisible(); - - const languageOptions = dropdownMenu.getByRole('option'); - const optionCount = await languageOptions.count(); - expect(optionCount).toBeGreaterThan(0); - await expect(dropdownMenu.getByRole('option', { name: 'English (en)' })).toBeVisible(); - await expect(languageOptions.nth(1)).toBeVisible(); - }); - }); - - test('Workflow 3: Translation Filtering by Tabs', async ({ page }) => { - const formBuilderPage = new FormBuilderPage(page); - - await test.step('When I visit the form builder', async () => { - await formBuilderPage.gotoFormBuilder(); - }); - - await test.step('And I search for the form and open it for editing', async () => { - await formBuilderPage.searchForForm(formDetails.name); - await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); - }); - - await test.step('And I open the Translation builder tab', async () => { - await formBuilderPage.translationBuilderTab().click(); }); - await test.step('Then I should see the translation builder actions', async () => { - await expect(formBuilderPage.downloadTranslationButton()).toBeVisible(); - }); - const allEntries = page.locator('[data-testid="translation-entry"]'); - const totalEntries = await allEntries.count(); - - await test.step('When I click on the All translations tab', async () => { + await test.step('Filter translations using tabs', async () => { await formBuilderPage.allTranslationsTab().click(); await expect(formBuilderPage.allTranslationsTab()).toHaveAttribute('aria-selected', 'true'); - }); - - await test.step('Then I should see all translation entries', async () => { - const entries = formBuilderPage.page.locator('[data-testid="translation-entry"]'); - await expect(entries.first()).toBeVisible(); - }); - await test.step('When I click on the Translated tab', async () => { await formBuilderPage.translatedTab().click(); - const translatedEntries = page.locator('[data-status="translated"]'); - await expect(translatedEntries).toHaveCount(0); - }); + await expect(page.locator('[data-status="translated"]')).toHaveCount(0); - await test.step('When I click on the Untranslated tab', async () => { await formBuilderPage.untranslatedTab().click(); await expect(formBuilderPage.untranslatedTab()).toHaveAttribute('aria-selected', 'true'); - - const untranslatedEntries = page.locator('[data-status="untranslated"]'); - await expect(untranslatedEntries.first()).toBeVisible(); - - const totalEntries = await page.locator('[data-testid="translation-entry"]').count(); - - await expect(untranslatedEntries).toHaveCount(totalEntries); - }); - }); - - test('Workflow 4: Translation Search Functionality', async ({ page }) => { - const formBuilderPage = new FormBuilderPage(page); - - await test.step('When I visit the form builder', async () => { - await formBuilderPage.gotoFormBuilder(); - }); - - await test.step('And I search for the form and open it for editing', async () => { - await formBuilderPage.searchForForm(formDetails.name); - await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); + await expect(page.locator('[data-status="untranslated"]').first()).toBeVisible(); }); - await test.step('And I open the Translation builder tab', async () => { - await formBuilderPage.translationBuilderTab().click(); - }); - - await test.step('Then I should see the translation builder actions', async () => { - await expect(formBuilderPage.downloadTranslationButton()).toBeVisible(); - }); - - await test.step('And the search input is present and functional', async () => { + await test.step('Search for a translation string', async () => { const searchInput = formBuilderPage.translationSearchInput(); - await expect(searchInput).toBeVisible(); - await expect(searchInput).toBeEnabled(); - }); - - await test.step('When I type in the search input', async () => { - const searchInput = formBuilderPage.translationSearchInput(); - - await searchInput.fill('test'); - await expect(searchInput).toHaveValue('test'); - }); - - await test.step('Then the search input should contain the typed text', async () => { - const searchInput = formBuilderPage.translationSearchInput(); - await expect(searchInput).toHaveValue('test'); - }); - - await test.step('When I clear the search input', async () => { - const searchInput = formBuilderPage.translationSearchInput(); - await searchInput.clear(); - }); - - await test.step('Then the search input should be empty', async () => { - const searchInput = formBuilderPage.translationSearchInput(); - await expect(searchInput).toHaveValue(''); - }); - - await test.step('When I search for a common term that should exist', async () => { - const searchInput = formBuilderPage.translationSearchInput(); - await searchInput.fill('Visit Details'); await expect(searchInput).toHaveValue('Visit Details'); - }); - await test.step('Then I should see filtered search results', async () => { - const translationEntries = formBuilderPage.page.locator('[data-testid="translation-entry"]'); - await expect(translationEntries).not.toHaveCount(0); - await expect(translationEntries.first()).toBeVisible(); + const results = page.locator('[data-testid="translation-entry"]'); + await expect(results).not.toHaveCount(0); + await expect(results.first()).toBeVisible(); }); }); - test('Workflow 5: Edit Individual Translation', async ({ page }) => { + test('Edit and update an individual translation', async ({ page }) => { const formBuilderPage = new FormBuilderPage(page); - await test.step('When I visit the form builder', async () => { + await test.step('When I open a form in the translation builder', async () => { await formBuilderPage.gotoFormBuilder(); - }); - - await test.step('And I search for the form and open it for editing', async () => { await formBuilderPage.searchForForm(formDetails.name); await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); - }); - - await test.step('And I open the Translation builder tab', async () => { await formBuilderPage.translationBuilderTab().click(); }); - await test.step('Then I should see the translation builder actions', async () => { - await expect(formBuilderPage.downloadTranslationButton()).toBeVisible(); - }); - - await test.step('When I click the edit button on a translation entry', async () => { - const editButton = formBuilderPage.editTranslationButton(0); - await expect(editButton).toBeVisible(); - await editButton.click(); - }); - - await test.step('Then the translation modal should open', async () => { - await expect(formBuilderPage.translationModal()).toBeVisible(); - await expect(formBuilderPage.translationValueInput()).toBeVisible(); - await expect(formBuilderPage.saveTranslationButton()).toBeVisible(); - }); - - await test.step('When I edit the translation value', async () => { + await test.step('Edit a translation string and save it', async () => { + await formBuilderPage.editTranslationButton(0).click(); const translationInput = formBuilderPage.translationValueInput(); - const originalValue = await translationInput.inputValue(); - await translationInput.fill('Test Translation Updated'); - await expect(translationInput).toHaveValue('Test Translation Updated'); - }); - - await test.step('And I save the translation', async () => { await formBuilderPage.saveTranslationButton().click(); - }); - - await test.step('Then the modal should close', async () => { await expect(formBuilderPage.translationModal()).toBeHidden(); - }); - - await test.step('And the translation should be updated', async () => { - const editButton = formBuilderPage.editTranslationButton(0); - await expect(editButton).toBeEnabled(); - }); - }); - - test('Workflow 6: Download Translation File', async ({ page }) => { - const formBuilderPage = new FormBuilderPage(page); - - await test.step('When I visit the form builder', async () => { - await formBuilderPage.gotoFormBuilder(); - }); - - await test.step('And I search for the form and open it for editing', async () => { - await formBuilderPage.searchForForm(formDetails.name); - await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); - }); - - await test.step('And I open the Translation builder tab', async () => { - await formBuilderPage.translationBuilderTab().click(); - }); - - await test.step('Then I should see the translation builder components (Download/Upload buttons, Translation filter tabs: All/Translated/Untranslated, and the search input)', async () => { - await expect(formBuilderPage.downloadTranslationButton()).toBeVisible(); - }); - - await test.step('And the download translation button is functional', async () => { - const downloadButton = formBuilderPage.downloadTranslationButton(); - - await expect(downloadButton).toBeVisible({ timeout: 10000 }); - await expect(downloadButton).toBeEnabled({ timeout: 10000 }); - }); - - await test.step('When I click the download translation button', async () => { - const downloadButton = formBuilderPage.downloadTranslationButton(); - - const [download] = await Promise.all([ - formBuilderPage.page.waitForEvent('download', { timeout: 15000 }), - downloadButton.click(), - ]); - - expect(download.suggestedFilename()).toMatch(/\.json$/); - }); - await test.step('Then a translation file should be downloaded', async () => { - await expect(formBuilderPage.downloadTranslationButton()).toBeEnabled(); - }); - - await test.step('And the download button should remain functional', async () => { - const downloadButton = formBuilderPage.downloadTranslationButton(); - await expect(downloadButton).toBeEnabled(); - - await expect(downloadButton).toBeVisible(); - }); - }); - - test('Workflow 7: Upload Translation File', async ({ page }) => { - const formBuilderPage = new FormBuilderPage(page); - - await test.step('When I visit the form builder', async () => { - await formBuilderPage.gotoFormBuilder(); - }); - - await test.step('And I search for the form and open it for editing', async () => { - await formBuilderPage.searchForForm(formDetails.name); - await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); - }); - - await test.step('And I open the Translation builder tab', async () => { - await formBuilderPage.translationBuilderTab().click(); - }); - - await test.step('Then I should see the translation builder components (Download/Upload buttons, Translation filter tabs: All/Translated/Untranslated, and the search input)', async () => { - await expect(formBuilderPage.uploadTranslationButton()).toBeVisible(); - }); - - await test.step('And the upload translation button is functional', async () => { - const uploadButton = formBuilderPage.uploadTranslationButton(); - - await expect(uploadButton).toBeVisible({ timeout: 10000 }); - await expect(uploadButton).toBeEnabled({ timeout: 10000 }); - }); - - await test.step('When I click the upload translation button', async () => { - const uploadButton = formBuilderPage.uploadTranslationButton(); - - await uploadButton.click(); - - await expect(uploadButton).toBeEnabled(); - }); - - await test.step('Then the upload functionality should be triggered', async () => { - const uploadButton = formBuilderPage.uploadTranslationButton(); - await expect(uploadButton).toBeVisible(); - await expect(uploadButton).toBeEnabled(); - }); - - await test.step('And the upload button should remain functional for subsequent uploads', async () => { - const uploadButton = formBuilderPage.uploadTranslationButton(); - - await expect(uploadButton).toBeEnabled(); - await expect(uploadButton).toBeVisible(); - - await uploadButton.click(); - await expect(uploadButton).toBeEnabled(); + await expect(formBuilderPage.editTranslationButton(0)).toBeEnabled(); }); }); - test('Workflow 8: Translation State Management', async ({ page }) => { - const formBuilderPage = new FormBuilderPage(page); - - await test.step('When I visit the form builder', async () => { - await formBuilderPage.gotoFormBuilder(); - }); - - await test.step('And I search for the form and open it for editing', async () => { - await formBuilderPage.searchForForm(formDetails.name); - await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); - }); - - await test.step('And I open the Translation builder tab', async () => { - await formBuilderPage.translationBuilderTab().click(); - }); - - await test.step('Then I should see the translation builder components (Download/Upload buttons, Translation filter tabs: All/Translated/Untranslated, and the search input)', async () => { - await expect(formBuilderPage.downloadTranslationButton()).toBeVisible(); - }); - - await test.step('And translation entries are displayed correctly', async () => { - const translationEntries = formBuilderPage.page.locator('[data-testid="translation-entry"]'); - await expect(translationEntries).not.toHaveCount(0); - - const firstEntry = translationEntries.first(); - await expect(firstEntry).toBeVisible(); - await expect(firstEntry.locator('[data-testid="translation-key"]')).toBeVisible(); - await expect(firstEntry.locator('[data-testid="translation-value"]')).toBeVisible(); - await expect(firstEntry.locator('[data-testid="edit-translation-button"]')).toBeVisible(); - }); - - await test.step('When I interact with translation entries', async () => { - const translationEntries = formBuilderPage.page.locator('[data-testid="translation-entry"]'); - await expect(translationEntries).not.toHaveCount(0); - - const firstEntry = translationEntries.first(); - await firstEntry.hover(); - await firstEntry.click(); - await expect(firstEntry).toBeVisible(); - }); - - await test.step('Then the translation entries should maintain their state', async () => { - const translationEntries = formBuilderPage.page.locator('[data-testid="translation-entry"]'); - await expect(translationEntries).not.toHaveCount(0); - - const editButton = formBuilderPage.editTranslationButton(0); - await expect(editButton).toBeVisible(); - await expect(editButton).toBeEnabled(); - }); - - await test.step('And the translation builder should remain stable', async () => { - await expect(formBuilderPage.downloadTranslationButton()).toBeVisible(); - await expect(formBuilderPage.uploadTranslationButton()).toBeVisible(); - await expect(formBuilderPage.translationSearchInput()).toBeVisible(); - - await expect(formBuilderPage.allTranslationsTab()).toBeVisible(); - await expect(formBuilderPage.translatedTab()).toBeVisible(); - await expect(formBuilderPage.untranslatedTab()).toBeVisible(); - }); + test.afterEach(async ({ api }) => { + if (formUuid) { + await deleteForm(api, formUuid); + } }); }); From dee15b28fee5e11902bccf7d2e623d3cfc3a9276 Mon Sep 17 00:00:00 2001 From: BharathKShetty Date: Sat, 23 Aug 2025 20:54:49 +0530 Subject: [PATCH 05/10] Updated the step names --- e2e/specs/translation-builder-workflows.spec.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/e2e/specs/translation-builder-workflows.spec.ts b/e2e/specs/translation-builder-workflows.spec.ts index c3c4c0890..9898c86c2 100644 --- a/e2e/specs/translation-builder-workflows.spec.ts +++ b/e2e/specs/translation-builder-workflows.spec.ts @@ -26,21 +26,21 @@ test.describe('Translation Builder Workflows', () => { test('Manage translations: switch languages, filter, and search', async ({ page }) => { const formBuilderPage = new FormBuilderPage(page); - await test.step('Open a form in the translation builder', async () => { + await test.step('When i open a form in the translation builder', async () => { await formBuilderPage.gotoFormBuilder(); await formBuilderPage.searchForForm(formDetails.name); await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); await formBuilderPage.translationBuilderTab().click(); }); - await test.step('Switch between languages', async () => { + await test.step('And i switch between languages', async () => { await formBuilderPage.languageDropdown().click(); const dropdownMenu = formBuilderPage.translationBuilderPanel().locator('.cds--list-box__menu'); await expect(dropdownMenu).toBeVisible(); await expect(dropdownMenu.getByRole('option', { name: 'English (en)' })).toBeVisible(); }); - await test.step('Filter translations using tabs', async () => { + await test.step('And i filter translations using tabs', async () => { await formBuilderPage.allTranslationsTab().click(); await expect(formBuilderPage.allTranslationsTab()).toHaveAttribute('aria-selected', 'true'); @@ -52,7 +52,7 @@ test.describe('Translation Builder Workflows', () => { await expect(page.locator('[data-status="untranslated"]').first()).toBeVisible(); }); - await test.step('Search for a translation string', async () => { + await test.step('And i search for a translation string', async () => { const searchInput = formBuilderPage.translationSearchInput(); await searchInput.fill('Visit Details'); await expect(searchInput).toHaveValue('Visit Details'); @@ -73,7 +73,7 @@ test.describe('Translation Builder Workflows', () => { await formBuilderPage.translationBuilderTab().click(); }); - await test.step('Edit a translation string and save it', async () => { + await test.step('And i edit a translation string and save it', async () => { await formBuilderPage.editTranslationButton(0).click(); const translationInput = formBuilderPage.translationValueInput(); await translationInput.fill('Test Translation Updated'); From 4b007bafda850eb8ee743fa41d73d429c33b292d Mon Sep 17 00:00:00 2001 From: BharathKShetty Date: Sat, 23 Aug 2025 21:39:06 +0530 Subject: [PATCH 06/10] Added workflow for upload and download translation file --- .../translation-builder-workflows.spec.ts | 54 ++++++++++++++++--- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/e2e/specs/translation-builder-workflows.spec.ts b/e2e/specs/translation-builder-workflows.spec.ts index 9898c86c2..7fe542033 100644 --- a/e2e/specs/translation-builder-workflows.spec.ts +++ b/e2e/specs/translation-builder-workflows.spec.ts @@ -26,21 +26,21 @@ test.describe('Translation Builder Workflows', () => { test('Manage translations: switch languages, filter, and search', async ({ page }) => { const formBuilderPage = new FormBuilderPage(page); - await test.step('When i open a form in the translation builder', async () => { + await test.step('When I open a form in the translation builder', async () => { await formBuilderPage.gotoFormBuilder(); await formBuilderPage.searchForForm(formDetails.name); await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); await formBuilderPage.translationBuilderTab().click(); }); - await test.step('And i switch between languages', async () => { + await test.step('And I switch between languages', async () => { await formBuilderPage.languageDropdown().click(); const dropdownMenu = formBuilderPage.translationBuilderPanel().locator('.cds--list-box__menu'); await expect(dropdownMenu).toBeVisible(); await expect(dropdownMenu.getByRole('option', { name: 'English (en)' })).toBeVisible(); }); - await test.step('And i filter translations using tabs', async () => { + await test.step('And I filter translations using tabs', async () => { await formBuilderPage.allTranslationsTab().click(); await expect(formBuilderPage.allTranslationsTab()).toHaveAttribute('aria-selected', 'true'); @@ -52,7 +52,7 @@ test.describe('Translation Builder Workflows', () => { await expect(page.locator('[data-status="untranslated"]').first()).toBeVisible(); }); - await test.step('And i search for a translation string', async () => { + await test.step('And I search for a translation string', async () => { const searchInput = formBuilderPage.translationSearchInput(); await searchInput.fill('Visit Details'); await expect(searchInput).toHaveValue('Visit Details'); @@ -66,14 +66,14 @@ test.describe('Translation Builder Workflows', () => { test('Edit and update an individual translation', async ({ page }) => { const formBuilderPage = new FormBuilderPage(page); - await test.step('When I open a form in the translation builder', async () => { + await test.step('When I open a form in the Translation Builder', async () => { await formBuilderPage.gotoFormBuilder(); await formBuilderPage.searchForForm(formDetails.name); await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); await formBuilderPage.translationBuilderTab().click(); }); - await test.step('And i edit a translation string and save it', async () => { + await test.step('And I edit a Translation string and save it', async () => { await formBuilderPage.editTranslationButton(0).click(); const translationInput = formBuilderPage.translationValueInput(); await translationInput.fill('Test Translation Updated'); @@ -82,6 +82,48 @@ test.describe('Translation Builder Workflows', () => { await expect(formBuilderPage.editTranslationButton(0)).toBeEnabled(); }); }); + test('Download a Translation file from a form', async ({ page }) => { + const formBuilderPage = new FormBuilderPage(page); + + await test.step('When I open a form in the Translation Builder', async () => { + await formBuilderPage.gotoFormBuilder(); + await formBuilderPage.searchForForm(formDetails.name); + await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); + await formBuilderPage.translationBuilderTab().click(); + }); + + await test.step('And I download the Translation file', async () => { + const downloadButton = formBuilderPage.downloadTranslationButton(); + const [download] = await Promise.all([ + formBuilderPage.page.waitForEvent('download', { timeout: 15000 }), + downloadButton.click(), + ]); + expect(download.suggestedFilename()).toMatch(/\.json$/); + }); + }); + + test('Upload a Translation file to backend', async ({ page }) => { + const formBuilderPage = new FormBuilderPage(page); + + await test.step('When I open a form in the translation builder', async () => { + await formBuilderPage.gotoFormBuilder(); + await formBuilderPage.searchForForm(formDetails.name); + await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); + + await formBuilderPage.translationBuilderTab().click(); + }); + + await test.step('And I upload a translation file', async () => { + const uploadButton = formBuilderPage.uploadTranslationButton(); + await expect(uploadButton).toBeEnabled(); + await expect(uploadButton).toBeVisible(); + await expect(formBuilderPage.translationBuilderPanel()).toBeVisible(); + + await uploadButton.click(); + await expect(formBuilderPage.page.getByText(/Translations Uploaded./i)).toBeVisible(); + await expect(formBuilderPage.page.getByText(/Translation file uploaded successfully/i)).toBeVisible(); + }); + }); test.afterEach(async ({ api }) => { if (formUuid) { From 7090561bfcb795f26d25807a05bdb2387ab16727 Mon Sep 17 00:00:00 2001 From: BharathKShetty Date: Sun, 24 Aug 2025 10:44:04 +0530 Subject: [PATCH 07/10] Made all the tests pass --- .../translation-builder-workflows.spec.ts | 247 ++++++++++-------- .../translation-builder.component.tsx | 31 +-- 2 files changed, 148 insertions(+), 130 deletions(-) diff --git a/e2e/specs/translation-builder-workflows.spec.ts b/e2e/specs/translation-builder-workflows.spec.ts index 7fe542033..5a8d526b6 100644 --- a/e2e/specs/translation-builder-workflows.spec.ts +++ b/e2e/specs/translation-builder-workflows.spec.ts @@ -13,121 +13,138 @@ const formDetails = { version: '1.0', published: true, }; +test.beforeEach(async ({ api }) => { + const form = await createForm(api, false, formDetails); + formUuid = form.uuid; -test.describe('Translation Builder Workflows', () => { - test.beforeEach(async ({ api }) => { - const form = await createForm(api, false, formDetails); - formUuid = form.uuid; - - const valueReference = await createValueReference(api); - await addFormResources(api, valueReference, formUuid); - }); - - test('Manage translations: switch languages, filter, and search', async ({ page }) => { - const formBuilderPage = new FormBuilderPage(page); - - await test.step('When I open a form in the translation builder', async () => { - await formBuilderPage.gotoFormBuilder(); - await formBuilderPage.searchForForm(formDetails.name); - await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); - await formBuilderPage.translationBuilderTab().click(); - }); - - await test.step('And I switch between languages', async () => { - await formBuilderPage.languageDropdown().click(); - const dropdownMenu = formBuilderPage.translationBuilderPanel().locator('.cds--list-box__menu'); - await expect(dropdownMenu).toBeVisible(); - await expect(dropdownMenu.getByRole('option', { name: 'English (en)' })).toBeVisible(); - }); - - await test.step('And I filter translations using tabs', async () => { - await formBuilderPage.allTranslationsTab().click(); - await expect(formBuilderPage.allTranslationsTab()).toHaveAttribute('aria-selected', 'true'); - - await formBuilderPage.translatedTab().click(); - await expect(page.locator('[data-status="translated"]')).toHaveCount(0); - - await formBuilderPage.untranslatedTab().click(); - await expect(formBuilderPage.untranslatedTab()).toHaveAttribute('aria-selected', 'true'); - await expect(page.locator('[data-status="untranslated"]').first()).toBeVisible(); - }); - - await test.step('And I search for a translation string', async () => { - const searchInput = formBuilderPage.translationSearchInput(); - await searchInput.fill('Visit Details'); - await expect(searchInput).toHaveValue('Visit Details'); - - const results = page.locator('[data-testid="translation-entry"]'); - await expect(results).not.toHaveCount(0); - await expect(results.first()).toBeVisible(); - }); - }); - - test('Edit and update an individual translation', async ({ page }) => { - const formBuilderPage = new FormBuilderPage(page); - - await test.step('When I open a form in the Translation Builder', async () => { - await formBuilderPage.gotoFormBuilder(); - await formBuilderPage.searchForForm(formDetails.name); - await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); - await formBuilderPage.translationBuilderTab().click(); - }); - - await test.step('And I edit a Translation string and save it', async () => { - await formBuilderPage.editTranslationButton(0).click(); - const translationInput = formBuilderPage.translationValueInput(); - await translationInput.fill('Test Translation Updated'); - await formBuilderPage.saveTranslationButton().click(); - await expect(formBuilderPage.translationModal()).toBeHidden(); - await expect(formBuilderPage.editTranslationButton(0)).toBeEnabled(); - }); - }); - test('Download a Translation file from a form', async ({ page }) => { - const formBuilderPage = new FormBuilderPage(page); - - await test.step('When I open a form in the Translation Builder', async () => { - await formBuilderPage.gotoFormBuilder(); - await formBuilderPage.searchForForm(formDetails.name); - await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); - await formBuilderPage.translationBuilderTab().click(); - }); - - await test.step('And I download the Translation file', async () => { - const downloadButton = formBuilderPage.downloadTranslationButton(); - const [download] = await Promise.all([ - formBuilderPage.page.waitForEvent('download', { timeout: 15000 }), - downloadButton.click(), - ]); - expect(download.suggestedFilename()).toMatch(/\.json$/); - }); - }); - - test('Upload a Translation file to backend', async ({ page }) => { - const formBuilderPage = new FormBuilderPage(page); - - await test.step('When I open a form in the translation builder', async () => { - await formBuilderPage.gotoFormBuilder(); - await formBuilderPage.searchForForm(formDetails.name); - await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); - - await formBuilderPage.translationBuilderTab().click(); - }); - - await test.step('And I upload a translation file', async () => { - const uploadButton = formBuilderPage.uploadTranslationButton(); - await expect(uploadButton).toBeEnabled(); - await expect(uploadButton).toBeVisible(); - await expect(formBuilderPage.translationBuilderPanel()).toBeVisible(); - - await uploadButton.click(); - await expect(formBuilderPage.page.getByText(/Translations Uploaded./i)).toBeVisible(); - await expect(formBuilderPage.page.getByText(/Translation file uploaded successfully/i)).toBeVisible(); - }); - }); - - test.afterEach(async ({ api }) => { - if (formUuid) { - await deleteForm(api, formUuid); - } + const valueReference = await createValueReference(api); + await addFormResources(api, valueReference, formUuid); +}); + +test('Manage translations: switch languages, filter, and search', async ({ page }) => { + const formBuilderPage = new FormBuilderPage(page); + + await test.step('When I open a form in the translation builder', async () => { + await formBuilderPage.gotoFormBuilder(); + await formBuilderPage.searchForForm(formDetails.name); + await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); + }); + + await test.step('And then I go to the translation builder', async () => { + await formBuilderPage.translationBuilderTab().click(); + }); + + await test.step('And I switch between languages', async () => { + await formBuilderPage.languageDropdown().click(); + const dropdownMenu = formBuilderPage.translationBuilderPanel().locator('.cds--list-box__menu'); + await expect(dropdownMenu).toBeVisible(); + await expect(dropdownMenu.getByRole('option', { name: 'English (en)' })).toBeVisible(); + }); + + await test.step('And I filter translations using tabs', async () => { + await formBuilderPage.allTranslationsTab().click(); + await expect(formBuilderPage.allTranslationsTab()).toHaveAttribute('aria-selected', 'true'); + + await formBuilderPage.translatedTab().click(); + await expect(page.locator('[data-status="translated"]')).toHaveCount(0); + + await formBuilderPage.untranslatedTab().click(); + await expect(formBuilderPage.untranslatedTab()).toHaveAttribute('aria-selected', 'true'); + await expect(page.locator('[data-status="untranslated"]').first()).toBeVisible(); + }); + + await test.step('And I search for a translation string', async () => { + const searchInput = formBuilderPage.translationSearchInput(); + await searchInput.fill('Visit Details'); + await expect(searchInput).toHaveValue('Visit Details'); + + const results = page.locator('[data-testid="translation-entry"]'); + await expect(results).not.toHaveCount(0); + await expect(results.first()).toBeVisible(); + }); +}); + +test('Edit and update an individual translation', async ({ page }) => { + const formBuilderPage = new FormBuilderPage(page); + + await test.step('When I open a form in the Translation Builder', async () => { + await formBuilderPage.gotoFormBuilder(); + await formBuilderPage.searchForForm(formDetails.name); + await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); + }); + + await test.step('And then I go to the translation builder', async () => { + await formBuilderPage.translationBuilderTab().click(); + }); + + await test.step('And then I select the French language', async () => { + await formBuilderPage.languageDropdown().click(); + const dropdownMenu = formBuilderPage.translationBuilderPanel().locator('.cds--list-box__menu'); + await expect(dropdownMenu).toBeVisible(); + await dropdownMenu.getByRole('option', { name: 'French (fr)' }).click(); }); + + await test.step('And then I edit a translation string and save it', async () => { + await formBuilderPage.editTranslationButton(0).click(); + const translationInput = formBuilderPage.translationValueInput(); + await translationInput.fill('Test Translation Updated'); + }); + await test.step('And then when I preview the form in the language, I should see the edited translation strings', async () => { + await formBuilderPage.saveTranslationButton().click(); + await expect(formBuilderPage.translationModal()).toBeHidden(); + await expect(formBuilderPage.editTranslationButton(0)).toBeEnabled(); + }); +}); +test('Download a translation file from a form', async ({ page }) => { + const formBuilderPage = new FormBuilderPage(page); + + await test.step('When I open a form in the translation Builder', async () => { + await formBuilderPage.gotoFormBuilder(); + await formBuilderPage.searchForForm(formDetails.name); + await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); + }); + + await test.step('And then I go to the translation builder', async () => { + await formBuilderPage.translationBuilderTab().click(); + }); + + await test.step('And I download the translation file', async () => { + const downloadButton = formBuilderPage.downloadTranslationButton(); + const [download] = await Promise.all([ + formBuilderPage.page.waitForEvent('download', { timeout: 15000 }), + downloadButton.click(), + ]); + expect(download.suggestedFilename()).toMatch(/\.json$/); + }); +}); + +test('Upload a translation file to backend', async ({ page }) => { + const formBuilderPage = new FormBuilderPage(page); + + await test.step('When I open a form in the translation builder', async () => { + await formBuilderPage.gotoFormBuilder(); + await formBuilderPage.searchForForm(formDetails.name); + await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); + }); + + await test.step('And then I go to the translation builder', async () => { + await formBuilderPage.translationBuilderTab().click(); + }); + + await test.step('And I upload a translation file', async () => { + const uploadButton = formBuilderPage.uploadTranslationButton(); + await expect(uploadButton).toBeEnabled(); + await expect(uploadButton).toBeVisible(); + await expect(formBuilderPage.translationBuilderPanel()).toBeVisible(); + + await uploadButton.click(); + await expect(formBuilderPage.page.getByText(/Translations Uploaded./i)).toBeVisible(); + await expect(formBuilderPage.page.getByText(/Translation file uploaded successfully/i)).toBeVisible(); + }); +}); + +test.afterEach(async ({ api }) => { + if (formUuid) { + await deleteForm(api, formUuid); + } }); diff --git a/src/components/translation-builder/translation-builder.component.tsx b/src/components/translation-builder/translation-builder.component.tsx index 6f441d110..3511f3f20 100644 --- a/src/components/translation-builder/translation-builder.component.tsx +++ b/src/components/translation-builder/translation-builder.component.tsx @@ -223,21 +223,22 @@ const TranslationBuilder: React.FC = ({ formSchema, onU onChange={({ selectedItem }) => selectedItem && languageChanger(selectedItem.code)} />
- -
- - -
+ {formSchema ? ( +
+ + +
+ ) : null}
From 4d2d42e5db46a0b2a97427da92d5add72bba3ab4 Mon Sep 17 00:00:00 2001 From: BharathKShetty Date: Wed, 27 Aug 2025 19:26:28 +0530 Subject: [PATCH 08/10] remove eslint-disable and update to use formBuilderPage.page queries --- .../translation-builder-workflows.spec.ts | 270 +++++++++--------- 1 file changed, 135 insertions(+), 135 deletions(-) diff --git a/e2e/specs/translation-builder-workflows.spec.ts b/e2e/specs/translation-builder-workflows.spec.ts index 5a8d526b6..252fcd9f1 100644 --- a/e2e/specs/translation-builder-workflows.spec.ts +++ b/e2e/specs/translation-builder-workflows.spec.ts @@ -1,5 +1,3 @@ -/* eslint-disable testing-library/prefer-screen-queries */ - import { test } from '../core'; import { expect } from '@playwright/test'; import { deleteForm, createForm, createValueReference, addFormResources } from '../commands/form-operations'; @@ -13,138 +11,140 @@ const formDetails = { version: '1.0', published: true, }; -test.beforeEach(async ({ api }) => { - const form = await createForm(api, false, formDetails); - formUuid = form.uuid; - - const valueReference = await createValueReference(api); - await addFormResources(api, valueReference, formUuid); -}); - -test('Manage translations: switch languages, filter, and search', async ({ page }) => { - const formBuilderPage = new FormBuilderPage(page); - - await test.step('When I open a form in the translation builder', async () => { - await formBuilderPage.gotoFormBuilder(); - await formBuilderPage.searchForForm(formDetails.name); - await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); - }); - - await test.step('And then I go to the translation builder', async () => { - await formBuilderPage.translationBuilderTab().click(); - }); - - await test.step('And I switch between languages', async () => { - await formBuilderPage.languageDropdown().click(); - const dropdownMenu = formBuilderPage.translationBuilderPanel().locator('.cds--list-box__menu'); - await expect(dropdownMenu).toBeVisible(); - await expect(dropdownMenu.getByRole('option', { name: 'English (en)' })).toBeVisible(); +test.describe('Translation Builder', () => { + test.beforeEach(async ({ api }) => { + const form = await createForm(api, false, formDetails); + formUuid = form.uuid; + + const valueReference = await createValueReference(api); + await addFormResources(api, valueReference, formUuid); + }); + + test('Manage translations: switch languages, filter, and search', async ({ page }) => { + const formBuilderPage = new FormBuilderPage(page); + + await test.step('When I open a form in the translation builder', async () => { + await formBuilderPage.gotoFormBuilder(); + await formBuilderPage.searchForForm(formDetails.name); + await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); + }); + + await test.step('And then I go to the translation builder', async () => { + await formBuilderPage.translationBuilderTab().click(); + }); + + await test.step('And I switch between languages', async () => { + await formBuilderPage.languageDropdown().click(); + const dropdownMenu = formBuilderPage.translationBuilderPanel().locator('.cds--list-box__menu'); + await expect(dropdownMenu).toBeVisible(); + await expect(formBuilderPage.page.getByRole('option', { name: 'English (en)' })).toBeVisible(); + }); + + await test.step('And I filter translations using tabs', async () => { + await formBuilderPage.allTranslationsTab().click(); + await expect(formBuilderPage.allTranslationsTab()).toHaveAttribute('aria-selected', 'true'); + + await formBuilderPage.translatedTab().click(); + await expect(page.locator('[data-status="translated"]')).toHaveCount(0); + + await formBuilderPage.untranslatedTab().click(); + await expect(formBuilderPage.untranslatedTab()).toHaveAttribute('aria-selected', 'true'); + await expect(page.locator('[data-status="untranslated"]').first()).toBeVisible(); + }); + + await test.step('And I search for a translation string', async () => { + const searchInput = formBuilderPage.translationSearchInput(); + await searchInput.fill('Visit Details'); + await expect(searchInput).toHaveValue('Visit Details'); + + const results = page.locator('[data-testid="translation-entry"]'); + await expect(results).not.toHaveCount(0); + await expect(results.first()).toBeVisible(); + }); + }); + + test('Edit and update an individual translation', async ({ page }) => { + const formBuilderPage = new FormBuilderPage(page); + + await test.step('When I open a form in the Translation Builder', async () => { + await formBuilderPage.gotoFormBuilder(); + await formBuilderPage.searchForForm(formDetails.name); + await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); + }); + + await test.step('And then I go to the translation builder', async () => { + await formBuilderPage.translationBuilderTab().click(); + }); + + await test.step('And then I select the French language', async () => { + await formBuilderPage.languageDropdown().click(); + const dropdownMenu = formBuilderPage.translationBuilderPanel().locator('.cds--list-box__menu'); + await expect(dropdownMenu).toBeVisible(); + await formBuilderPage.page.getByRole('option', { name: 'French (fr)' }).click(); + }); + + await test.step('And then I edit a translation string and save it', async () => { + await formBuilderPage.editTranslationButton(0).click(); + const translationInput = formBuilderPage.translationValueInput(); + await translationInput.fill('Test Translation Updated'); + }); + await test.step('And then when I preview the form in the language, I should see the edited translation strings', async () => { + await formBuilderPage.saveTranslationButton().click(); + await expect(formBuilderPage.translationModal()).toBeHidden(); + await expect(formBuilderPage.editTranslationButton(0)).toBeEnabled(); + }); + }); + test('Download a translation file from a form', async ({ page }) => { + const formBuilderPage = new FormBuilderPage(page); + + await test.step('When I open a form in the translation Builder', async () => { + await formBuilderPage.gotoFormBuilder(); + await formBuilderPage.searchForForm(formDetails.name); + await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); + }); + + await test.step('And then I go to the translation builder', async () => { + await formBuilderPage.translationBuilderTab().click(); + }); + + await test.step('And I download the translation file', async () => { + const downloadButton = formBuilderPage.downloadTranslationButton(); + const [download] = await Promise.all([ + formBuilderPage.page.waitForEvent('download', { timeout: 15000 }), + downloadButton.click(), + ]); + expect(download.suggestedFilename()).toMatch(/\.json$/); + }); + }); + + test('Upload a translation file to backend', async ({ page }) => { + const formBuilderPage = new FormBuilderPage(page); + + await test.step('When I open a form in the translation builder', async () => { + await formBuilderPage.gotoFormBuilder(); + await formBuilderPage.searchForForm(formDetails.name); + await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); + }); + + await test.step('And then I go to the translation builder', async () => { + await formBuilderPage.translationBuilderTab().click(); + }); + + await test.step('And I upload a translation file', async () => { + const uploadButton = formBuilderPage.uploadTranslationButton(); + await expect(uploadButton).toBeEnabled(); + await expect(uploadButton).toBeVisible(); + await expect(formBuilderPage.translationBuilderPanel()).toBeVisible(); + + await uploadButton.click(); + await expect(formBuilderPage.page.getByText(/Translations Uploaded./i)).toBeVisible(); + await expect(formBuilderPage.page.getByText(/Translation file uploaded successfully/i)).toBeVisible(); + }); + }); + + test.afterEach(async ({ api }) => { + if (formUuid) { + await deleteForm(api, formUuid); + } }); - - await test.step('And I filter translations using tabs', async () => { - await formBuilderPage.allTranslationsTab().click(); - await expect(formBuilderPage.allTranslationsTab()).toHaveAttribute('aria-selected', 'true'); - - await formBuilderPage.translatedTab().click(); - await expect(page.locator('[data-status="translated"]')).toHaveCount(0); - - await formBuilderPage.untranslatedTab().click(); - await expect(formBuilderPage.untranslatedTab()).toHaveAttribute('aria-selected', 'true'); - await expect(page.locator('[data-status="untranslated"]').first()).toBeVisible(); - }); - - await test.step('And I search for a translation string', async () => { - const searchInput = formBuilderPage.translationSearchInput(); - await searchInput.fill('Visit Details'); - await expect(searchInput).toHaveValue('Visit Details'); - - const results = page.locator('[data-testid="translation-entry"]'); - await expect(results).not.toHaveCount(0); - await expect(results.first()).toBeVisible(); - }); -}); - -test('Edit and update an individual translation', async ({ page }) => { - const formBuilderPage = new FormBuilderPage(page); - - await test.step('When I open a form in the Translation Builder', async () => { - await formBuilderPage.gotoFormBuilder(); - await formBuilderPage.searchForForm(formDetails.name); - await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); - }); - - await test.step('And then I go to the translation builder', async () => { - await formBuilderPage.translationBuilderTab().click(); - }); - - await test.step('And then I select the French language', async () => { - await formBuilderPage.languageDropdown().click(); - const dropdownMenu = formBuilderPage.translationBuilderPanel().locator('.cds--list-box__menu'); - await expect(dropdownMenu).toBeVisible(); - await dropdownMenu.getByRole('option', { name: 'French (fr)' }).click(); - }); - - await test.step('And then I edit a translation string and save it', async () => { - await formBuilderPage.editTranslationButton(0).click(); - const translationInput = formBuilderPage.translationValueInput(); - await translationInput.fill('Test Translation Updated'); - }); - await test.step('And then when I preview the form in the language, I should see the edited translation strings', async () => { - await formBuilderPage.saveTranslationButton().click(); - await expect(formBuilderPage.translationModal()).toBeHidden(); - await expect(formBuilderPage.editTranslationButton(0)).toBeEnabled(); - }); -}); -test('Download a translation file from a form', async ({ page }) => { - const formBuilderPage = new FormBuilderPage(page); - - await test.step('When I open a form in the translation Builder', async () => { - await formBuilderPage.gotoFormBuilder(); - await formBuilderPage.searchForForm(formDetails.name); - await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); - }); - - await test.step('And then I go to the translation builder', async () => { - await formBuilderPage.translationBuilderTab().click(); - }); - - await test.step('And I download the translation file', async () => { - const downloadButton = formBuilderPage.downloadTranslationButton(); - const [download] = await Promise.all([ - formBuilderPage.page.waitForEvent('download', { timeout: 15000 }), - downloadButton.click(), - ]); - expect(download.suggestedFilename()).toMatch(/\.json$/); - }); -}); - -test('Upload a translation file to backend', async ({ page }) => { - const formBuilderPage = new FormBuilderPage(page); - - await test.step('When I open a form in the translation builder', async () => { - await formBuilderPage.gotoFormBuilder(); - await formBuilderPage.searchForForm(formDetails.name); - await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); - }); - - await test.step('And then I go to the translation builder', async () => { - await formBuilderPage.translationBuilderTab().click(); - }); - - await test.step('And I upload a translation file', async () => { - const uploadButton = formBuilderPage.uploadTranslationButton(); - await expect(uploadButton).toBeEnabled(); - await expect(uploadButton).toBeVisible(); - await expect(formBuilderPage.translationBuilderPanel()).toBeVisible(); - - await uploadButton.click(); - await expect(formBuilderPage.page.getByText(/Translations Uploaded./i)).toBeVisible(); - await expect(formBuilderPage.page.getByText(/Translation file uploaded successfully/i)).toBeVisible(); - }); -}); - -test.afterEach(async ({ api }) => { - if (formUuid) { - await deleteForm(api, formUuid); - } }); From 96485a838947d80941b2825731ef397df2c84499 Mon Sep 17 00:00:00 2001 From: BharathKShetty Date: Fri, 29 Aug 2025 17:12:42 +0530 Subject: [PATCH 09/10] Refined the step names of the workflows --- .../translation-builder-workflows.spec.ts | 42 +++++++++++++++---- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/e2e/specs/translation-builder-workflows.spec.ts b/e2e/specs/translation-builder-workflows.spec.ts index 252fcd9f1..9ad9d607d 100644 --- a/e2e/specs/translation-builder-workflows.spec.ts +++ b/e2e/specs/translation-builder-workflows.spec.ts @@ -19,7 +19,6 @@ test.describe('Translation Builder', () => { const valueReference = await createValueReference(api); await addFormResources(api, valueReference, formUuid); }); - test('Manage translations: switch languages, filter, and search', async ({ page }) => { const formBuilderPage = new FormBuilderPage(page); @@ -27,38 +26,67 @@ test.describe('Translation Builder', () => { await formBuilderPage.gotoFormBuilder(); await formBuilderPage.searchForForm(formDetails.name); await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); - }); - - await test.step('And then I go to the translation builder', async () => { await formBuilderPage.translationBuilderTab().click(); }); - await test.step('And I switch between languages', async () => { + await test.step('When I open the language dropdown', async () => { await formBuilderPage.languageDropdown().click(); + }); + + await test.step('Then I should see the language list', async () => { const dropdownMenu = formBuilderPage.translationBuilderPanel().locator('.cds--list-box__menu'); await expect(dropdownMenu).toBeVisible(); + }); + + await test.step('And I should see "English (en)" in the language list', async () => { await expect(formBuilderPage.page.getByRole('option', { name: 'English (en)' })).toBeVisible(); }); - await test.step('And I filter translations using tabs', async () => { + await test.step('When I select the "All" translations tab', async () => { await formBuilderPage.allTranslationsTab().click(); + }); + + await test.step('Then the "All" translations tab should be selected', async () => { await expect(formBuilderPage.allTranslationsTab()).toHaveAttribute('aria-selected', 'true'); + }); + await test.step('When I select the "Translated" translations tab', async () => { await formBuilderPage.translatedTab().click(); + }); + + await test.step('Then I should see 0 "translated" entries', async () => { await expect(page.locator('[data-status="translated"]')).toHaveCount(0); + }); + await test.step('When I select the "Untranslated" translations tab', async () => { await formBuilderPage.untranslatedTab().click(); + }); + + await test.step('Then the "Untranslated" translations tab should be selected', async () => { await expect(formBuilderPage.untranslatedTab()).toHaveAttribute('aria-selected', 'true'); + }); + + await test.step('And I should see at least 1 "untranslated" entry', async () => { await expect(page.locator('[data-status="untranslated"]').first()).toBeVisible(); }); - await test.step('And I search for a translation string', async () => { + await test.step('When I search translations for "Visit Details"', async () => { const searchInput = formBuilderPage.translationSearchInput(); await searchInput.fill('Visit Details'); + }); + + await test.step('Then the translation search input should contain "Visit Details"', async () => { + const searchInput = formBuilderPage.translationSearchInput(); await expect(searchInput).toHaveValue('Visit Details'); + }); + await test.step('And I should see at least 1 translation result', async () => { const results = page.locator('[data-testid="translation-entry"]'); await expect(results).not.toHaveCount(0); + }); + + await test.step('And the first translation result should be visible', async () => { + const results = page.locator('[data-testid="translation-entry"]'); await expect(results.first()).toBeVisible(); }); }); From b1af41d7fe8e94692abd2e11d05d9257ade0592b Mon Sep 17 00:00:00 2001 From: BharathKShetty Date: Sat, 30 Aug 2025 14:56:04 +0530 Subject: [PATCH 10/10] Update the step names of the upload translation workflow --- e2e/specs/translation-builder-workflows.spec.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/e2e/specs/translation-builder-workflows.spec.ts b/e2e/specs/translation-builder-workflows.spec.ts index 9ad9d607d..1b316b215 100644 --- a/e2e/specs/translation-builder-workflows.spec.ts +++ b/e2e/specs/translation-builder-workflows.spec.ts @@ -125,17 +125,17 @@ test.describe('Translation Builder', () => { test('Download a translation file from a form', async ({ page }) => { const formBuilderPage = new FormBuilderPage(page); - await test.step('When I open a form in the translation Builder', async () => { + await test.step('Given I have opened a form in the Form Builder', async () => { await formBuilderPage.gotoFormBuilder(); await formBuilderPage.searchForForm(formDetails.name); await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); }); - await test.step('And then I go to the translation builder', async () => { + await test.step('When I navigate to the Translation Builder', async () => { await formBuilderPage.translationBuilderTab().click(); }); - await test.step('And I download the translation file', async () => { + await test.step('Then I should be able to download the translation file', async () => { const downloadButton = formBuilderPage.downloadTranslationButton(); const [download] = await Promise.all([ formBuilderPage.page.waitForEvent('download', { timeout: 15000 }), @@ -148,17 +148,17 @@ test.describe('Translation Builder', () => { test('Upload a translation file to backend', async ({ page }) => { const formBuilderPage = new FormBuilderPage(page); - await test.step('When I open a form in the translation builder', async () => { + await test.step('Given I have opened a form in the Form Builder', async () => { await formBuilderPage.gotoFormBuilder(); await formBuilderPage.searchForForm(formDetails.name); await formBuilderPage.page.getByRole('row', { name: formDetails.name }).getByLabel('Edit Schema').first().click(); }); - await test.step('And then I go to the translation builder', async () => { + await test.step('When I navigate to the Translation Builder', async () => { await formBuilderPage.translationBuilderTab().click(); }); - await test.step('And I upload a translation file', async () => { + await test.step('Then I should be able to upload a translation file successfully', async () => { const uploadButton = formBuilderPage.uploadTranslationButton(); await expect(uploadButton).toBeEnabled(); await expect(uploadButton).toBeVisible();