diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 8e6d6307..b49166cd 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -2,16 +2,16 @@ # Info -Closes **[ISSUE NUMBER]**. (If there is no issue for this pull request yet, please create one or -delete this line if the pull request is for a very minor tweak). +Closes **[ISSUE NUMBER]**. -# Description - -What changes did you make? List all distinct problems that this PR addresses. Explain any relevant -motivation or context. + [description] + + ## Changes - [Fill in here] @@ -33,21 +33,18 @@ motivation or context. I have tested that my changes fully resolve the linked issue ... - [ ] locally on Desktop. -- [ ] locally on mobile - use https://ngrok.io to get a copy on a mobile device - [ ] on the live deployment preview on Desktop. - [ ] on the live deployment preview on Mobile. -- [ ] I have run and passed all new and existing Cypress tests. Add screenshots below. +- [ ] I have added new Cypress tests that are passing. # Checklist - [ ] I have performed a self-review of my own code. - [ ] I have followed the style guidelines of this project. -- [ ] I have documented my code's `src/lib` functions and commented hard to understand areas +- [ ] I have documented any new functions in `/src/lib/*` and commented hard to understand areas anywhere else. - [ ] My changes produce no new warnings. # Screenshots -Please include a screenshot of your Cypress testing suite passing successfully. - -If you made any visual changes to the website, please include relevant screenshots below. + diff --git a/.github/workflows/cypress.yml b/.github/workflows/cypress.yml new file mode 100644 index 00000000..f5987efb --- /dev/null +++ b/.github/workflows/cypress.yml @@ -0,0 +1,18 @@ +name: E2E Cypress tests +on: push +jobs: + cypress-run: + runs-on: ubuntu-22.04 + steps: + - name: Checkout + uses: actions/checkout@v4 + # Install npm dependencies, cache them correctly + # and run all Cypress tests + - name: Cypress run + uses: cypress-io/github-action@v6 + env: + NEXT_PUBLIC_ACM_API_URL: https://testing.api.acmucsd.com/api/v2 + with: + start: yarn dev:start + wait-on: 'http://localhost:3000' + install-command: yarn install diff --git a/cypress/e2e/pages/auth/login.cy.ts b/cypress/e2e/pages/auth/login.cy.ts deleted file mode 100644 index ff9ae820..00000000 --- a/cypress/e2e/pages/auth/login.cy.ts +++ /dev/null @@ -1,20 +0,0 @@ -/// - -describe('Login Page', () => { - beforeEach(() => { - cy.visit('/login'); - }); - - it('Can login with valid credentials', () => { - cy.fixture('accounts').then(accounts => { - const { admin } = accounts; - cy.get('input[name="email"]').type(admin.username); - cy.get('input[name="password"]').type(admin.password); - cy.contains('Sign In').click(); - - cy.location().should(loc => { - expect(loc.pathname).to.eq('/'); - }); - }); - }); -}); diff --git a/cypress/e2e/pages/forgot-password.cy.ts b/cypress/e2e/pages/forgot-password.cy.ts new file mode 100644 index 00000000..87d0be72 --- /dev/null +++ b/cypress/e2e/pages/forgot-password.cy.ts @@ -0,0 +1,30 @@ +/// + +describe('Forgot Password Page', () => { + beforeEach(() => { + cy.visit('/forgot-password'); + }); + + it('Should fail with missing email', () => { + cy.contains('button', 'Submit').click(); + cy.contains('p', 'Required').should('exist'); + }); + + it('Should fail with unknown email', () => { + const email = 'test@ucsd.edu'; + cy.get('input[name="email"]').type(email); + cy.contains('button', 'Submit').click(); + + cy.get('.Toastify').contains('There is no account associated with that email').should('exist'); + }); + + it('Should succeed with valid email', () => { + cy.fixture('accounts').then(({ standard }) => { + const { email } = standard; + cy.get('input[name="email"]').type(email); + cy.contains('button', 'Submit').click(); + + cy.get('.Toastify').contains('Success').should('exist'); + }); + }); +}); diff --git a/cypress/e2e/pages/login.cy.ts b/cypress/e2e/pages/login.cy.ts new file mode 100644 index 00000000..c0b90816 --- /dev/null +++ b/cypress/e2e/pages/login.cy.ts @@ -0,0 +1,79 @@ +/// + +describe('Login Page', () => { + beforeEach(() => { + cy.visit('/login'); + }); + + it('Should succeed with valid member login', () => { + cy.fixture('accounts').then(({ standard }) => { + const { email, password } = standard; + + cy.get('input[name="email"]').type(email); + cy.get('input[name="password"]').type(password); + cy.get('button').contains('Sign In').click(); + + cy.location('pathname').should('equal', '/'); + cy.getCookie('ACCESS_TOKEN').should('exist'); + }); + }); + + it('Should succeed with valid admin login', () => { + cy.fixture('accounts').then(({ admin }) => { + const { email, password } = admin; + + cy.get('input[name="email"]').type(email); + cy.get('input[name="password"]').type(password); + cy.get('button').contains('Sign In').click(); + + cy.location('pathname').should('equal', '/'); + cy.getCookie('ACCESS_TOKEN').should('exist'); + cy.getCookie('USER').should('exist'); + }); + }); + + it('Should fail with invalid credentials', () => { + const [email, password] = ['abc123@xyz.com', 'abc']; + + cy.get('input[name="email"]').type(email); + cy.get('input[name="password"]').type(password); + cy.get('button').contains('Sign In').click(); + + cy.get('.Toastify').contains('Unable to login').should('exist'); + cy.location('pathname').should('equal', '/login'); + }); + + it('Should fail with missing username', () => { + cy.fixture('accounts').then(({ standard }) => { + const { password } = standard; + + cy.get('input[name="password"]').type(password); + cy.get('button').contains('Sign In').click(); + + cy.location('pathname').should('equal', '/login'); + cy.contains('p', 'Required').should('exist'); + }); + }); + + it('Should fail with missing password', () => { + cy.fixture('accounts').then(({ standard }) => { + const { email } = standard; + + cy.get('input[name="email"]').type(email); + cy.get('button').contains('Sign In').click(); + + cy.location('pathname').should('equal', '/login'); + cy.contains('p', 'Required').should('exist'); + }); + }); + + it('Should link to forgot password page', () => { + cy.get('a').contains('Forgot your password?').click(); + cy.location('pathname').should('equal', '/forgot-password'); + }); + + it('Should link to account register page', () => { + cy.get('a').contains('Sign Up').click(); + cy.location('pathname').should('equal', '/register'); + }); +}); diff --git a/cypress/e2e/pages/register.cy.ts b/cypress/e2e/pages/register.cy.ts new file mode 100644 index 00000000..deb559c2 --- /dev/null +++ b/cypress/e2e/pages/register.cy.ts @@ -0,0 +1,7 @@ +/// + +describe('Register Page', () => { + beforeEach(() => { + cy.visit('/register'); + }); +}); diff --git a/cypress/fixtures/accounts.json b/cypress/fixtures/accounts.json index 6e8bde1b..ff6d630e 100644 --- a/cypress/fixtures/accounts.json +++ b/cypress/fixtures/accounts.json @@ -1,6 +1,10 @@ { "admin": { - "username": "acm@ucsd.edu", + "email": "acm@ucsd.edu", + "password": "password" + }, + "standard": { + "email": "acm_standard@ucsd.edu", "password": "password" } } diff --git a/package.json b/package.json index 33dc76fe..d3480b4e 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "lint:fix": "yarn prettier && eslint --fix \"src/**/*.+(js|jsx|ts|tsx)\" && stylelint --fix \"**/*.scss\"", "type-css": "yarn typed-scss-modules src/ --exportType default --logLevel silent --watch", "dev": "yarn type-css & yarn lint && next dev", + "dev:start": "next dev", "build": "next build", "start": "next start", "prod": "next build && next start", @@ -31,7 +32,7 @@ "axios": "^1.6.0", "axios-middleware": "^0.3.1", "cookies-next": "^2.1.1", - "cypress": "^13.2.0", + "cypress": "13.6.2", "ics": "^3.7.2", "luxon": "^3.3.0", "next": "^13.2.5-canary.30", @@ -48,11 +49,11 @@ "validator": "^13.9.0" }, "devDependencies": { - "@types/totp-generator": "^0.0.5", "@types/lodash": "^4.14.191", "@types/luxon": "^3.3.0", "@types/node": "18.8.1", "@types/react": "18.0.21", + "@types/totp-generator": "^0.0.5", "@types/validator": "^13.7.14", "@typescript-eslint/eslint-plugin": "^5.40.1", "eslint": "8.24.0", diff --git a/yarn.lock b/yarn.lock index 48d3105c..7412bc1e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2686,10 +2686,10 @@ csstype@^3.0.2, csstype@^3.1.2: resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b" integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ== -cypress@^13.2.0: - version "13.2.0" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-13.2.0.tgz#10f73d06a0764764ffbb903a31e96e2118dcfc1d" - integrity sha512-AvDQxBydE771GTq0TR4ZUBvv9m9ffXuB/ueEtpDF/6gOcvFR96amgwSJP16Yhqw6VhmwqspT5nAGzoxxB+D89g== +cypress@13.6.2: + version "13.6.2" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-13.6.2.tgz#c70df09db0a45063298b3cecba2fa21109768e08" + integrity sha512-TW3bGdPU4BrfvMQYv1z3oMqj71YI4AlgJgnrycicmPZAXtvywVFZW9DAToshO65D97rCWfG/kqMFsYB6Kp91gQ== dependencies: "@cypress/request" "^3.0.0" "@cypress/xvfb" "^1.2.4"