Skip to content

Commit

Permalink
Merge branch 'release/2.0-screenplay' into main
Browse files Browse the repository at this point in the history
Implemented Screenplay pattern
  • Loading branch information
thiagojacinto committed Oct 5, 2020
2 parents 55110f3 + 68abd59 commit 2a7b4fb
Show file tree
Hide file tree
Showing 36 changed files with 2,481 additions and 124 deletions.
17 changes: 17 additions & 0 deletions .eslintrc.init.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"env": {
"browser": true,
"es6": true
},
"extends": "eslint:recommended",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module"
},
"rules": {
}
}
17 changes: 17 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"env": {
"browser": true,
"es6": true
},
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module"
},
"extends": "eslint:recommended",
"globals": {
"cy": "readonly",
"Cypress": "readonly"
},
"rules": {
}
}
12 changes: 12 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Extensions
*.html
*.feature

# Node
node_modules

# Report outputs
results

# Cypress example and initial structure
cypress/integration/examples
92 changes: 80 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,97 @@
# Cypress.io with Patterns

Using Cypress to handle automation tests implementing Page Objects and Screenplay patterns.
Using Cypress to handle automation tests implementing Page Objects and Screenplay patterns.

## BDD Features with Gherkin

The goal was to develop automation tests to the simple list app available at http://repo-listing.web.app

To achieve that, Gherkin features lead the way of thinking the core features of that system. Given/When/Then strategy was used here:

* [_adicionar.feature_](./features/adicionar.feature)
* [_remover.feature_](./features/remover.feature)
- [_adicionar.feature_](./features/adicionar.feature)
- [_remover.feature_](./features/remover.feature)

## Page objects pattern

