diff --git a/packages/app/components/dev/apps/list/ApplicationItem.tsx b/packages/app/components/dev/apps/list/ApplicationItem.tsx index 38f935a..9646aed 100644 --- a/packages/app/components/dev/apps/list/ApplicationItem.tsx +++ b/packages/app/components/dev/apps/list/ApplicationItem.tsx @@ -124,6 +124,7 @@ export default class ApplicationItem extends React.Component< skin={SKIN_LIGHT} disabled value={app.clientSecret} + data-testid="client-secret" copy /> @@ -228,6 +229,7 @@ export default class ApplicationItem extends React.Component< color={COLOR_RED} className={styles.appActionButton} onClick={this.onSubmitDelete} + data-testid="delete-app" small /> )} diff --git a/tests-e2e/cypress/integration/dev/applications.test.ts b/tests-e2e/cypress/integration/dev/applications.test.ts new file mode 100644 index 0000000..9f643c9 --- /dev/null +++ b/tests-e2e/cypress/integration/dev/applications.test.ts @@ -0,0 +1,117 @@ +describe('Applications', () => { + describe('user', () => { + before(() => { + cy.login({ accounts: ['default'] }).then(({ accounts: [user] }) => { + cy.visit('/dev/applications'); + + // remove all previously added apps + cy.window().then(async win => { + const { oauthApi } = (win as any) as { + oauthApi: typeof import('app/services/api/oauth').default; + }; + const apps = await oauthApi.getAppsByUser(user.id); + + await Promise.all(apps.map(app => oauthApi.delete(app.clientId))); + }); + }); + }); + + it('should add website app', () => { + cy.server(); + cy.route({ + method: 'POST', + url: '/api/v1/oauth2/*/reset', + }).as('revoke'); + cy.route({ + method: 'DELETE', + url: '/api/v1/oauth2/*', + }).as('delete'); + cy.route({ + method: 'POST', + url: '/api/v1/oauth2/*/reset?regenerateSecret', + }).as('revokeSecret'); + + cy.visit('/dev/applications'); + + cy.get('[data-e2e="noApps"]').should('exist'); + + cy.get('[data-e2e="newApp"]').click(); + + cy.url().should('include', '/dev/applications/new'); + + cy.get('[value="application"]').check({ force: true }); + + cy.get('[name="name"]').type('The Foo'); + cy.get('[name="description"]').type('The Foo Description'); + cy.get('[name="websiteUrl"]').type('https://ely.by'); + cy.get('[name="redirectUri"]').type('https://ely.by/the/redirect/uri'); + + cy.get('[type="submit"]').click(); + + cy.url().should('include', '/dev/applications#the-foo'); + + cy.get('[data-e2e-app-name="The Foo"]').should('exist'); + + // test cancel + cy.contains('Cancel').should('not.exist'); + cy.contains('Revoke all tokens').click(); + cy.contains('Cancel').click(); + cy.contains('Cancel').should('not.exist'); + + // test revoke tokens + cy.contains('Revoke all tokens').click(); + cy.contains('Continue').click(); + cy.wait('@revoke'); + cy.contains('Cancel').should('not.exist'); + + // test reset client secret + cy.getByTestId('client-secret').then(([el]) => { + const prevSecret = el.value; + + cy.getByTestId('client-secret').should('have.value', prevSecret); + cy.contains('Reset Client Secret').click(); + cy.contains('Continue').click(); + cy.wait('@revokeSecret'); + cy.contains('Cancel').should('not.exist'); + cy.getByTestId('client-secret').should('not.have.value', prevSecret); + }); + + // test delete + cy.contains('Delete').click(); + cy.getByTestId('delete-app').click(); + cy.wait('@delete'); + cy.contains("You don't have any app registered yet.").should( + 'be.visible', + ); + }); + }); + + describe('guest', () => { + it('should render login button', () => { + cy.visit('/dev/applications'); + + cy.get('[data-e2e-content] [href="/login"]').click(); + + cy.url().should('include', '/login'); + }); + + it('should not allow create new app', () => { + cy.visit('/dev/applications/new'); + + cy.url().should('include', '/login'); + }); + + it('should not allow edit app', () => { + cy.visit('/dev/applications/foo-bar'); + + cy.url().should('include', '/login'); + }); + + it('should have feedback popup link', () => { + cy.visit('/dev/applications'); + + cy.get('[data-e2e-content] [data-e2e-button="feedbackPopup"]').click(); + cy.getByTestId('feedbackPopup').should('be.visible'); + }); + }); +}); diff --git a/tests-e2e/cypress/integration/dev/guest.test.ts b/tests-e2e/cypress/integration/dev/guest.test.ts deleted file mode 100644 index ff1b159..0000000 --- a/tests-e2e/cypress/integration/dev/guest.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -describe('/dev/applications - guest', () => { - it('should render login button', () => { - cy.visit('/dev/applications'); - - cy.get('[data-e2e-content] [href="/login"]').click(); - - cy.url().should('include', '/login'); - }); - - it('should not allow create new app', () => { - cy.visit('/dev/applications/new'); - - cy.url().should('include', '/login'); - }); - - it('should not allow edit app', () => { - cy.visit('/dev/applications/foo-bar'); - - cy.url().should('include', '/login'); - }); - - it('should have feedback popup link', () => { - cy.visit('/dev/applications'); - - cy.get('[data-e2e-content] [data-e2e-button="feedbackPopup"]').click(); - cy.getByTestId('feedbackPopup').should('be.visible'); - }); -}); diff --git a/tests-e2e/cypress/integration/dev/user.test.ts b/tests-e2e/cypress/integration/dev/user.test.ts deleted file mode 100644 index dfba4b2..0000000 --- a/tests-e2e/cypress/integration/dev/user.test.ts +++ /dev/null @@ -1,40 +0,0 @@ -describe('/dev/applications - user', () => { - before(() => { - cy.login({ accounts: ['default'] }).then(({ user }) => { - cy.visit('/dev/applications'); - - // remove all previously added apps - cy.window().then(async (/** @type {any} */ { oauthApi }) => { - const apps = await oauthApi.getAppsByUser(user.id); - - await Promise.all(apps.map(app => oauthApi.delete(app.clientId))); - }); - }); - }); - - // TODO: test the first screen is without any list rendered - // TODO: test validation - - it('should add website app', () => { - cy.visit('/dev/applications'); - - cy.get('[data-e2e="noApps"]').should('exist'); - - cy.get('[data-e2e="newApp"]').click(); - - cy.url().should('include', '/dev/applications/new'); - - cy.get('[value="application"]').check({ force: true }); - - cy.get('[name="name"]').type('The Foo'); - cy.get('[name="description"]').type('The Foo Description'); - cy.get('[name="websiteUrl"]').type('https://ely.by'); - cy.get('[name="redirectUri"]').type('https://ely.by/the/redirect/uri'); - - cy.get('[type="submit"]').click(); - - cy.url().should('include', '/dev/applications#the-foo'); - - cy.get('[data-e2e-app-name="The Foo"]').should('exist'); - }); -}); diff --git a/tests-e2e/cypress/support/index.d.ts b/tests-e2e/cypress/support/index.d.ts index da7dd32..33df5a7 100644 --- a/tests-e2e/cypress/support/index.d.ts +++ b/tests-e2e/cypress/support/index.d.ts @@ -2,8 +2,8 @@ type AccountAlias = 'default' | 'default2'; -interface Account { - id: string; +interface TAccount { + id: number; username: string; password: string; email: string; @@ -31,7 +31,7 @@ declare namespace Cypress { * Whether return raw api response without any conversion. Defaults to: `false` */ rawApiResp?: boolean; - }): Promise<{ accounts: Account[] }>; + }): Promise<{ accounts: TAccount[] }>; getByTestId( id: string,