Skip to content

Commit 1390e8c

Browse files
test(button): adiciona testes e2e com cypress nos samples
Configura Cypress no projeto e cria testes e2e para os três samples do componente po-button: basic, labs e social-network. Importa os samples originais no app via caminho relativo e adiciona path mapping no tsconfig.app.json para resolver @po-ui/ng-components. Testes cobrem (39 no total): - basic (5): renderização, clique/alert, kind, disabled, classe CSS - labs (25): estado inicial, label, disabled, loading, danger, ícones, kind, type, size, interação Danger/Tertiary, click/dialog, restore - social-network (9): widget, dados, botões, fluxos completos, avatar Co-Authored-By: aline.lariguet <alinecbgmoreira@gmail.com>
1 parent 68a14bd commit 1390e8c

10 files changed

Lines changed: 350 additions & 3 deletions

File tree

cypress.config.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { defineConfig } from 'cypress';
2+
3+
export default defineConfig({
4+
e2e: {
5+
baseUrl: 'http://localhost:4200',
6+
supportFile: 'cypress/support/e2e.ts',
7+
specPattern: 'cypress/e2e/**/*.cy.ts',
8+
video: false,
9+
screenshotOnRunFailure: true,
10+
viewportWidth: 1280,
11+
viewportHeight: 720,
12+
defaultCommandTimeout: 10000
13+
}
14+
});
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
describe('PO Button Basic Sample', () => {
2+
beforeEach(() => {
3+
cy.visit('/button/basic');
4+
});
5+
6+
it('deve renderizar o botão com o label "PO Button"', () => {
7+
cy.get('po-button').should('exist');
8+
cy.get('po-button button.po-button').should('be.visible');
9+
cy.get('po-button .po-button-label').should('contain.text', 'PO Button');
10+
});
11+
12+
it('deve exibir um alerta ao clicar no botão', () => {
13+
const stub = cy.stub();
14+
cy.on('window:alert', stub);
15+
16+
cy.get('po-button button.po-button')
17+
.click()
18+
.then(() => {
19+
expect(stub).to.have.been.calledWith('Po Button!');
20+
});
21+
});
22+
23+
it('deve possuir o atributo p-kind padrão secondary', () => {
24+
cy.get('po-button').should('have.attr', 'p-kind', 'secondary');
25+
});
26+
27+
it('não deve estar desabilitado', () => {
28+
cy.get('po-button button.po-button').should('not.be.disabled');
29+
});
30+
31+
it('deve ter a classe po-button no elemento button', () => {
32+
cy.get('po-button button').should('have.class', 'po-button');
33+
});
34+
});
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
describe('PO Button Labs Sample', () => {
2+
beforeEach(() => {
3+
cy.visit('/button/labs');
4+
});
5+
6+
describe('Estado inicial', () => {
7+
it('deve renderizar o botão principal', () => {
8+
cy.get('sample-po-button-labs po-button').first().find('button.po-button').should('be.visible');
9+
});
10+
11+
it('deve iniciar com kind secondary', () => {
12+
cy.get('sample-po-button-labs po-button').first().should('have.attr', 'p-kind', 'secondary');
13+
});
14+
15+
it('deve renderizar o formulário de configuração', () => {
16+
cy.get('sample-po-button-labs form').should('exist');
17+
});
18+
19+
it('deve exibir o campo de input para Label', () => {
20+
cy.get('sample-po-button-labs po-input').should('exist');
21+
});
22+
23+
it('deve exibir o checkbox group de Properties', () => {
24+
cy.get('sample-po-button-labs po-checkbox-group').should('exist');
25+
});
26+
27+
it('deve exibir os radio groups de configuração', () => {
28+
cy.get('sample-po-button-labs po-radio-group').should('have.length', 4);
29+
});
30+
31+
it('deve exibir o botão Sample Restore', () => {
32+
cy.get('sample-po-button-labs po-button').last().find('.po-button-label').should('contain.text', 'Sample Restore');
33+
});
34+
});
35+
36+
describe('Alteração de Label', () => {
37+
it('deve atualizar o label do botão ao digitar no campo Label', () => {
38+
cy.get('sample-po-button-labs po-input input').clear().type('Meu Botão');
39+
cy.get('sample-po-button-labs po-button').first().find('.po-button-label').should('contain.text', 'Meu Botão');
40+
});
41+
});
42+
43+
describe('Propriedade Disabled', () => {
44+
it('deve desabilitar o botão ao marcar a opção Disabled', () => {
45+
cy.get('sample-po-button-labs po-checkbox-group').contains('Disabled').click();
46+
cy.get('sample-po-button-labs po-button').first().find('button.po-button').should('be.disabled');
47+
});
48+
});
49+
50+
describe('Propriedade Loading', () => {
51+
it('deve exibir o ícone de loading ao marcar a opção Loading', () => {
52+
cy.get('sample-po-button-labs po-checkbox-group').contains('Loading').click();
53+
cy.get('sample-po-button-labs po-button').first().find('button.po-button').should('be.disabled');
54+
cy.get('sample-po-button-labs po-button').first().find('.po-button-loading-icon').should('exist');
55+
});
56+
});
57+
58+
describe('Propriedade Danger', () => {
59+
it('deve aplicar o atributo danger ao marcar a opção Danger', () => {
60+
cy.get('sample-po-button-labs po-checkbox-group').contains('Danger').click();
61+
cy.get('sample-po-button-labs po-button').first().should('have.attr', 'p-danger', 'true');
62+
});
63+
});
64+
65+
describe('Alteração de Icon', () => {
66+
it('deve aplicar o ícone an an-newspaper ao botão', () => {
67+
cy.get('sample-po-button-labs po-radio-group[name="icon"]').contains('an an-newspaper').click();
68+
cy.get('sample-po-button-labs po-button').first().find('po-icon.po-button-icon').should('exist');
69+
cy.get('sample-po-button-labs po-button').first().find('po-icon i.an-newspaper').should('exist');
70+
});
71+
72+
it('deve aplicar o ícone an an-calendar-dots ao botão', () => {
73+
cy.get('sample-po-button-labs po-radio-group[name="icon"]').contains('an an-calendar-dots').click();
74+
cy.get('sample-po-button-labs po-button').first().find('po-icon i.an-calendar-dots').should('exist');
75+
});
76+
77+
it('deve aplicar o ícone an an-user ao botão', () => {
78+
cy.get('sample-po-button-labs po-radio-group[name="icon"]').contains('an an-user').click();
79+
cy.get('sample-po-button-labs po-button').first().find('po-icon i.an-user').should('exist');
80+
});
81+
82+
it('deve aplicar o ícone fa fa-podcast ao botão', () => {
83+
cy.get('sample-po-button-labs po-radio-group[name="icon"]').contains('fa fa-podcast').click();
84+
cy.get('sample-po-button-labs po-button').first().find('po-icon i.fa-podcast').should('exist');
85+
});
86+
});
87+
88+
describe('Alteração de Kind', () => {
89+
it('deve alterar o kind para primary', () => {
90+
cy.get('sample-po-button-labs po-radio-group[name="kind"]').contains('primary').click();
91+
cy.get('sample-po-button-labs po-button').first().should('have.attr', 'p-kind', 'primary');
92+
});
93+
94+
it('deve alterar o kind para tertiary', () => {
95+
cy.get('sample-po-button-labs po-radio-group[name="kind"]').contains('tertiary').click();
96+
cy.get('sample-po-button-labs po-button').first().should('have.attr', 'p-kind', 'tertiary');
97+
});
98+
});
99+
100+
describe('Alteração de Type', () => {
101+
it('deve alterar o type para submit', () => {
102+
cy.get('sample-po-button-labs po-radio-group[name="type"]').contains('submit').click();
103+
cy.get('sample-po-button-labs po-button').first().find('button.po-button').should('have.attr', 'type', 'submit');
104+
});
105+
106+
it('deve alterar o type para reset', () => {
107+
cy.get('sample-po-button-labs po-radio-group[name="type"]').contains('reset').click();
108+
cy.get('sample-po-button-labs po-button').first().find('button.po-button').should('have.attr', 'type', 'reset');
109+
});
110+
});
111+
112+
describe('Alteração de Size', () => {
113+
it('deve alterar o tamanho para large', () => {
114+
cy.get('sample-po-button-labs po-radio-group[name="size"]').contains('large').click();
115+
cy.get('sample-po-button-labs po-button').first().find('button.po-button').should('have.class', 'po-button-large');
116+
});
117+
118+
it('deve alterar o tamanho de large para medium', () => {
119+
// Muda para large primeiro
120+
cy.get('sample-po-button-labs po-radio-group[name="size"]').contains('large').click();
121+
cy.get('sample-po-button-labs po-button').first().find('button.po-button').should('have.class', 'po-button-large');
122+
123+
// Volta para medium
124+
cy.get('sample-po-button-labs po-radio-group[name="size"]').contains('medium').click();
125+
cy.get('sample-po-button-labs po-button').first().find('button.po-button').should('not.have.class', 'po-button-large');
126+
});
127+
});
128+
129+
describe('Interação Danger e Kind Tertiary', () => {
130+
it('deve desabilitar a opção Danger ao selecionar kind tertiary', () => {
131+
cy.get('sample-po-button-labs po-radio-group[name="kind"]').contains('tertiary').click();
132+
// Quando kind é tertiary, a opção Danger fica desabilitada
133+
cy.get('sample-po-button-labs po-checkbox-group po-checkbox').last().find('span.po-checkbox').should('have.attr', 'aria-disabled', 'true');
134+
});
135+
136+
it('deve desabilitar a opção tertiary ao marcar Danger', () => {
137+
cy.get('sample-po-button-labs po-checkbox-group').contains('Danger').click();
138+
cy.get('sample-po-button-labs po-radio-group[name="kind"]').find('po-radio').last().find('input').should('be.disabled');
139+
});
140+
});
141+
142+
describe('Botão Click', () => {
143+
it('deve exibir um diálogo ao clicar no botão principal', () => {
144+
cy.get('sample-po-button-labs po-button').first().find('button.po-button').click();
145+
cy.get('po-modal').should('be.visible');
146+
cy.get('po-modal').should('contain.text', 'Hello PO World!!!');
147+
});
148+
});
149+
150+
describe('Restore', () => {
151+
it('deve restaurar o estado inicial completo ao clicar em Sample Restore', () => {
152+
// Altera várias propriedades
153+
cy.get('sample-po-button-labs po-input input').clear().type('Teste');
154+
cy.get('sample-po-button-labs po-radio-group[name="kind"]').contains('primary').click();
155+
cy.get('sample-po-button-labs po-radio-group[name="size"]').contains('large').click();
156+
cy.get('sample-po-button-labs po-radio-group[name="icon"]').contains('an an-user').click();
157+
cy.get('sample-po-button-labs po-checkbox-group').contains('Disabled').click();
158+
159+
// Clica em restaurar
160+
cy.get('sample-po-button-labs po-button').last().find('button.po-button').click();
161+
162+
// Verifica que tudo voltou ao estado inicial
163+
cy.get('sample-po-button-labs po-button').first().should('have.attr', 'p-kind', 'secondary');
164+
cy.get('sample-po-button-labs po-button').first().find('button.po-button').should('not.be.disabled');
165+
cy.get('sample-po-button-labs po-button').first().find('button.po-button').should('not.have.class', 'po-button-large');
166+
cy.get('sample-po-button-labs po-button').first().find('po-icon').should('not.exist');
167+
});
168+
});
169+
});
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
describe('PO Button Social Network Sample', () => {
2+
beforeEach(() => {
3+
cy.visit('/button/social-network');
4+
});
5+
6+
it('deve renderizar o widget de Friend Request', () => {
7+
cy.get('po-widget').should('exist');
8+
cy.get('po-widget').should('contain.text', 'Friend Request');
9+
});
10+
11+
it('deve exibir o primeiro amigo (Mr. Dev PO)', () => {
12+
cy.get('sample-po-button-social-network').should('contain.text', 'Mr. Dev PO');
13+
cy.get('sample-po-button-social-network').should('contain.text', '7 mutual friends');
14+
cy.get('sample-po-button-social-network').should('contain.text', 'Mountain View, CA');
15+
});
16+
17+
it('deve renderizar os três botões de ação', () => {
18+
cy.get('sample-po-button-social-network po-button').should('have.length', 3);
19+
cy.get('sample-po-button-social-network po-button').eq(0).find('.po-button-label').should('contain.text', 'Confirm');
20+
cy.get('sample-po-button-social-network po-button').eq(1).find('.po-button-label').should('contain.text', 'Ignore');
21+
cy.get('sample-po-button-social-network po-button').eq(2).find('.po-button-label').should('contain.text', 'Block');
22+
});
23+
24+
it('deve avançar para o próximo amigo ao clicar em Confirm', () => {
25+
cy.get('sample-po-button-social-network po-button').eq(0).find('button.po-button').click();
26+
27+
// Verifica notificação de sucesso
28+
cy.get('po-toaster').should('contain.text', 'User added successfully!');
29+
30+
// Verifica que o segundo amigo é exibido
31+
cy.get('sample-po-button-social-network').should('contain.text', 'Mr. AI PO');
32+
cy.get('sample-po-button-social-network').should('contain.text', '99+ mutual friends');
33+
cy.get('sample-po-button-social-network').should('contain.text', 'New York City, NY');
34+
});
35+
36+
it('deve avançar para o próximo amigo ao clicar em Ignore', () => {
37+
cy.get('sample-po-button-social-network po-button').eq(1).find('button.po-button').click();
38+
39+
// Verifica notificação de warning
40+
cy.get('po-toaster').should('contain.text', 'User ignored successfully!');
41+
42+
// Verifica que o segundo amigo é exibido
43+
cy.get('sample-po-button-social-network').should('contain.text', 'Mr. AI PO');
44+
});
45+
46+
it('deve avançar para o próximo amigo ao clicar em Block', () => {
47+
cy.get('sample-po-button-social-network po-button').eq(2).find('button.po-button').click();
48+
49+
// Verifica notificação de informação
50+
cy.get('po-toaster').should('contain.text', 'User blocked successfully!');
51+
52+
// Verifica que o segundo amigo é exibido
53+
cy.get('sample-po-button-social-network').should('contain.text', 'Mr. AI PO');
54+
});
55+
56+
it('deve exibir mensagem final após interagir com todos os amigos', () => {
57+
// Primeiro amigo - Confirm
58+
cy.get('sample-po-button-social-network po-button').eq(0).find('button.po-button').click();
59+
cy.get('sample-po-button-social-network').should('contain.text', 'Mr. AI PO');
60+
61+
// Segundo amigo - Ignore
62+
cy.get('sample-po-button-social-network po-button').eq(1).find('button.po-button').click();
63+
cy.get('sample-po-button-social-network').should('contain.text', 'Mr. UX PO');
64+
65+
// Terceiro amigo - Block
66+
cy.get('sample-po-button-social-network po-button').eq(2).find('button.po-button').click();
67+
68+
// Verifica mensagem final
69+
cy.get('sample-po-button-social-network').should('contain.text', 'Congratulations TOTVS, no more requests!');
70+
});
71+
72+
it('não deve exibir botões após interagir com todos os amigos', () => {
73+
// Interage com os três amigos
74+
cy.get('sample-po-button-social-network po-button').eq(0).find('button.po-button').click();
75+
cy.get('sample-po-button-social-network po-button').eq(0).find('button.po-button').click();
76+
cy.get('sample-po-button-social-network po-button').eq(0).find('button.po-button').click();
77+
78+
// Verifica que não há mais botões de ação
79+
cy.get('sample-po-button-social-network po-button').should('have.length', 0);
80+
});
81+
82+
it('deve exibir o avatar do usuário', () => {
83+
cy.get('po-avatar').should('exist');
84+
});
85+
});

