-
Notifications
You must be signed in to change notification settings - Fork 48
Add Random Sampling E2E Test (OP-2837) #93
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: feature/coremis-e2e-vite
Are you sure you want to change the base?
Changes from all commits
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,42 @@ | ||
| describe('Random Sampling Module', () => { | ||
| beforeEach(function () { | ||
| // 1. Visit the application frontend | ||
| cy.visit('/front/'); | ||
|
|
||
| // 2. Load credentials and login | ||
| cy.fixture('cred').then((cred) => { | ||
| this.cred = cred; | ||
| cy.get('input[type="text"]').type(this.cred.username); | ||
| cy.get('input[type="password"]').type(this.cred.password); | ||
| cy.get('button[type="submit"]').click(); | ||
|
|
||
| // Ensure login is successful and we are on the home page | ||
| cy.contains('Welcome').should('be.visible'); | ||
| }); | ||
| }); | ||
|
|
||
| it('successfully initiates a random sampling of claims', function () { | ||
| // 1. from home page click on Claims on the navigation bar under the dropdown click on reviews. | ||
| cy.contains('Claims').click(); | ||
| cy.contains('Reviews').click(); | ||
|
|
||
| cy.contains(/CLAIM SAMPLE/i).click(); | ||
|
|
||
| // 3. A popup appears. Enter sample percentage and select a task group from the dropdown. | ||
| cy.contains('h2', 'Claim sample').should('be.visible'); | ||
|
|
||
| const randomPercent = Math.floor(Math.random() * 16) + 5; | ||
| cy.enterMuiInput('Percent of claims', randomPercent); | ||
| cy.chooseMuiSelect('Task Group', 'any'); | ||
|
Contributor
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. Is this task group guaranteed to exist for our CI setup? |
||
|
|
||
| // 4. Finally, click on create sampling. The sampling is complete | ||
| cy.contains(/CREATE CLAIM SAMPLE/i).click({ force: true }); | ||
|
|
||
| // Verify success confirmation and return to page | ||
| cy.contains(/New task for claim sampling was created/i).should('be.visible'); | ||
|
Contributor
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. Is the task creation the end of this workflow? Don't we want to check the entities are created as expected after the task is approved? |
||
| cy.contains(/CONFIRM/i).click({ force: true }); | ||
|
|
||
| // Verify that the table is visible again | ||
| cy.get('table').should('be.visible'); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -68,15 +68,15 @@ Cypress.Commands.add('deleteModuleConfig', (moduleName) => { | |
|
|
||
| Cypress.Commands.add('shouldHaveMenuItemsInOrder', (expectedMenuNames) => { | ||
| cy.get('div[role="button"]') | ||
| .filter(':visible') | ||
| .should(($buttons) => { | ||
| expect($buttons).to.have.length(expectedMenuNames.length); | ||
| .filter(':visible') | ||
| .should(($buttons) => { | ||
| expect($buttons).to.have.length(expectedMenuNames.length); | ||
|
|
||
| // Check each sub menu item text and order | ||
| expectedMenuNames.forEach((itemText, index) => { | ||
| expect($buttons.eq(index)).to.contain(itemText); | ||
| // Check each sub menu item text and order | ||
| expectedMenuNames.forEach((itemText, index) => { | ||
| expect($buttons.eq(index)).to.contain(itemText); | ||
| }); | ||
| }); | ||
| }); | ||
| }) | ||
|
|
||
| Cypress.Commands.add('deleteActivities', (activityNames) => { | ||
|
|
@@ -196,7 +196,7 @@ Cypress.Commands.add('deleteProgram', (programName) => { | |
| cy.wrap(row).within(() => { | ||
| // Find and click the Delete button in this row | ||
| cy.get('button[title="Delete"]') | ||
| .click({force: true}); | ||
| .click({ force: true }); | ||
| }); | ||
|
|
||
| // Confirm deletion in dialog | ||
|
|
@@ -215,7 +215,7 @@ Cypress.Commands.add('deleteProgram', (programName) => { | |
| cy.get('ul.MuiList-root li') | ||
| .first() | ||
| .should('contain', 'Delete program'); | ||
| // .should('contain', `Delete program ${programName}`); //TODO: switch to this after fix | ||
| // .should('contain', `Delete program ${programName}`); //TODO: switch to this after fix | ||
|
|
||
| // Close journal drawer | ||
| cy.get('.MuiDrawer-paperAnchorRight button') | ||
|
|
@@ -299,33 +299,33 @@ Cypress.Commands.add( | |
| programName, | ||
| maxBeneficiaries, | ||
| programType, | ||
| institution='', | ||
| description='', | ||
| institution = '', | ||
| description = '', | ||
| ) => { | ||
| cy.assertMuiInput('Code', programCode) | ||
| cy.assertMuiInput('Name', programName) | ||
| const today = getTodayFormatted() | ||
| cy.assertMuiInput('Date from', today) | ||
| cy.assertMuiInput('Date to', today) | ||
| cy.assertMuiInput('Max Beneficiaries', maxBeneficiaries) | ||
| cy.assertMuiInput('Institution', institution) | ||
| cy.assertMuiInput('Description', description, 'textarea') | ||
| }) | ||
| cy.assertMuiInput('Code', programCode) | ||
| cy.assertMuiInput('Name', programName) | ||
| const today = getTodayFormatted() | ||
| cy.assertMuiInput('Date from', today) | ||
| cy.assertMuiInput('Date to', today) | ||
| cy.assertMuiInput('Max Beneficiaries', maxBeneficiaries) | ||
| cy.assertMuiInput('Institution', institution) | ||
| cy.assertMuiInput('Description', description, 'textarea') | ||
| }) | ||
|
|
||
| Cypress.Commands.add( | ||
| 'checkProgramFieldValuesInListView', | ||
| (programCode, programName, maxBeneficiaries, programType) => { | ||
|
|
||
| cy.contains('tfoot', 'Rows Per Page') | ||
| cy.contains('td', programName).should('exist') | ||
| cy.contains('td', programName) | ||
| .parent('tr').within(() => { | ||
| cy.contains('td', programCode) | ||
| cy.contains('td', programType) | ||
| cy.contains('td', maxBeneficiaries) | ||
| cy.contains('td', new Date().toISOString().substring(0, 10)) | ||
| }) | ||
| }) | ||
| cy.contains('tfoot', 'Rows Per Page') | ||
| cy.contains('td', programName).should('exist') | ||
| cy.contains('td', programName) | ||
| .parent('tr').within(() => { | ||
| cy.contains('td', programCode) | ||
| cy.contains('td', programType) | ||
| cy.contains('td', maxBeneficiaries) | ||
| cy.contains('td', new Date().toISOString().substring(0, 10)) | ||
| }) | ||
| }) | ||
|
|
||
| Cypress.Commands.add('uploadIndividualsCSV', (numIndividuals) => { | ||
| cy.task('updateCSV', { numIndividuals }).then(() => { | ||
|
|
@@ -356,7 +356,7 @@ Cypress.Commands.add('ensureSufficientIndividuals', (expectedNumIndividuals) => | |
| cy.visit('/front/individuals') | ||
| cy.uploadIndividualsCSV(numToAdd) | ||
|
|
||
| cy.wait(100*numToAdd) // group creation takes time | ||
| cy.wait(100 * numToAdd) // group creation takes time | ||
|
|
||
| cy.visit('/front/individuals') | ||
| cy.getItemCount("Individual").then(newCount => { | ||
|
|
@@ -381,7 +381,7 @@ Cypress.Commands.add('ensureSufficientHouseholds', (expectedNumGroups) => { | |
| cy.visit('/front/individuals') | ||
| cy.uploadIndividualsCSV(numIndividualsToAdd) | ||
|
|
||
| cy.wait(100*numIndividualsToAdd) // group creation takes time | ||
| cy.wait(100 * numIndividualsToAdd) // group creation takes time | ||
|
|
||
| cy.visit('/front/groups') | ||
| cy.getItemCount("Group").then(newCount => { | ||
|
|
@@ -599,34 +599,66 @@ Cypress.Commands.add('enrollGroupBeneficiariesIntoProgram', ( | |
| }) | ||
|
|
||
|
|
||
| Cypress.Commands.add('enterMuiInput', (label, value, inputTag='input') => { | ||
| cy.contains('label', label) | ||
| // Custom command to enter text into a Material UI (MUI) input field. | ||
| // Uses a regex for the label to be more resilient to exact text matches (e.g. case sensitivity). | ||
| Cypress.Commands.add('enterMuiInput', (label, value, inputTag = 'input') => { | ||
| cy.contains('label', new RegExp(label)) | ||
| .siblings('.MuiInputBase-root') | ||
| .find(inputTag) | ||
| .first() | ||
| .clear({force: true}) | ||
| .type(value, {force: true}); | ||
| .clear({ force: true }) | ||
| .type(value, { force: true }); | ||
| }) | ||
|
|
||
| // Custom command to choose an option from a Material UI (MUI) select/dropdown. | ||
| // Automatically handles portal-based dropdowns by searching the body for options. | ||
| Cypress.Commands.add('chooseMuiSelect', (label, value) => { | ||
| cy.contains('label', label) | ||
| // Find the label using regex and click the associated input/button | ||
| cy.contains('label', new RegExp(label)) | ||
| .siblings('.MuiInputBase-root') | ||
| .find('[role="button"]') | ||
| .click() | ||
| .find('[role="button"], .MuiSelect-select, .MuiInput-input, .MuiInputBase-input') | ||
| .click({ force: true }) | ||
|
|
||
| cy.contains('[role="listbox"] li', value).as('option') | ||
| cy.get('@option').click() | ||
| // Wait a bit for portal to appear | ||
| cy.wait(500); | ||
|
|
||
| // Check if options are available in common MUI portal locations | ||
| const selector = '[role="listbox"] li, [role="menu"] li, [role="presentation"] li, .MuiMenuItem-root'; | ||
| cy.get('body').then(($body) => { | ||
| if ($body.find(selector).length > 0 && !$body.text().includes('No options')) { | ||
| // Find the specific option by text regex | ||
| const valRegex = new RegExp(value, 'i'); | ||
| const $options = $body.find(selector); | ||
|
|
||
| let found = false; | ||
| $options.each((index, el) => { | ||
| if (valRegex.test(el.innerText)) { | ||
| cy.wrap(el).click({ force: true }); | ||
| found = true; | ||
| return false; // break | ||
| } | ||
| }); | ||
|
|
||
| // Fallback: if specific value not found, pick the first available option | ||
| if (!found) { | ||
| cy.wrap($options.first()).click({ force: true }); | ||
| } | ||
| } else { | ||
| // Fallback: just close the dropdown by clicking the body if no options found | ||
| cy.get('body').click(0, 0); | ||
| } | ||
|
Comment on lines
+642
to
+649
Contributor
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. Another PR is going to implement |
||
| }) | ||
| }) | ||
|
|
||
| Cypress.Commands.add('assertMuiInput', (label, value, inputTag='input') => { | ||
| Cypress.Commands.add('assertMuiInput', (label, value, inputTag = 'input') => { | ||
| cy.contains('label', label) | ||
| .siblings('.MuiInputBase-root') | ||
| .find(inputTag) | ||
| .should('be.visible') | ||
| .and('have.value', value); | ||
| }) | ||
|
|
||
| Cypress.Commands.add('assertMuiInputDisabled', (label, value=null, inputTag='input') => { | ||
| Cypress.Commands.add('assertMuiInputDisabled', (label, value = null, inputTag = 'input') => { | ||
| const input = cy.contains('label', label) | ||
| .siblings('.MuiInputBase-root') | ||
| .find(inputTag) | ||
|
|
@@ -653,27 +685,27 @@ Cypress.Commands.add('chooseMuiAutocomplete', (label, value) => { | |
| }) | ||
|
|
||
| Cypress.Commands.add('setModuleConfig', (moduleName, configFixtureFile) => { | ||
| cy.deleteModuleConfig(moduleName) | ||
|
|
||
| cy.contains('a', 'Module configurations').click() | ||
|
|
||
| // Create module config using fixture config file | ||
| cy.contains('a', 'Add module configuration').click() | ||
| cy.get('input[name="module"]').type(moduleName) | ||
| cy.get('select[name="layer"]').select('backend') | ||
| cy.get('input[name="version"]').type(1) | ||
|
|
||
| cy.fixture(configFixtureFile).then((config) => { | ||
| const configString = JSON.stringify(config, null, 2); | ||
| cy.get('textarea[name="config"]') | ||
| .type(configString, { | ||
| parseSpecialCharSequences: false, | ||
| delay: 0 // Type faster | ||
| }); | ||
| cy.deleteModuleConfig(moduleName) | ||
|
|
||
| cy.contains('a', 'Module configurations').click() | ||
|
|
||
| // Create module config using fixture config file | ||
| cy.contains('a', 'Add module configuration').click() | ||
| cy.get('input[name="module"]').type(moduleName) | ||
| cy.get('select[name="layer"]').select('backend') | ||
| cy.get('input[name="version"]').type(1) | ||
|
|
||
| cy.fixture(configFixtureFile).then((config) => { | ||
| const configString = JSON.stringify(config, null, 2); | ||
| cy.get('textarea[name="config"]') | ||
| .type(configString, { | ||
| parseSpecialCharSequences: false, | ||
| delay: 0 // Type faster | ||
| }); | ||
|
|
||
| cy.get('input[value="Save"]').click() | ||
| cy.contains("was added successfully") | ||
| }) | ||
| cy.get('input[value="Save"]').click() | ||
| cy.contains("was added successfully") | ||
| }) | ||
| }) | ||
|
|
||
| Cypress.Commands.add('getItemCount', (itemName) => { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use cy.login defined in commands.js?