O Nuxt.js tem sido muito divertido de usar em aplicativos Web de produção e projetos paralelos. É simples, rápido e parece muito alinhado com os padrões da Web no que diz respeito à criação de componentes, importação de plug-ins etc. Igualmente empolgante foi o surgimento do Storybook. Ele ganhou um grande número de seguidores no último ano por sua facilidade de uso na criação de bibliotecas de componentes/padrões e por sua capacidade de fazer testes instantâneos baseados em componentes de forma isolada.
Recentemente, eu estava querendo iniciar um novo projeto paralelo e queria usar o Storybook com o Nuxt. Fiquei empolgado ao ver a documentação sobre o uso do Storybook com o Vue (embora React, React Native e Angular também sejam suportados), mas quando estava começando, encontrei alguns obstáculos no caminho. Depois de passar a noite toda trabalhando e fazer algumas solicitações de pull, consegui fazer tudo funcionar! Este é um repositório do produto final e esta é a história de minha jornada naquela noite.
Antecedentes
Para aqueles que não estão familiarizados com o Livro de histórias (como eu fiz na semana passada) ou Nuxt Gostaria de falar um pouco sobre eles. O Nuxt é uma estrutura objetivamente excelente para criar aplicativos. Ele é orientado pela comunidade, fácil de aprender e funciona bem com projetos existentes que usam o Node.js. Há muitos projetos excelentes por aí usando o Nuxt e alguns desenvolvedores importantes que eu sugeriria seguir para obter mais informações seriam Sarah Drasner, Evan O senhore Rachel Nabors. O Storybook cresceu rapidamente no último ano e se tornou parte essencial do conjunto de testes de muitas equipes, além de ser uma ótima maneira de acompanhar a interface do usuário do componente. A premissa principal é que, após criar um componente, o senhor cria sua “história”. A história conterá diferentes estados de um componente que fornece uma representação visual. Quando o senhor escreve várias histórias, tem o seu Storybook.
Instalação e configuração
Isso foi muito simples. Eu uso vue-cli para criar um novo projeto Nuxt (especificamente a variante Express) e, em seguida, usou o Documentação do Storybook sobre a instalação do pacote deles com o Vue. Em sua documentação, eles mostram um exemplo de um arquivo de configuração para o Storybook. Ele discute o uso do Vuex como um plug-in, mas isso não é necessário para que as coisas funcionem. Se quiser começar sem os plug-ins por enquanto, o senhor pode verificar o arquivo de configuração no repositório da minha jornada.
O Storybook tem “add-ons” integrados que agregam muito valor ao pacote. Eu estava interessado em fazer com que os addons Action e Storyshot funcionassem. As ações permitem que o Storybook exiba dados de manipuladores de eventos em um painel. Isso é especialmente útil quando o senhor deseja ver quais dados são passados quando um botão é clicado ou quando algum outro tipo de evento é acionado por meio da interação com a IU. Fotos de histórias crie um instantâneo do componente isoladamente para que, à medida que as atualizações forem feitas, o senhor possa executar um teste de comparação nos componentes para garantir que não haja alterações inesperadas na interface do usuário. Para ser sincero, o teste de snapshot era um termo novo para mim há uma semana, mas ele realmente provou ser útil. Por trás do capô, o Storyshots está usando o Jest para fazer seus testes. Falaremos sobre minha desventura com o Storyshots e o Jest daqui a pouco. Se estiver interessado, o senhor pode encontrar um lista completa de add-ons, tanto nativos quanto criados pela comunidade, em seu site.
Ações
A única parte com a qual tive dificuldade para configurar esse addon foi fazer com que o pacote fosse executado corretamente quando eu iniciei o npm run storybook
. Esse comando é o que inicia o servidor local para a interface do usuário do Storybook. Inicialmente, ao fazer isso, acabei vendo um painel de histórias, mas sem ações, apesar de instalar o storybook/addon-actions por meio do NPM. Acontece que estava faltando um arquivo addons.js no diretório .storybook. Esse arquivo deve ter a seguinte aparência para importar os add-ons que o senhor deseja usar na interface do usuário do Storybook:
import '@storybook/addon-actions/register' import '@storybook/addon-links/register'
Depois de adicionar esse arquivo, o painel apareceu, mas eu ainda não estava vendo as ações aparecerem quando clicava no botão na história do Button/template + methods. Descobri, por tentativa e erro, que alterar o @click no modelo do botão para :handle-click daria o resultado que eu esperava. Acho que isso se deve ao fato de estarmos testando o componente isoladamente, de modo que o painel de ação está observando as alterações nos dados e ouvindo os manipuladores de eventos dentro desse componente específico. Ainda não confirmei isso com a comunidade, mas acredito que faça sentido.
Histórias: Primeira rodada
É aqui que nossa jornada se torna difícil. Para instalar os pacotes corretos, tive que sair um pouco do do que é fornecido na documentação. Aqui está o comando completo a ser usado para todos os pacotes corretos: npm install --save-dev @storybook/addon-storyshots jest react-test-renderer jest-vue-preprocessor
. Ainda não tenho certeza do motivo pelo qual o react-test-renderer é necessário. Acredito que seja um bug, mas ainda estou confirmando isso. Nesse ponto, houve alguns erros e enviei alguns problemas. Enquanto esperava por essas respostas, em vez de ir dormir como uma pessoa sã, decidi mexer um pouco no Jest para fazer alguns testes de ponta a ponta.
Vamos para a toca do coelho
Eu não tinha usado o Jest antes e queria me aprofundar um pouco nos detalhes para ver como ele funcionava. Comecei criando um test/unit para conter o diretório de especificações e alguns arquivos de configuração. Pesquisando, encontrei um repositório de Brant Willis no GitHub que realmente ajudou a resolver como deve ser o arquivo jest.config.js ao trabalhar com o Nuxt. Acontece que esse arquivo também seria usado pelo Storyshots mais tarde. (Então, talvez essa não tenha sido uma decisão totalmente fora do tópico!)
Depois de resolver a configuração, consegui fazer com que os testes passassem! Não fiz nada de louco para os testes. Há muitos tutoriais on-line para criar testes com o Jest. Criei um teste simples para cada componente, o layout padrão no Nuxt e cada página no Nuxt. Quando tentei executar o teste no Footer.vue, recebi um erro. Isso acabou acontecendo porque o Footer.vue não tinha uma área de script no arquivo.
Histórias: Segunda rodada
Depois de descobrir o Jest, eu ainda não tinha uma resposta para os problemas enviados. Na lógica clássica das 3 da manhã, decidi pesquisar novamente e me deparei com o um arquivo enterrado no repositório oficial do Storybook. Esse é o arquivo necessário para informar ao storyshots onde encontrar o arquivo de configuração, qual estrutura usar com o Storybook e algumas outras opções periféricas. Eu o configurei para Vue, mas ainda estava encontrando erros. Ele estava dizendo que o storybook/react não foi encontrado, embora eu tenha definido o Vue como a estrutura. Depois de usar o npm install --save-dev storybook/react
tudo ficou bem. (Sim, muito estranho.) Ao tentar executar o npm test
ele me forneceu um unexpected token
. Algo que não estava bem documentado era a necessidade de ter um arquivo .babelrc. Acontece que ele não estava transpilando o código com o Babel antes de executar os testes. Acabei com este arquivo .babelrc depois de ver este problema no pacote jest-vue-preprocessor.
A meia hora seguinte foi um borrão. Quando me dei conta, eu tinha bagunçado muito o repositório e decidi reverter para um commit que eu sabia que estava funcionando. Além disso, minha esposa acordou e me disse que eu estava digitando muito alto e que deveria ir para o meu escritório. #truLove (Quem achou que isso era uma boa ideia?)
Depois de tomar um pouco de café, percebi que havia adicionado um arquivo webpack.config.js no .storybook que estava substituindo muitas configurações no arquivo de configuração do Nuxt. Juntei o humpty dumpty novamente e sabia que estava chegando perto. Depois de executar o npm test
e tentar algumas coisas diferentes, ainda recebi um erro dizendo storyshots is intended only to be used with storybook
. Acontece que o Storyshots é disponível a partir do Storybook 3.4.0-alpha.5. Para atualizar para essa versão, tive que definir a versão do storybook-vue, storybook/addon-action e storybook/addon-storyshots. Também descobri que o @storybook/addon é necessário para que os addons funcionem. Parece que é uma nova maneira de fazer com que os complementos funcionem em uma atualização futura.
Quando eu executei o npm test
novamente, obtive o seguinte:
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){<template> ^ SyntaxError: Unexpected token < at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/script_transformer.js:318:17) at Object.<anonymous> (node_modules/@storybook/vue/dist/client/preview/render.js:24:21) at Object.<anonymous> (node_modules/@storybook/vue/dist/client/preview/index.js:32:15)
Agradecimentos à comunidade do Storybook Descobri que havia uma solução alternativa para esse bug adicionando o seguinte ao jest.conf.js
transformIgnorePatterns: [ '/node_modules/(?!(@storybook/.*\\.vue$))', ],
E TA-DA!!! Funciona!
Quando o sol começou a se levantar…
Fiquei muito animado ao ver isso funcionando. Acontece que meus testes Jest estavam criando snapshots para minhas especificações e o Storyshots estava criando snapshots das histórias. Ele também vem com estatísticas de cobertura, o que foi um belo easter egg. Embora eu não tenha certeza por que só obtive 50% de cobertura no meu arquivo Button.vue. (Alguém sabe por quê? Deixe um comentário!) Ao longo do caminho, encontrei um ótimo recurso para especificações Jest com Vue. Estou animado para me aprofundar mais nas especificações e brincar com mais alguns add-ons para o Storybook.
Sentindo-me invencível e extremamente exausto, decidi fechar o laptop e me deitar para descansar um pouco. Foi quando ouvi… o choro da minha filha de 2 anos, o lamento de um garotinho ranzinza de 4 anos e o latido alto de um cachorro que precisava sair. Sério… de quem foi essa ideia?