cypress/support/e2e.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Arquivo de suporte para testes E2E com Cypress
2+
// Importações e comandos customizados podem ser adicionados aqui
3+
4+
Cypress.on('uncaught:exception', () => {
5+
// Previne falhas de teste por exceções não tratadas da aplicação
6+
return false;
7+
});

cypress/tsconfig.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES2020",
4+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
5+
"types": ["cypress", "node"],
6+
"moduleResolution": "node",
7+
"module": "commonjs",
8+
"strict": true,
9+
"esModuleInterop": true,
10+
"skipLibCheck": true,
11+
"forceConsistentCasingInFileNames": true,
12+
"resolveJsonModule": true,
13+
"isolatedModules": true
14+
},
15+
"include": ["**/*.ts"]
16+
}

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@
107107
"@animaliads/animalia-icon": "1.0.5",
108108
"@commitlint/cli": "^18.4.3",
109109
"@commitlint/config-angular": "^18.4.3",
110+
"@cypress/schematic": "^5.0.0",
110111
"@po-ui/ng-schematics": "^18.0.0",
111112
"@types/jasmine": "~5.1.4",
112113
"@types/jasminewd2": "~2.0.13",
@@ -115,6 +116,7 @@
115116
"@types/systemjs": "^6.13.5",
116117
"@typescript-eslint/eslint-plugin": "^8.33.1",
117118
"@typescript-eslint/parser": "^8.33.1",
119+
"cypress": "^15.11.0",
118120
"del": "^6.0.0",
119121
"dgeni": "file:libs/dgeni-0.4.15.tgz",
120122
"dgeni-packages": "file:libs/dgeni-packages-0.30.1.tgz",
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<router-outlet></router-outlet>

