Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Ready-To-Review] Added automated scripts for Income Expense App #1

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Cypress test

on: [push]

jobs:
cypress-run:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Build the stack
run: docker-compose up -d
- name: Install dependencies
run: npm install
working-directory: ./e2e
- name: Cypress run
run: npx cypress run
working-directory: ./e2e
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,8 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# cypress
/e2e/node_modules
/e2e/cypress/videos
/e2e/cypress/screenshots
16 changes: 16 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
DOCKERBUILDCMD=docker-compose build
DOCKERUPCMD=docker-compose up
CYPRESSRUNCMD=cd e2e npx && cypress run --record --key 9ec01591-2bc4-43b2-ba2b-85658f48980a
CYPRESSGUICMD=cd e2e && npx cypress open

test:
$(CYPRESSRUNCMD)

test-gui:
$(CYPRESSGUICMD)

docker-build:
$(DOCKERBUILDCMD)

docker-up:
$(DOCKERUPCMD)
9 changes: 9 additions & 0 deletions cypress-run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash

echo "Building services using docker-compose"

docker-compose build

echo "Start the application and run all automated scripts"

docker-compose up
13 changes: 13 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,16 @@ services:
ports:
- "3567:3000"
container_name: qa-webapp

e2e:
image: cypress
build: ./e2e
container_name: cypress
depends_on:
- qa-webapp
environment:
- CYPRESS_baseUrl=http://host.docker.internal:3567
command: npx cypress run --record --key 9ec01591-2bc4-43b2-ba2b-85658f48980a
volumes:
- ./e2e/cypress:/app/cypress
- ./e2e/cypress.json:/app/cypress.json
10 changes: 10 additions & 0 deletions e2e/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM cypress/base:14
WORKDIR /app

COPY package.json .
COPY package-lock.json .

ENV CI=1
RUN npm ci

RUN npx cypress verify
133 changes: 133 additions & 0 deletions e2e/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
## Tools used

### Cypress

An automation framework called cypress is used for automating the test cases for the Income Expense app. Cypress is a JavaScript based front end testing tool built for the modern web. It is more developer-friendly and allows unique DOM manipulation that other automation frameworks cannot. Also, this runs directly on the browser so, one can manipulate with the requests and responses too.

Components of Cypress
- Cypress Test Runner
- Cypress allows tests to run in a unique interactive runner that allows the user to see commands as they execute while also viewing the application under test. This is achieved using a component of Cypress called Test runner. For this project, please go inside the `e2e` folder and then use the command below to access test runner or, use makefile to run the command - `make test-gui` directly.
`npx cypress open`

- Cypress Dashboard
- Use this invitation link to join a project I created for this automated suite. Cypress dashboard can be used to provide insights on tests ran, DOM request/response, recorded videos, screenshots so that we understand the tests better.

https://dashboard.cypress.io/invitation/800a9c22-b9ca-4acd-93a9-336316c316a5


### Docker

Docker is used to building services and running an automated test script against that.

### MakeFile

A makefile has also been included that contains the basic recipe required to cook the program.

### Github Actions

A yml file has been included which is intended to run cypress test script on each push to the repository. This is a first step taken towards a complete CI/CD pipeline for automated tests.

## Project Structure

The project structure and how each sub-folders are utilized are listed below:

```
e2e
└──cypress
└── Fixtures
└── budgetTestData.json
└── categoryTestUserOne.json
└── ...
└── integration
└── automation_scripts
└── budget-app.spec.js
└── plugins
└── index.js
└── support
└── commands.js
└── index.js
└── cypress.json
└── package.json
```

- Fixtures:
All test data has been stored inside fixtures folder. This is a recommended practice encouraged by cypress and, allows effective capture of test data in our main test suite file.

- integration:
The integration folder consists of our main test script file. `budget-app.spec.js` is the main test suite file which governs the entire automated test of this particular app.

- plugins:
The plugins folder contains a js file where we need to declare any plugins that we might use for testing purpose. In our case, a plugin has been used to log messages in headless mode.

- support:
Here is where all the magic happens. Cypress basically allows developers to create custom commands and there commands are declared in a commands.js file. Here in our case too, we have made use to multiple custom commands and used those re-usable commands in the test.

- cypress.json:
This is a cypress configuration file where we include items required to configure cypress behaviour.

## Test Cases Covered

- [x] Verify sign-up of multiple users.
- [x] Verify log-in functionality.
- [x] Verify budgets can be created.
- [x] Verify budget can be allocated to another user.
- [x] Verify multiple categories can be added to a single user budget.
- [x] Verify multiple categories can be added to a multi-user budget.
- [x] Compare the expense for categories with respect to users in Stats page.
- [x] Verify deletion of the budget created.

## Testing/Execution Strategy

Multiple execution techniques have been included for easy execution of the test suite.

### Using shell file

The shell file can be used to run all services and automation suite using a single command.

````
./cypress-run.sh
````
### Using Makefile

A makefile has been included to perform some of the basic tasks required.

