-
Notifications
You must be signed in to change notification settings - Fork 112
(test) O3-4968: Adding e2e tests for TranslationBuilder component #833
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 16 commits
ef2959e
f6514ea
3be06ac
2bec8c3
ed1dfe7
90abacd
977c97f
f93ebdc
95d0bd9
fae2941
dee15b2
4b007ba
833dfdc
7090561
49fe191
2581cb8
9f73bc6
5bf32e7
03cf72e
e9871f9
4d2d42e
cd025b2
04820c4
76adcd2
78a81e4
6891076
96485a8
8eec6a6
fbbed14
b1af41d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,150 @@ | ||
| /* 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, | ||
| }; | ||
Bharath-K-Shetty marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 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(); | ||
| }); | ||
|
|
||
| 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); | ||
|
|
||
Bharath-K-Shetty marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 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); | ||
| } | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,6 +25,7 @@ const EditTranslationModal: React.FC<EditTranslationModalProps> = ({ onClose, or | |
| labelText={t('translationValue', 'Translated Value')} | ||
| value={newValue} | ||
| onChange={(e) => setNewValue(e.target.value)} | ||
| data-testid="translation-value-input" | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. question: Is the data test id necessary? Can't we target the button from the label text? |
||
| /> | ||
| </ModalBody> | ||
| <ModalFooter> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -223,21 +223,22 @@ const TranslationBuilder: React.FC<TranslationBuilderProps> = ({ formSchema, onU | |
| onChange={({ selectedItem }) => selectedItem && languageChanger(selectedItem.code)} | ||
| /> | ||
| </div> | ||
|
|
||
| <div className={styles.translationActions}> | ||
| <button className={styles.linkButton} onClick={handleDownloadTranslation}> | ||
| {t('downloadTranslation', 'Download translation')} | ||
| <Download size={16} /> | ||
| </button> | ||
| <button | ||
| className={styles.linkButton} | ||
| onClick={handleUploadTranslationFromSchema} | ||
| disabled={translationsUploading} | ||
| > | ||
| {t('uploadTranslation', 'Upload translation')} | ||
| {!translationsUploading ? <Upload size={16} /> : <InlineLoading />} | ||
| </button> | ||
| </div> | ||
| {formSchema ? ( | ||
| <div className={styles.translationActions}> | ||
| <button className={styles.linkButton} onClick={handleDownloadTranslation}> | ||
| {t('downloadTranslation', 'Download translation')} | ||
| <Download size={16} /> | ||
| </button> | ||
| <button | ||
| className={styles.linkButton} | ||
| onClick={handleUploadTranslationFromSchema} | ||
| disabled={translationsUploading} | ||
| > | ||
| {t('uploadTranslation', 'Upload translation')} | ||
| {!translationsUploading ? <Upload size={16} /> : <InlineLoading />} | ||
| </button> | ||
| </div> | ||
| ) : null} | ||
Bharath-K-Shetty marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| </div> | ||
|
|
||
| <div className={styles.translationTabs}> | ||
|
|
@@ -287,16 +288,26 @@ const TranslationBuilder: React.FC<TranslationBuilderProps> = ({ formSchema, onU | |
| <div className={styles.translationEditor}> | ||
| {filteredTranslations.length > 0 ? ( | ||
| filteredTranslations.map(([key, value]) => ( | ||
| <div key={key} className={styles.translationRow}> | ||
| <div className={styles.translationKey}>{key}</div> | ||
| <div className={styles.translatedKey}>{value}</div> | ||
| <div | ||
| key={key} | ||
| className={styles.translationRow} | ||
| data-testid="translation-entry" | ||
| data-status="untranslated" | ||
| > | ||
| <div className={styles.translationKey} data-testid="translation-key"> | ||
| {key} | ||
| </div> | ||
| <div className={styles.translatedKey} data-testid="translation-value"> | ||
| {value} | ||
| </div> | ||
| <div className={styles.inlineControls}> | ||
| <IconButton | ||
| kind="ghost" | ||
| label={t('editString', 'Edit string')} | ||
| onClick={() => handleEditClick(key)} | ||
| size="md" | ||
| className={styles.deleteButton} | ||
| data-testid="edit-translation-button" | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same question here about the label |
||
| > | ||
| <Edit /> | ||
| </IconButton> | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.