projects/app/src/app/app.module.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,26 @@ import { PoModule } from '../../../ui/src/public-api';
88

99
import { AppComponent } from './app.component';
1010

11+
import { SamplePoButtonBasicComponent } from '../../../ui/src/lib/components/po-button/samples/sample-po-button-basic/sample-po-button-basic.component';
12+
import { SamplePoButtonLabsComponent } from '../../../ui/src/lib/components/po-button/samples/sample-po-button-labs/sample-po-button-labs.component';
13+
import { SamplePoButtonSocialNetworkComponent } from '../../../ui/src/lib/components/po-button/samples/sample-po-button-social-network/sample-po-button-social-network.component';
14+
1115
@NgModule({
12-
declarations: [AppComponent],
16+
declarations: [AppComponent, SamplePoButtonBasicComponent, SamplePoButtonLabsComponent, SamplePoButtonSocialNetworkComponent],
1317
bootstrap: [AppComponent],
14-
imports: [BrowserModule, FormsModule, RouterModule.forRoot([], {}), PoModule],
18+
imports: [
19+
BrowserModule,
20+
FormsModule,
21+
RouterModule.forRoot(
22+
[
23+
{ path: 'button/basic', component: SamplePoButtonBasicComponent },
24+
{ path: 'button/labs', component: SamplePoButtonLabsComponent },
25+
{ path: 'button/social-network', component: SamplePoButtonSocialNetworkComponent }
26+
],
27+
{}
28+
),
29+
PoModule
30+
],
1531
providers: [provideHttpClient(withInterceptorsFromDi())]
1632
})
1733
export class AppModule {}

projects/app/tsconfig.app.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
"extends": "../../tsconfig.json",
33
"compilerOptions": {
44
"outDir": "../../out-tsc/app",
5-
"types": []
5+
"types": [],
6+
"paths": {
7+
"@po-ui/ng-components": ["projects/ui/src/public-api"]
8+
}
69
},
710
"files": ["src/main.ts", "src/polyfills.ts"],
811
"include": ["src/**/*.d.ts"]

0 commit comments

Comments
 (0)