describe('Authentication flows', () => { beforeEach(() => { cy.exec('npm run db:seed') }) afterEach(() => { cy.exec('npm run db:wipe') }) it('unauthenticated home redirects to login', () => { cy.visit('/home') cy.url().should('include', '/login') }) it('login form submits and redirects to home', () => { cy.visit('/login') cy.get('#email').type('user@example.com') cy.get('#password').type('password1') cy.get('#login-form').submit() cy.url().should('include', '/home') cy.get('h1').should('contain', 'Home') }) it('login shows error on wrong password', () => { cy.visit('/login') cy.get('#email').type('user@example.com') cy.get('#password').type('wrongpassword') cy.get('#login-form').submit() cy.get('#login-error').should('be.visible') cy.url().should('include', '/login') }) it('register creates user and redirects to home', () => { cy.visit('/register') cy.get('#email').type('fresh@example.com') cy.get('#password').type('password1') cy.get('#register-form').submit() cy.url().should('include', '/home') }) it('register shows error on short password', () => { cy.visit('/register') cy.get('#email').type('another@example.com') cy.get('#password').invoke( 'removeAttr', 'minlength' ) cy.get('#password').type('short') cy.get('#register-form').submit() cy.get('#register-error').should('be.visible') cy.url().should('include', '/register') }) it('register shows error on duplicate email', () => { cy.visit('/register') cy.get('#email').type('user@example.com') cy.get('#password').type('password1') cy.get('#register-form').submit() cy.get('#register-error').should('be.visible') cy.url().should('include', '/register') }) it('logout clears session and redirects to login', () => { cy.loginAsUser() cy.visit('/home') cy.get('#logout').click() cy.url().should('include', '/login') cy.visit('/home') cy.url().should('include', '/login') }) it('non-admin user hitting /admin gets 403', () => { cy.loginAsUser() cy.request({ url: '/admin', failOnStatusCode: false, }).then((response) => { expect(response.status).to.eq(403) }) }) it('admin user can access /admin', () => { cy.loginAsAdmin() cy.visit('/admin') cy.get('#texts').should('exist') }) })