~$ git clone https://github.com/Pieter-hogent/recipeapp.git (or git pull) ~$ cd recipeapp ~/recipeapp$ git checkout -b week6 3bfdae5 ~/recipeapp$ npm install
~$ npm install --save-dev cypress@4.1.0
~$ npx cypress open
cypress/integration/myfirsttest.spec.js
describe('My First Test', function() {
it('Does not do much!', function() {
expect(true).to.equal(true);
});
it('Still not doing a lot', function() {
expect(true).to.equal(false);
});
});
cypress/integration/myfirsttest.spec.js
describe('My First Test', function() {
it('our app runs', function() {
cy.visit('http://localhost:4200');
cy.get('button').should('be.disabled');
});
});
afd0439
selector | recommended | notes |
---|---|---|
cy.get('button') | Never | too generic |
cy.get('.btn.btn-large') | Never | What if the designer changes styling? Bad |
cy.get('#main') | Sparingly | still coupled to styling or js |
cy.contains('Submit') | Depends | Better, but coupled to text content (which might change) |
cy.get('[data-cy=submit]') | Good | Best, use a dedicated attribute in your html |
src/app/recipe/recipe-list/recipe-list.component.html
<div fxLayout="column" fxLayoutGap="2%">
<app-add-recipe (newRecipe)="addNewRecipe($event)"></app-add-recipe>
<mat-card>
<mat-form-field>
<input
matInput
(keyup)="filterRecipe$.next($event.target.value)"
...
data-cy="filterInput"
/>
</mat-form-field>
</mat-card>
<div *ngIf="(recipes$ | async) as recipes; else loadingOrError">
<div fxLayout="row wrap" ... >
<div *ngFor="let recipe of (recipes | recipeFilter: filterRecipeName)" ...>
<app-recipe [recipe]="recipe" data-cy="recipeCard"></app-recipe>
</div>
</div>
</div>
f3574f3]
cypress/interaction/myfirsttest.spec.js
describe('My First Test', function() {
it('our app runs', function() {
cy.visit('http://localhost:4200');
cy.get('[data-cy=filterInput]').type('sp');
cy.get('[data-cy=recipeCard]').should('have.length', 1);
});
});
cypress/interaction/myfirsttest.spec.js
it('mock recipe get', function() {
cy.server({ delay: 1000 });
cy.route({
method: 'GET',
url: 'http://localhost:4200/api/recipes',
status: 200,
response: [{ name: 'rec1', ingredients: [] },
{ name: 'rec2', ingredients: [] },{ name: 'rec3', ingredients: [] }]
});
cy.visit('http://localhost:4200/');
cy.get('[data-cy=recipeCard]').should('have.length', 3);
});
cypress/fixtures/recipes.json
[
{
"id": 1,
"name": "Spaghetti",
"created": "2019-03-13T12:40:03.184905",
"chef": null,
"ingredients": [
{
"id": 1,
"name": "Tomatoes",
"amount": 0.75,
"unit": "liter"
},
{
"id": 2,
"name": "Minced Meat",
"amount": 500.0,
"unit": "grams"
},
{
"id": 3,
"name": "Onion",
"amount": 2.0,
"unit": null
}
]
},
{
"id": 2,
"name": "Lasagne",
"created": "2019-02-07T12:40:03.184905",
"chef": null,
"ingredients": [
{
"id": 1,
"name": "Tomatoes",
"amount": 0.75,
"unit": "liter"
},
{
"id": 2,
"name": "Minced Meat",
"amount": 500.0,
"unit": "grams"
},
{
"id": 3,
"name": "Butter",
"amount": 100,
"unit": "grams"
}
]
},
{
"id": 3,
"name": "Risotto",
"created": "2019-02-07T12:40:03.184905",
"chef": null,
"ingredients": [
{
"id": 1,
"name": "Rise",
"amount": 300,
"unit": "grams"
},
{
"id": 2,
"name": "parmesan",
"amount": 300,
"unit": "grams"
}
]
}
]
cypress/interaction/myfirsttest.spec.js
it('mock recipe get', function() {
cy.server({ delay: 1000 });
cy.route({
method: 'GET',
url: 'http://localhost:4200/api/recipes',
status: 200,
response: 'fixture:recipes.json'[{ name: 'rec1', ingredients: [] },
{ name: 'rec2', ingredients: [] },{ name: 'rec3', ingredients: [] }]
});
cy.visit('http://localhost:4200/');
cy.get('[data-cy=recipeCard]').should('have.length', 3);
});
cypress.json
{
"baseUrl": "http://localhost:4200"
}
cypress/interaction/myfirsttest.spec.js
it('on error should show error message', function() {
cy.server();
cy.route({
method: 'GET',
url: '/api/recipes',
status: 500,
response: 'ERROR'
});
cy.visit('/');
cy.get('[data-cy=appError]').should('be.visible');
});
be18b22