diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml new file mode 100644 index 0000000..ec8c145 --- /dev/null +++ b/.github/workflows/e2e-tests.yml @@ -0,0 +1,36 @@ +name: End-to-End Tests + +on: + push: + branches: + - main + - develop # You can add other branches as needed + pull_request: + branches: + - main + - develop + +jobs: + e2e: + runs-on: ubuntu-latest + + services: + xserver: + image: cypress/browsers:node14.17.0-chrome93-ff92 + options: >- + --shm-size 2g + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v2 + with: + node-version: '14' # Match this with your local Node.js version + + - name: Install dependencies + run: npm install + + - name: Run E2E tests + run: npx cypress run --headless diff --git a/cypress.config.js b/cypress.config.js new file mode 100644 index 0000000..97f47c4 --- /dev/null +++ b/cypress.config.js @@ -0,0 +1,9 @@ +const { defineConfig } = require("cypress"); + +module.exports = defineConfig({ + e2e: { + setupNodeEvents(on, config) { + // implement node event listeners here + }, + }, +}); diff --git a/cypress/e2e/favs.cy.js b/cypress/e2e/favs.cy.js new file mode 100644 index 0000000..5d9e9bd --- /dev/null +++ b/cypress/e2e/favs.cy.js @@ -0,0 +1,27 @@ +describe('Favorites Page Tests', () => { + beforeEach(() => { + // Assuming you have a way to navigate to the favorites page + cy.visit('favs.html'); + }); + + it('Should check if the GIFs list exists', () => { + cy.get('#gifs-list').should('exist'); // Expect the GIFs list to exist + }); + + it('Should navigate to the login page when "Log In" button is clicked', () => { + cy.get('button.secondary-btn').contains('Log In').click({ force: true }); // Force the click + cy.url().should('include', 'login.html'); // Check if the URL is correct + }); + + it('Should toggle light/dark mode', () => { + cy.get('#toggle').click(); // Assuming this toggles the light/dark mode + // You may add assertions here to check the theme has changed + }); + + it('Should display a message when no favorites are present', () => { + // You can check for a message or specific element that indicates no favorites + cy.get('#gifs-list').should('exist'); // Ensure the GIFs list exists + cy.get('#gifs-list').should('be.empty'); // Check that it's empty, which is expected + // Add any additional assertions for your "no favorites" message if applicable + }); +}); diff --git a/cypress/e2e/login.cy.js b/cypress/e2e/login.cy.js new file mode 100644 index 0000000..82854cb --- /dev/null +++ b/cypress/e2e/login.cy.js @@ -0,0 +1,35 @@ +describe('Login Page Tests', () => { + it('Should visit the login page and check elements', () => { + cy.visit('/login.html'); + cy.get('h2').should('contain', 'Login'); + cy.get('form').within(() => { + cy.get('input[name="username"]').should('exist'); + cy.get('input[name="password"]').should('exist'); + cy.get('button[type="submit"]').should('contain', 'Login'); + }); + }); + + it('Should display error if username or password is missing', () => { + cy.visit('/login.html'); + cy.get('button[type="submit"]').click(); + cy.on('window:alert', (txt) => { + expect(txt).to.contains('Please enter both username and password'); + }); + }); + + it('Should successfully log in with correct credentials', () => { + cy.visit('/login.html'); + cy.get('input[name="username"]').type('testuser'); + cy.get('input[name="password"]').type('password123'); + cy.get('button[type="submit"]').click(); + cy.on('window:alert', (txt) => { + expect(txt).to.contains('Logged in successfully'); + }); + }); + + it('Should navigate to the sign-up page when clicking sign up link', () => { + cy.visit('/login.html'); + cy.get('.signup-link a').click(); + cy.url().should('include', 'signup.html'); + }); +}); diff --git a/cypress/e2e/navigation.cy.js b/cypress/e2e/navigation.cy.js new file mode 100644 index 0000000..0662366 --- /dev/null +++ b/cypress/e2e/navigation.cy.js @@ -0,0 +1,24 @@ +describe('Navigation Tests', () => { + it('Should navigate to the home page and verify elements', () => { + cy.visit('/'); + cy.get('#logo').should('contain', 'Giphy Search'); + }); + + it('Should open GitHub link in a new tab', () => { + cy.visit('/'); + cy.get('#github-link a').should('have.attr', 'href', 'https://github.com/lcrojano/Giphy_Explorer'); + cy.get('#github-link a').should('have.attr', 'target', '_blank'); + }); + + it('Should navigate to the login page', () => { + cy.visit('/'); + cy.get('a[href="login.html"]').click(); + cy.url().should('include', 'login.html'); + }); + + it('Should show the scroll-to-top button on scroll down', () => { + cy.visit('/'); + cy.scrollTo(0, 500); + cy.get('#myBtn').should('be.visible'); + }); +}); diff --git a/cypress/e2e/search.cy.js b/cypress/e2e/search.cy.js new file mode 100644 index 0000000..5c0b749 --- /dev/null +++ b/cypress/e2e/search.cy.js @@ -0,0 +1,29 @@ +describe('GIF Search Bar', () => { + it('Should type a search term and display results', () => { + cy.visit('/'); + cy.get('input[type="search"]').type('funny cats'); + cy.get('#search-btn').click(); + + // Check if the GIF list exists and is not empty + cy.get('#gifs-list', { timeout: 10000 }).should('exist').and('not.be.empty'); + + // Check if any GIF images are present instead of a specific text + cy.get('#gifs-list img').should('have.length.greaterThan', 0); // Ensure at least one GIF is present + + // Alternatively, you can check if it contains a class or another attribute + // Example: Check if it contains any GIF-related class or image element + // cy.get('#gifs-list').should('have.class', 'gif-class'); // Update as necessary + }); + + it('Should navigate to the favorites page when clicked', () => { + cy.visit('/'); + cy.get('#fav-btn a').click(); + cy.url().should('include', 'favs.html'); + }); + + it('Should toggle light/dark mode', () => { + cy.visit('/'); + cy.get('#toggle').click(); + cy.get('body').should('have.class', 'dark-mode'); // Assuming body toggles a class + }); +}); diff --git a/cypress/e2e/signup.cy.js b/cypress/e2e/signup.cy.js new file mode 100644 index 0000000..962ae44 --- /dev/null +++ b/cypress/e2e/signup.cy.js @@ -0,0 +1,31 @@ +describe('Sign Up Page Tests', () => { + beforeEach(() => { + cy.visit('signup.html'); // Change this path if your file is located differently + }); + + it('Should fill out the signup form and submit successfully', () => { + cy.get('#username').type('testuser'); // Type a username + cy.get('#email').type('testuser@example.com'); // Type an email + cy.get('#password').type('password123'); // Type a password + cy.get('button[type="submit"]').click(); // Click the sign-up button + + // Verify that the alert is shown with the expected message + cy.on('window:alert', (txt) => { + expect(txt).to.contains('Signed up successfully!'); // Check for success message + }); + }); + + it('Should show an alert when fields are left empty', () => { + cy.get('button[type="submit"]').click(); // Click the sign-up button without filling out the form + + // Verify that the alert is shown with the expected message + cy.on('window:alert', (txt) => { + expect(txt).to.contains('Please fill in all fields.'); // Check for alert message + }); + }); + + it('Should navigate to the login page when clicking the login link', () => { + cy.get('.login-text a').click(); // Click the login link + cy.url().should('include', 'login.html'); // Check if the URL is correct + }); +}); diff --git a/cypress/fixtures/example.json b/cypress/fixtures/example.json new file mode 100644 index 0000000..02e4254 --- /dev/null +++ b/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/cypress/screenshots/favs.cy.js/Favorites Page Tests -- Should toggle lightdark mode (failed).png b/cypress/screenshots/favs.cy.js/Favorites Page Tests -- Should toggle lightdark mode (failed).png new file mode 100644 index 0000000..a2fc0d8 Binary files /dev/null and b/cypress/screenshots/favs.cy.js/Favorites Page Tests -- Should toggle lightdark mode (failed).png differ diff --git a/cypress/screenshots/navigation.cy.js/Navigation Tests -- Should navigate to the home page and verify elements (failed).png b/cypress/screenshots/navigation.cy.js/Navigation Tests -- Should navigate to the home page and verify elements (failed).png new file mode 100644 index 0000000..2ec7eee Binary files /dev/null and b/cypress/screenshots/navigation.cy.js/Navigation Tests -- Should navigate to the home page and verify elements (failed).png differ diff --git a/cypress/screenshots/search.cy.js/GIF Search Bar -- Should toggle lightdark mode (failed).png b/cypress/screenshots/search.cy.js/GIF Search Bar -- Should toggle lightdark mode (failed).png new file mode 100644 index 0000000..66d8dc1 Binary files /dev/null and b/cypress/screenshots/search.cy.js/GIF Search Bar -- Should toggle lightdark mode (failed).png differ diff --git a/cypress/support/commands.js b/cypress/support/commands.js new file mode 100644 index 0000000..66ea16e --- /dev/null +++ b/cypress/support/commands.js @@ -0,0 +1,25 @@ +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) \ No newline at end of file diff --git a/cypress/support/e2e.js b/cypress/support/e2e.js new file mode 100644 index 0000000..0e7290a --- /dev/null +++ b/cypress/support/e2e.js @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/e2e.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') \ No newline at end of file diff --git a/package.json b/package.json index dcf80a8..a23b542 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,9 @@ "test": "jest", "prepare": "husky", "lint": "eslint --max-warnings=0", - "commit": "cz" + "commit": "cz", + "cypress:open": "cypress open", + "cypress:run": "cypress run" }, "keywords": [], "author": "", @@ -17,6 +19,7 @@ "@commitlint/config-conventional": "^19.5.0", "@eslint/js": "^9.12.0", "commitizen": "^4.3.1", + "cypress": "^13.15.0", "cz-conventional-changelog": "^3.3.0", "cz-customizable": "^7.2.1", "eslint": "^9.12.0", @@ -32,4 +35,4 @@ "path": "./node_modules/cz-customizable" } } -} +} \ No newline at end of file