Skip to content

Quick Start

Requisitos básicos

Para se dar bem com esta stack é importante que você tenha conhecimento sobre:

Diferença entre componentes

Nesta stack optamos por separar os componentes em 2 tipos, tomando emprestado um pouco o conceito de Dumb and Smart Components e o padrão MVVM do android.

Nossos componentes podem ser UI-componentes, cujo funcionamento é semelhante ao "Dumb component", eles são livres de manipulação de dados advindos de models ou qualquer outra fonte externa, são uma parte puramente UI. E os viewmodel-components, cujo funcionamento é semelhante ao "Smart component", eles realizam somente a manipulação dos dados e orquestração de um ou mais componentes normais. O objetivo disto é separar a camada de ui da camada de requisição e manipulação de dados, tornando os testes automatizados mais fáceis.

Um UI-componente ou viewmodel-componente pode ser utilizado em qualquer nível. Por exemplo, imagine os seguintes arquivos:

  • MyPageViewModel.svelte
  • MyPage.svelte
  • FileUploader.svelte
  • FileUploaderViewModel.svelte

Geralmente uma página realiza requisições http, e por isso possui 2 componentes um que é a página UI, e outra que é a viewmodel desta página, para lidar com as manipulações de dados externos.

Agora imagine que queremos adicionar um formulário de upload de arquivos à página, podemos fazer um componente simples e adicionar ele dentro do componente da página, assim deixamos a viewmodel da página lidar com a requisição do upload. Entretanto devemos elevar os estados do componente de upload para o componente da página, desta forma a viewmodel da página pode lidar com as requisições.

Agora imagine que a página tem um contexto que não o de upload, ela é um dashboard, mas possui um botão de ajuda que possui um formulário. Não faz sentido sermos obrigados a elevar o estado do componente de upload, ele é algo desconexo da página, e ainda pode ser utilizado em vários lugares, nos obrigando a replicar código. Por esse motivo podemos criar uma viewmodel do componente de upload de arquivos, sendo assim a página irá utilizar a viewmodel que é auto-suficiente. Porém, agora nosso componente de UI possui dependência de um componente que está acoplado a algo externo, e devemos tratar isso nos testes. Veja mais detalhes na seção de testes.

Criando um componente

Vamos esquecer um pouco as viewmodel-componentes e focar em UI-components, que são a grande maioria.

Ao desenvolver algo, que seja uma página complexa, ou um simples site, devemos utilizar a abordagem Component Drive Development. Isso nos direciona a criar componentes isolados que podem ser reutilizados, e a não nos preocuparmos muito com a camada de dados durante a criação da UI, isolando as camadas: [UI, Manipulação de dados, API, Persistência dos dados]. Claro que os componentes irão lidar com dados, mas sempre bem isolados por uma interface que fazem sentido ao objetivo do componente. Seguindo esta abordagem uma página é composta de componentes que são formados por componentes menores.

Em um projeto guiado pelo CDD devemos pensar no todo, mas desenvolver o componente isoladamente, isto é, ele deve ser criado e testado isoladamente.

✅ Abordagem correta:

Criar um botão renderizando e trabalhando somente no botão, criando uma
interface que me permita utilizá-ló nos diversos lugares que ele aparece no
meu projeto.

❌ Abordagem incorreta:

Criar a página que usa o botão, criar o componente botão e trabalhar nele somente para atender os requisitos desta página.

Criar outra página que usa o botão, modificar o botão já criado para atender os requisitos das duas páginas.

Entendido esta abordagem, o storybook entra em ação, facilitando que o componente seja renderizado isoladamente.

Sendo assim para todo UI-component devemos criar um arquivo svelte e um arquivo do storybook que servirá de interface isolada para desenvolvimento, servirá de teste visual, e documentação.

Em seu storybook você deve:

  • Criar stories para que fique claro quais são os principais estados que seu componente pode assumir.
  • Documentar manualmente aquilo que não foi bem autogerado.

Você também pode criar um componente somente para criar uma story mais livre, mostrando melhor um caso de uso de seu componente. Por exemplo para um botão, você poderia criar um componente que mostre todas as cores padrões dos botões em uma única story. Ou em um input, criar um componente que mostre o valor devolvido pelo componente de input. Como será gerado um snapshot para esta story também, você pode externalizar na UI algum estado interno para ser gerado e testado pelo snapshot, desde que exibir esse dado faça sentido para a documentação.

Quanto aos viewmodel-componentes, caso seu componente precise de um, crie livremente, entretanto ele não deve constar no storybook, sua documentação deve ser interna com comentários e tipos bem determinados com typescript. Nestes componentes, por mais que ele seja somente uma camada para tratar os dados, é recomendado isolar as funções que você deseja testar em um arquivo TS (isso será tratado na seção de testes automatizados).

Testes automatizados

Agora que você entendeu a respeito de como criar os componentes e desenvolve-los, vamos falar dos testes.