Development with this pattern was done under the branch [feature/page-objects](https://github.com/thiagojacinto/cypress-with-patterns/tree/feature/page-objects).

> Objeto _Home_:
> Object _Home_:
- [support/](./cypress/support)
- [pageObjects/](./cypress/support/pageObjects)
- [Home/](./cypress/support/pageObjects/Home)
- [elements.components.js](./cypress/support/pageObjects/Home/elements.components.js)
- [index.js](./cypress/support/pageObjects/Home/index.js)

> Tests:
- [integration/](./cypress/integration)
- [page-objects/](./cypress/integration/page-objects)
- [adicionar.spec.js](./cypress/integration/page-objects/adicionar.spec.js)
- [remover.spec.js](./cypress/integration/page-objects/remover.spec.js)

## Screenplay pattern

Implementation of this pattern was developed after the page object approuch. Another strategy was using fixture to handle import data from external file (ex: json) and randomize inputs.

> Fixture:
* [fixtures/](./cypress/fixtures)
* [repositorios.json](./cypress/fixtures/repositorios.json)

> _Screenplay pattern_ base files:
Five original blocks were simplified to 3: [Actor](./cypress/support/screenplay/agente/Agente.js), [Task](./cypress/support/screenplay/tarefa/Tarefa.js) and [Questions](./cypress/support/screenplay/dado-quando-entao/DadoQuandoEntao.js), here translated to _Agente, Tarefa_ e _DadoQuandoEntao_, respectively.

* [support/](./cypress/support)
* [pageObjects/](./cypress/support/pageObjects)
* [Home/](./cypress/support/pageObjects/Home)
* [elements.components.js](./cypress/support/pageObjects/Home/elements.components.js)
* [index.js](./cypress/support/pageObjects/Home/index.js)
* [screenplay/](./cypress/support/screenplay)
* [agente/](./cypress/support/screenplay/agente)
* [Agente.js](./cypress/support/screenplay/agente/Agente.js)
* [Usuario.js](./cypress/support/screenplay/agente/Usuario.js)
* [index.js](./cypress/support/screenplay/agente/index.js)
* [dado-quando-entao/](./cypress/support/screenplay/dado-quando-entao)
* [DadoQuandoEntao.js](./cypress/support/screenplay/dado-quando-entao/DadoQuandoEntao.js)
* [index.js](./cypress/support/screenplay/dado-quando-entao/index.js)
* [tarefa/](./cypress/support/screenplay/tarefa)
* [Tarefa.js](./cypress/support/screenplay/tarefa/Tarefa.js)
* [index.js](./cypress/support/screenplay/tarefa/index.js)
* [utils/](./cypress/support/screenplay/utils)
* [index.js](./cypress/support/screenplay/utils/index.js)
* [naoImplementado.error.js](./cypress/support/screenplay/utils/naoImplementado.error.js)
* [ScreenplayItem.js](./cypress/support/screenplay/ScreenplayItem.js)
* [index.js](./cypress/support/screenplay/index.js)

> Tests:
> Testes:
* [integration/](./cypress/integration)
* [page-objects/](./cypress/integration/page-objects)
* [adicionar.spec.js](./cypress/integration/page-objects/adicionar.spec.js)
* [remover.spec.js](./cypress/integration/page-objects/remover.spec.js)
* [screenplay/](./cypress/integration/screenplay)
* [Tarefas/](./cypress/integration/screenplay/Tarefas)
* [AcessarHome.tarefa.js](./cypress/integration/screenplay/Tarefas/AcessarHome.tarefa.js)
* [AdicionarValorVazio.tarefa.js](./cypress/integration/screenplay/Tarefas/AdicionarValorVazio.tarefa.js)
* [EsperarListaContendoDoisItens.tarefa.js](./cypress/integration/screenplay/Tarefas/EsperarListaContendoDoisItens.tarefa.js)
* [EsperarListaContendoUmItem.tarefa.js](./cypress/integration/screenplay/Tarefas/EsperarListaContendoUmItem.tarefa.js)
* [ExibirLista.tarefa.js](./cypress/integration/screenplay/Tarefas/ExibirLista.tarefa.js)
* [ExibirListaContendoTres.tarefa.js](./cypress/integration/screenplay/Tarefas/ExibirListaContendoTres.tarefa.js)
* [InserirNovoRepositorio.tarefa.js](./cypress/integration/screenplay/Tarefas/InserirNovoRepositorio.tarefa.js)
* [LimparLista.tarefa.js](./cypress/integration/screenplay/Tarefas/LimparLista.tarefa.js)
* [RemoverItem.tarefa.js](./cypress/integration/screenplay/Tarefas/RemoverItem.tarefa.js)
* [VisualizarListaComItens.tarefa.js](./cypress/integration/screenplay/Tarefas/VisualizarListaComItems.tarefa.js)
* [VisualizarListaVazia.tarefa.js](./cypress/integration/screenplay/Tarefas/VisualizarListaVazia.tarefa.js)
* [index.js](./cypress/integration/screenplay/Tarefas/index.js)
* [adicionar/](./cypress/integration/screenplay/adicionar)
* [adicionar.screenplay.spec.js](./cypress/integration/screenplay/adicionar/adicionar.screenplay.spec.js)
* [componentes/](./cypress/integration/screenplay/componentes)
* [home.componentes.js](./cypress/integration/screenplay/componentes/home.componentes.js)
* [remover/](./cypress/integration/screenplay/remover)
* [remover.screenplay.spec.js](./cypress/integration/screenplay/remover/remover.screenplay.spec.js)

## Lint and precommit hook

This project uses ESLint, Prettier and lint-staged to handle linting operations and precommit hook.

Before hands-on, do not forget to run:

```
npm install
npx mrm lint-staged
```
2 changes: 1 addition & 1 deletion cypress.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"video": false,
"nodeVersion": "system",
"baseUrl": "https://repo-listing.web.app",
"testFiles": "page-objects/**.spec.js",
"testFiles": ["screenplay/**/**.spec.js", "page-objects/**/**.spec.js"],

"reporter": "mochawesome",
"reporterOptions": {
Expand Down
9 changes: 9 additions & 0 deletions cypress/fixtures/repositorios.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"lista": [
"thiagojacinto/es6-review",
"cypress-io/cypress-example-recipes",
"rust-lang/rust",
"hapijs/hapi",
"cli/cli"
]
}
16 changes: 16 additions & 0 deletions cypress/integration/screenplay/Tarefas/AcessarHome.tarefa.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Tarefa, Agente } from "../../../support/screenplay"; //eslint-disable-line
/**
* @class {Tarefa} que representa navegar para homescreen.
*/
export class AcessarHome extends Tarefa {
/**
* Navega para a homescreen.
* @param {Agente} agente
* @returns {Agente} agente
*/
executaComo(agente) {
cy.visit(""); // cypress.json setting baseUrl
cy.viewport("samsung-note9");
return agente;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Tarefa } from "../../../support/screenplay";
import { ELEMENTS } from "../componentes/home.componentes";

/**
* @class AdicionarValorVazio
* @classdesc {Tarefa} que representa inserir um valor vazio no texto e inserir a lista.
*/
export class AdicionarValorVazio extends Tarefa {
/**
* Sem inserir nenhum valor para o campo de texto, adiciona valor vazio a lista.
* @param {Agente} agente
*/
executaComo(agente) {
cy.get(ELEMENTS.submitButton)
.focus()
.click()
.wait(100);
cy.get(ELEMENTS.unorderedList, { timeout: 3000 });
return agente;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { ExibirLista } from "./ExibirLista.tarefa";
/**
* @class ExibirListaContendoTresItems
* @classdesc extende o comportamento da class ExibirLista e verifica se a lista apresenta 2 items.
*/
export class EsperarListaContendoDoisItens extends ExibirLista {
constructor() {
super();
this.contendo(2);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { ExibirLista } from "./ExibirLista.tarefa";
/**
* @class ExibirListaContendoTresItems
* @classdesc extende o comportamento da class ExibirLista e verifica se a lista apresenta 1 item.
*/
export class EsperarListaContendoUmItem extends ExibirLista {
constructor() {
super();
this.contendo(1);
}
}
28 changes: 28 additions & 0 deletions cypress/integration/screenplay/Tarefas/ExibirLista.tarefa.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Tarefa, Agente } from "../../../support/screenplay"; //eslint-disable-line
import { ELEMENTS } from "../componentes/home.componentes";
/**
* @class {Tarefa} que retorna os repositórios expostos na lista.
*/
export class ExibirLista extends Tarefa {
/**
* Insere o número esperado a ser exibido na lista
* @param {number} quantidade de repositórios a serem exibidos
* @default 1
*/
contendo(numero = 1) {
this.numero = numero;
}

/**
* Ver.
* @param {Agente} agente
* @returns {Agente} agente
*/
executaComo(agente) {
cy.get(ELEMENTS.listItems, { timeout: 3000 }).should(
"have.length",
this.numero || 1
);
return agente;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { ExibirLista } from "./ExibirLista.tarefa";
/**
* @class ExibirListaContendoTresItems
* @classdesc extende o comportamento da class ExibirLista e verifica se a lista apresenta 3 items.
*/
export class ExibirListaContendoTres extends ExibirLista {
constructor() {
super();
this.numero = 3;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Tarefa, Agente } from "../../../support/screenplay/tarefa"; //eslint-disable-line
import { ELEMENTS } from "../componentes/home.componentes";
/**
* @class {Tarefa} que representa inserir novo repositório a lista.
*/
export class InserirNovoRepositorio extends Tarefa {
/**
* Insere o username do usuário do GitHub
* @param {string} username do usuario no GitHub
* @default "cypress-io"
*/
doUsuario(usuario = "cypress-io") {
this.usuario = usuario;
return this;
}
/**
* Insere o repositório do usuário disponível publicamente no GitHub
* @param {string} repositorio mesmo nome público do repositório disponível no GitHub
* @default "cypress-example-recipes"
*/
comNome(repositorio = "cypress-example-recipes") {
this.repositorio = repositorio;
return this;
}

/**
* Adiciona novo repositório.
* @param {Agente} agente
* @returns {Agente} agente
*/
executaComo(agente) {
cy.fixture("repositorios.json").then(data => {
let random = Math.floor(Math.random() * data.lista.length);
// let [usuario, repositorio] = data.lista[random].split("/");
// cy.get(ELEMENTS.input).type(`${usuario}/${repositorio}`);
cy.get(ELEMENTS.input).type(data.lista[random]);
});
cy.get(ELEMENTS.submitButton)
.focus()
.click()
.wait(200);
cy.get(ELEMENTS.listItems, { timeout: 3000 });
return agente;
}
}
19 changes: 19 additions & 0 deletions cypress/integration/screenplay/Tarefas/LimparLista.tarefa.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Tarefa } from "../../../support/screenplay";
import { ELEMENTS } from "../componentes/home.componentes";

/**
* @class LimparLista
* @classdesc Limpa a lista removendo todos os items.
*/
export class LimparLista extends Tarefa {
/**
* Remove todos os itens listados.
* @param {Agente} agente
*/
executaComo(agente) {
cy.get(ELEMENTS.clearButton)
.focus()
.click();
return agente;
}
}
23 changes: 23 additions & 0 deletions cypress/integration/screenplay/Tarefas/RemoverItem.tarefa.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Tarefa } from "../../../support/screenplay";
import { ELEMENTS } from "../componentes/home.componentes";

/**
* @class RemoverItem
* @classdesc Remove um item da lista de tarefas.
*/
export class RemoverItem extends Tarefa {
/**
* Procura o primeiro botão "Remove" da lista e clica.
* @param {Agente} agente
*/
executaComo(agente) {
cy.get(ELEMENTS.listItems, { timeout: 3000 }).within(() => {
cy.get(ELEMENTS.listItemRemoveButton)
.first()
.focus()
.click();
});

return agente;
}
}
Loading

0 comments on commit 2a7b4fb

Please sign in to comment.