Commit 0ae1a874 authored by NilsTesdal's avatar NilsTesdal
Browse files

Opprettet repo

parents
# BDD-testing med cucumber og cypress
Dette er en superenkel eksempelapplikasjon som er satt opp med BDD-testing med cucumber og cypress. Applikasjonen server en enkel webside med express.js.
### Instruksjoner
1. Klon prosjektet:
```
git clone https://gitlab.stud.idi.ntnu.no/nilstesd/cypress-bdd-start.git
```
2. Installer avhengigheter med npm:
```
cd cypress-start
npm install
```
3. Kjør express-serveren med applikasjonen:
```
npm start
```
4. Sjekk at applikasjonen kjører:
[http://localhost:8080](http://localhost:8080)
5. Kjør cypress:
Åpne et nytt konsoll i prosjektmappen.
```
npx cypress open
```
Hvis du får feilmelding som sier at cypress executable ikke er funnet kan du kjøre følgende før du prøver å starte cypress på nytt (jeg måtte det):
```
npx cypress install
```
(npx er inkludert med npm > v5.2)
6. Kjør testene
Det er lagt inn script-definisjon i package.json så vi kan enkelt kjøre testene med:
```
npm test
```
7. Sjekk resultatet
Denne testen kjørte nå i en "headless" eller virtuell browser. Dette betyr at vi også kan kjøre testene som endel av et skript, f.eks på en CI-server.
Resultatet vises på konsollet, men kan også sees i en video under mappen *cypress/video*.
Ved veil kommer det også skjermdumper under *cypress/screenshots*.
\ No newline at end of file
{
"baseUrl": "http://localhost:8080",
"testFiles": "**/*.feature"
}
{}
\ No newline at end of file
# language: no
Egenskap: Handlekurv
Som kunde av nettkiosken
Ønsker jeg å legge varer i handlekurven
Slik at jeg kan få godis i posten
Scenario: Legge til varer i handlekurven
Gitt at jeg har åpnet nettkiosken
Når jeg legger inn varer og kvanta
skal handlekurven inneholde det jeg har lagt inn
Og den skal ha riktig totalpris
import { Given, When, Then, And } from "cypress-cucumber-preprocessor/steps";
Given(/^at jeg har åpnet nettkiosken$/, () => {
cy.visit('http://localhost:8080');
});
When(/^jeg legger inn varer og kvanta$/, () => {
cy.get('#product').select('Hubba bubba');
cy.get('#quantity').clear().type('4');
cy.get('#saveItem').click();
cy.get('#product').select('Smørbukk');
cy.get('#quantity').clear().type('5');
cy.get('#saveItem').click();
cy.get('#product').select('Stratos');
cy.get('#quantity').clear().type('1');
cy.get('#saveItem').click();
cy.get('#product').select('Hobby');
cy.get('#quantity').clear().type('2');
cy.get('#saveItem').click();
});
Then(/^skal handlekurven inneholde det jeg har lagt inn$/, () => {
// Sjekk innholdet i lista
});
And(/^den skal ha riktig totalpris$/, function () {
cy.get('#price').should('have.text', '33');
});
const cucumber = require('cypress-cucumber-preprocessor').default;
module.exports = (on, config) => {
on('file:preprocessor', cucumber())
};
\ No newline at end of file
// ***********************************************
// 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) => { ... })
// ***********************************************************
// This example support/index.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')
{
"name": "cypress-bdd-start",
"version": "1.0.0",
"description": "",
"main": "src/index.js",
"scripts": {
"start": "node ./src/index.js",
"test": "cypress run --spec \"**/*.feature\""
},
"author": "Nils Tesdal",
"dependencies": {
"express": "^4.17.1"
},
"devDependencies": {
"cypress": "^6.6.0",
"cypress-cucumber-preprocessor": "^4.0.1"
},
"cypress-cucumber-preprocessor": {
"nonGlobalStepDefinitions": true
}
}
<html>
<head>
<title>cypress-start example application</title>
<link rel="stylesheet" href="styles.css">
<script src="storage.js"></script>
</head>
<body onload="createInventory()">
<h2>Superkiosken</h2>
<p>Legg til varer og antall i handlekurven.</p>
<div id="entry">
<label for="product">Vare</label>
<select id="product"></select>
<label for="quantity">Antall</label>
<input type=text id=quantity>
<input type=button id="saveItem" value="Lagre" onclick="saveItem()">
<input type=button id="deleteItem" value="Slett" onclick="deleteItem()">
</div>
<div id="cart">
<h3>Handlekurv</h3>
<ul id=list></ul>
<div>Totalpris: <span id="price"></span> kr</div>
</div>
<input type=button id="emptyCart" value="Tøm handlevogna" onclick="emptyCart()">
<input type=button id="goToPayment" value="Gå til betaling" onclick="if(localStorage.length > 0) window.location.href = 'payment.html'">
</body>
</html>
let express = require('express');
let app = express();
let path = require('path');
app.use('/', express.static('src'))
app.listen(8080);
\ No newline at end of file
<html>
<head>
<title>cypress-start example application</title>
<link rel="stylesheet" href="styles.css">
<script src="storage.js"></script>
</head>
<body onload="updateCart()">
<h2>Superkiosken</h2>
<p>Legg inn navn, adresse og kortopplysninger for å fullføre handelen.</p>
<div id="cart">
<h3>Handlekurv</h3>
<ul id=list></ul>
<div>Totalpris: <span id="price"></span> kr</div>
</div>
<div id="entry">
<form action="receipt.html" onsubmit="return validateForm()">
<div class="formField">
<label for="fullName">Navn</label>
<input type=text id="fullName" onblur="validate('fullName')">
<span class="formError" id="fullNameError"></span>
</div>
<div class="formField">
<label for="address">Adresse</label>
<input type=text id="address" onblur="validate('address')">
<span class="formError" id="addressError"></span>
</div>
<div class="formField">
<label for="postCode">Postnummer</label>
<input type=text id="postCode" onblur="validate('postCode')">
<span class="formError" id="postCodeError"></span>
</div>
<div class="formField">
<label for="city">Poststed</label>
<input type=text id="city" onblur="validate('city')">
<span class="formError" id="cityError"></span>
</div>
<div class="formField">
<label for="creditCardNo">Kredittkortnummer</label>
<input type=text id=creditCardNo onblur="validateCreditCardNo()">
<span class="formError" id="creditCardNoError"></span>
</div>
<div class="formField">
<input type=submit value="Fullfør handel">
<input type=button id="cancel" value="Avbryt" onclick="window.location.href='index.html'">
</div>
</form>
</div>
</body>
</html>
<html>
<head>
<title>cypress-start example application</title>
<link rel="stylesheet" href="styles.css">
<script src="storage.js"></script>
</head>
<body>
<h2>Superkiosken</h2>
<div class="confirmation">
Din ordre er registrert.
</div>
<input type="button" value="Tilbake til kiosken" onclick="localStorage.clear(); window.location.href='/';">
</body>
</html>
function saveItem() {
let key = document.getElementById('product').value;
let value = document.getElementById('quantity').value;
if(key && value && !isNaN(value)) {
localStorage.setItem(key, value);
updateCart();
}
}
function deleteItem() {
let key = document.getElementById('product').value;
localStorage.removeItem(key);
updateCart();
}
function emptyCart() {
localStorage.clear();
updateCart();
}
const inventory = {
'Stratos': 8,
'Hubba bubba': 2,
'Smørbukk': 1,
'Hobby': 6,
'Lakrisbåter': 20,
'Smil': 12
}
function createInventory() {
let options = '<option value selected>-- Velg vare --</option>';
Object.keys(inventory).forEach(key => {
options += '<option value="' + key + '">' + key + ' (' + inventory[key] + ' kr)' + '</option>';
});
document.getElementById('product').innerHTML = options;
updateCart();
}
function updateCart() {
let list = "";
let totalPrice = 0;
if (localStorage.length > 0) {
Object.keys(localStorage).forEach(key => {
let quantity = localStorage.getItem(key);
let price = quantity * inventory[key];
totalPrice += price;
list += '<li>' + quantity + ' ' + key + '; ' + price + ' kr</li>';
});
} else {
list = "(tomt)";
}
document.getElementById('list').innerHTML = list;
document.getElementById('price').innerHTML = totalPrice;
}
function validate(id) {
let value = document.getElementById(id).value;
let ok = !!value && value.length > 0;
if(!ok) {
document.getElementById(id + 'Error').innerHTML = 'Feltet må ha en verdi'
} else {
document.getElementById(id + 'Error').innerHTML = ''
}
return ok;
}
function validateForm() {
return validate('fullName') && validate('address') && validate('postCode') && validate('city') && validateCreditCardNo();
}
function validateCreditCardNo() {
let ccNo = document.getElementById('creditCardNo').value;
if(ccNo.trim().length !== 16 || isNaN(ccNo.trim())) {
document.getElementById('creditCardNoError').innerHTML = "Kredittkortnummeret må bestå av 16 siffer"
return false;
} else {
document.getElementById('creditCardNoError').innerHTML = "";
return true;
}
}
\ No newline at end of file
body {
font-family: verdana;
font-size: 11pt;
}
#quantity {
width: 2rem;
}
#product, #quantity {
margin-right: 0.5rem;
}
#entry, #cart {
background-color: #00bbee;
border-radius: 1rem;
padding: 0.5rem;
margin-bottom: 0.5rem
}
h3 {
margin-top: 0;
}
.formField {
margin-bottom: 0.5rem;
}
.formError {
color: tomato;
}
.confirmation {
background-color: #44cc44;
border-radius: 1rem;
padding: 1rem;
margin-bottom: 0.5rem
}
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment