Skip to content

Commit

Permalink
test(*): mock all api endpoints in cypress tests (#151)
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewwylde authored Jul 15, 2023
1 parent f4c612a commit 083f636
Show file tree
Hide file tree
Showing 20 changed files with 127 additions and 15 deletions.
12 changes: 10 additions & 2 deletions cypress.config.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
const { defineConfig } = require('cypress')
const cypressSplit = require('cypress-split')
const dotenv = require('dotenv')

dotenv.config()

module.exports = defineConfig({
e2e: {
setupNodeEvents (on, config) {
require('cypress-terminal-report/src/installLogsPrinter')(on)
cypressSplit(on, config)

config.env = {
...process.env,
...config.env
}


// IMPORTANT: return the config object
return config
},
Expand All @@ -22,11 +31,10 @@ module.exports = defineConfig({
fixturesFolder: 'cypress/e2e/fixtures',
includeShadowDom: true,
reporter: 'spec',
retries: 2,
screenshotsFolder: 'cypress/e2e/screenshots',
scrollBehavior: 'center',
trashAssetsBeforeRuns: false,
videoCompression: false,
videosFolder: 'cypress/e2e/videos',
watchForFileChanges: false
watchForFileChanges: true
})
11 changes: 1 addition & 10 deletions cypress.server.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,7 @@ const __dirname = path.resolve()
app.use(express.static('dist', { index: false }))
app.use(express.json())

app.get('/portal_assets/logo', (req, res) => {
res.sendFile(
path.join(
__dirname,
'./cypress/e2e.kong-logo.png'
)
)
})

app.get(/^\/(?!portal_api|kauth).*/, (req, res) => {
app.get(/^\/(?!kauth).*/, (req, res) => {
res.status(200).sendFile(path.join(__dirname, './dist/index.html'))
})

Expand Down
Binary file added cypress/downloads/downloads.html
Binary file not shown.
File renamed without changes
1 change: 1 addition & 0 deletions cypress/e2e/specs/api_documentation.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ describe('Api Documentation Page', () => {
cy.mockGetProductDocumentBySlug(product.id, 'bar')
cy.mockGetProductDocuments(product.id)
cy.mockProductOperations()
cy.mockStylesheetFont()
})

const PARENT_DOCUMENT_URL = `/docs/${product.id}/${documentTreeJSON[0].slug}`
Expand Down
8 changes: 7 additions & 1 deletion cypress/e2e/specs/application_registration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ describe('Application Registration', () => {

beforeEach(() => {
cy.mockPrivatePortal()
cy.mockAppearance()
cy.mockStylesheetCss()
cy.mockStylesheetFont()
})

it('displays empty dashboard for my apps', () => {
Expand Down Expand Up @@ -163,9 +166,12 @@ describe('Application Registration', () => {
}
}).as('postApplicationRegistration')
mockApplicationWithCredAndReg(apps[3])
mockApplicationWithCredAndReg(apps[0])

cy.get(submitButton).click()



cy.wait('@postApplicationRegistration').then(() => {
cy.get('[data-testid="copy-secret-modal"]').should('exist')
cy.get('[data-testid="copy-button"]').eq(0).should('exist').should('contain', 'your-client-id')
Expand Down Expand Up @@ -225,7 +231,7 @@ describe('Application Registration', () => {
cy.get('[data-testid="applications-table"] tbody tr')
.contains(apps[0].name)
.click()

// use breadcrumb to navigate back to My Apps
cy.get('.k-breadcrumbs .k-breadcrumbs-item a').contains('My Apps').click()
cy.url().should('include', 'my-apps')
Expand Down
9 changes: 8 additions & 1 deletion cypress/e2e/specs/catalog.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ const mockProductSearchResults = (searchResults:SearchResultsDataInner[], pageNu
}

describe('Catalog', () => {

beforeEach(() => {
cy.mockStylesheetFont()
cy.mockAppearance()
cy.mockStylesheetCss()
})

describe('Catalog card view', () => {
beforeEach(() => {
cy.mockPublicPortal()
Expand Down Expand Up @@ -170,7 +177,7 @@ describe('Catalog', () => {
it('renders the documentation link for catalog item ', () => {
cy.mockPrivatePortal()
cy.mockProductsCatalog(1, [{ description: 'great description', document_count: 1 }])

cy.mockProduct()
cy.visit('/')

cy.wait('@productSearch').then(() => {
Expand Down
2 changes: 2 additions & 0 deletions cypress/e2e/specs/forbidden.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
describe('Forbidden Page', () => {
beforeEach(() => {
cy.mockPrivatePortal()
cy.mockStylesheetFont()
})

it('shows a "forbidden" page', () => {
Expand All @@ -10,6 +11,7 @@ describe('Forbidden Page', () => {
})

it('allows able to move to home using button', () => {
cy.mockProductsCatalog()
cy.visit('/403')
cy.get('[data-testid="go-home"]').click()
cy.get('.products-welcome').should('exist')
Expand Down
1 change: 1 addition & 0 deletions cypress/e2e/specs/forgot_password.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
describe('Forgot Password Page', () => {
beforeEach(() => {
cy.mockPrivatePortal()
cy.mockStylesheetFont()
})

it('has link from login page', () => {
Expand Down
2 changes: 2 additions & 0 deletions cypress/e2e/specs/login.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
describe('Login Page', () => {
beforeEach(() => {
cy.mockPrivatePortal()
cy.mockStylesheetFont()
cy.intercept('POST', '**/developer/logout', {
statusCode: 204,
body: {},
Expand Down Expand Up @@ -253,6 +254,7 @@ describe('Login Page', () => {
})

it('does not hang on loading when loginSuccess provided by user', () => {
cy.mockDeveloperRefresh()
cy.intercept('GET', '**/api/v2/developer/me', {
statusCode: 401,
body: {
Expand Down
2 changes: 2 additions & 0 deletions cypress/e2e/specs/not_found.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
describe('Not Found Page', () => {
beforeEach(() => {
cy.mockPrivatePortal()
cy.mockStylesheetFont()
})

describe('not found spec', () => {
Expand All @@ -12,6 +13,7 @@ describe('Not Found Page', () => {
})

it('allows able to move to home using button available on 404 page', () => {
cy.mockProductsCatalog()
cy.visit('/oooooooooo')
cy.get('[data-testid="go-home"]').click()
cy.get('.products-welcome').should('exist')
Expand Down
17 changes: 17 additions & 0 deletions cypress/e2e/specs/portal_auth.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,14 @@ const aliasVisitAndWait = (route, useOriginalFn = true) => {
}

describe('Portal Auth', () => {
beforeEach(() => {
cy.mockStylesheetFont()
})

describe('Private Portal - Unauthenticated', () => {
beforeEach(() => {
cy.mockPrivatePortal()
cy.mockDeveloperLogout()
})

matrix.isNotPublic.unauthenticated.redirectToLogin.forEach((route) => {
Expand Down Expand Up @@ -120,6 +125,9 @@ describe('Portal Auth', () => {
describe('Private Portal - Authenticated', () => {
beforeEach(() => {
cy.mockPrivatePortal()
cy.mockProductsCatalog()
cy.mockStylesheetFont()
cy.mockStylesheetCss()
})

matrix.isNotPublic.authenticated.viewable.forEach((route) => {
Expand Down Expand Up @@ -148,6 +156,11 @@ describe('Portal Auth', () => {
describe('Public Portal - Authenticated', () => {
beforeEach(() => {
cy.mockPublicPortal()
cy.mockProductsCatalog()
cy.mockStylesheetFont()
cy.mockStylesheetCss()
cy.mockAppearance()
cy.mockApplications()
})

matrix.isPublic.unauthenticated.viewable.forEach((route) => {
Expand Down Expand Up @@ -176,6 +189,10 @@ describe('Portal Auth', () => {
describe('Public Portal - Unauthenticated', () => {
beforeEach(() => {
cy.mockPublicPortal()
cy.mockProductsCatalog()
cy.mockStylesheetFont()
cy.mockStylesheetCss()
cy.mockAppearance()
})

matrix.isPublic.unauthenticated.viewable.forEach((route) => {
Expand Down
2 changes: 2 additions & 0 deletions cypress/e2e/specs/register.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
describe('Register Page', () => {
beforeEach(() => {
cy.mockPrivatePortal()
cy.mockStylesheetFont()
cy.mockDeveloperLogout()
})

describe('register', () => {
Expand Down
1 change: 1 addition & 0 deletions cypress/e2e/specs/reset_password.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ describe('Reset Password Page', () => {
beforeEach(() => {
cy.mockPrivatePortal()
cy.mockSuccessfulPasswordReset()
cy.mockStylesheetFont()
})
it('Sends token to backend that developer can get from email and resets password', () => {
cy.intercept('POST', '**/developer/reset-password', {
Expand Down
17 changes: 17 additions & 0 deletions cypress/e2e/specs/spec_renderer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ describe('Spec Renderer Page', () => {
beforeEach(() => {
cy.mockPrivatePortal()
cy.mockProductDocument()
cy.mockProductsCatalog()
cy.mockProduct()
cy.mockProductDocumentTree()
cy.mockProductOperations()
Expand Down Expand Up @@ -135,6 +136,15 @@ describe('Spec Renderer Page', () => {
})

describe('Multiple Versions', () => {
beforeEach(() => {
cy.mockPrivatePortal()
cy.mockProductDocument()
cy.mockProductsCatalog()
cy.mockProduct()
cy.mockProductDocumentTree()
cy.mockProductOperations()
cy.mockProductVersionSpec()
})
const weirdVersionName = 'weird <> % $ `'

const v2BetaVersion = {
Expand Down Expand Up @@ -311,6 +321,8 @@ describe('Spec Renderer Page', () => {
cy.mockProduct()
cy.mockProductVersionSpec()
cy.mockProductVersionApplicationRegistration(versions[0])
cy.mockProductDocumentTree()
cy.mockProductOperations()
})

it('redirects to 403 page when developer does not have permissions to see the spec', () => {
Expand Down Expand Up @@ -386,6 +398,11 @@ describe('Spec Renderer Page', () => {
cy.mockProduct()
cy.mockProductVersionSpec()
cy.mockProductVersionApplicationRegistration(versions[0])
cy.mockProductDocumentTree()
cy.mockProductOperations()
cy.mockStylesheetFont()
cy.mockStylesheetCss()
cy.mockAppearance()
})

it('allows seeing spec when portal is public and rbac enabled, does not call developers/me/permissions', () => {
Expand Down
12 changes: 11 additions & 1 deletion cypress/e2e/specs/themeing.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ beforeEach(() => {
})

describe('loads color theme variables', () => {
beforeEach(() => {
cy.mockStylesheetFont()
cy.mockAppearance()
})
it('loads mint_rocket theme', () => {
cy.mockStylesheetCss('mint_rocket')
cy.visit('/')
Expand Down Expand Up @@ -49,6 +53,8 @@ describe('loads color theme variables', () => {
describe('fonts', () => {
it('loads default fonts', () => {
cy.mockStylesheetFont()
cy.mockStylesheetCss()
cy.mockAppearance()
cy.visit('/')
cy.get('#site-header')
cy.get('body').should('have.css', 'font').should('contain', DEFAULT_FONTS.base)
Expand All @@ -66,6 +72,10 @@ describe('fonts', () => {
})

describe('custom Catalog', () => {
beforeEach(() => {
cy.mockStylesheetFont()
cy.mockStylesheetCss()
})
it('loads default values', () => {
cy.mockPublicPortal()
cy.mockAppearance()
Expand All @@ -76,7 +86,7 @@ describe('custom Catalog', () => {
cy.get('.products-top-section').should('have.css', 'background-image').and('not.match', /catalog_cover/)
})
it('loads custom values', () => {
cy.readFile('cypress/e2e/kong-logo.png', 'base64').then(b => {
cy.readFile('cypress/e2e/fixtures/images/kong-logo.png', 'base64').then(b => {
cy.mockAppearance({
variables: {
catalog: {
Expand Down
18 changes: 18 additions & 0 deletions cypress/e2e/support/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Import commands.js using ES2015 syntax:
import { GetApplicationResponse, GetRegistrationResponse, PortalAppearance, PortalContext, Product, ProductCatalogIndexSource, ProductVersion, ProductVersionSpecOperationsOperationsInner } from '@kong/sdk-portal-js'
import './mock-commands'
import { SinonStub } from 'cypress/types/sinon'

// from https://docs.cypress.io/guides/tooling/typescript-support
declare global {
Expand Down Expand Up @@ -35,11 +36,28 @@ declare global {
mockStylesheetFont(fonts?: {[key:string]:string}): Chainable<JQuery<HTMLElement>>
mockStylesheetCss(themeName?: string, fonts?: {[key:string]:string}): Chainable<JQuery<HTMLElement>>
mockAppearance(appearance?: PortalAppearance): Chainable<JQuery<HTMLElement>>
mockLogo(): Chainable<JQuery<HTMLElement>>
mockCatalogCover(): Chainable<JQuery<HTMLElement>>
mockLaunchDarklyFlags(flags: Array<{name:string, value:boolean}>): Chainable<JQuery<HTMLElement>>
mockDeveloperRefresh(): Chainable<JQuery<HTMLElement>>
mockDeveloperLogout(): Chainable<JQuery<HTMLElement>>
}
}
}

// Import commands.js using ES2015 syntax:
require('cypress-terminal-report/src/installLogsCollector')()


beforeEach(() => {
const API_URL = Cypress.env('VITE_PORTAL_API_URL')
const notMockedRequests = cy.stub().as('notMockedRequests')

cy.intercept(`**${API_URL}**`, notMockedRequests)
})

afterEach(() => {
cy.get<SinonStub>('@notMockedRequests')
.then(stub => cy.wrap(stub.getCalls().map(call => call.args[0].url).join(', ')))
.should('be.empty')
})
Loading

0 comments on commit 083f636

Please sign in to comment.