diff --git a/.github/workflows/Regression-tests.yaml b/.github/workflows/Regression-tests.yaml index 971eeaca78..b8e02ca9d8 100644 --- a/.github/workflows/Regression-tests.yaml +++ b/.github/workflows/Regression-tests.yaml @@ -62,3 +62,4 @@ jobs: with: name: cypress-report path: testing/regression/cypress-report.zip + diff --git a/testing/regression/cypress/e2e/features/nbs-classic/organization.feature b/testing/regression/cypress/e2e/features/nbs-classic/organization.feature index 51957ed856..c141cc20bf 100644 --- a/testing/regression/cypress/e2e/features/nbs-classic/organization.feature +++ b/testing/regression/cypress/e2e/features/nbs-classic/organization.feature @@ -3,14 +3,193 @@ Feature: Classic NBS - Dedupe - User can view data in NBS Organization Search Pa Background: Given I am logged in as secure user and stay on classic - Scenario: Add organization - Then Navigate to classic organization add page - Then Click on Add button on organization add page - Then Enter quick code for new organisation - Then Click Submit button on organization add page - - Scenario: Search organization - Then Navigate to classic organization Search pane - Then Enter organization name in input text field "test" - Then Click on Search in classic organization Search pane - Then View organization details through classic search + # Data Entry Tests + + ## Search Organization + + Scenario: Verify organization exists by searching name + When I navigate to classic organization Search pane + And I enter organization name in input text field "Piedmont Hospital" + And I click on the Submit button + Then the search results should include "Piedmont Hospital" + + Scenario: Verify organization exists by searching address + When I navigate to classic organization Search pane + And I enter organization address in input text field "1364 Clifton Road" + And I click on the Submit button + Then the search results should include "Emory University Hospital" + And the search results should include address "1364 Clifton Road" + + Scenario: Add new organization with basic info + When I navigate to classic organization Search pane + And I enter a unique organization name in the name field + And I click on the Submit button + Then I should see a message that no matching organizations were found + And I click the Add button + And I select the role "Allergy clinic" + And I click on the Submit button + And I click the Add button + And I navigate to classic organization Search pane + And I enter the same organization name in the Search Pane + And I click on the Submit button + Then the organization should appear in search results + + Scenario: Add new organization with all info + When I navigate to classic organization Search pane + And I enter a unique organization name in the name field + And I click on the Submit button + Then I should see a message that no matching organizations were found + And I click the Add button + And I select a random ID Type + And I select a random Assigning Authority + And I enter a random ID Value + And I click the Add Identification button + And I select address use "Primary Work Place" + And I select address type "Office" + And I enter street address "1600 Clifton Road NE" + And I enter city "Atlanta" + And I enter zip code "30333" + And I click the Add Address button + And I select telephone use "Primary Work Place" + And I select telephone type "Phone" + And I enter telephone number "404", "639", "3311" + And I click the Add Telephone button + And I click on the Submit button + And I navigate to classic organization Search pane + And I enter the same organization name in the Search Pane + And I click on the Submit button + Then the organization should appear in search results + + ## View Organization + + Scenario: All organization details exist + When I navigate to classic organization Search pane + And I enter organization name in input text field "Piedmont Hospital" + And I click on the Submit button + And I click View on the search results + Then I should see all organization details are correct + + Scenario: Edit with overwrite + When I navigate to classic organization Search pane + And I enter organization name in input text field "CHOA - Scottish Rite" + And I click on the Submit button + And I click View on the search results + And I click the Edit button + And I select "Typographical error correction or additional information" as the reason for edit + And I select address use "Primary Work Place" + And I select address type "Office" + And I enter street address "1600 Clifton Road NE" + And I enter city "Atlanta" + And I enter zip code "30333" + And I click the Add Address button + And I select telephone use "Primary Work Place" + And I select telephone type "Phone" + And I enter telephone number "404", "639", "3311" + And I click the Add Telephone button + And I click on the Submit button + And I navigate to classic organization Search pane + And I enter organization name in input text field "CHOA - Scottish Rite" + And I click on the Submit button + Then the search results should include "CHOA - Scottish Rite" + And the search results should include address "1600 Clifton Road NE" + And the search results should include telephone "404-639-3311" + + Scenario: Edit with new organization + When I navigate to classic organization Search pane + And I enter organization name in input text field "CHOA - Scottish Rite" + And I click on the Submit button + And I save the number of search results + And I click View on the search results + And I click the Edit button + And I select "A change to existing information for non typographical reasons" as the reason for edit + And I enter a unique quick code + And I delete the existing address + And I select address use "Organizational Contact" + And I select address type "Postal/Mailing" + And I enter street address "456 Main Street" + And I click the Add Address button + And I click on the Submit button + And I navigate to classic organization Search pane + And I enter organization name in input text field "CHOA - Scottish Rite" + And I click on the Submit button + Then there should be 1 more search result than before + And one of the search results should have the generated quick code + And the search results should include address "456 Main Street" + + Scenario: Provide multiple contact records (two new telephone numbers) for organization + When I navigate to classic organization Search pane + And I enter organization name in input text field "Northside Hospital" + And I click on the Submit button + And I click View on the search results + And I click the Edit button + And I select "Typographical error correction or additional information" as the reason for edit + And I add a new telephone with use "Primary Work Place", type "Phone", number "770"-"555"-"1234" + And I add a new telephone with use "Alternate Work Place", type "Phone", number "678"-"555"-"5678" + And I click on the Submit button + And I navigate to classic organization Search pane + And I enter organization name in input text field "Northside Hospital" + And I click on the Submit button + Then the search results should include telephone "770-555-1234" + And the search results should include telephone "678-555-5678" + + Scenario: Provide multiple contact records (two new addresses) for organization + When I navigate to classic organization Search pane + And I enter organization name in input text field "St. Joseph's Hospital" + And I click on the Submit button + And I click View on the search results + And I click the Edit button + And I select "Typographical error correction or additional information" as the reason for edit + And I select address use "Alternate Work Place" + And I select address type "Office" + And I enter street address "123 Drury Lane" + And I enter city "Oakland" + And I enter zip code "94611" + And I click the Add Address button + And I select address use "Organizational Contact" + And I select address type "Postal/Mailing" + And I enter street address "456 Main Street" + And I enter city "Oakland" + And I enter zip code "94611" + And I click the Add Address button + And I click on the Submit button + And I navigate to classic organization Search pane + And I enter organization name in input text field "St. Joseph's Hospital" + And I click on the Submit button + Then the search results should include address "123 Drury Lane" + And the search results should include address "456 Main Street" + + Scenario: Provide multiple ID records for organization + When I navigate to classic organization Search pane + And I enter organization name in input text field "St. Joseph's Hospital" + And I click on the Submit button + And I click View on the search results + And I click the Edit button + And I select "Typographical error correction or additional information" as the reason for edit + And I add a new ID record with type "ABCs Hospital ID", authority "CMS Provider", value "CMS1234" + And I add a new ID record with type "Organization identifier", authority "CLIA (CMS)", value "CLIA5678" + And I click on the Submit button + And I navigate to classic organization Search pane + And I enter organization name in input text field "St. Joseph's Hospital" + And I click on the Submit button + Then the search results should include ID Type "ABCs Hospital ID" with ID Value "CMS1234" + And the search results should include ID Type "Organization identifier" with ID Value "CLIA5678" + + Scenario: Inactivate an existing organization + + When I navigate to classic organization Search pane + And I enter a unique organization name in the name field + And I click on the Submit button + And I click the Add button + And I select the role "Allergy clinic" + And I click on the Submit button + And I click the Add button + And I navigate to classic organization Search pane + And I enter the same organization name in the Search Pane + And I click on the Submit button + And I click View on the search results + And I click the Inactivate button + And I confirm the inactivation + And I navigate to classic organization Search pane + And I enter the same organization name in the Search Pane + And I click on the Submit button + Then I should see a message that no matching organizations were found \ No newline at end of file diff --git a/testing/regression/cypress/e2e/pages/nbs-classic/editOrganization.page.js b/testing/regression/cypress/e2e/pages/nbs-classic/editOrganization.page.js new file mode 100644 index 0000000000..9b0b5b9575 --- /dev/null +++ b/testing/regression/cypress/e2e/pages/nbs-classic/editOrganization.page.js @@ -0,0 +1,209 @@ +import { selectRandomDropdownValue } from "./utils"; + +class EditOrganizationPage { + selectEditReason(reasonValue) { + cy.get(`input[type="radio"][value="${reasonValue}"]`, { timeout: 10000 }) + .should('be.visible') + .check({ force: true }); + cy.log(`Selected edit reason: ${reasonValue}`); + } + enterUniqueQuickCode() { + cy.log('Entering unique quick code'); + + // Generate a random 6-character alphanumeric string + const quickCode = Math.random().toString(36).substring(2, 8).toUpperCase(); + cy.log(`Generated quick code: ${quickCode}`); + + // Find the Quick Code input field and type the generated code + cy.get('input[name="quickCodeIdDT.rootExtensionTxt"]', { timeout: 10000 }) + .should('be.visible') + .clear() + .type(quickCode); + + // Store the generated quick code for later verification if needed + cy.wrap(quickCode).as('generatedQuickCode'); + } + selectRole(roleName) { + cy.log(`Selecting role: ${roleName}`); + cy.get('select#rolesList', { timeout: 10000 }) + .should('be.visible') + .select(roleName); + } + + selectRandomIdType() { + selectRandomDropdownValue('select[fieldlabel="ID Type"]'); + } + + selectRandomAssigningAuthority() { + selectRandomDropdownValue('select[header="Authority"]'); + } + enterRandomIdValue() { + cy.log('Entering random ID Value'); + + // Generate a random string (8 characters alphanumeric) + const randomId = Math.random().toString(36).substring(2, 10).toUpperCase(); + cy.log(`Random ID Value: ${randomId}`); + + // Find the ID Value textbox and type the random string + cy.get('[id="organization.entityIdDT_s[i].rootExtensionTxt"]', { timeout: 10000 }) + .should('be.visible') + .clear() + .type(randomId); + + cy.wrap(randomId).as('generatedIdValue'); + } + + clickAddIdentificationButton() { + cy.log('Clicking Add Identification button'); + + // Click the Add Identification button + cy.get('#BatchEntryAddButtonIdentification', { timeout: 10000 }) + .should('be.visible') + .click(); + + cy.log('Add Identification button clicked'); + + } + + + addNewIdEntry(idDetails) { + cy.log(`Adding new ID entry with Type: ${idDetails.type}, Authority: ${idDetails.authority}`); + + // Scroll to Identification section + cy.contains('Identification Information').scrollIntoView(); + + // Click the Type dropdown arrow and select + cy.get('[name="organization.entityIdDT_s[i].typeCd_button"]').click(); + cy.wait(500); + cy.get('select[name="organization.entityIdDT_s[i].typeCd"]').select(idDetails.type, { force: true }); + + // Click the Assigning Authority dropdown arrow and select + cy.get('[name="organization.entityIdDT_s[i].assigningAuthorityCd_button"]').click() + cy.wait(500); + cy.get('select[name="organization.entityIdDT_s[i].assigningAuthorityCd"]').select(idDetails.authority, { force: true }); + + cy.get('[id="organization.entityIdDT_s[i].rootExtensionTxt"]', { timeout: 10000 }) + .should('be.visible') + .clear() + .type(idDetails.idValue); + this.clickAddIdentificationButton(); + } + + deleteExistingAddress() { + cy.log('Deleting first address entry'); + + // Scroll to Address section + cy.contains('Address Information').scrollIntoView(); + + // Find the first address entry in the history box and click its Delete link + cy.get('#nestedElementsHistoryBox\\|Address tr', { timeout: 10000 }) + .first() + .within(() => { + cy.contains('Delete').click(); + }); + + cy.wait(500); // Wait for the deletion to process + } + + // Methods to add new contact information (telephone and address) + + addNewTelephoneEntry(telephoneDetails) { + cy.log(`Adding new telephone: ${telephoneDetails.areaCode}-${telephoneDetails.prefix}-${telephoneDetails.lineNumber}`); + + // Scroll to Telephone section + cy.contains('Telephone Information').scrollIntoView(); + + // Click the Use dropdown arrow and select + cy.get('[name="telephone[i].useCd_button"]').click(); + cy.wait(500); + cy.get('select[name="telephone[i].useCd"]').select(telephoneDetails.use, { force: true }); + + // Click the Type dropdown arrow and select + cy.get('[name="telephone[i].cd_button"]').click(); + cy.wait(500); + cy.get('select[name="telephone[i].cd"]').select(telephoneDetails.type, { force: true }); + + // Find empty phone number fields and fill them + cy.get('input[id*="phoneNbrTxt1"]').filter((i, el) => !el.value).first() + .clear().type(telephoneDetails.areaCode); + cy.get('input[id*="phoneNbrTxt2"]').filter((i, el) => !el.value).first() + .clear().type(telephoneDetails.prefix); + cy.get('input[id*="phoneNbrTxt3"]').filter((i, el) => !el.value).first() + .clear().type(telephoneDetails.lineNumber); + + // Click Add Telephone button + cy.get('#BatchEntryAddButtonTelephone').click(); + cy.wait(1000); + } + + enterTelephoneUse(useValue) { + cy.log(`Selecting telephone use: ${useValue}`); + cy.get('select[name="telephone[i].useCd"]').select(useValue, { force: true }); + } + + enterTelephoneType(typeValue) { + cy.log(`Selecting telephone type: ${typeValue}`); + cy.get('select[name="telephone[i].cd"]').select(typeValue, { force: true }); + } + + enterTelephoneNumber(areaCode, prefix, lineNumber) { + cy.log(`Entering telephone: ${areaCode}-${prefix}-${lineNumber}`); + cy.get('input[id*="phoneNbrTxt1"]').clear().type(areaCode); + cy.get('input[id*="phoneNbrTxt2"]').clear().type(prefix); + cy.get('input[id*="phoneNbrTxt3"]').clear().type(lineNumber); + } + + clickAddTelephoneButton() { + cy.log('Clicking Add Telephone button'); + cy.get('#BatchEntryAddButtonTelephone', { timeout: 10000 }) + .should('be.visible') + .click(); + cy.wait(500); + } + + enterAddressUse(useValue) { + cy.log(`Selecting address use: ${useValue}`); + cy.get('select[name="address[i].useCd"]').select(useValue, { force: true }); + } + + enterAddressType(typeValue) { + cy.log(`Selecting address type: ${typeValue}`); + cy.get('select[name="address[i].cd"]').select(typeValue, { force: true }); + } + + enterStreetAddress1(address) { + cy.log(`Entering street address: ${address}`); + cy.get('input[name="address[i].thePostalLocatorDT_s.streetAddr1"]') + .should('be.visible') + .clear() + .type(address); + } + + enterCity(city) { + cy.log(`Entering city: ${city}`); + cy.get('input[name="address[i].thePostalLocatorDT_s.cityDescTxt"]') + .should('be.visible') + .clear() + .type(city); + } + + enterZipCode(zip) { + cy.log(`Entering zip code: ${zip}`); + cy.get('input[name="address[i].thePostalLocatorDT_s.zipCd"]') + .should('be.visible') + .clear() + .type(zip); + } + + clickAddAddressButton() { + cy.log('Clicking Add Address button'); + cy.get('#BatchEntryAddButtonAddress', { timeout: 10000 }) + .should('be.visible') + .click(); + cy.wait(500); + } + + +} + +export default new EditOrganizationPage(); \ No newline at end of file diff --git a/testing/regression/cypress/e2e/pages/nbs-classic/organization.page.js b/testing/regression/cypress/e2e/pages/nbs-classic/organization.page.js index 209a4d9f75..1363c55070 100644 --- a/testing/regression/cypress/e2e/pages/nbs-classic/organization.page.js +++ b/testing/regression/cypress/e2e/pages/nbs-classic/organization.page.js @@ -1,42 +1,295 @@ -class ClassicPatientSearchPage { +class ClassicOrganizationPage { + + // Navigation methods navigateToClassicOrganizationSearchPane() { cy.contains('Data Entry').eq(0).click() cy.contains('Organization').eq(0).click() } - enterNameInClassicSearchOrganizationPage(text) { - cy.get('input[id="organizationSearch.nmTxt"]').type(text).should('have.value', text) - cy.wait(1000) + // Search methods + enterOrganizationNameInSearch(name) { + cy.get('input[id="organizationSearch.nmTxt"]').type(name) + } + + enterOrganizationAddressInSearch(address) { + cy.get('input[id="organizationSearch.streetAddr1"]').type(address) + } + + enterUniqueOrganizationNameInSearch() { + const timestamp = Date.now(); + const uniqueName = `random string ${timestamp}`; + cy.log(`Using unique organization name: ${uniqueName}`); + cy.wrap(uniqueName).as('orgName'); + cy.get('input[id="organizationSearch.nmTxt"]').type(uniqueName) + cy.wrap(uniqueName).as('createdOrgName'); + } + + enterSameOrganizationNameInSearchPane() { + // Retrieve the name from the alias and use it + cy.get('@createdOrgName').then((orgName) => { + cy.log(`Using stored organization name in search pane: ${orgName}`); + cy.get('input[id="organizationSearch.nmTxt"]') + .should('be.visible') + .clear() + .type(orgName); + }); + } + + saveSearchResultsCount() { + cy.log('Saving search results count'); + + // Get the text from the red result message + cy.get('div.boldTenDkRed', { timeout: 10000 }) + .should('be.visible') + .invoke('text') + .then((text) => { + // Extract the number from text like "resulted in 3 possible matches" + const match = text.match(/resulted in (\d+) possible matches/); + const count = match ? parseInt(match[1]) : 0; + + cy.log(`Found ${count} search results`); + + // Save to alias for later use + cy.wrap(count).as('searchResultsCount'); + }); + } + + // Add/Edit methods + + clickEditButton() { + cy.get('input[name="Edit"]').eq(0).click() + } + + /** + * Click the Inactivate button on the View Organization page + */ + clickInactivateButton() { + cy.log('Clicking Inactivate button'); + cy.get('#Inactivate').eq(0).click(); + } + acceptConfirmationPopup() { + cy.log('Accepting confirmation popup'); + + // Cypress automatically handles native browser dialogs + // This event listener will click OK on the confirm popup + cy.on('window:confirm', () => { + cy.log('Confirmation popup accepted'); + return true; // true clicks OK, false would click Cancel + }); + } + + // Navigation from search results to view + clickViewOnSearchResults() { + cy.log('Clicking View on search results'); + cy.contains('View').eq(0).click(); + } + + + // Verification methods + verifySearchResultsContain(expectedText) { + cy.log(`Verifying search results include: ${expectedText}`); + cy.get('#searchResultsTable', { timeout: 10000 }) + .should('be.visible') + .and('contain', expectedText); + } + + verifySearchResultContainsGeneratedQuickCode() { + cy.log('Verifying search result contains generated quick code'); + + cy.get('@generatedQuickCode').then((quickCode) => { + cy.log(`Looking for quick code: ${quickCode}`); + + cy.get('#searchResultsTable', { timeout: 10000 }) + .should('be.visible') + .and('contain', quickCode); + }); + } + + verifySearchResultsContainAddress(expectedAddress) { + cy.log(`Verifying search results include address: ${expectedAddress}`); + cy.get('#searchResultsTable', { timeout: 10000 }) + .should('be.visible') + .and('contain', expectedAddress); + } + + verifySearchResultsContainTelephone(expectedTelephone) { + cy.log(`Verifying search results include telephone: ${expectedTelephone}`); + cy.get('#searchResultsTable', { timeout: 10000 }) + .should('be.visible') + .and('contain', expectedTelephone); + } + + verifySearchResultsContainIdTypeAndValue(expectedType, expectedValue) { + cy.log(`Verifying search results include ID Type: ${expectedType} with ID Value: ${expectedValue}`); + cy.get('#searchResultsTable', { timeout: 10000 }) + .should('be.visible') + .and('contain', expectedType) + .and('contain', expectedValue); + } + + verifyNoResultsFound() { + cy.log('Verifying no results message'); + cy.get('div.boldTenDkRed', { timeout: 10000 }) + .should('be.visible') + .and('contain', 'resulted in 0 possible matches'); + cy.get('div.boldTenDkRed a') + .should('be.visible') + .and('contain', 'refine your search?'); + cy.get('#searchResultsTable') + .should('contain', 'There is no information to display'); + } + + verifyOrganizationWasCreated() { + cy.get('@createdOrgName').then((orgName) => { + cy.log(`Verifying search results include: ${orgName}`); + cy.get('#searchResultsTable', { timeout: 10000 }) + .should('be.visible') + .and('contain', orgName); + }); + + } + verifySuccessMessage() { + cy.url().should('include', 'ViewOrganization'); + cy.get('body').should('contain', 'created') + .or('contain', 'added') + .or('contain', 'successful'); + } + + verifySearchResultsCountIncreasedBy(additionalCount) { + cy.log(`Verifying search results count increased by ${additionalCount}`); + + // Get the previously saved count + cy.get('@searchResultsCount').then((savedCount) => { + const expectedCount = savedCount + additionalCount; + + cy.log(`Saved count: ${savedCount}, Expected: ${expectedCount} (${additionalCount > 0 ? '+' : ''}${additionalCount})`); + + // Check the current count from the red text + cy.get('div.boldTenDkRed', { timeout: 10000 }) + .should('be.visible') + .invoke('text') + .then((text) => { + const match = text.match(/resulted in (\d+) possible matches/); + const currentCount = match ? parseInt(match[1]) : 0; + + cy.log(`Current count: ${currentCount}`); + expect(currentCount).to.equal(expectedCount); + }); + }); + } + + + // Administrative Information verification + verifyQuickCode(expectedValue) { + cy.log(`Verifying Quick Code: ${expectedValue}`); + cy.get('#test').should('contain', expectedValue); + } + + verifyStandardIndustryClass(expectedValue) { + cy.log(`Verifying Standard Industry Class: ${expectedValue}`); + cy.get('[id="organization.theOrganizationDT.standardIndustryClassCd"]').should('contain', expectedValue); + } + + verifyRole(expectedRole) { + cy.log(`Verifying Role: ${expectedRole}`); + cy.get('#rolesList').should('contain', expectedRole); + } + + // Name verification + verifyOrganizationName(expectedName) { + cy.log(`Verifying Organization Name: ${expectedName}`); + cy.get('#name\\.nmTxt').should('contain', expectedName); + } + + // Identification Information verification + verifyIdentificationType(expectedType) { + cy.log(`Verifying Identification Type: ${expectedType}`); + cy.get('#nestedElementsHistoryBox\\|Identification tr').first().find('td').eq(1).should('contain', expectedType); + } + + verifyIdentificationAuthority(expectedAuthority) { + cy.log(`Verifying Identification Authority: ${expectedAuthority}`); + cy.get('#nestedElementsHistoryBox\\|Identification tr').first().find('td').eq(2).should('contain', expectedAuthority); + } + + verifyIdentificationValue(expectedValue) { + cy.log(`Verifying Identification Value: ${expectedValue}`); + cy.get('#nestedElementsHistoryBox\\|Identification tr').first().find('td').eq(3).should('contain', expectedValue); + } + + // Address Information verification + verifyAddressUse(expectedUse) { + cy.log(`Verifying Address Use: ${expectedUse}`); + cy.get('#nestedElementsHistoryBox\\|Address tr').first().find('td').eq(1).should('contain', expectedUse); + } + + verifyStreetAddress(expectedAddress) { + cy.log(`Verifying Street Address: ${expectedAddress}`); + cy.get('#nestedElementsHistoryBox\\|Address tr').first().find('td').eq(2).should('contain', expectedAddress); + } + + verifyCity(expectedCity) { + cy.log(`Verifying City: ${expectedCity}`); + cy.get('#nestedElementsHistoryBox\\|Address tr').first().find('td').eq(3).should('contain', expectedCity); } - clickSearchBtnInClassicOrganizationSearchPane() { - cy.get('input[name="Submit"][id="Submit"]').eq(0).click() + verifyState(expectedState) { + cy.log(`Verifying State: ${expectedState}`); + cy.get('#nestedElementsHistoryBox\\|Address tr').first().find('td').eq(4).should('contain', expectedState); } - viewOrganizationDetails() { - cy.contains('View', { timeout: 10000 }).eq(0).click() + verifyZip(expectedZip) { + cy.log(`Verifying Zip: ${expectedZip}`); + cy.get('#nestedElementsHistoryBox\\|Address tr').first().find('td').eq(5).should('contain', expectedZip); } - navigateToAddOrganisation() { - this.navigateToClassicOrganizationSearchPane() - this.enterNameInClassicSearchOrganizationPage('test') - this.clickSearchBtnInClassicOrganizationSearchPane() + // Telephone Information verification + verifyTelephoneUse(expectedUse) { + cy.log(`Verifying Telephone Use: ${expectedUse}`); + cy.get('#nestedElementsHistoryBox\\|Telephone tr').first().find('td').eq(1).should('contain', expectedUse); } - clickAddButtonOnAddOrganisation() { - cy.get('#Add').eq(0).click() + verifyTelephoneType(expectedType) { + cy.log(`Verifying Telephone Type: ${expectedType}`); + cy.get('#nestedElementsHistoryBox\\|Telephone tr').first().find('td').eq(2).should('contain', expectedType); } - enterQuickCode() { - const newName = Math.random().toString(36).substring(2, 8) - cy.get('input[name="quickCodeIdDT.rootExtensionTxt"]').eq(0).type(newName) + verifyTelephoneNumber(expectedNumber) { + cy.log(`Verifying Telephone Number: ${expectedNumber}`); + cy.get('#nestedElementsHistoryBox\\|Telephone tr').first().find('td').eq(3).should('contain', expectedNumber); } - clickSubmitBtnOnOrganisation() { - cy.get('input[name="Submit"][id="Submit"]').eq(0).click() + // Combined verification method for all organization details + verifyAllOrganizationDetails() { + cy.log('Verifying all organization details'); + + // Administrative Information + this.verifyQuickCode('1'); + this.verifyStandardIndustryClass('Health Care and Social Assistance'); + this.verifyRole('Hospital'); + + // Name + this.verifyOrganizationName('Piedmont Hospital'); + + // Identification Information + this.verifyIdentificationType('Organization identifier'); + this.verifyIdentificationAuthority('CMS Provider'); + this.verifyIdentificationValue('CMS1234'); + + // Address Information + this.verifyAddressUse('Primary Work Place'); + this.verifyStreetAddress('1968 Peachtree Road NW'); + this.verifyCity('Atlanta'); + this.verifyState('Georgia'); + this.verifyZip('30056'); + + // Telephone Information + this.verifyTelephoneUse('Primary Work Place'); + this.verifyTelephoneType('Phone'); + this.verifyTelephoneNumber('404-605-5000'); } } -export default new ClassicPatientSearchPage(); +export default new ClassicOrganizationPage(); \ No newline at end of file diff --git a/testing/regression/cypress/e2e/pages/nbs-classic/utils.js b/testing/regression/cypress/e2e/pages/nbs-classic/utils.js new file mode 100644 index 0000000000..df1247aebf --- /dev/null +++ b/testing/regression/cypress/e2e/pages/nbs-classic/utils.js @@ -0,0 +1,43 @@ + +/** + * Utility functions for handling dropdowns + */ + +/** + * Select a random value from any dropdown + * @param {string} dropdownSelector - Selector for the dropdown element + * @returns {Cypress.Chainable} - The selected value + */ + +export function selectRandomDropdownValue(dropdownSelector) { + cy.log(`Selecting random value from dropdown: ${dropdownSelector}`); + + // Get all non-empty option values from the dropdown + cy.get(`${dropdownSelector} option:not([value=""])`).then(($options) => { + const optionCount = $options.length; + + if (optionCount === 0) { + cy.log('No options found in dropdown'); + return; + } + + cy.log(`Dropdown has ${optionCount} options`); + + // Create array of values and pick a random one + const optionValues = $options.toArray().map(opt => opt.value); + const randomValue = optionValues[Math.floor(Math.random() * optionCount)]; + + cy.log(`Selected value: ${randomValue}`); + + // Select the random value (using force: true in case the select is disabled) + cy.get(dropdownSelector).select(randomValue, { force: true }); + }); +} +export function clickSubmitButton() { + cy.get('input[name="Submit"][id="Submit"]').eq(0).click() + cy.wait(1000); +} + +export function clickAddButton() { + cy.get('#Add').eq(0).click() +} \ No newline at end of file diff --git a/testing/regression/cypress/step_definitions/nbs-classic/organization.steps.js b/testing/regression/cypress/step_definitions/nbs-classic/organization.steps.js index 0e81a0a525..ed7324ccc4 100644 --- a/testing/regression/cypress/step_definitions/nbs-classic/organization.steps.js +++ b/testing/regression/cypress/step_definitions/nbs-classic/organization.steps.js @@ -1,34 +1,201 @@ -import { Given, When, Then } from "@badeball/cypress-cucumber-preprocessor"; -import classicSearchOrganizationPage from "@pages/nbs-classic/organization.page"; +import { When, Then } from "@badeball/cypress-cucumber-preprocessor"; +import classicOrganizationPage from "../../e2e/pages/nbs-classic/organization.page"; +import editOrganizationPage from "../../e2e/pages/nbs-classic/editOrganization.page"; +import { maps } from "../organizationValueMaps"; +import { clickSubmitButton, clickAddButton } from "../../e2e/pages/nbs-classic/utils"; -Then("Navigate to classic organization Search pane", () => { - classicSearchOrganizationPage.navigateToClassicOrganizationSearchPane() +// Navigation and search steps +When("I navigate to classic organization Search pane", () => { + classicOrganizationPage.navigateToClassicOrganizationSearchPane() }); -Then("Enter organization name in input text field {string}", (text) => { - classicSearchOrganizationPage.enterNameInClassicSearchOrganizationPage(text) +When("I enter organization name in input text field {string}", (text) => { + classicOrganizationPage.enterOrganizationNameInSearch(text) }); -Then("Click on Search in classic organization Search pane", () => { - classicSearchOrganizationPage.clickSearchBtnInClassicOrganizationSearchPane() +When("I enter a unique organization name in the name field", () => { + classicOrganizationPage.enterUniqueOrganizationNameInSearch() }); -Then("View organization details through classic search", () => { - classicSearchOrganizationPage.viewOrganizationDetails() +When("I enter the same organization name in the Search Pane", () => { + classicOrganizationPage.enterSameOrganizationNameInSearchPane(); }); -Then("Navigate to classic organization add page", () => { - classicSearchOrganizationPage.navigateToAddOrganisation() +When("I save the number of search results", () => { + classicOrganizationPage.saveSearchResultsCount(); }); -Then("Click on Add button on organization add page", () => { - classicSearchOrganizationPage.clickAddButtonOnAddOrganisation() +When("I enter organization address in input text field {string}", (text) => { + classicOrganizationPage.enterOrganizationAddressInSearch(text) }); -Then("Enter quick code for new organisation", () => { - classicSearchOrganizationPage.enterQuickCode() +When("I click on the Submit button", () => { + clickSubmitButton() }); -Then("Click Submit button on organization add page", () => { - classicSearchOrganizationPage.clickSubmitBtnOnOrganisation() +// Add organization steps + +When("I enter a random ID Value", () => { + editOrganizationPage.enterRandomIdValue() +}); + + +When("I select the role {string}", (roleName) => { + editOrganizationPage.selectRole(roleName) +}); + +When ("I click the Add button", () => { + clickAddButton() +}); + +When ("I select a random ID Type", () => { + editOrganizationPage.selectRandomIdType() +}); + +When ("I select a random Assigning Authority", () => { + editOrganizationPage.selectRandomAssigningAuthority() +}); + +When ("I click the Add Identification button", () => { + editOrganizationPage.clickAddIdentificationButton() +}); + +When("I add two new ID records with different ID Types and Assigning Authorities", () => { + classicOrganizationPage.addTwoNewIdRecords(); +}); + +When("I click View on the search results", () => { + classicOrganizationPage.clickViewOnSearchResults(); +}); + +// Address Information steps +When("I select address use {string}", (useDisplay) => { + editOrganizationPage.enterAddressUse(maps.addressUseToValue(useDisplay)); +}); + +When("I select address type {string}", (typeDisplay) => { + editOrganizationPage.enterAddressType(maps.addressTypeToValue(typeDisplay)); +}); + +When("I enter street address {string}", (address) => { + editOrganizationPage.enterStreetAddress1(address); +}); + +When("I enter city {string}", (city) => { + editOrganizationPage.enterCity(city); +}); + +When("I enter zip code {string}", (zip) => { + editOrganizationPage.enterZipCode(zip); +}); + +When("I click the Add Address button", () => { + editOrganizationPage.clickAddAddressButton(); +}); + + +// Telephone Information steps +When("I select telephone use {string}", (useDisplay) => { + editOrganizationPage.enterTelephoneUse(maps.telephoneUseToValue(useDisplay)); +}); + +When("I select telephone type {string}", (typeDisplay) => { + editOrganizationPage.enterTelephoneType(maps.telephoneTypeToValue(typeDisplay)); +}); + +When("I enter telephone number {string}, {string}, {string}", (areaCode, prefix, lineNumber) => { + editOrganizationPage.enterTelephoneNumber(areaCode, prefix, lineNumber); +}); + +When("I click the Add Telephone button", () => { + editOrganizationPage.clickAddTelephoneButton(); }); + +When("I add a new telephone with use {string}, type {string}, number {string}-{string}-{string}", + (useDisplay, typeDisplay, areaCode, prefix, lineNumber) => { + editOrganizationPage.addNewTelephoneEntry({ + use: maps.telephoneUseToValue(useDisplay), + type: maps.telephoneTypeToValue(typeDisplay), + areaCode: areaCode, + prefix: prefix, + lineNumber: lineNumber + }); +}); + +// ID Information steps +When("I add a new ID record with type {string}, authority {string}, value {string}", + (typeDisplay, authorityDisplay, value) => { + editOrganizationPage.addNewIdEntry({ + type: maps.idTypeToValue(typeDisplay), + authority: maps.idAuthorityToValue(authorityDisplay), + idValue: value + }); +}); + + +// Edit organization steps +When("I click the Edit button", () => { + classicOrganizationPage.clickEditButton(); +}); + +When("I select {string} as the reason for edit", (reasonDisplay) => { + editOrganizationPage.selectEditReason(maps.editReasonToValue(reasonDisplay)); +}); + +When("I enter a unique quick code", () => { + editOrganizationPage.enterUniqueQuickCode(); +}); + +When("I delete the existing address", () => { + editOrganizationPage.deleteExistingAddress(); +}); + +// Inactivate organization steps +When("I click the Inactivate button", () => { + classicOrganizationPage.clickInactivateButton(); +}); + +When("I confirm the inactivation", () => { + classicOrganizationPage.acceptConfirmationPopup(); +}); + +// Verification steps +Then("the search results should include {string}", (expectedText) => { + classicOrganizationPage.verifySearchResultsContain(expectedText) +}); + +Then("there should be {int} more search result than before", (additionalResultCount) => { + classicOrganizationPage.verifySearchResultsCountIncreasedBy(additionalResultCount); +}); + +Then("one of the search results should have the generated quick code", () => { + classicOrganizationPage.verifySearchResultContainsGeneratedQuickCode(); +}); + +Then("the search results should include address {string}", (expectedAddress) => { + classicOrganizationPage.verifySearchResultsContainAddress(expectedAddress) +}); + +Then("I should see a message that no matching organizations were found", () => { + classicOrganizationPage.verifyNoResultsFound() +}); + +Then("the organization should appear in search results", () => { + classicOrganizationPage.verifyOrganizationWasCreated(); +}); + +Then("I should see a success message", () => { + classicOrganizationPage.verifySuccessMessage() +}); + +Then("I should see all organization details are correct", () => { + classicOrganizationPage.verifyAllOrganizationDetails(); +}); + +Then("the search results should include telephone {string}", (expectedTelephone) => { + classicOrganizationPage.verifySearchResultsContainTelephone(expectedTelephone); +}); + +Then("the search results should include ID Type {string} with ID Value {string}", (expectedType, expectedValue) => { + classicOrganizationPage.verifySearchResultsContainIdTypeAndValue(expectedType, expectedValue); +}); \ No newline at end of file diff --git a/testing/regression/cypress/step_definitions/organizationValueMaps.js b/testing/regression/cypress/step_definitions/organizationValueMaps.js new file mode 100644 index 0000000000..6bac1eb0fc --- /dev/null +++ b/testing/regression/cypress/step_definitions/organizationValueMaps.js @@ -0,0 +1,109 @@ + +// ============================================================================ +// DISPLAY TEXT TO VALUE MAPPING FUNCTIONS +// ============================================================================ + +export const maps = { + /** + * Map address use display text to value + * @param {string} displayText - Display text (e.g., 'Primary Work Place') + * @returns {string} - Value code (e.g., 'WP') + */ + addressUseToValue(displayText) { + const map = { + 'Primary Work Place': 'WP', + 'Alternate Work Place': 'SB', + 'Organizational Contact': 'OC' + }; + return map[displayText] || displayText; + }, + + /** + * Map address type display text to value + * @param {string} displayText - Display text (e.g., 'Office') + * @returns {string} - Value code (e.g., 'O') + */ + addressTypeToValue(displayText) { + const map = { + 'Office': 'O', + 'Postal/Mailing': 'M' + }; + return map[displayText] || displayText; + }, + + /** + * Map telephone use display text to value + * @param {string} displayText - Display text (e.g., 'Primary Work Place') + * @returns {string} - Value code (e.g., 'WP') + */ + telephoneUseToValue(displayText) { + const map = { + 'Primary Work Place': 'WP', + 'Alternate Work Place': 'SB', + 'Organizational Contact': 'OC' + }; + return map[displayText] || displayText; + }, + + /** + * Map telephone type display text to value + * @param {string} displayText - Display text (e.g., 'Phone') + * @returns {string} - Value code (e.g., 'PH') + */ + telephoneTypeToValue(displayText) { + const map = { + 'Phone': 'PH', + 'FAX': 'FAX', + 'Answering service': 'AN' + }; + return map[displayText] || displayText; + }, + + /** + * Map ID type display text to value + * @param {string} displayText - Display text (e.g., 'ABCs Hospital ID') + * @returns {string} - Value code (e.g., 'ABC') + */ + idTypeToValue(displayText) { + const map = { + 'ABCs Hospital ID': 'ABC', + 'Clinical Laboratory Improvement Amendments': 'CLIA', + 'Facility ID': 'FI', + 'Manufacturer Identifier': 'MID', + 'National employer identifier': 'NE', + 'National health plan identifier': 'NH', + 'Organization identifier': 'XX', + 'Partner Services Site ID': 'PSID', + 'Other': 'OTH' + }; + return map[displayText] || displayText; + }, + + /** + * Map ID authority display text to value + * @param {string} displayText - Display text (e.g., 'CMS Provider') + * @returns {string} - Value code (e.g., 'CMS') + */ + idAuthorityToValue(displayText) { + const map = { + 'AHA': 'AHA', + 'CLIA (CMS)': 'CLIA', + 'CMS Provider': 'CMS', + 'Other': 'OTH' + }; + return map[displayText] || displayText; + }, + + /** + * Map edit reason display text to value + * @param {string} displayText - Display text + * @returns {string} - Value code ('c' or 'n') + */ + editReasonToValue(displayText) { + const map = { + 'Typographical error correction or additional information': 'c', + 'A change to existing information for non typographical reasons': 'n' + }; + return map[displayText] || displayText; + } +}; \ No newline at end of file