- Build services:
```
make docker-build
````
- Run services:
```
make docker-up
````
- Run tests headlessly:
```
make test
````
- Run tests using a test runner:
```
make test-gui
```
### Using docker compose

Use docker compose to build services

```
docker-compose build
```
```
docker-compose up
```

### Using Test Runner

Test runner can be built locally and used to test the automated scripts. For this test runner should be opened. In order to open the test run, go inside the `e2e` folder and then use the command below:

```
make test-gui
```

OR,

```
npx cypress open
```
4 changes: 4 additions & 0 deletions e2e/cypress.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"baseUrl": "http://localhost:3567",
"projectId": "szsb7a"
}
4 changes: 4 additions & 0 deletions e2e/cypress/fixtures/budgetTestData.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"budgetUserOne": "Salary For User One",
"budgetMultiUser": "Salary For Multi-User"
}
10 changes: 10 additions & 0 deletions e2e/cypress/fixtures/categoryTestUserOne.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"firstCategoryName": "Food Allocation",
"firstCategory": "Food and Drinks",
"firstCategoryValue": "Food",
"firstCategoryExpense": "5000",
"secondCategoryName": "Transport Expenditure",
"secondCategory": "Transport",
"secondCategoryValue": "Transport",
"secondCategoryExpense": "1000"
}
10 changes: 10 additions & 0 deletions e2e/cypress/fixtures/categoryTestUserTwo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"firstCategoryName": "House Maintainence Fund",
"firstCategory": "House and Garden",
"firstCategoryValue": "Home",
"firstCategoryExpense": "20000",
"secondCategoryName": "Gym Expenditure",
"secondCategory": "Health and Beauty",
"secondCategoryValue": "Health",
"secondCategoryExpense": "2000"
}
6 changes: 6 additions & 0 deletions e2e/cypress/fixtures/userTestData.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"userOneUsername": "UserOne",
"userOnePassword": "@Test123",
"userTwoUsername": "UserTwo",
"userTwoPassword": "@Test1234"
}
88 changes: 88 additions & 0 deletions e2e/cypress/integration/automation_scripts/budget-app.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
describe("Verify End to End Test of Income Expense Web App", function() {

let userData;
let budgetData;
let categoryUserOne;
let categoryMultiUser;

before(() => {
cy.clearLocalStorageSnapshot();
});

beforeEach(() => {
cy.fixture("userTestData").then(function(user){
userData = user
})
cy.fixture("budgetTestData").then(function(budget){
budgetData = budget
})
cy.fixture("categoryTestUserOne").then(function(categoryOne){
categoryUserOne = categoryOne
})
cy.fixture("categoryTestUserTwo").then(function(categoryTwo){
categoryMultiUser = categoryTwo
})
cy.restoreLocalStorage();
});

afterEach(() => {
cy.saveLocalStorage();
});

const userType = new Map([
["UserOne", "@Test123"],
["UserTwo", "@Test1234"]
]);
for (const [key, value] of userType.entries()) {
it(`SignUp as ${key}`, () => {
cy.signUp(key, value)
});
}

it("Sign-In", () => {
cy.task('log', userData.userOneUsername + " Logging in")
cy.signIn(userData.userOneUsername, userData.userOnePassword)
})

it("Add multiple budgets", () => {
cy.addBudgets(budgetData.budgetUserOne, budgetData.budgetMultiUser)
cy.task('log', "Multiple budgets have been added")
})

it("Add multi user to the budget", () => {
cy.get(".sc-jrQzAO.hDXECM", {timeout: 15000}).eq(1).select(userData.userTwoUsername)
cy.task('log', "User Two has been added to a budget")
})

it("Add categories for single user budget - userOne", () => {
cy.get(".sc-eCImPb.bnYItG").eq(0).click()
cy.addCategory(categoryUserOne.firstCategoryName, categoryUserOne.firstCategory, categoryUserOne.firstCategoryValue, categoryUserOne.firstCategoryExpense)
cy.task('log', "First category has been created for User One")
cy.addCategory(categoryUserOne.secondCategoryName, categoryUserOne.secondCategory, categoryUserOne.secondCategoryValue, categoryUserOne.secondCategoryExpense, userData.userOneUsername)
cy.task('log', "Second category has been created for User One")
cy.get(".sc-kDTinF.fMjHiC.sc-crHmcD.dVfNok").click()
})

it("Add categories for Multi User Budget", () => {
cy.get(".sc-eCImPb.bnYItG").eq(1).click()
cy.addCategory(categoryMultiUser.firstCategoryName, categoryMultiUser.firstCategory, categoryMultiUser.firstCategoryValue, categoryMultiUser.firstCategoryExpense)
cy.task('log', "First category has been created for Multi User Budget")
cy.addCategory(categoryMultiUser.secondCategoryName, categoryMultiUser.secondCategory, categoryMultiUser.secondCategoryValue, categoryMultiUser.secondCategoryExpense, userData.userTwoUsername)
cy.task('log', "Second category has been created for Multi User Budget")
})

it("Verify Income/Expense stats for User One", () => {
cy.verifyStats(budgetData.budgetUserOne, userData.userOneUsername, categoryUserOne.firstCategoryExpense, true)
})

it("Verify Income/Expense stats for User Two", () => {
cy.verifyStats(budgetData.budgetMultiUser, userData.userTwoUsername, categoryMultiUser.secondCategoryExpense, false)
})

it("Delete budget's of both users", () => {
cy.deleteBudget()
cy.task("log", "Budget's for both users have been deleted")
})

})

28 changes: 28 additions & 0 deletions e2e/cypress/plugins/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/// <reference types="cypress" />
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************

// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)

/**
* @type {Cypress.PluginConfig}
*/
// eslint-disable-next-line no-unused-vars
module.exports = (on, config) => {
on('task', {
log(message) {
console.log(message)

return null
},
})

}
Loading