Attainly/frontend/website/cypress/e2e/session-auth.cy.ts

138 lines
3.3 KiB
TypeScript

const authenticatedUser = {
id: 7,
email: 'user@example.com',
}
function interceptLogoutFlow(): void {
let authenticated = true
cy.intercept('GET', '**/api/me', (request) => {
if (authenticated) {
request.alias = 'me'
request.reply({
statusCode: 200,
body: { user: authenticatedUser },
})
return
}
request.alias = 'loggedOutMe'
request.reply({
statusCode: 401,
body: { error: 'unauthenticated' },
})
})
cy.intercept('POST', '**/api/logout', (request) => {
expect(request.headers.accept).to.equal('application/json')
authenticated = false
request.reply({ statusCode: 204 })
}).as('logout')
}
function visitDashboardAndLogout(): void {
cy.visit('/dashboard')
cy.wait('@me')
cy.contains('button', 'Log out').click()
cy.wait('@logout')
cy.wait('@loggedOutMe')
}
describe('session authentication', () => {
beforeEach(() => {
cy.intercept('GET', '**/api/sets', {
statusCode: 200,
body: { sets: [] },
})
cy.intercept('GET', '**/api/schedules', {
statusCode: 200,
body: { schedules: [] },
})
cy.intercept('GET', '**/api/assignments?date=*', (request) => {
request.reply({
statusCode: 200,
body: { date: request.query.date, assignments: [] },
})
})
})
it('restores an authenticated session on a protected route', () => {
cy.intercept('GET', '**/api/me', {
statusCode: 200,
body: { user: authenticatedUser },
}).as('me')
cy.visit('/dashboard')
cy.wait('@me')
cy.location('pathname').should('equal', '/dashboard')
cy.get('#sets-heading').should('have.text', 'Available sets')
})
it('redirects an unauthenticated protected route to login', () => {
cy.intercept('GET', '**/api/me', {
statusCode: 401,
body: { error: 'unauthenticated' },
}).as('me')
cy.visit('/dashboard')
cy.wait('@me')
cy.location('pathname').should('equal', '/login')
cy.location('search').should('include', 'redirect=/dashboard')
})
it('redirects a restored session away from a guest-only route', () => {
cy.intercept('GET', '**/api/me', {
statusCode: 200,
body: { user: authenticatedUser },
}).as('me')
cy.visit('/login')
cy.wait('@me')
cy.location('pathname').should('equal', '/dashboard')
})
it('redirects a restored session away from the home route', () => {
cy.intercept('GET', '**/api/me', {
statusCode: 200,
body: { user: authenticatedUser },
}).as('me')
cy.visit('/')
cy.wait('@me')
cy.location('pathname').should('equal', '/dashboard')
})
it('rejects a malformed authenticated-user response', () => {
cy.intercept('GET', '**/api/me', {
statusCode: 200,
body: { user: { id: 7 } },
}).as('me')
cy.visit('/dashboard')
cy.wait('@me')
cy.location('pathname').should('equal', '/login')
})
it('logs out and redirects to login', () => {
interceptLogoutFlow()
visitDashboardAndLogout()
cy.location('pathname').should('equal', '/login')
})
it('keeps protected routes inaccessible after logout', () => {
interceptLogoutFlow()
visitDashboardAndLogout()
cy.visit('/dashboard')
cy.wait('@loggedOutMe')
cy.location('pathname').should('equal', '/login')
cy.location('search').should('include', 'redirect=/dashboard')
})
})