# Contribuindo para Coruja Web UI
Reserve um momento para revisar este documento para tornar o processo de contribuição fácil e eficaz para todos os envolvidos.
Seguir essas diretrizes ajuda a comunicar que você respeita o tempo dos desenvolvedores gerenciando e desenvolvendo este projeto. Em troca, eles devem retribuir esse respeito ao abordar seu problema ou avaliar as alterações.
Toda ajuda será bem-vinda, basta se atentar ao padrões e guias descritos aqui.
# Problemas erros ou novas sugestões e funcionalidades
Caso tenha alguma sugestão de funcionalidade ou erro para reportar, recomendamos que crie uma nova Issue (opens new window), assim conseguimos manter um histórico de decisões além de facilitar a gestão do projeto. 😄
Caso tenha alguma dúvida, busque o time de DesignOps no Slack no canal #tech-team-design-system
.
# Fluxo de contribuição
Novas contribuições são muito bem vindas, porém é necessário alinhar as expectativas primeiro. Mudanças conceituais, de interação, design e propósito das peças do Design System devem sempre vir como uma demanda do time de Design primeiramente, e preferencialmente passando pelo time de DesignOps.
Claro que pequenas correções de erros ou ajustes de bugs podem ser realizadas diretamente a nível de código, realizando um Pull Request e seguindo nosso template de PR. Mas ainda sim é recomendado alinhar com o time de DesignOps primeiro ou abrindo uma Issue (opens new window), já que as vezes aquele bug pode ser uma feature 😄, ou o time pode já ter um fix em encaminhado para aquele problema.
# Contribuindo com uma PR
Antes de realizar grandes mudanças pedimos que cheque primeiro com o time de DesignOps se essas alterações fazem sentido, com o intuito de prover agilidade entre os times seguindo os passos descritos em Fluxo de contribuição.
Feito isso, ao abrir uma PR leve em consideração sempre os seguintes pontos:
- Alinhei previamente com designer responsável ou com o time de DesignOps;
- Tenho ciência de que as mudanças feitas aqui devem servir para outros projetos também;
- Meu código segue os padrões declarados no Padrões de código do nosso projeto;
- Realizei as alterações necessárias na documentação e Storybook.
# Documentação
Nossa documentação é construída utilizando o Vuepress (opens new window), usando apenas arquivos Markdown e fica alocada na pasta docs
. Toda alteração de API dos componentes como uma nova prop, mudança de uma prop atual e etc. deve ser documentada para garantirmos que essas alterações serão propagadas para os outros times de forma fácil, não causando atritos ou quebras no desenvolvimento dos outros times.
# Criação da PR
Siga essas boas práticas para criar a PR da melhor maneira:
# Branch
Para nomear suas branches utilize nomes descritivos separados por hífen e em português.
Tipo | Nome |
---|---|
❌ Errado | branchDaFuncionalidadeXQueAdicionaTudoQuePrecisa |
❌ Errado | feat/bubbles |
✅ Certo | funcionalidade-x |
✅ Certo | melhoria-y |
✅ Certo | correcao-z |
# Commits
Ao fazer seus commits utilize uma mensagem curta, no presente do indicativo e em português. A mensagem deve responder a pergunta: O que esse commit faz?
.
Exemplos:
Tipo | Mensagem |
---|---|
❌ Errado | Essa é uma mensagem de paz, tranquilidade, amor e esperança que visa apresentar as melhorias na funcionalidade XPTO |
✅ Certo | Adiciona melhoria na funcionalidade X |
✅ Certo | Corrige fluxo de integração contínua |
✅ Certo | Altera escopo de funcionalidade Y |
# Pull Request
Utilize títulos declarativos e adicione o número do cartão do Jira (caso disponível). Exemplo:
Tipo | Título |
---|---|
✅ Certo | [SVWEB-00] Padronização de documentação |
❌ Errado | (00) Melhorias |
❌ Errado | Correções |
Não se esqueça de incluir as informações do que foi feito e como pode ser testado 😉
# Padrões de código
Aqui estão as definições dos padrões que estamos seguindo com o desenvolvimento dentro do Design System, com o objetivo de gerar um código acessível, manutenível, e visando o seu uso em diversas plataformas e projetos diferentes.
# Estrutura
.
├── .storybook # Configurações do Storybook
├── docs # Documentação de Design System
├── public # Arquivos públicos
├── scripts # Scripts de automatização de rotinas
│ └── templates # Templates de componentes
└── src # Arquivos do projeto
├── assets # Ativos do projeto
|-- cdk # Component Development Kit: Utilizades Core para criação de componentes
├── components # Componentes do projeto
├── icons # Ícones do projeto
├── styles # Estilos do projeto
└── utils # Utilidades do projeto
2
3
4
5
6
7
8
9
10
11
12
13
# Componentes
Usar CSS na hora de estilizar os componentes e definir suas classes usando o prefixo c-
com nomes distintos referentes ao componente.
Correto:
.c-button {
display: flex;
background-color: var(--color-primary);
}
2
3
4
Incorreto (ex.: usando Tailwind):
<div class="flex ui-bg-primary"></div>
#
Usar a semântica correta para os elementos.
Correto:
<button @click="doSomething()">Clique aqui!</button>
Incorreto:
<div @click="doSomething()">Clique aqui!</div>
#
Preferir unidades em valores relativos ao root element (rem) do que pixel e outras unidades.
Correto:
.c-button {
height: 3.5rem;
}
2
3
Incorreto:
.c-button {
height: 56px;
}
2
3
# Testes
Criar uma função de setup que cuidará de realizar o mount do componente, e retornará um objeto com o qual iremos realizar as asserções.
Para os testes estamos utilizando a Vue Testing Library (opens new window).
Para um guia de boas práticas do Testing Library consulte aqui (opens new window)
O Padrão abaixo da função setup se chama Testing Object Factory, você pode ler mais sobre aqui (opens new window) e aqui (opens new window)
import { render, screen } from '@testing-library/vue'
import userEvent from '@testing-library/user-event'
import Component from './Component.vue'
function setup (props = {}, slots = {}, listeners = {}) {
return render(Component, {
props: {
...props
},
slots: {
...slots
},
listeners: {
...listeners
}
})
}
describe('Component', () => {
it('should match the snapshot', () => {
// Não precisamos usar o retorno aqui para casos simples
setup()
// Acessamos o que esta renderizado através do screen
// O screen é limpo automaticamente em cada render
expect(screen.getByText('my-component')).toMatchSnapshot()
})
// Disparando eventos
it('should allow to be clicked', () => {
const clickStub = jest.fn()
setup({}, {}, {
click: clickStub
})
userEvent.click(screen.getByRole('button'))
expect(clickStub).toHaveBeenCalled()
})
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Nos testes devemos sempre testar levando em conta o user behaviour - o que o usuário vê e interage na aplicação, dessa forma devemos priorizar testes que checam por textos, e elementos visíveis na tela na hora de buscar por eles e então testar se eles atendem nossos cenários e evitar a todo custo testar detalhes da implementação (como props, data do Vue, etc).
Alguns exemplos:
Checar se a string que passamos na prop do componente bate com o valor.
Correto:
it('should match the text', () => {
setup({
myText: 'Meu texto de teste'
})
expect(screen.getByText('Meu texto de teste')).toBeVisible()
})
2
3
4
5
6
7
Incorreto:
it('should match the text', () => {
const wrapper = shallowMount(Component, {
propsData: {
myText: 'Meu texto de teste'
}
})
expect(wrapper.vm.$props.myText).toEqual('Meu texto de teste')
})
2
3
4
5
6
7
8
9
#
# Como testar
Como nossos componentes serão usados por diversos projetos e situações diferentes, é importante testarmos suas funcionalidades de forma bem abrangente.
Temos duas formas de visualizar o trabalho feito hoje:
Rodando o storybook localmente
npm run story
Rodando a documentação localmente
npm run docs
E ainda temos um comando de health check geral, que irá fazer tudo: rodar testes, lint, build do storybook para prod, build da documentação para prod, e build da propria lib para prod gerando todos os assets.
Recomendamos que o desenvolvimento de novas funcionalidades seja feito pelo Storybook, e que ao final dele seja executado o comando de health check:
npm run healthcheck
Para o futuro imaginamos ter um projeto de exemplo rodando todos os componentes e com testes de integração automatizados.
# Browser Support
Não temos um suporte de cross-browser definido hoje, porém a princípio seria de dar cobertura aos browsers que suportam a sintaxe do ES6 (opens new window) e do Flexbox (opens new window).
# Como executo a lib em outro projeto localmente?
Para poder testar como suas alterações impactam os outros projetos, deixe o build rodando no modo watch
, com o comando:
npm run build:watch
E faça um install apontando para a sua pasta do Coruja localmente. Ex.:
Caso seu repositório do Coruja esteja em: ~/Sites/coruja-web-ui
e seu projeto esteja em: ~/Sites/meu-projeto-cool
, você irá de dentro do seu projeto precisar subir um nível de pasta ao apontar para o coruja, rodando o seguinte comando:
npm i ../coruja-web-ui
Esse comando idealmente só deve precisar ser executado uma vez, e irá atualizar seu package.json
com o caminho para a lib do Coruja, assim:
{
// package.json
"dependencies": {
"@estrategiahq/coruja-web-ui": "file:../coruja-web-ui",
//...outras deps
}
}
2
3
4
5
6
7
Formando então um symlink. Dessa forma toda vez que nosso comando de watch
re-buildar nossos arquivos, a sua aplicação poderá acessá-los na mesma hora.
# Executando o pacote já criado
Caso você tenha alguma necessidade maior nos seus testes e precise de um ambiente mais limpo para testar suas alterações (já que nem sempre o symlink nos fornece a melhor Developer Experience), pode usar o Verdaccio (opens new window) que é um registro NPM local, que com alguns comandos você consegue publicar seus pacotes e consumi-los localmente.