Em nossa stack temos 4 tipos de testes:

  • testes de unitário e de integração com jest para módulos javascript;
  • testes de interação para UI-componentes com jest e outros;
  • testes de screenshot auto gerados em cima de stories do storybook;
  • testes de snapshot auto gerados em cima de stories do storybook;

Os testes de snapshot são auto gerados para todos os stories de todos os componentes, mas você pode desabilitá-los caso precise.

Os testes de screenshot foram configurados para se auto gerarem para os componentes de página, por motivos de otimização e pela falta de necessidade de testar um componente isoladamente, sendo que será já testado na página. Mas você pode habilita-lo para o seu componente caso ache necessário.

Os testes com jest para módulos devem ser feitos manualmente, assim como para UI-componentes.

Testes de módulos sempre devem ser feitos. Isto é, para cada arquivos .ts criado que possui funções que fazem algo, essas funções devem ser testadas.

Testes de UI-components nem sempre precisão ser testados com jest. Recomendamos o uso do jest para simular algumas interações do usuário, e verificar se o comportamento do nosso componente condiz com o esperado. Se o caso de uso do seu componente já é coberto pelos testes auto gerados não há necessidade de também testa-ló com o jest.

NOTA: não caia na falacia de acreditar que só snapshots ou screenshots são suficiente, seja verdadeira consigo: "Este componente possui interações que devo testar?". Uma ótima forma de fazer esta avaliação é verificar o coverage de seu componente, caso falte passar por muitas ramificações provavelmente você deveria testa-lo com o jest.

✅ Exemplo onde devo utilizar jest

Um select customizável, onde é extremamente necessário que algo ocorra ao clicar no item selecionado.

Um modal, que deve abrir ao clicar no trigger e fechar ao clicar no x ou fora da caixa do modal.

Um input com mask, onde ao inputar algo a mask deve ser aplicada, e o componente deve disparar um evento retornando o valor sem mask.

✅ Exemplo onde não preciso utilizar jest

Um botão, cuja UI se altera baseada somente nas props, e a única interação é a de retornar um callback ao clicar

Um input nativo, cujo meu componente somente altera a UI e externaliza todos os valores e eventos nativos

Quanto aos viewmodel-componentes, você pode utilizar o jest para testar alguma função exportada pelo svelte-module. Funções internas ao componente não podem ser acessadas para testas, por esse motivo recomendamos que as funções importantes, que transformam os dados, sejam externalizada em um arquivo ts separado, para que sejam testados como módulos javascript, além de facilitar a leitura do componente. Em último caso, você pode criar uma fixture ou mockup das requests e testar o componente inteiro.

Organização das pastas e padrões de nomenclatura

Iremos tratar aqui somente as pastas principais dentro de src.

  • /assets
    • contém imagens, fontes, e outros arquivos de recursos, podem ser agrupados conforme necessidade
    • sem regra de nomenclatura
  • /components
    • contém todos os componentes .svelte do projeto
    • possui regras definidas mais abaixo
  • /helpers
    • contém arquivos .ts com funções ou classes úteis para todo o projeto
    • possui regras definidas mais abaixo
  • /styles
    • contém estilos globais ou que podem ser importados por qualquer um, como mixins e variáveis, também podem ser agrupados conforme necessidade
    • devem ser nomeados em minúsculo e em kebab case (parando palavras por -).

/components

  • Podemos agrupar os componente em subpastas para limitar contexto, devem conter nome minúsculo e as palavras separadas por -.
  • Componentes dentro desta pasta devem estar dentro de uma pasta com mesmo nome do componente.
  • Arquivos .svelte devem ser PascalCase, bem como seus derivados como arquivos de testes e stories.
  • Arquivos de teste com jest devem terminar em .test.ts e estar dentro da pasta do componente.
  • Arquivos de stories devem terminar em stories.ts e estar dentro da pasta do componente.
  • Caso o componente tenha uma viewmodel, a viewmodel, e quaisquer outros arquivos relativos a ele devem ficar na pasta do componente.
  • Arquivos de viewmodel devem terminar em "ViewModel.svelte".
  • Arquivos de tipos e helpers que sejam relativos somente a este componente, também devem ficar dentro da pasta do componente.
  • Arquivos de helpers devem seguir a mesma nomenclatura utilizada na pasta helpers.
  • Arquivos de tipos devem se chamar types.ts e só pode haver 1 por componente.
  • Componentes podem necessitar de outros componentes que só fazem sentido para ele, neste caso, os componentes filhos podem:
    • ficar dentro da pasta do componente pai, seguindo as regras a cima;
    • ficar dentro de uma pasta "components" dentro da pasta pai, caso sejam muitos componentes filhos, seguindo as regras a cima;
    • componentes filhos não podem ter pastas de componentes filhos, a profundidade termina neste segundo nível;
  • Componentes que são páginas devem terminar em Page.svelte

✅ Pasta de componentes válida:

