Skip to content

Commit c286f80

Browse files
committed
Initial commit: Add Cypress test framework with GitHub Actions and Pages
1 parent 85434b8 commit c286f80

File tree

12 files changed

+109
-141
lines changed

12 files changed

+109
-141
lines changed

.github/workflows/cypress.yml

Lines changed: 11 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,20 @@ on:
66
pull_request:
77
branches: [ master ]
88

9-
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
10-
permissions:
11-
contents: read
12-
pages: write
13-
id-token: write
14-
15-
# Allow only one concurrent deployment
16-
concurrency:
17-
group: "pages"
18-
cancel-in-progress: true
19-
209
jobs:
2110
cypress-run:
2211
runs-on: ubuntu-latest
2312
steps:
2413
- name: Checkout
25-
uses: actions/checkout@v4
14+
uses: actions/checkout@v3
2615

2716
- name: Setup Node.js
28-
uses: actions/setup-node@v4
17+
uses: actions/setup-node@v3
2918
with:
30-
node-version: '20.x'
19+
node-version: '18'
3120

3221
- name: Install dependencies
33-
run: npm ci
22+
run: npm install
3423

3524
- name: Create env file
3625
run: |
@@ -40,46 +29,13 @@ jobs:
4029
"password": "secret_sauce"
4130
}' > cypress.env.json
4231
43-
- name: Cypress run
44-
uses: cypress-io/github-action@v6
45-
with:
46-
browser: chrome
47-
headless: true
48-
49-
- name: Upload screenshots
50-
uses: actions/upload-artifact@v4
51-
if: failure()
52-
with:
53-
name: cypress-screenshots
54-
path: cypress/screenshots
32+
- name: Run Cypress tests
33+
run: npx cypress run
5534

56-
- name: Upload reports
57-
uses: actions/upload-artifact@v4
35+
- name: Deploy report to GitHub Pages
5836
if: always()
37+
uses: peaceiris/actions-gh-pages@v3
5938
with:
60-
name: cypress-reports
61-
path: cypress/reports
62-
63-
- name: Setup Pages
64-
if: success()
65-
uses: actions/configure-pages@v4
66-
67-
- name: Upload Pages artifact
68-
if: success()
69-
uses: actions/upload-pages-artifact@v3
70-
with:
71-
path: 'cypress/reports/html'
72-
73-
deploy:
74-
needs: cypress-run
75-
runs-on: ubuntu-latest
76-
if: github.ref == 'refs/heads/master'
77-
78-
environment:
79-
name: github-pages
80-
url: ${{ steps.deployment.outputs.page_url }}
81-
82-
steps:
83-
- name: Deploy to GitHub Pages
84-
id: deployment
85-
uses: actions/deploy-pages@v4
39+
github_token: ${{ secrets.GITHUB_TOKEN }}
40+
publish_dir: ./cypress/reports/html
41+
keep_files: true

README.md

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
# Sauce Demo Cypress Tests
22

3-
This project contains automated tests for the Sauce Demo website using Cypress with TypeScript.
3+
This project contains automated tests for the Sauce Demo website using Cypress with TypeScript and Page Object Model pattern.
44

55
## Project Structure
66

