Skip to content

Commit

Permalink
Merge branch 'main' into smart-ui
Browse files Browse the repository at this point in the history
  • Loading branch information
bhargav-garlapati committed Nov 25, 2024
2 parents e7d22f5 + ad3d768 commit 04bf779
Show file tree
Hide file tree
Showing 16 changed files with 302 additions and 16 deletions.
63 changes: 59 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,64 @@
# cypress-example-e2e
It's a simple Cypress project which presents how you can set up GitHub Actions to publish the test result on GitHub Page.
# Cypress Example E2E

Test execution result page can be accessed on: https://bhargav-garlapati.github.io/cypress-example-e2e/
This repository demonstrates how to set up and run end-to-end tests using Cypress, integrated with a CI/CD pipeline for automated testing. The project is configured to run tests through GitHub Actions, making it easy to execute and publish results automatically.

[![To view Percy.io visual regression testing results.](https://percy.io/static/images/percy-badge.svg)](https://percy.io/b72d4388/web/cypress-example-e2e)
## Features

- **End-to-End Testing**: Using Cypress to test web applications.
- **CI/CD Integration**: GitHub Actions workflow to run tests on every push.
- **Automated Reporting**: Test results published to GitHub Pages.
- **Cross-browser Testing**: Supports testing on different browsers via Cypress.
- **Configuration**: Configurable for different environments and use cases.

## Getting Started

To set up this project locally:

1. Clone the repository:
```bash
git clone https://github.com/bhargav-garlapati/cypress-example-e2e.git

2. Install dependencies:
```bash
./init.sh
(This shell script will fetch env variables from GCP and install dependencies)
If you encounter access issues, please create a file named `cypress.env.json` in the root directory of the repository locally, and add the following test secrets:
{
"BASIC_AUTH_USERNAME": "admin",
"BASIC_AUTH_PASSWORD": "admin",
"USERNAME": "tomsmith",
"PASSWORD": "SuperSecretPassword!",
"test": "test"
}
Next, install dependencies `npm install`
3. Run Tests
```bash
npm run cypress:production

The tests are automatically triggered on every push request, with the results displayed on GitHub Pages.

## Test Demos
- A/B Variation
- Accessibility
- Add and Remove Elements
- Basic Auth Test
- Interacting with Checkboxes
- Drag and Drop Items
- Handling Iframes
- Handling JS Alerts, Confirm, and Prompt
- Login Flow test
- Upload file
- UI Visual Testing using Percy (smart UI, Applitools Eyes are coming soon...)
Each test can be run individually or as part of the complete test suite.

You can view the test execution results here:
https://bhargav-garlapati.github.io/cypress-example-e2e/

Percy.io visual regression results:[![To view Percy.io visual regression testing results.](https://percy.io/static/images/percy-badge.svg)](https://percy.io/b72d4388/web/cypress-example-e2e)

License:
This project is licensed under the MIT License. See the LICENSE file for details.
2 changes: 1 addition & 1 deletion cypress/e2e/ab_variation.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ describe('Welcome to the-internet', () => {

it('A/B Test Variation', () => {

// Visit login page
// Visit abtest page
cy.visitPage('/abtest');

// Check h3 text
Expand Down
64 changes: 64 additions & 0 deletions cypress/e2e/accessibilty_on_dynamic_controls.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
describe('Welcome to the-internet', () => {
const data = require('../fixtures/content.json');

it('Accessibility on dynamic_controls h4 tag - Pass', () => {

// Visit dynamicControls page
cy.visitPage('/dynamic_controls');

// Check h3 text
cy.get('h4')
.contains(data.dynamicControls);

// Inject axe-core and check accessibility
// This will pass
cy.injectAxe()
cy.checkA11y('h4', {
runOnly: {
type: 'tag',
values: ['wcag2a', 'wcag2aa'],
},
});
})

it('Accessibility on dynamic_controls on p tag - Pass', () => {

// Visit dynamicControls page
cy.visitPage('/dynamic_controls');

// Check h3 text
cy.get('h4')
.contains(data.dynamicControls);

// Inject axe-core and check accessibility
// This will pass
cy.injectAxe()
cy.checkA11y('p', {
runOnly: {
type: 'tag',
values: ['wcag2a', 'wcag2aa'],
},
});

})

it.skip('Accessibility on dynamic_controls on form - Fail', () => {

// Visit dynamicControls page
cy.visitPage('/dynamic_controls');

// Check h3 text
cy.get('h4')
.contains(data.dynamicControls);

// This will fail
cy.checkA11y('form', {
runOnly: {
type: 'tag',
values: ['wcag2a', 'wcag2aa'],
},
});

})

})
2 changes: 1 addition & 1 deletion cypress/e2e/add_delete_elements.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ describe('Welcome to the-internet', () => {
it('Add and Remove elements on the page', () => {

let times = 7;
// Visit login page
// Visit add_remove_elements page
cy.visitPage('/add_remove_elements/');

cy.get('h3')
Expand Down
2 changes: 2 additions & 0 deletions cypress/e2e/basic_auth_test.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ describe('Basic Auth Testing', () => {
const data = require('../fixtures/content.json');

it('Successfully loads the-internet.herokuapp.com and test basic auth', () => {

// Visit basic_auth page
cy.visitPage('/basic_auth');

// Check h3 text
Expand Down
2 changes: 1 addition & 1 deletion cypress/e2e/checkboxes.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ describe('Welcome to the-internet', () => {

it('Checkboxes', () => {

// Visit login page
// Visit checkboxes page
cy.visitPage('/checkboxes');

// Check h3 text
Expand Down
2 changes: 1 addition & 1 deletion cypress/e2e/drag_drop_elements.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ describe('Welcome to the-internet', () => {

it('Drag and Drop elements', () => {

// Visit login page
// Visit drag_and_drop page
cy.visitPage('/drag_and_drop');

// Check h3 text
Expand Down
26 changes: 26 additions & 0 deletions cypress/e2e/file_upload_test.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
describe('Welcome to the-internet', () => {
const data = require('../fixtures/content.json');

it('File upload test demo', () => {

// Visit upload page
cy.visitPage('/upload');

// Check h3 text
cy.get('h3')
.contains(data.fileUploader);

// Upload file
cy.get("#file-upload").selectFile("cypress/fixtures/content.json");

// Click on upload button
cy.get("#file-submit").click();

// Check h3 text
cy.get("h3", { timeout: 30000 }).should("have.text","File Uploaded!");

// Check uploaded file name
cy.get("#uploaded-files").contains("content.json");

})
})
21 changes: 21 additions & 0 deletions cypress/e2e/handle_iframe.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
describe('Welcome to the-internet', () => {
const data = require('../fixtures/content.json');

// This code is to handle iframes is correct.
// However, herokuapp iframe example reached its billing limit.
// So this test case will fail!
it.skip('Handle Iframes', () => {

// Visit iframe page
cy.visitPage('/iframe');

// Check h3 text
cy.get('h3')
.contains(data.iframeHeading);

// This is a custom command located in the global-commands file under the support directory.
// It is used to locate the iframe and switch to it. For implementation details, please check the global-commands file.
cy.iframeLocator('[id="mce_0_ifr"]', '[role="menuitem"]:nth-child(2)', '');

})
})
71 changes: 69 additions & 2 deletions cypress/e2e/handle_js_alert.cy.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
describe('Welcome to the-internet', () => {
const data = require('../fixtures/content.json');

it('Handle JS Alert', () => {
it('Handle Window Alert', () => {

// Visit login page
// Visit context_menu page
cy.visitPage('/context_menu');

// Check h3 text
Expand All @@ -18,4 +18,71 @@ describe('Welcome to the-internet', () => {
expect(text).to.equal(`You selected a context menu`)
})
})

it('Handle jsAlert Alert', () => {

// Visit javascript_alerts page
cy.visitPage('/javascript_alerts');

// Check h3 text
cy.get('h3')
.contains(data.javaScriptAlerts);

// Click on JS Alert button
cy.get('[onclick="jsAlert()"]').click();

// Check JS Alert text click OK
cy.on('window:alert', (text) => {
expect(text).to.equal(`I am a JS Alert`)
// note: Cypress automatically accepts alerts
})

// Check Alert result text
cy.get('#result').contains('You successfully clicked an alert');
})

it('Handle jsConfirm Alert', () => {

// Visit javascript_alerts page
cy.visitPage('/javascript_alerts');

// Check h3 text
cy.get('h3')
.contains(data.javaScriptAlerts);

// Click on JS Confirm button
cy.get('[onclick="jsConfirm()"]').click();

// Check JS Alert text click OK
cy.on('window:alert', (text) => {
expect(text).to.equal(`I am a JS Confirm`)
// note: Cypress automatically accepts alerts
})

// Check Alert result text
cy.get('#result').contains('You clicked: Ok');
})

it('Handle jsPrompt Alert and enter data', () => {

// Visit javascript_alerts page
cy.visitPage('/javascript_alerts');

// Check h3 text
cy.get('h3')
.contains(data.javaScriptAlerts);

cy.window().then((win) => {

//stub the prompt window
cy.stub(win, "prompt").returns("Prompt test");

// click on Click for JS Prompt button
cy.get("[onclick='jsPrompt()']").click();

// Check Alert result text
cy.get('#result').contains('You entered: Prompt test')
});

})
})
4 changes: 4 additions & 0 deletions cypress/e2e/welcome_to_the_internet_fail.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ describe.skip('Welcome to the-internet', () => {
const data = require('../fixtures/content.json');

it('Successfully loads the-internet page: Fail assertion', () => {

// Visit the-internet page
cy.visitPage('/');

// Check h1 text
cy.get('h1')
.contains(data.welcomeToTheInternet);
// cy.get('[name="q"]').compareSnapshot('googleTest', 0.2, { limit: 6, delay: 1000 });
Expand Down
8 changes: 7 additions & 1 deletion cypress/fixtures/content.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
"basicAuthMessage": "Congratulations! You must have the proper credentials",
"checkboxes": "Checkboxes",
"contextMenu": "Context Menu",
"javaScriptAlerts": "JavaScript Alerts",
"dragDrop": "Drag and Drop",
"dynamicContent": "Dynamic Content"
"dynamicContent": "Dynamic Content",
"dynamicControls": "Dynamic Controls",
"floatingMenu": "Floating Menu",
"iframeHeading": "An iFrame containing the TinyMCE WYSIWYG Editor",
"fileUploader": "File Uploader",
"fileUploaded": "File Uploaded!"
}
2 changes: 2 additions & 0 deletions cypress/support/e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import "./global-commands";
import 'cypress-iframe';
import '@percy/cypress';
import 'cypress-axe';


// Alternatively you can use CommonJS syntax:
// require('./commands')
Expand Down
24 changes: 19 additions & 5 deletions cypress/support/global-commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,30 @@ const getStagingOpts = () => {
});

// Sending locators to the iframe
Cypress.Commands.add("sendToiframeLocator", (iframeId, cssLocator, value) => {
// Check if the iframe exists and is loaded
Cypress.Commands.add("iframeLocator", (iframeId, cssLocator, value) => {
// Ensure iframe exists and is loaded
cy.get(`iframe${iframeId}`).should('exist');
cy.frameLoaded(`iframe${iframeId}`);

// Interact with the iframe's content
cy.iframe(`iframe${iframeId}`)
.find(cssLocator)
.type(value, { force: true, log: false, delay: 100 });
cy.get('body').click(); // click outside the iframe
.click();

// If needed, you can use .contains() instead to find specific text
// cy.iframe(`iframe${iframeId}`).find(cssLocator)
// .contains(value, { force: true, log: false, delay: 100 });

// If needed, you can use .type text instead to find specific text
// cy.iframe(`iframe${iframeId}`).find(cssLocator)
// .type(value, { force: true, log: false, delay: 100 });

// Click outside the iframe to remove focus
cy.get('body').click();

// Optionally, wait for a short period
cy.wait(1000);
});
});

Cypress.Commands.add('dragAndDrop', (source, destination) => {
const dataTransfer = new DataTransfer();
Expand Down
Loading

0 comments on commit 04bf779

Please # to comment.