IonicButton/
├─ IonicButton.svelte
├─ IonicButton.stories.ts
├─ IonicButton.test.ts
ComplexComponent/
├─ ComplexComponent.svelte
├─ ComplexComponent.stories.ts
├─ types.ts
├─ complex-functions-helper.ts
├─ MyClassHelper.ts
DashboardPage/
├─ DashboardPage.svelte
├─ DashboardPage.stories.ts
├─ DashboardPageViewModel.svelte
├─ components/
│  ├─ FileUpload/
│  │  ├─ FileUpload.svelte
│  │  ├─ FileUpload.stories.ts
│  │  ├─ FileUploadViewModel.svelte
│  ├─ custom-dashsboards/
│  │  ├─ NpsDashboard/
│  │  │  ├─ NpsDashboard.stories.ts
│  │  │  ├─ NpsDashboard.svelte

❌ Pasta de componentes inválidas:´

// só tem 1 filho, não precisa da pasta components

DashboardPage/
├─ DashboardPage.svelte
├─ DashboardPage.stories.ts
├─ components/
│  ├─ MySubComponent/
│  │  ├─ MySubComponent.svelte
// O filho não está dentro da pasta MySubComponent

DashboardPage/
├─ DashboardPage.svelte
├─ DashboardPage.stories.ts
├─ MySubComponent.svelte

NOTE: O padrão é bem amplo, em geral siga o bom senso, evite profundidade de mais. E lembre-se, se eu precisar de algo relativo ao meu componente que não é global, deve tudo estar a mão, deve estar próximo, mas organizado.

/helpers

  • Podemos agrupar os componente em subpastas para limitar contexto, devem conter nome minúsculo e as palavras separadas por -.
  • Se for uma classe deve ser pascal case.
  • Em um arquivo deve haver somente 1 classe.
  • Se for um módulo com funções deve conter nome em minúsculo e as palavras separadas por -.
  • Arquivos de teste devem ter o mesmo nome do arquivo de helper mas terminado em test.ts.
  • Se um helper tiver mais de 2 arquivos relativos a ele, tudo deve estar dentro de uma pasta de mesmo nome do helper, e o helper principal renomeado para index.ts.
  • Um helper complexo, ou classe, pode necessitar de vários arquivos para boa separação do código, você pode cria-los dentro da pasta do helper e agrupá-los em pastas por contexto.
  • Se um helper estiver dentro da pasta de um componente deve conter o sufixo -helper, ou Helper em caso de classe.
  • Se um componente tiver vários helpers dentro de sua pasta, pode ser criado uma pasta de nome "helper", e os itens dentro não precisam mais do sufixo -helper ou Helper.

✅ Helpers válidos dentro de componentes:

ComplexComponent/
├─ ComplexComponent.svelte
├─ ComplexComponent.stories.ts
├─ types.ts
├─ complex-functions-helper.ts
├─ MyClassHelper.ts
ComplexComponent/
├─ ComplexComponent.svelte
├─ ComplexComponent.stories.ts
├─ types.ts
├─ helpers
│  ├─ complex-functions.ts
│  ├─ MyClass.ts

✅ Helpers válidos dentro da pasta /helpers:

helpers/
├─ utils.ts
├─ utils.test.ts
├─ math/
│  ├─ sum.ts
│  ├─ sum.test.ts
│  ├─ pow.ts
│  ├─ pow.test.ts
├─ User/
│  ├─ index.ts
│  ├─ User.test.ts

❌ Helpers inválidos:

Helpers/
├─ UserHelper.ts
Helpers/
├─ User/
│  ├─ User.ts
│  ├─ User.test.ts

NOTE: O padrão é bem amplo, em geral siga o bom senso, evite profundidade de mais, respeite a nomenclatura. E lembre-se, se eu precisar de algo relativo ao meu helper que não é global, deve tudo estar a mão, deve estar próximo, mas organizado.

Padrões de código

Até aqui falamos de como utilizar a stack e o que ela tem de recursos para garantir um bom código, manutenível, legível e de fácil transporte para outro projeto. Mas não falamos do código em sí, para isso temos o ESLint e o Editor config, entretanto separamos alguns arquivos apresentando os padrões de código, para que fique um pouco mais claro e também para cobrir os casos onde o Lint não vai:

Instalação do linter e editor config

Como falamos para garantir os padrões de código, a stack possui linter e editor config configurados. Antes de iniciar o desenvolvimento garanta que seu editor de texto está configurado para utilizá-los.

TUTORIAL AINDA A SER FEITO.

Fim

Se você chegou até aqui, leu tudo, e atendeu os requisitos básicos, você deve estar pronto para iniciar um projeto nesta stack. Mas caso queira se aprofundar mais, entender algumas nuances remos mais sessões no Guia de uso SPA em svelte.

Não se esqueça, esse guia foi feito por humanos, contribua para que ele fique cada vez melhor, mais direto e claro.

Para deixar tudo mais claro preparamos um video prático aplicando os guias de uso aqui listados, https://youtu.be/an5x4yXSL-E.