Skip to content

Commit

Permalink
[CLD-637] E2E test install app happy path (#252)
Browse files Browse the repository at this point in the history
  • Loading branch information
dannd4 authored Jan 8, 2020
1 parent 7c6cfbd commit 807a8d2
Show file tree
Hide file tree
Showing 14 changed files with 255 additions and 32 deletions.
10 changes: 10 additions & 0 deletions cypress/components/app-card.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export default {
actions: {
clickAppCardWithName(name: string) {
return cy.get(`div[data-test-app-name="${name}"]`).click()
},
clickAppCardSettingWithId(id: string) {
return cy.get(`div[data-test="app-settings_${id}"]`).click()
}
}
}
13 changes: 13 additions & 0 deletions cypress/components/app-detail-modal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export default {
selectors: {
buttonInstallApp: 'button[data-test="detail-modal-install-button"]',
buttonUninstallApp: 'button[data-test="detail-modal-uninstall-button"]',
buttonEditDetail: 'button[data-test="detail-modal-edit-button"]',
buttonAgree: 'button[data-test="agree-btn"]',
buttonDisagree: 'button[data-test="disagree-btn"]',
buttonSuccess: 'button[data-test="installations-success-button"]',

divInstalled: 'div[data-test="detail-modal-installed"]',
divSuccessMessage: 'div[data-test="installations-success-message"]'
}
}
5 changes: 5 additions & 0 deletions cypress/components/client-welcome-modal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default {
selectors: {
buttonAceptWelcome: 'button[data-test="button-accept-welcome-message-modal"]'
}
}
8 changes: 7 additions & 1 deletion cypress/fixtures/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@ export default {
scopes: `${apiEndPoint}/scopes`,
appsOfDeveloper: `${apiEndPoint}/apps?developerId=**&PageNumber=**&PageSize=**`,
apps: `${apiEndPoint}/apps`,
approvals: `${apiEndPoint}/approvals`,
appDetail: `${apiEndPoint}/apps/**?clientId=**`,
installedApps: `${apiEndPoint}/apps?clientId=**&OnlyInstalled=**&PageNumber=**&PageSize=**&IsDirectApi=**`,
manageApps: `${apiEndPoint}/apps?clientId=**&OnlyInstalled=**&PageNumber=**&PageSize=**`,
developers: `${apiEndPoint}/developers`,
approveApp: `${apiEndPoint}/apps/**/revisions/**/approve`,
revision: `${apiEndPoint}/apps/**/revisions`,
changePassword: `${Cypress.env('COGNITO_API_BASE_URL')}/password/change`
changePassword: `${apiEndPoint}/password/change`,
installations: `${apiEndPoint}/installations`,
terminateApp: `${apiEndPoint}/installations/**/terminate`
}
118 changes: 118 additions & 0 deletions cypress/integration/flow-install-app-happy-path.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import loginPage from '../pages/login-page'
import apiRoutes from '../fixtures/routes'
import appRequest from '../requests/app'
import developerAppsPage from '../pages/developer-apps-page'
import adminApprovalsPage from '../pages/admin-approvals-page'
import installedAppsPage from '../pages/installed-apps-page'
import manageAppsPage from '../pages/manage-apps-page'

import clientWelcomeModal from '../components/client-welcome-modal'
import appDetailModal from '../components/app-detail-modal'
import appCard from '../components/app-card'
import nanoid from 'nanoid'

const {
actions: { loginUsingClientAccount, loginUsingDeveloperAccount, loginUsingAdminAccount }
} = loginPage

const {
selectors: { buttonAceptWelcome }
} = clientWelcomeModal

const {
actions: { listedAppWithName }
} = developerAppsPage

const {
actions: { approveAppWithId }
} = adminApprovalsPage

const { url: installedAppsPageUrl } = installedAppsPage

const { url: manageAppsPageUrl } = manageAppsPage

const {
selectors: { buttonAgree, buttonInstallApp, buttonUninstallApp, buttonSuccess, divSuccessMessage }
} = appDetailModal

const {
actions: { clickAppCardSettingWithId }
} = appCard

const appName = `E2E Test App - ${nanoid()}`
let appId = ''

describe('Install app happy path', () => {
before(() => {
cy.server()
appRequest.createApp(appName)
})

after(() => {
cy.server()
appRequest.deleteApp(appId)
})

it('Log into developer and listed app successfully', () => {
cy.server()
loginUsingDeveloperAccount()
listedAppWithName(appName, res => {
appId = res
})
})

it('Log into admin and approve app successfully', () => {
cy.server()
loginUsingAdminAccount()
approveAppWithId(appId)
})

it('Log into client and install and uninstall app successfully', () => {
cy.server()
cy.clearCookies()

cy.route('GET', apiRoutes.manageApps).as('getManageApps')
cy.route('GET', apiRoutes.installedApps).as('getInstalledApps')
cy.route('POST', apiRoutes.installations).as('installApp')
cy.route('POST', apiRoutes.terminateApp).as('uninstallApp')

loginUsingClientAccount()

cy.get(buttonAceptWelcome).click()

cy.get(`div[data-test-app-name="${appName}"]`).click()

cy.get(buttonInstallApp).should('have.length', 1)
cy.get(buttonInstallApp).click()
cy.get(buttonAgree).click()

cy.wait('@installApp')

cy.route('GET', apiRoutes.appDetail).as('getAppDetail')

cy.get(divSuccessMessage).should('have.length', 1)
cy.get(buttonSuccess).click()

cy.wait('@getAppDetail')

cy.visit(installedAppsPageUrl)

cy.wait('@getInstalledApps')

cy.visit(manageAppsPageUrl)

cy.wait('@getManageApps')

clickAppCardSettingWithId(appId)

cy.get(buttonUninstallApp).click()
cy.get(buttonAgree).click()

cy.wait('@uninstallApp')

cy.get(divSuccessMessage).should('have.length', 1)
cy.get(buttonSuccess).click()

cy.wait('@getManageApps')
})
})
12 changes: 12 additions & 0 deletions cypress/pages/admin-approvals-page.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import routes from '@/constants/routes'
import apiRoutes from '../fixtures/routes'

const adminApprovalsPageMetaData = {
url: routes.ADMIN_APPROVALS,
Expand All @@ -16,6 +17,17 @@ const adminApprovalsPage = {
actions: {
clickViewDetailsButtonWithAppId(id: string) {
cy.get(`button[data-test="view-details-button_${id}"]`).click()
},
approveAppWithId(id: string) {
const { buttonApprove, btnConfirmApproval, divApproveAppSuccessfully } = adminApprovalsPageMetaData.selectors
cy.get(`button[data-test="view-details-button_${id}"]`).click()
cy.get(buttonApprove).click()

cy.route('POST', apiRoutes.approveApp).as('requestApproveApp')
cy.get(btnConfirmApproval).click()
cy.wait('@requestApproveApp')

cy.get(divApproveAppSuccessfully).should('have.length', 1)
}
}
}
Expand Down
37 changes: 37 additions & 0 deletions cypress/pages/developer-apps-page.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import webRoutes from '@/constants/routes'
import appRequests from '../requests/app'
import apiRoutes from '../fixtures/routes'
import developerSubmitAppPage from '../pages/developer-submit-app-page'

const developerAppsPageMetadata = {
url: webRoutes.DEVELOPER_MY_APPS,
Expand All @@ -11,6 +12,10 @@ const developerAppsPageMetadata = {
}
}

const {
selectors: { checkBoxIsListed, buttonSubmit, checkboxAgreeTheTermsAndConditions }
} = developerSubmitAppPage

const developerAppsPageActions = {
clickAppCardWithName(name: string) {
return cy.get(`div[data-test-app-name="${name}"]`).click()
Expand All @@ -26,6 +31,38 @@ const developerAppsPageActions = {
.then(appId => {
appRequests.deleteApp(appId as any)
})
},

listedAppWithName(name: string, callback: (appId: string) => void) {
const { buttonEditDetails } = developerAppsPageMetadata.selectors
cy.visit(developerAppsPage.url)
cy.route(apiRoutes.appsOfDeveloper).as('getAppsOfDeveloper')
cy.wait('@getAppsOfDeveloper')
cy.get(`div[data-test-app-name='${name}']`)
.click()
.invoke('attr', 'data-test-app-id')
.then(appId => {
callback(appId as any)
})

cy.route(apiRoutes.categories).as('requestGetCategories')
cy.route(apiRoutes.scopes).as('requestGetScopes')

cy.get(buttonEditDetails).click()

cy.wait('@requestGetCategories')
cy.wait('@requestGetScopes')

cy.get(checkBoxIsListed).click({ force: true })
cy.get(checkboxAgreeTheTermsAndConditions).click({ force: true })

cy.route('POST', apiRoutes.revision).as('requestSubmitRevision')
cy.get(buttonSubmit).click()
cy.wait('@requestSubmitRevision')

cy.get(buttonEditDetails)
.should('have.text', 'Pending Revision')
.should('be.disabled')
}
}

Expand Down
5 changes: 5 additions & 0 deletions cypress/pages/installed-apps-page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import routes from '@/constants/routes'

export default {
url: routes.INSTALLED_APPS
}
5 changes: 5 additions & 0 deletions cypress/pages/manage-apps-page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import routes from '@/constants/routes'

export default {
url: routes.MY_APPS
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`InstalledAppCard should match a snapshot 1`] = `
<Tile
heading="test"
image={
<img
alt="test"
className="image"
src="https://reapit-app-store-app-media.s3.eu-west-2.amazonaws.com/d10e790c-2bf2-40ae-9c43-82c1534bde31.png"
/>
}
onClick={[MockFunction]}
subHeading="Pete's Proptech World Ltd"
<div
data-test-app-id="09043eb8-9e5e-4650-b7f1-f0cb62699027"
data-test-app-name="test"
>
<p>
nXXT2zaK807ysWgy8F0WEhIYRP3TgosAtfuiLtQCImoSx0kynxbIF0nkGHU36Oz13kM3DG0Bcsicr8L6eWFKLBg4axlmiOEWcvwHAbBP9LRvoFkCl58k1wjhOExnpaZItEyOT1AXVKv8PE44aMGtVz
</p>
</Tile>
<Tile
heading="test"
image={
<img
alt="test"
className="image"
src="https://reapit-app-store-app-media.s3.eu-west-2.amazonaws.com/d10e790c-2bf2-40ae-9c43-82c1534bde31.png"
/>
}
onClick={[MockFunction]}
subHeading="Pete's Proptech World Ltd"
>
<p>
nXXT2zaK807ysWgy8F0WEhIYRP3TgosAtfuiLtQCImoSx0kynxbIF0nkGHU36Oz13kM3DG0Bcsicr8L6eWFKLBg4axlmiOEWcvwHAbBP9LRvoFkCl58k1wjhOExnpaZItEyOT1AXVKv8PE44aMGtVz
</p>
</Tile>
</div>
`;
4 changes: 3 additions & 1 deletion src/components/ui/app-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ const AppCard: React.FunctionComponent<AppCardProps> = ({ app, onClick, onSettin
menu={
app.installedOn &&
onSettingsClick && (
<FaEllipsisH className="media-icon" onClick={onSettingsClick} data-test={`app-settings_${app.id}`} />
<div data-test={`app-settings_${app.id}`}>
<FaEllipsisH className="media-icon" onClick={onSettingsClick} />
</div>
)
}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ exports[`AppDetailInner should match a snapshot when appDetailModalState = VIEW_
}
footerItems={
<Button
dataTest="detail-modal-install-button"
onClick={[MockFunction]}
type="button"
variant="primary"
Expand Down Expand Up @@ -98,6 +99,7 @@ exports[`AppDetailInner should match a snapshot when appDetailModalState = VIEW_
}
footerItems={
<Button
dataTest="detail-modal-install-button"
onClick={[MockFunction]}
type="button"
variant="primary"
Expand Down
9 changes: 5 additions & 4 deletions src/components/ui/app-detail-modal/app-detail-inner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,20 +58,20 @@ export const handleCloseModal = (

export const renderFooterAppDetailBrowse = ({ appDetailData, setStateViewInstall }) => {
return appDetailData.installedOn ? (
<div className={styles.installed}>
<div data-test="detail-modal-installed" className={styles.installed}>
<FaCheck />
<span>Installed</span>
</div>
) : (
<Button type="button" variant="primary" onClick={setStateViewInstall}>
<Button dataTest="detail-modal-install-button" type="button" variant="primary" onClick={setStateViewInstall}>
Install App
</Button>
)
}

export const renderFooterAppDetailManage = ({ setStateViewUninstall }) => {
return (
<Button type="button" variant="primary" onClick={setStateViewUninstall}>
<Button dataTest="detail-modal-uninstall-button" type="button" variant="primary" onClick={setStateViewUninstall}>
Uninstall App
</Button>
)
Expand Down Expand Up @@ -121,7 +121,8 @@ export const AppDetailInner: React.FunctionComponent<AppDetailInnerProps> = ({
<CallToAction
title="Success"
buttonText="Back to List"
dataTest="alertInstalledSuccess"
dataTest="installations-success-message"
buttonDataTest="installations-success-button"
onButtonClick={handleCloseModal(setStateViewBrowse, afterClose, installationsSetFormState)}
isCenter
>
Expand Down
24 changes: 13 additions & 11 deletions src/components/ui/installed-app-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export interface InstalledAppCardProps {
const InstalledAppCard: React.FC<InstalledAppCardProps> = ({ app, onClick }: InstalledAppCardProps) => {
if (isMobile()) {
return (
<div className={installedAppCardStyles.container}>
<div data-test-app-id={app.id} data-test-app-name={app.name} className={installedAppCardStyles.container}>
<div data-test={`app-installed_${app.id}`} onClick={onClick} className={installedAppCardStyles.wrapIcon}>
<img className={installedAppCardStyles.icon} src={app.iconUri} alt="iconUri" />
</div>
Expand All @@ -22,16 +22,18 @@ const InstalledAppCard: React.FC<InstalledAppCardProps> = ({ app, onClick }: Ins
}

return (
<Tile
onClick={onClick as () => void}
heading={app.name || ''}
subHeading={app.developer || ''}
image={
<img className="image" src={app.iconUri || 'https://bulma.io/images/placeholders/48x48.png'} alt={app.name} />
}
>
<p className={installedAppCardStyles.content}>{app.summary}</p>
</Tile>
<div data-test-app-id={app.id} data-test-app-name={app.name}>
<Tile
onClick={onClick as () => void}
heading={app.name || ''}
subHeading={app.developer || ''}
image={
<img className="image" src={app.iconUri || 'https://bulma.io/images/placeholders/48x48.png'} alt={app.name} />
}
>
<p className={installedAppCardStyles.content}>{app.summary}</p>
</Tile>
</div>
)
}

Expand Down

0 comments on commit 807a8d2

Please sign in to comment.