77
```
88
├── cypress/
99
│ ├── e2e/ # Test files
1010
│ ├── fixtures/ # Test data
11-
│ ├── pages/ # Page Objects
12-
│ └── support/ # Support files
11+
│ ├── pages/ # Page objects
12+
│ └── support/ # Support files and commands
1313
├── cypress.config.ts # Cypress configuration
14-
├── cypress.env.json # Environment variables (gitignored)
14+
├── cypress.env.json # Environment variables (not in git)
1515
├── tsconfig.json # TypeScript configuration
1616
└── package.json # Project dependencies
1717
```
@@ -44,11 +44,14 @@ To run tests in headless mode:
4444
npx cypress run
4545
```
4646

47-
To open Cypress Test Runner:
48-
```bash
49-
npx cypress open
50-
```
47+
The test report will be generated in `cypress/reports/html/index.html`
5148

52-
## Test Reports
49+
## Features
5350

54-
Test reports are generated using cypress-mochawesome-reporter and can be found in the `cypress/reports` directory after test execution.
51+
- TypeScript support
52+
- Page Object Model pattern
53+
- Custom commands for common actions
54+
- Detailed logging using custom Cypress task
55+
- Mochawesome HTML reporter
56+
- GitHub Actions integration
57+
- GitHub Pages for test reports

cypress.config.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,26 @@ import { defineConfig } from 'cypress'
22

33
export default defineConfig({
44
reporter: 'cypress-mochawesome-reporter',
5+
reporterOptions: {
6+
charts: true,
7+
reportPageTitle: 'Sauce Demo Tests Report',
8+
embeddedScreenshots: true,
9+
inlineAssets: true,
10+
saveAllAttempts: false,
11+
},
512
e2e: {
613
setupNodeEvents(on, config) {
714
require('cypress-mochawesome-reporter/plugin')(on);
815

9-
// Task for console logging
16+
// Custom task for logging
1017
on('task', {
1118
log(message) {
12-
console.log(message)
13-
return null
19+
console.log(message);
20+
return null;
1421
},
15-
})
22+
});
1623
},
1724
baseUrl: 'https://www.saucedemo.com',
1825
supportFile: 'cypress/support/e2e.ts',
1926
},
20-
})
27+
});

cypress/e2e/login.cy.ts

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
1-
import LoginPage from '../pages/LoginPage'
2-
import InventoryPage from '../pages/InventoryPage'
1+
import { LoginPage } from '../pages/LoginPage';
32

43
describe('Sauce Demo Login Tests', () => {
4+
const loginPage = new LoginPage();
5+
56
beforeEach(() => {
6-
LoginPage.visit()
7-
})
7+
loginPage.visit();
8+
});
89

910
it('should login successfully with standard user', () => {
10-
LoginPage.login(Cypress.env('standardUser'), Cypress.env('password'))
11-
InventoryPage.isVisible()
12-
InventoryPage.logout()
13-
})
11+
cy.task('log', '✅ Testing standard user login');
12+
cy.login(Cypress.env('standardUser'), Cypress.env('password'));
13+
cy.url().should('include', '/inventory.html');
14+
cy.logout();
15+
});
1416

1517
it('should show error message for locked out user', () => {
16-
LoginPage.login(Cypress.env('lockedOutUser'), Cypress.env('password'))
17-
LoginPage.getErrorMessage().should('contain.text', 'Epic sadface: Sorry, this user has been locked out')
18-
})
19-
})
18+
cy.task('log', '❌ Testing locked out user login');
19+
cy.login(Cypress.env('lockedOutUser'), Cypress.env('password'));
20+
loginPage.getErrorMessage()
21+
.should('be.visible')
22+
.and('contain', 'Epic sadface: Sorry, this user has been locked out');
23+
});
24+
});

cypress/pages/InventoryPage.ts

Lines changed: 0 additions & 20 deletions
This file was deleted.

cypress/pages/LoginPage.ts

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,16 @@
1-
class LoginPage {
2-
// Selectors
3-
private usernameInput = '[data-test="username"]'
4-
private passwordInput = '[data-test="password"]'
5-
private loginButton = '[data-test="login-button"]'
6-
private errorMessage = '[data-test="error"]'
1+
export class LoginPage {
2+
private selectors = {
3+
username: '[data-test="username"]',
4+
password: '[data-test="password"]',
5+
loginButton: '[data-test="login-button"]',
6+
errorMessage: '[data-test="error"]'
7+
};
78

8-
// Methods
99
visit() {
10-
cy.visit('/')
11-
return this
12-
}
13-
14-
login(username: string, password: string) {
15-
cy.task('log', `Logging in with username: ${username}`)
16-
cy.get(this.usernameInput).type(username)
17-
cy.get(this.passwordInput).type(password)
18-
cy.get(this.loginButton).click()
19-
return this
10+
cy.visit('/');
2011
}
2112

2213
getErrorMessage() {
23-
return cy.get(this.errorMessage)
14+
return cy.get(this.selectors.errorMessage);
2415
}
25-
}
26-
27-
export default new LoginPage()
16+
}

cypress/support/commands.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/// <reference types="cypress" />
2+
3+
Cypress.Commands.add('login', (username: string, password: string) => {
4+
cy.task('log', `👤 Logging in with username: ${username}`);
5+
cy.get('[data-test="username"]').type(username);
6+
cy.get('[data-test="password"]').type(password);
7+
cy.get('[data-test="login-button"]').click();
8+
});
9+
10+
Cypress.Commands.add('logout', () => {
11+
cy.task('log', '👋 Logging out');
12+
cy.get('#react-burger-menu-btn').click();
13+
cy.get('#logout_sidebar_link').click();
14+
});
15+
16+
declare global {
17+
namespace Cypress {
18+
interface Chainable {
19+
login(username: string, password: string): Chainable<void>
20+
logout(): Chainable<void>
21+
}
22+
}
23+
}

cypress/support/e2e.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
1-
import 'cypress-mochawesome-reporter/register'
1+
import './commands';
2+
import 'cypress-mochawesome-reporter/register';
23

3-
// Hide fetch/XHR requests from command log
4-
const app = window.top;
5-
if (app && !app.document.head.querySelector('[data-hide-command-log-request]')) {
6-
const style = app.document.createElement('style');
7-
style.innerHTML =
8-
'.command-name-request, .command-name-xhr { display: none }';
9-
style.setAttribute('data-hide-command-log-request', '');
10-
app.document.head.appendChild(style);
11-
}
4+
beforeEach(() => {
5+
cy.task('log', '🚀 Starting test...');
6+
});

promptv4.txt renamed to notes/promptv4(working version with GH pages).txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ Scenario 2: Locked Out User
88
6. Allow the MCP Server to complete the code generation.
99
7.Use the code found in the temp_codegen folder as a reference.
1010
8.Transpile the test code to a Cypress framework using TypeScript.
11-
9. Organize the Cypress project, create the tests(each one should be independent, no dependencies between them), Use the Page Object Model structure. Store reusable data in the fixtures folder(if they are credentials, put them in the cypress.env.json) like test data or expected results.
11+
9. Organize the Cypress project without running "cypress open" configure everything by yourself, create the tests(each one should be independent, no dependencies between them), Use the Page Object Model structure. Store reusable data in the fixtures folder(if they are credentials, put them in the cypress.env.json) like test data or expected results.
1212
10. In the root directory Create a .gitignore file that excludes node_modules and cypress.env.json.
1313
11. Create a cy task to get detail logs for the actions, and assertions in the terminal, implement it in the framework, just call the cy task to print console logs.
1414
12. Integrate the Cypress Plugin "cypress-mochawesome-reporter" and its latest version, make all the required configurations. Using the latest version there is only 1 dependency required.
1515
13. In the root directory Add a README.md file that documents how to run the tests and describes the project structure.
1616
14. Install dependencies and Run the framework in headless mode by CLI using cypress run. Check that Cypress and all the tests runs without issues. Failures are accepted, framework configuration issues are not.
1717
15. In the root directory Set up a GitHub Actions workflow to install dependencies and run the Cypress tests, The branch name is not main as usualy, it is master.
1818
16. Then, push the latest changes using the GitHub MCP Server root directory to the remote repository. The repo already exists.
19+
17. Using the GitHub MCP Server configure the repository to publish a github page based on on the /cypress/reports/html/index.html file.
1920

20-
In the chat post: "Run the 16 steps until all the process is completed."
21+
In the chat post: "Run the 17 steps until all the process is completed."

package-lock.json

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)