Programação – Luby Software https://luby.com.br Transformação Digital da concepção à entrega Fri, 04 Aug 2023 17:37:17 +0000 pt-BR hourly 1 Como criar uma API REST e validar dados com Fastify, Zod e Typescript https://luby.com.br/desenvolvimento/software/programacao/api/como-criar-uma-api-rest/ Tue, 11 Oct 2022 19:24:31 +0000 https://luby.com.br/?p=12303 Durante o processo de aprendizado, é comum que o desenvolvedor back-end seja introduzido apenas ao Express, mas será que essa é a única opção? Neste artigo, iremos ver alternativas para o desenvolvimento de API’s, como criar uma API REST e como podemos aumentar a produtividade e a segurança do código com Typescript e validações do […]

O post Como criar uma API REST e validar dados com Fastify, Zod e Typescript apareceu primeiro em Luby Software.

]]>
Durante o processo de aprendizado, é comum que o desenvolvedor back-end seja introduzido apenas ao Express, mas será que essa é a única opção? Neste artigo, iremos ver alternativas para o desenvolvimento de API’s, como criar uma API REST e como podemos aumentar a produtividade e a segurança do código com Typescript e validações do Zod.

O que é uma API REST?

Simplificadamente, uma API REST é uma forma de pedir algo para um servidor por meio de um protocolo de comunicação (HTTP), executando uma função no servidor e retornando uma informação. Durante todo esse processo, podem ocorrer diversas validações e transformações para garantir que o que foi pedido seja retornado corretamente.

Por que utilizar Typescript?

O Typescript permite que você escreva o código Javascript com mais segurança, menos erros e mais facilidade de manutenção. Além disso, ele permite que você utilize o “auto complete” da sua ferramenta de programação, como o VS Code, para te ajudar a escrever o código.

Somado a isso, tanto o Fastify quanto o Zod possuem suporte a Typescript, o que facilita ainda mais o desenvolvimento.

Por que utilizar Fastify?

O Fastify é um framework que permite que você crie servidores REST, bem como uma API REST. Em comparação com o Express, a forma como se desenvolve uma API é bem parecida. Entretanto, ele é mais performático, moderno e de fácil aprendizado, contando com várias outras vantagens. Por exemplo, um ecossistema de plugins que são mantidos tanto pela comunidade quanto pela própria equipe do Fastify.

Além de ter vantagens mais avançadas, como Decorators, Encapsulation, Lifecycle, Serialization, Hooks, entre outros.

Por que utilizar Zod?

O Zod é uma biblioteca que permite que você defina regras para validar dados, gerando automaticamente os tipos para o Typescript. Utilizaremos ele para validar os dados que serão enviados para o servidor REST. Caso os dados não correspondam às regras definidas, o servidor irá retornar um erro apontando qual campo está incorreto e o que era
esperado.

Além disso, o Zod gerará automaticamente os tipos do Typescript para você, permitindo a utilização dos dados recebidos de forma mais segura.

Passo a passo para criar uma API REST com Fastify e Zod

Para este tutorial de criação de uma API REST, foram utilizadas as seguintes ferramentas:

  • Node.js (v18.10.0);
  • VS Code;
  • Insomnia.

Instalando as dependências

Primeiro, vamos criar uma pasta chamada fastify_zod e abrir o terminal nela. Em seguida, vamos instalar as dependências necessárias para o projeto com os seguintes comandos:

1. npm init -y
2. npm i fastify zod
3. npm i -D typescript @types/node tsx

Importando as dependências

Após o primeiro passo, vamos criar um arquivo chamado server.ts e importar as dependências que instalamos anteriormente:

import Fastify from "fastify"
import { z } from "zod"

Instanciando o Fastify e criando as regras de validação do objeto User

Iremos instanciar o Fastify em uma constante chamada server e criar as regras de validação do objeto User com o Zod.

Para isso, vamos criar uma constante chamada userSchema e definir as regras de validação do objeto User. Neste caso, este é um objeto com os campos name, email e password. Para cada campo, iremos definir o tipo, o tamanho
mínimo e máximo de caracteres e o formato do campo (email).

const server = Fastify()

const userSchema = z.object({
name: z.string().min(3).max(50),
email: z.string().email(),
password: z.string().min(8).max(50)
})

Simulando um banco de dados

Para simular um banco de dados, iremos criar uma constante chamada users que será um array de objetos do tipo User. Podemos aproveitar a tipagem feita pelo Zod para inferir o tipo do objeto User da seguinte forma:

type User = z.infer <typeof userSchema>
const users: User[] = []

Criando a rota de criação de usuário

Agora, vamos criar a rota de criação de usuário. Para isso, vamos utilizar o método post do Fastify e passar como primeiro parâmetro a rota que será acessada e como segundo parâmetro uma função que irá receber como parâmetro o objeto request e reply.

Dentro dessa função, iremos pegar os dados enviados pelo usuário e validar se eles estão de acordo com as regras definidas anteriormente. Caso estejam, iremos adicionar o usuário no array de usuários e retornar o usuário criado.

Caso não estejam, iremos verificar se o erro é do tipo ZodError e retornar o erro para o usuário (lembrando sempre de retornar o Status Code correto).

server.post("/users", (request, reply) => {
try {
const user = userSchema.parse(request.body)
users.push(user)
return user
} catch (error) {
const errorJson = JSON.stringify(error)
if (error instanceof z.ZodError) return
reply.status(400).send(errorJson)
else return reply.status(500).send(errorJson)
}
})

Criando a rota de listagem de usuários

Semelhante ao passo anterior, criaremos a rota de listagem de usuários utilizando o método get e retornaremos o array de usuários.

server.get("/users", () => users)

Configurando a inicialização do servidor

Por fim, vamos iniciar o servidor utilizando o método listen do Fastify e passando como parâmetro um objeto com a porta que o servidor irá funcionar e uma função anônima que será executada quando o servidor estiver pronto para receber requisições.

server.listen({ port: 3000 }, (err, address) => {
if (err) {
console.error(err)
process.exit(1)
}
console.log(`Server listening at ${address}`)
})

Inicializando o servidor

Após verificar que o código está correto, basta executar o comando npx tsx ./server.ts no terminal para executar o código. O servidor irá iniciar na porta 3000 e enviará uma mensagem no terminal informando que está pronto para receber requisições.

Inicializando o servidor - como criar uma API REST

 

Testando a API

Para testar a API, vamos utilizar o Insomnia (ou qualquer outra ferramenta de sua preferência). Primeiro, vamos criar um novo usuário com uma requisição do tipo POST para a rota http://localhost:3000/users e passar como corpo da requisição um objeto JSON com os campos name, email e password.

Ao enviar a requisição, o corpo da resposta será o objeto JSON do usuário criado e o Status Code será 200.

Testando a API - como criar uma API REST

Caso tentemos criar um usuário com um campo inválido, como o email, o corpo da resposta será o erro retornado pelo Zod e o Status Code será 400.

Como criar uma API REST e validar dados com Fastify, Zod e Typescript Luby Software

Para listar os usuários, basta enviar uma requisição do tipo GET para a rota http://localhost:3000/users. Dessa forma, o corpo da resposta será um array com todos os usuários criados e o Status Code será 200.

Testando a API 3 - como criar uma API REST

Conclusão

Neste artigo, vimos como utilizar o Fastify para criar uma API REST e utilizar o Zod para validar os dados enviados pelo usuário. Pensando em melhor ainda mais sua experiência na criação de uma API REST, confira as referências de documentação utilizadas neste artigo:

Autor: João Carlos Magalhães de Castro.

O post Como criar uma API REST e validar dados com Fastify, Zod e Typescript apareceu primeiro em Luby Software.

]]>
Como criar snippets no VSCode para agilizar o desenvolvimento em React https://luby.com.br/desenvolvimento/software/criar-snippets-no-vscode/ Tue, 04 Oct 2022 11:01:28 +0000 https://luby.com.br/?p=12272 Quem costuma desenvolver aplicações em React provavelmente já se deparou escrevendo diversas vezes o mesmo bloco de código. Se estiver criando um componente funcional, por exemplo, você terá que criar uma função cujo nome inicia com letra maiúscula, que retorna XML (aquele JavaScript que parece HTML) e exportá-la. Neste artigo, vamos explorar um tutorial para […]

O post Como criar snippets no VSCode para agilizar o desenvolvimento em React apareceu primeiro em Luby Software.

]]>
Quem costuma desenvolver aplicações em React provavelmente já se deparou escrevendo diversas vezes o mesmo bloco de código. Se estiver criando um componente funcional, por exemplo, você terá que criar uma função cujo nome inicia com letra maiúscula, que retorna XML (aquele JavaScript que parece HTML) e exportá-la. Neste artigo, vamos explorar um tutorial para você aprender a criar snippets no VSCode.

Para estilizar utilizando uma biblioteca como Styled Components, é necessário criar um componente retornado pela função styled e também exportá-lo. Embora pareça pouca coisa, essa etapa será necessária em absolutamente todo o componente que será criado, o que é quase certo que serão muitos. E estamos falando aqui apenas em criar as condições necessária para iniciar o projeto!

Felizmente, há uma solução muito simples de ser implementada e que causa um grande impacto na produtividade: os snippets, que são blocos de códigos pré-configurados e facilmente acessíveis. O VSCode possui muitas extensões de snippets excelentes que podem ser encontradas sem dificuldade pesquisando “[nome da tecnologia] snippets”.

No entanto, muitas vezes faz mais sentido criar seus próprios snippets, utilizando o seu padrão de escrita ou o padrão estabelecido pelo seu time.

Nesse artigo, vamos aprender o básico sobre como criar snippets no VSCode e aplicar esses conhecimentos na criação de códigos muito familiares para os desenvolvedores de React: a criação de um componente funcional e estilização utilizando o Styled Components.

Passos iniciais para criar snippets no VSCode

Vamos criar nosso primeiro snippet:

  1. No VSCode, digite o atalho Ctrl + Shift + P para ter acesso às opções;
  2. Selecione “Snippets: Configure User Snippets”;
  3. Selecione “New Global Snippets File…” (como ele deverá estar disponível para todos os projetos que faremos, deverá ser um arquivo global). Se o snippet em questão deverá ser disponibilizado para apenas uma linguagem, ele poderá ser criado no arquivo específico ao invés do arquivo global;
  4. Escolha um nome para o seu arquivo de snippets. Uma sugestão é separar seus arquivos por tecnologia. Como estamos criando snippets de React, esse será o nome do nosso arquivo.
![[criar snippet.gif]]

Estrutura de configuração do snippet

Assim, criamos um arquivo JSON contendo as instruções de como criar um snippet comentadas e um exemplo simples. Vamos destrinchar a estrutura desse exemplo que o VSCode nos forneceu.

"Print to console": {
"scope": "javascript,typescript",
"prefix": "log",
"body": [
"console.log('$1');",
"$2"
],
"description": "Log output to console"
}

O primeiro passo é definir o nome do snippet, no caso, “Print to console”. Dentro desse objeto, vamos definir:

  • “scope” – serão as extensões de arquivo que terão acesso ao snippet (observe a formatação: uma única string com as extensões separadas por vírgula)
  • “prefix” – apelido para o VSCode entender que queremos utilizá-lo
  • “body” – onde estará contido o código que queremos reutilizar (mais adiante vamos detalhar como formatar o código dentro desse body)
  • “description” – detalhará o que o código faz.

Para utilizar esse snippet de exemplo, vamos criar um arquivo com extensão “ts” (perceba que o TypeScript está definido no scope) e digitar o prefix para verificar se ele será reconhecido.

![[2022-09-16 (2).png]]

De fato, ao digitar “log”, a sugestão do nosso snippet é exibida e o nome que foi definido é mostrado no canto direito.

Formatação do código no body do JSON

Você deve ter notado que o “body” (espaço onde armazenamos o código que queremos reaproveitar) tem uma estrutura de array de strings. Portanto, não podemos simplesmente copiar um código escrito em JavaScript e inseri-lo em um espaço que está esperando receber um array de strings.

Uma alternativa seria separar o código em várias strings, indicando os locais onde deveria haver quebra de linha. Porém, isso seria uma tarefa mais trabalhosa do que pode parecer e ainda haveria a preocupação com a indentação do código.

Felizmente há uma ferramenta para nos ajudar nesse processo. Com o Snippet Generator, é possível escrever o código de maneira convencional e ele se preocupa em convertê-lo para a estrutura do snippet.

No exemplo a seguir, definimos um título, o prefixo e o corpo do código e obtemos uma estrutura pronta. Sem a definição do scope, o snippet fica acessível para todo tipo de arquivo. Se esse não for um comportamento desejado, é importante acrescentar o scope manualmente dentro do seu arquivo.

![[2022-09-16 (3).png]]

Sintaxe para a criação do snippet

É comum que você queira criar um snippet mais flexível. Uma maneira de alcançar esse objetivo é definir pontos do código que não serão fixos. Ou seja, em cada contexto específico, o usuário poderá complementar o snippet da maneira que quiser. Assim, o VSCode possibilita definir os locais de parada do cursor e o usuário poderá navegar entre eles mais rapidamente utilizando a tecla Tab.

Esses pontos serão definidos digitando $1, $2, etc., e o cursor irá seguir em ordem crescente. Além disso, o último local do cursor será definido por $0 . Os pontos que tiverem a mesma identificação serão atualizados simultaneamente. Vamos ver um exemplo:

"body": [
"function $1() {",
" return(",
" <$1Container>",
" $0",
" <$1Container/>",
" )",
"}",
"",
"const $1Container = styled.div``",
"",
""
],

O exemplo acima é o body de um snippet que cria um componente funcional e um componente para estilização com o Styled Components.

O primeiro ponto desse código que será modificável é o título do componente. Além disso, esse título deverá aparecer no componente de estilização e ser retornado como container do componente na função. Ou seja, teríamos que digitar esse texto 4 vezes, se não fosse a possibilidade de marcar o local do cursor com $1 e digitá-lo nos 4 locais simultaneamente.

Definição de estrutura

Definido o nome do componente, o próximo passo seria definir sua estrutura. Por isso, a posição final do cursor foi definida com $0 no return da função dentro da tag pai. Dessa forma, precisaríamos apenas dos seguintes passos para iniciar a criação desse componente:

  1. Chamar o snippet com o prefix;
  2. Digitar o nome do componente + Tab + começar a criar sua estrutura HTML.

Outra maneira de deixar o código mais flexível é utilizando as variáveis do VSCode. As variáveis nos permitem acessar informações importantes que poderão ser úteis para a criação do snippet. Para utilizá-las, basta digitar ${name}, onde name é o nome da variável.

Outra possibilidade é definir um valor padrão para quando a variável não tiver definida com ${name:default}. Alguns exemplos de variáveis são:

  • TM_FILENAME: o nome do arquivo em que o snippet está sendo chamado;
  • TM_DIRECTORY: o caminho do diretório em que o snippet está sendo chamado;
  • TM_SELECTED_TEXT: o texto selecionado no momento em que o snippet é chamado;
  • CURRENT_YEAR: ano atual (há outras variáveis relacionadas à data).

As demais variáveis podem ser visualizadas nesta documentação. Os valores das variáveis também podem ser modificados através de expressões regulares. Essa situação acontece, por exemplo, quando se deseja remover a extensão do nome do arquivo.

Criando nosso primeiro snippet

Agora é hora de colocar a mão na massa! Vamos aplicar esses conhecimentos para criar 2 snippets no VSCode com blocos de código familiares a quem desenvolve aplicações com o React: o componente funcional e um componente para estilização com o Styled Components.

Componente funcional

Vamos utilizar a ferramenta de geração de snippets vista anteriormente. O primeiro passo é definir o seu nome. Esse nome não deverá ser tão grande, já que ele será exibido no momento em que o prefix for digitado.

No entanto, ele deverá ser bem descritivo, para que possamos diferenciá-lo de outros snippets. O nome utilizado aqui será “Create React Function Component”.

Definição do prefix

O próximo passo é definir o seu prefix. Uma sugestão é utilizar as primeiras letras do nome do snippet. Assim, teremos “crfc”. Vamos copiar e colar essa estrutura inicial dentro do nosso JSON global.

Ainda precisamos definir o scope do nosso snippet. Como eu desejo acessá-lo apenas em projetos de React sem TypeScript, a escolha natural aqui para o scope é “javascript, javascriptreact”. Caso deseje verificar como o nome das extensões foi definido no VSCode para ser reconhecido no scope, acesse as opções com Ctrl + Shift + P e selecione “Snippets: Configure User Snippets”. Dessa forma, será exibida uma lista com as extensões.

Pensando nisso, essa é a nossa estrutura inicial:

"Create React Function Component": {
"scope": "javascript, javascriptreact",
"prefix": "crfc",
"body": [
"",
"",
""
],
"description": "Create React Function Component"
}

Criação do body

Vamos agora nos dedicar à criação do body. Uma estrutura “crua” de um componente seria:

function Component() {
return(
<div>
</div>
);
}
export default Component;

Perceba, no entanto, que o nome do componente já vem definido, assim como a tag “div”, e esses são elementos que certamente desejaremos mudar, dependendo de onde esse código estiver sendo utilizado.

Então, é mais interessante que o nome do componente e a tag do container não sejam definidos. E, ao invés disso, o usuário tenha acesso mais fácil a esses locais para que possa manipular o código. Portanto, vamos definir locais de parada para o cursor.

"body": [
"function $1() {",
" return(",
" <$2>",
" $0",
" </$2>",
" );",
"}",
"",
"export default $1;"
],

Note agora que no local do nome do componente tem $1, que também aparece na linha do export, para que o usuário digite apenas uma vez. Esse é o primeiro ponto de parada do cursor.

Tag HTML

O próximo ponto é na tag HTML do container para que o usuário possa escolher por si mesmo qual tag utilizar. E o último ponto de parada é o $0, permitindo que a estrutura do componente seja desenvolvida sem a necessidade de nenhum click adicional no mouse.

Outra forma de deixar o nome do componente flexível é utilizando as variáveis. Para o caso em que o nome do arquivo é o mesmo que o nome do componente, basta utilizar a variável “TM_FILENAME_BASE”, que retorna o nome do arquivo sem sua extensão.

"body": [
"function ${TM_FILENAME_BASE}() {",
" return(",
" <$1>",
" $0",
" </$1>",
" );",
"}",
"",
"export default ${TM_FILENAME_BASE};"
],

Agora, se você utiliza uma estrutura de diretório diferente, mas também muito comum, de criar uma pasta com o nome do componente e chamar o arquivo do componente de “index.jsx”, outra variável deverá ser utilizada: a TM_DIRECTORY.

![[2022-09-19 (1).png]]

O problema é que essa variável não retorna apenas o nome do diretório, mas todo o seu caminho. Por isso, é necessário fazer uma pequena transformação utilizando uma expressão regular para que seja retornado apenas o seu nome.

Sem entrar nos detalhes de como funcionam as expressões regulares, podemos utilizar a variável ${TM_DIRECTORY/^.+[\\/\\\\]+(.*)$/$1/}.

Dessa forma, o snippet ficará assim:

"Create React Function Component": {
"scope": "javascript, javascriptreact",
"prefix": "crfc",
"body": [
"function ${TM_DIRECTORY/^.+[\\/\\\\]+(.*)$/$1/}() {",
" return(",
" <$1>",
" $0",
" </$1>",
" );",
"}",
"",
"export default ${TM_DIRECTORY/^.+[\\/\\\\]+(.*)$/$1/};"
],
"description": "Create React Function Component"
}
![[criar componente.gif]]

Componente de estilização

Para criar o componente de estilização com o Styled Components, vamos aplicar a mesma estratégia. Dessa vez, o nome do snippet será “Create Styled Component” e o seu prefix será “csc”. Serão acrescentadas ao scope as extensões “typescript”(.ts) e “typescriptreact” (.tsx).

Então, teremos a seguinte estrutura inicial:

"Create Styled Component": {
"scope": "javascript, javascriptreact, typescript, typescriptreact",
"prefix": "csc",
"body": [
"",
"",
""
],
"description": "Create Styled Component"
}

Para o nome do componente, utilizaremos também a variável TM_DIRECTORY modificada pela expressão regular utilizada anteriormente. Além disso, a tag HTML do componente deverá ser flexível, portanto, o primeiro ponto de parada do cursor será no local da tag.

Por fim, o cursor deve estar posicionado de forma que o usuário possa iniciar a configuração de estilos facilmente. O snippet final ficará assim:

"Create Styled Component": {
"scope": "javascript, javascriptreact, typescript, typescriptreact",
"prefix": "csc",
"body": [
"import styled from 'styled-components';",
"",
"const ${TM_DIRECTORY/^.+[\\/\\\\]+(.*)$/$1/}Container = styled.$1`",
" $0",
"`",
"",
"export default ${TM_DIRECTORY/^.+[\\/\\\\]+(.*)$/$1/}Container;"
],
"description": "Create Styled Component"
}
![[styled.gif]]

Snippet para integrar o componente funcional ao componente de estilização

Se estivermos criando um componente que será estilizado com o Styled Components, é certo que o arquivo com a estilização será importado e, muito provavelmente, a tag HTML retornada por esse componente será o próprio componente criado pelo Styled Components. Assim, podemos criar um snippet de componente que já prevê essa estilização.

O nome deverá especificar que esse é um componente funcional que já importa o componente de estilização. Portanto, um nome possível para esse snippet é “Create React Function Component with Styled Components” e o prefix será “crfcsc”. À estrutura do body será adicionado o import e a tag do componente de estilização criado.

Portanto, o resultado será o seguinte snippet.

"Create React Function Component with Styled Components": {
"scope": "javascript, javascriptreact",
"prefix": "crfcsc",
"body": [
"import ${TM_DIRECTORY/^.+[\\\\\\\\/\\\\\\\\\\\\\\\\]+(.*)$/$1/}Container from
\"./styles\";",
"",
"function ${TM_DIRECTORY/^.+[\\\\\\\\/\\\\\\\\\\\\\\\\]+(.*)$/$1/}() {",
" return(",
" <${TM_DIRECTORY/^.+[\\\\\\\\/\\\\\\\\\\\\\\\\]+(.*)$/$1/}Container>",
" $0 ",
" </${TM_DIRECTORY/^.+[\\\\\\\\/\\\\\\\\\\\\\\\\]+(.*)$/$1/}Container>",
" );",
"}",
"",
"export default ${TM_DIRECTORY/^.+[\\\\\\\\/\\\\\\\\\\\\\\\\]+(.*)$/$1/};"
],
"description": "Create React Function Component with Styled Components"
}
![[function com styled.gif]]

Veja também:

Como criar CRUD Básico com NestJS, GraphQL e MySQL

Próximos passos

Os snippets criados neste artigo têm como finalidade apenas ilustrar o potencial dessa ferramenta para aumentar a produtividade no desenvolvimento. Utilize a documentação e as dicas fornecidas aqui para criar snippets no VSCode de acordo com suas necessidades. Uma sugestão para praticar é reutilizar esses snippets para o caso com TypeScript.

Autor: Vinícius Ribeiro.

O post Como criar snippets no VSCode para agilizar o desenvolvimento em React apareceu primeiro em Luby Software.

]]>
Como configurar atalhos do GIT https://luby.com.br/desenvolvimento/software/como-configurar-atalhos-do-git/ Wed, 10 Aug 2022 13:43:09 +0000 https://luby.com.br/?p=12159 Você está cansado de escrever repetidamente “git add .” && “git commit -m” “seu commit””? Pois bem, neste artigo, vamos aprender a utilizar atalhos do GIT. Os atalhos do GIT permitirão que possamos otimizar o trabalho do dia a dia, resultando em melhor experiência e principalmente no aumento de produtividade. [adrotate banner=”4″] Como utilizar atalhos […]

O post Como configurar atalhos do GIT apareceu primeiro em Luby Software.

]]>
Você está cansado de escrever repetidamente “git add .” && “git commit -m” “seu commit””? Pois bem, neste artigo, vamos aprender a utilizar atalhos do GIT.

Os atalhos do GIT permitirão que possamos otimizar o trabalho do dia a dia, resultando em melhor experiência e principalmente no aumento de produtividade.

[adrotate banner=”4″]

Como utilizar atalhos do GIT?

Toda a lógica dos atalhos consiste na criação de nossos próprios comandos do GIT. Assim, teremos comandos diferenciados e que agem conforme sua preferência, por exemplo:

~: git c “feat: melhorando sua produtividade com o GIT”

No comando acima, na minha máquina, ele executa dois comandos, o “git add .” e “git commit -m “feat: melhorando sua produtividade com o GIT””. Dessa forma, não precisamos mais escrever os dois comandos, mas sim apenas um.

Iniciando a configuração

Então, vamos lá! Primeiramente, abra seu terminal e digite o seguinte comando:

~: git config --global -e

Em seguida, você irá abrir o seu editor de preferência. No meu caso, deixei o arquivo bem cru, então ele está assim:

Como configurar atalhos do GIT Luby Software

Neste caso, não temos a sessão [alias]. Dessa forma, vou adicioná-la abaixo das configurações de [user], da seguinte forma:

Como configurar atalhos do GIT Luby Software

Após declararmos a sessão de Alias, podemos criar nosso primeiro atalho. Por isso, vamos começar com o comando do GIT que mostra o status. Porém, iremos fazer com que ele retorne o status de uma forma mais enxuta, utilizando o parâmetro “-s”, segue o código:

s = !git status -s

Como configurar atalhos do GIT Luby Software

Em seguida, vamos adicionar o comando que demonstrei no início deste artigo, aquele que adiciona os arquivos e “commita” logo em seguida, sendo ele:

c = !git add --all && git commit -m

Como configurar atalhos do GIT Luby Software

Obs.: lembre-se que, caso não queira adicionar todos os arquivos alterados para o processo de commit, você deve incluir individualmente os arquivos que deseja com o comando tradicional git add [nome do arquivo] e depois executarmos o comando git commit -m “[Mensagem Descritiva]”. Ou seja, o processo tradicional.

Git log

O próximo comando será o “git log”, usaremos a opção “—pretty=format:” para deixarmos o nosso log mais bonito:

l = !git log --pretty=format:'%C(blue)%h%C(red)%d %C(white)%s - %C(cyan)%cn, %C(green)%cr

Como configurar atalhos do GIT Luby Software

O código utilizado segue a seguinte lógica:

  • %h: o percentual com a letra h minúscula irá apresentar o hash reduzido do commit;
  • %d: o percentual com a letra d minúscula irá mostrar a branch, e também a tag (caso exista) do commit;
  • %s: o percentual coma letra s minúscula (de subject) irá demonstrar a mensagem do commit;
  • %cn: nome da pessoa que realizou o commit;
  • %cr: a data relativa do commit.

Também utilizamos a opção de mostrar cores diferentes para cada coluna, o que facilita a visualização. Para isso, utilizamos o parâmetro % com a letra C maiúscula (%C), seguido da cor que desejamos entre parênteses (blue).

Segue um exemplo de como fica o comando:

Como configurar atalhos do GIT Luby Software

Veja também:

Como criar um projeto com Vite

Tutoriais de desenvolvimento de software

Conclusão

Assim concluímos a configuração dos atalhos do GIT que mais utilizamos. Lembrando que existem diversas outras opções de configuração, que podem ser verificadas na documentação oficial do GIT clicando aqui.

Autor: Paulo Santana.

[adrotate banner=”5″]

O post Como configurar atalhos do GIT apareceu primeiro em Luby Software.

]]>
Introdução ao ReactJs: o que saber antes de iniciar os estudos? https://luby.com.br/desenvolvimento/software/introducao-ao-reactjs/ Wed, 03 Aug 2022 21:28:59 +0000 https://luby.com.br/?p=10426 [vc_row][vc_column][vc_column_text]O ReactJS é um dos mais famosos frameworks Javascript que se tem na atualidade. Por isso, neste artigo, vamos trazer a introdução ao ReactJS, abordando tudo o que você precisa saber para começar a utilizar este framework. O ReactJS foi criado com o propósito de criar interfaces. Assim, cada elemento em tela pode ser agrupado […]

O post Introdução ao ReactJs: o que saber antes de iniciar os estudos? apareceu primeiro em Luby Software.

]]>
[vc_row][vc_column][vc_column_text]O ReactJS é um dos mais famosos frameworks Javascript que se tem na atualidade. Por isso, neste artigo, vamos trazer a introdução ao ReactJS, abordando tudo o que você precisa saber para começar a utilizar este framework.

O ReactJS foi criado com o propósito de criar interfaces. Assim, cada elemento em tela pode ser agrupado e utilizado como um componente. O framework é também uma biblioteca fácil de iniciar e eficiente para a criação de SPAs (Single Page Applications), interfaces de usuários. Além disso, o ReactJS é utilizado pelas grandes empresas do mercado atual: Netflix, Facebook, Amazon Videos, Airbnb, dentre várias outras.

[adrotate banner=”4″]

Essa biblioteca tem um enorme poder nas mãos. Sua agilidade em aplicações complexas é notável, pois quando se trabalha com páginas web, os scripts que são executados em segundo plano acabam se tornando um gargalo na renderização e execução da página por inteiro.

Entretanto, como o ReactJs trata os elementos em tela como componentes, isso permite fazer atualizações em tela apenas daquele elemento que sofreu alteração, ao invés de se preocupar em recarregar toda a página. Isso é um dos recursos mais fascinantes dessa ferramenta. Então vamos conferir tudo sobre a introdução ao ReactJS?

A forma de código utilizada em React é o JSX, que é uma forma combinada de código Javascript e XML (eXtensible Markup Language). Dessa forma, não é considerada nem Javascript, nem XML, mas as semelhanças são notáveis:

Introdução ao ReactJS 1 - Exemplo de código escrito em JSX.
Introdução ao ReactJS 1 – Exemplo de código escrito em JSX.

Introdução ao ReactJS: por onde iniciar?

Na introdução ao ReactJS, o primeiro ponto de atenção é entender que o framework está apoiado nas ferramentas como: HTML (HyperText Markup Language), CSS (Cascading Style Sheet) e, certamente, Javascript. Esses são os blocos primordiais aos quais este framework se apoia. Isso porque esse “JSX”, que falamos anteriormente, se assemelha bastante à combinação dessas três ferramentas.

Portanto, a forma mais natural de se iniciar os estudos em uma ferramenta nova, como na introdução ao ReactJS, é justamente pelo começo: iniciando com HTML. Com essa ferramenta, vamos aprender sobre os elementos da página web, o que muitos consideram como o “esqueleto” do site.

Para ter um bom conhecimento da ferramenta não é preciso aprender necessariamente tudo o que ela fornece, mas é essencial ter um domínio sobre os tópicos abaixo:

HTML

Tags

O HTML apresenta uma quantidade vasta de tags, que são as estruturas que englobam o conteúdo que se deseja mostrar em tela.

Introdução ao ReactJS 2 - Exemplo de código em HTML.
Introdução ao ReactJS 2 – Exemplo de código em HTML.

No exemplo em questão, temos a uma tag “<h1>”, que representa uma tag de título de um texto ou da página de forma geral. Temos também as tags <p> e <span> , que são tags de textos, onde a primeira é utilizada para representar os parágrafos da página, e a segunda serve para dar ênfase à algum pequeno trecho do texto.

E, por último, tempos a tag “<div>”, que funciona como um contêiner para o conteúdo da nossa página, ela pode englobar o conteúdo textual, como apresentado acima, como também pode englobar conteúdos de imagens, ou até mesmo apenas para organizar o layout da página.

Esses são somente alguns exemplos, mas o HTML possui um leque gigantesco de tags: <footer>, <main>, <nav>, <header>, <address>, <code>, <ul>, <li>, dentre centenas de outras. Com isso, construímos o “esqueleto” da nossa aplicação web.

HTML Semântico

Com assuntos em alta como acessibilidade, usar as tags de forma correta, durante a construção da sua página web, é de extrema importância. Isso porque muitas pessoas que possuem deficiência visual fazem uso de leitores digitais que faz a leitura detalhada da página com base no arquivo HTML que está renderizando a página.

Dessa forma, ao utilizar a estrutura mais adequada na sua página, a pessoa com necessidades especiais pode entender com mais clareza o que está lendo, se aquele trecho da página é o cabeçalho, se é um parágrafo, se é o rodapé, etc. Por isso, temos as tags de valor semântico, como no caso da <header>, que vai delimitar o cabeçalho, <main>, que vai conter o conteúdo principal da página, <footer>, que vai apresentar o rodapé.

Usando como exemplo a imagem abaixo, conseguimos ter uma noção de como são distribuídas as tags com base no layout da página.

Introdução ao ReactJS 3 - Modelo simples de como podemos dividir os componentes de uma página em diferentes seções.
Introdução ao ReactJS 3 – Modelo simples de como podemos dividir os componentes de uma página em diferentes seções.

Existem diversas tags com poder semântico e esse é um assunto que merece uma atenção dedicada, pois vai gerar grande influência no nosso tópico seguinte. Para mais detalhes sobre HTML semântico, é altamente recomendado dar uma olhada nas documentações: w3schools.com e a developer.mozilla.org.

SEO

O SEO (Search Engine Optimization) é o mecanismo de busca do Google que faz o ranqueamento dos sites para definir quais domínios irão aparecer em primeiro lugar nas pesquisas feitas pelos usuários. O Google dá notas para os sites com base nas boas práticas pré-determinadas pelo Google.

E o HTML semântico é uma das formas de obter uma boa nota, além de adicionar as “meta tags” que veremos no próximo tópico. Por isso, é essencial ter noção de como melhorar o page rank da sua aplicação, para que seu domínio sempre apareça na primeira página de busca.

Meta Tags

As Meta Tags são pequenos trechos de código que indicam algumas informações sobre a página. Elas indicam quais os tipos de caracteres usados na página, o título da aplicação, descrições curtas sobre o conteúdo da página, instruções sobre como renderizar as dimensões dos elementos com base em diferentes dispositivos (móveis ou desktop).

Bem como podemos adicionar palavras-chaves que podem ajudar o Google a achar seu site com base nos termos utilizados pelos usuários no campo de pesquisa. Aqui temos alguns exemplos de meta tags:

Introdução ao ReactJS 4 - Exemplos de Meta Tags mais comuns.
Introdução ao ReactJS 4 – Exemplos de Meta Tags mais comuns.

Dentro da mesma área em que colocamos as nossas meta tags, também adicionamos as importações dos nossos arquivos de estilo “main.css”, assim como os nossos scripts “main.js”. Entretanto, é uma boa prática adicionar os scripts no fim do nosso código, mas ainda dentro da tag <body>:

Introdução ao ReactJS 5 - Localização mais adequada para se colocar os scripts.
Introdução ao ReactJS 5 – Localização mais adequada para se colocar os scripts.

Isso é devido ao fato do conteúdo em Javascript demorar um pouco mais para carregar, ao contrário dos elementos HTML e os estilos do CSS. Isso é outro fator que conta como boas práticas!

Estrutura de uma página

A estrutura de uma página HTML é bastante simples. Ela possui um esqueleto comum à toda aplicação web e é dividida nas tags, que englobam todo o conteúdo.

Introdução ao ReactJS 6 - Exemplo de uma estrutura básica de HTML
Introdução ao ReactJS 6 – Exemplo de uma estrutura básica de HTML

Dentro dela temos das tags <head> e <body>. A tag “head” recebe justamente os conteúdos das nossas meta tags, e a tag “body” vai receber todo o conteúdo que será mostrado na página. O elemento <!DOCTYPE> é um recurso que veio com a versão mais recente do HTML, ele indica que o código a seguir segue os padrões da última versão da linguagem, o HTML 5.

Entretanto, isso não é uma tag HTML, isso é apenas uma instrução para o navegador que indica o tipo de arquivo que ele está lidando. Por isso, ele é adicionado logo no começo. Já a tag <title> indica o título da página, aquele nome pequeno que aparece acima da aba, no navegador:

Introdução ao ReactJS 7 - Apresentando no navegador onde o conteúdo da tag "title" é apresentado.
Introdução ao ReactJS 7 – Apresentando no navegador onde o conteúdo da tag “title” é apresentado.

Formulários

Os formulários são parte essencial nas aplicações web, seja para criação de login, cadastro de usuários, campos de pesquisa ou em formulários de compras em sites de e-commerce. Independentemente do tipo de conteúdo do site, é possível que tenha, ao menos, um campo de formulário para inserir dados. É essencial dar uma atenção especial a esse tópico.

CSS

O CSS é responsável pela estilização da página. É ele quem dar cor, estilo e organização. Ele distribui os elementos em tela seguindo um determinado layout. Com, ele temos várias ferramentas essenciais no desenvolvimento web:

Seletores (classes, id)

Os Seletores servem para que possamos identificar qual elemento HTML especificamente nós queremos editar e aplicar às nossas propriedades de estilos. Para isso, adicionamos classes ou id, por exemplo, <header class=”container”> e <main id=”content”>. Segue abaixo imagem que mostra como selecionar cada um desses elementos, respectivamente:

Introdução ao ReactJS 8 - Exemplo de seleção de elementos usando classes e id, respectivamente.
Introdução ao ReactJS 8 – Exemplo de seleção de elementos usando classes e id, respectivamente.

Pseudo classes

As pseudo classes são palavras-chave que são adicionadas aos seletores e especifica um determinado estado do elemento selecionado. Seja quando passamos o mouse em cima do componente ou quando marcamos uma “checkbox”, podemos controlar esses estados.

Por exemplo, ao passar o mouse sob um botão, a cor de fundo seja alterada. Existem inúmeras pseudo classes e, com certeza, vai acrescer nas habilidades de estilização.

Flexbox e Grid

Essas duas ferramentas são amplamente utilizadas para desenhar o layout das páginas e organizar os elementos da melhor forma possível. Enquanto o flexbox torna o conteúdo de dentro do elemento contêiner mais flexível, o grid faz uso de “grades”, dividindo as dimensões do contêiner em quadrantes, onde cada elemento de dentro do grid possui tamanhos proporcionais.

Essas duas ferramentas são as principais para a estilização de qualquer página web atualmente. Dominá-las é de extrema importância!

Responsividade

A responsividade se faz muito presente no mundo em que vivemos, pois todo mundo carrega um “computador” no bolso diariamente. As pessoas estão mais acostumadas a utilizar o celular para consumir os conteúdos da internet e acessar as redes sociais. Contudo, com uma tela consideravelmente menor que a de um computador, é importante que os desenvolvedores pensem na criação de uma versão mobile de suas aplicações web.

Dessa forma, um usuário poderá acessar sua página tanto pelo dispositivo móvel (seja um celular ou tablet) quanto pelo desktop, e ainda assim não ter a sua experiência prejudicada. É aí onde entra o nosso próximo item.

Media Querie

O media querie é a expressão nativa do CSS que utilizamos para criar as nossas páginas responsivas com base no tamanho da tela do dispositivo. Dessa forma, podemos desenhar um layout completamente diferente dependendo da resolução do aparelho.

Segue abaixo um exemplo da aplicação de propriedades para quando a página for acessada por um dispositivo com resolução abaixo de “600px” (pixels) de largura.

Introdução ao ReactJS 10 - Aplicando media querie.
Introdução ao ReactJS 9 – Aplicando media querie.

Javascript

Com o Javascript, temos toda a parte lógica da nossa aplicação. Ele será responsável por observar os eventos em tela, as requisições a outros serviços da internet, além de ser o principal responsável pelas interações com o usuário. Seja em um evento de “click”, recarregamento de página, e demais funções que são executadas sem segundo plano.

É o Javascript que torna a página mais dinâmica, quase viva. E, para dominá-lo, é importante focar bem a atenção nos seguintes temas:

Tipos de dados

Os tipos de dados, como o próprio nome sugere, são toda variedade de dados que o Javascript consegue lidar, são eles: Number, String (caracteres), Object, Boolean (true or false), Null, Undefined e Arrays (reconhecido como um tipo de objeto, para o Javascript).

Operadores

Assim como qualquer outra linguagem de programação, o Javascript também possui os seus operadores aritméticos: / (divisão), * (multiplicação), + (adição), – (subtração). Bem como operadores de comparação, que servem para verificar se uma determinada condição é verdadeira ou falsa: == (igual), != (diferente), > (maior que), etc.

Para mais informações a respeito dos operadores, vale a pena dar uma olhada nesta documentação (clique aqui para acessar).

Arrays e seus métodos

Arrays é um objeto Javascript que se assemelha à uma lista. Nos Arrays, podemos armazenar uma série de dados e informações. Os métodos de arrays servem para manipular essa lista de itens da forma que desejarmos. Podemos fazer uma filtragem, onde retiramos da lista alguns itens de um determinado tipo, podemos mapear a lista e transformar os elementos de dentro dela, retornando um segundo array completamente diferente do anterior.

Dominar a manipulação de arrays e compreender com profundidade os seus métodos é um dos passos mais importantes para a introdução ao ReactJS. Confira o exemplo de um array e a aplicação do método de “map”:

Introdução ao ReactJS 11 - Criação de array e aplicação do método "map()" .
Introdução ao ReactJS 10 – Criação de array e aplicação do método “map()” .

DOM

O DOM (Document Object Model) é a representação dos elementos que compõem todo o conteúdo de uma página web. Ele é responsável por exibir na tela o conteúdo HTML, CSS e pode ser alterado e manipulado com Javascript.

Ter uma boa noção dos objetos que compõem a janela do seu navegador é de suma importância para o seu desenvolvimento na introdução ao ReactJS, já que essa é uma ferramenta majoritariamente direcionada à web.

Objetos

Os Objetos em Javascript são como uma coleção de propriedades que possuem um nome e um valor, e cada propriedade é separada por vírgula. De forma grosseira, podemos fazer uma comparação com os Arrays. Porém, os Objetos possuem um nome (chave) para cada elemento (valor) que está dentro dele.

Os valores atribuídos à uma propriedade dentro de um objeto pode ser de qualquer tipo: Boolean, String, uma função, Number, etc. Veja um exemplo de um objeto:

Introdução ao ReactJS 12 - Exemplo de um objeto em javascript.
Introdução ao ReactJS 11 – Exemplo de um objeto em javascript.

Funções

Funções são componentes fundamentais em Javascript. Uma função é um conjunto de instruções ou tarefas, que serão executadas assim que a função for chamada. Primeiro criamos a função, logo em seguida escolhemos quando queremos que ela seja executada, pode ser após um evento de “click”, pode ser ao recarregar página.

Enfim, cabe ao programador/ programadora decidir como e onde melhor aplicá-las. E, assim como Arrays e Objetos, as funções são protagonistas principais quando se trata de ReactJs. Esses três itens devem ser estudados com muita atenção, pois serão utilizados até exaustão.

Introdução ao ReactJS 13 - Exemplo de função que recebe um objeto e o retorna em tela.
Introdução ao ReactJS 12 – Exemplo de função que recebe um objeto e o retorna em tela.

API

As APIs (Application Programming Interfaces) são como “transportadores” que levam e trazem informações (dados). Elas funcionam como intermediários entre o front-end e o back-end. Assim, o front-end faz um pedido (requisição) ao back-end, por meio da API, que é responsável pela comunicação. Então, o back-end faz uma consulta ao banco de dados, faz uma varredura e busca a informação requisitada.

Após isso, retorna a resposta (response) para a API, que logo em seguida devolve a informação ao front-end para que seja mostrado em tela. Tudo isso ocorre em questão de milésimos de segundos. Atualmente, grande parte da aplicações web funcionam por meio de APIs, onde podemos ter um conteúdo dinâmico e atualizar as informações em página de forma automática.

ECMAScript 6

O ECMAScript é o nome oficial da linguagem que conhecemos como Javascript. E a sexta versão da linguagem é importante por conta da padronização que o Javascript sofreu no ano de 2015. Depois disso, vieram diversas atualizações, novos métodos para trabalhar com Arrays, Objetos, além de mais funcionalidades. Portanto, para se manter atualizado na linguagem, é importante iniciar os estudos em ECMAscript da versão 6 em diante.

Introdução ao ReactJs de fato

Finalmente chegamos à introdução ao ReactJS e por onde iniciar os estudos. Uma vez que você já possui um conhecimento sólido em HTML, CSS e Javascript, prosseguir com React não será uma barreira, pelo contrário, será extremamente intuitivo. A seguir, podemos conhecer um pouco mais sobre os alicerces que apoiam o desenvolvimento web em ReactJs.

Entendendo JSX

A sintaxe do JSX, por mais que tenha suas peculiaridades, é natural de se entender e utilizá-la. Isso porque, dentro do código JSX, nós utilizamos tags HTML como se estivéssemos trabalhando com HTML puro. Não muda em nada a forma de escrever, uma <div> continua tendo as mesmas propriedades, um <p> funciona da mesma forma.

A diferença é que não estamos escrevendo isso dentro de um arquivo .html, mas sim como retorno de uma função em Javascript. Entretanto, isso é uma vantagem, pois podemos passar dados (props) entre funções, que dentro do JSX as tratamos como componentes.

Props

As props são propriedades que podemos passar entre componentes. Como no React as nossas funções retornam JSX, podemos importar e exportar componentes e passar propriedades para eles por meio de props. Dessa forma, nós importamos um determinado componente para a nossa página e escrevemos nele uma propriedade como se estivéssemos um atributo em uma tag HTML.

Introdução ao ReactJS 14 - Passando propriedades e valores por meio de Props para outros componentes.
Introdução ao ReactJS 13 – Passando propriedades e valores por meio de Props para outros componentes.

useState

O useState é uma funcionalidade (Hook) especifica do React que nos permite guardar o estado de um componente, variável e componente de função. Ele armazena um determinado valor inicial que foi atribuído a ele. Porém, quando queremos alterar o valor que está contido nesse hook, atribuímos por meio de uma função, ao invés de utilizarmos a forma padrão de atribuição de variáveis.

Introdução ao ReactJS 15 - Utilizando useState para alterar o valor da variável "language".
Introdução ao ReactJS 14 – Utilizando useState para alterar o valor da variável “language”.

Hooks

Assim como o useState, existem vários outros Hooks que tornam o React um framework especial. Aprender a trabalhar com esses Hooks é o que diferencia um bom programador React de um iniciante. Os mais utilizados são: useState, useEffect, useContext, useRef, useReducer, useCallback e useMemo. Existem vários outros, mas, dominando esses será mais do que suficiente para trabalhar com a maioria dos projetos.

Para entender melhor como cada um deles funciona e onde utilizá-los, é altamente recomendado ler a documentação (clique aqui para acessar).

Estilização (CSS, SASS, Styled Components)

A estilização no React é vasta, especialmente devido ao fato de todo código JSX ser renderizado dentro de um “index.html”. Isso nos permite utilizar ferramentas baseadas em CSS, como o SASS ou o próprio arquivo “.css” mesmo. Além disso, ele faz o uso de bibliotecas de estilos que aplicam as propriedades de estilização através do Javascript, como o Styled Components.

Bibliotecas

Como citado no tópico anterior, podemos fazer uso de bibliotecas externas em nosso projeto para melhorar a nossa produtividade e implementar funcionalidades que normalmente seriam trabalhosas ou muito complexas para se fazer manualmente. Ainda mais se a programadora/programador for iniciante.

Felizmente, o ReactJS é rico em bibliotecas para as demais finalidades: estilização; criação e validação de formulários; aplicação de modais e pop-ups; adicionar ícones no projeto; realizar requisições HTTP; etc. Essa última é tema do nosso próximo tópico.

Data fetching

As requisições de dados (Data fetching) são justamente as requisições que fazemos ao utilizar uma API. Podemos fazer uma requisição de dados para um arquivo XML dentro do nosso projeto, além de poder buscar dados dentro de um arquivo “.json”. As aplicações do Data fetching foram crescendo à medida que o uso e criação de novas APIs estão aumentando.

Fazemos requisições o tempo todo, seja durante o login em um site, no cadastro de um cliente em uma rede social ou quando fazemos uma pesquisa no campo de busca da Netflix, também estamos fazendo uma requisição de dados. O Javascript possui um método nativo de requisições HTTP que é o “fetch()”, mas o React possui uma biblioteca muito mais performática e famosa, o Axios.

Gerenciamento de Estados

O gerenciamento de um estado global de uma aplicação React surge quando precisamos passar uma mesma informação por vários componentes, passando por meio de Props, de elemento pai para filho. Mas quando temos um fluxo enorme de propriedades e tentamos passar isso por meio de Props, as informações ficam muito dependentes de um componente passar para outro.

Esse tipo de problema poderia ser facilmente evitado se qualquer componente pudesse consultar essas informações direto do arquivo que está exportando, ou de um arquivo que centraliza todas as informações que são utilizadas em mais de uma página.

Felizmente, existem soluções para isso: ferramentas que conseguem manter o controle do estado das informações em um nível acima de todos os componentes. Dessa forma, qualquer componente pode ter acesso a essas informações sem que seja necessário a passagem dos dados de pai para filho.

Pensando nisso, o React conta com ferramentas excelente para essa função, como é o caso do Context API, que já vem nativo no framework, o Redux e Zustand. Apesar de existirem mais algumas, essas são as principais, sendo o Context e Redux, as mais populares.

Da introdução ao ReactJS para o mercado de trabalho

Uma vez estudando toda a introdução ao ReactJS com dedicação, diariamente, colocando em prática todos os temas, aplicando em projetos, você já poderá começar a se inscrever para as vagas e entrar para o mercado de trabalho. Não é uma jornada fácil, e não existe atalhos, mas você pode seguir por um caminho com menores chances de falha. Então mão na massa e vamos codar!

Clique aqui e inscreva-se nas vagas da Luby!

Veja também:

Aprenda o que é data fetching!

Autor: Everson Vinicius Soares do Nascimento.

[adrotate banner=”5″][/vc_column_text][/vc_column][/vc_row]

O post Introdução ao ReactJs: o que saber antes de iniciar os estudos? apareceu primeiro em Luby Software.

]]>
Como criar CRUD Básico com NestJS, GraphQL e MySQL https://luby.com.br/desenvolvimento/software/crud-com-nestjs-graphql-e-mysql/ Tue, 26 Jul 2022 17:55:44 +0000 https://luby.com.br/?p=10279 Neste artigo, vamos aprender a criar um CRUD básico com NestJS, GraphQL e MySQL. Entretanto, antes de qualquer coisa, vamos entender o conceito de todos esses frameworks? Então, vamos lá! Segundo a documentação, NestJS é: Nest (NestJS) é mais um framework, voltado principalmente para construção de aplicações Node.js paraservidores Back-end. Dessa forma, uma das vantagens […]

O post Como criar CRUD Básico com NestJS, GraphQL e MySQL apareceu primeiro em Luby Software.

]]>
Neste artigo, vamos aprender a criar um CRUD básico com NestJS, GraphQL e MySQL.

Entretanto, antes de qualquer coisa, vamos entender o conceito de todos esses frameworks? Então, vamos lá!

Segundo a documentação, NestJS é:

Nest (NestJS) é mais um framework, voltado principalmente para construção de aplicações Node.js para
servidores Back-end. Dessa forma, uma das vantagens de se usar o NestJS é a alta escalabilidade do lado do servidor e a estrutura automática criada incialmente, seguindo os princípios do S.O.L.I.D.

[adrotate banner=”4″]

Como o NestJS utiliza TypeScript, é possível a criação de códigos fortemente tipados, mas também é possível utilizá-lo com JS puro.

A construção do código inicialmente combina elementos de OOP (Programação Orientada a Objetos), FP (Programação Funcional) e FRP (Programação Reativa Funcional). Além disso, o Nest faz uso de estruturas robustas de servidor HTTP como o Express (o padrão). Bem como, opcionalmente, pode ser configurado para usar o Fastify também!

O Nest fornece um nível de abstração acima dessas estruturas comuns do Node.js (Express/Fastify), mas
também expõe suas APIs diretamente ao desenvolvedor. Dessa forma, oferecendo aos desenvolvedores a liberdade de usar a infinidade de módulos de terceiros que estão disponíveis para a plataforma subjacente.

O que é GraphQL?

Segundo a documentação, GraphQL é:

GraphQL é uma linguagem de consulta para APIs de alto desempenho, relacionado ao tempo de consulta aos principais SGBDs. Dessa forma, o GraphQL fornece uma descrição completa e compreensível dos dados e requisições de sua API, oferecendo aos clientes o poder de solicitar exatamente o que eles precisam e nada mais!

Iniciando com NestJS e GraphQL

Primeiramente, para iniciar nosso projeto CRUD, iremos realizar todas as instalações necessárias para a criação do projeto.

Instalações necessárias

Extensões:

  1. JavaScript (ES6) code snippets
  2. Tabnine AI Autocomplete
  3. Path Intellisense
  4. Nodejs Snippets
  5. Material Icon Theme
  6. GitLens — Git supercharged
  7. Gitmoji
  8. Dracula Official
  9. ENV
  10. [Deprecated] Bracket Pair Colorizer 2
  11. Code Spell Checker

Projeto no github

Para visualizar o projeto deste artigo, clique neste link.

Instalações e start do projeto CRUD

  1. Abra o terminal do S.O como admin e execute o comando para instalação do NestJS de maneira Global ⇒ npm i -g @nestjs/cli
  2. Agora, execute o terminal em um local da sua preferência para criação do projeto, e digite o comando ⇒ nest new nest-api-withgraphql

Então, após executar o comando acima, a imagem abaixo descreve o que vocês devem visualizar de saída.

Como criar CRUD Básico com NestJS, GraphQL e MySQL Luby Software
Como criar CRUD Básico com NestJS, GraphQL e MySQL 1

3. Na imagem 1, escolha o seu gerenciador de pacotes favorito! Neste caso, vamos escolher o YARN.

Dessa forma, após as instalações para o NestJS estiverem finalizadas, a imagem abaixo descreve o que você deve visualizar de saída.

Como criar CRUD Básico com NestJS, GraphQL e MySQL Luby Software
Como criar CRUD Básico com NestJS, GraphQL e MySQL 2
  1. Na imagem 2, digite o comando cd .\NOME_DO_PROJETO para acessar a pasta criada com o projeto que definimos. Logo após entrarmos no projeto, vamos abri-lo no VSCode com o comando code .. Perfeito, agora podemos fechar o terminal!
  2. Para entender a estrutura criada, leia a documentação deste link.

Integrando o NestJS com Typeorm e MySql

Documentações de referência para projeto CRUD: https://docs.nestjs.com/techniques/database e https://typeorm.io/.

  1. Antes de tudo vamos abrir o terminal em nosso VSCode, através do comando CTRL + J
  2. Agora vamos fazer a instalação das dependências do typeorm e mysql:
    yarn add @nestjs/typeorm typeorm mysql2

Observação: vou fazer a instalação do mysql, porque este é o SGBD que mais utilizei na minha trajetória como programador, mas você pode utilizar outros, como postgresql, mssql, etc. É só fazer a instalação da lib e adicionar os parâmetros de conexão conforme apresentado no código abaixo.

Dentro do diretório src , vamos modificar o arquivo app.module.ts.

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm'
/*
Arquivo para importação dos módulos utilizados no projeto e conexão com o banco de dados!
Sejam bem-vindos ao coração da nossa API!
*/
@Module({
imports: [
TypeOrmModule.forRoot({
type: "mysql",
host: "localhost",
port: 3306,
username: "root",
password: "",
database: "graphql_database",
entities: [
"dist/**/*.entity{.ts,.js}"
],
synchronize: true
})
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule { }
  1. Importe o TypeOrmModule e adicione-o dentro do array de imports: []. Isso vai possibilitar a utilização do TypeORM em nossa API. A função forRoot() precisa receber alguns parâmetros de conexão com o banco, através de um json.

Caso queira saber mais sobre esses parâmetros, consulte a documentação neste link.

4. Ative os serviços de mysql e apache no XAMMP ou outro software da sua preferência!

Como criar CRUD Básico com NestJS, GraphQL e MySQL Luby Software
Como criar CRUD Básico com NestJS, GraphQL e MySQL 3
  1. Levando em consideração que você já saiba como criar um banco de dados, faça os passos descritos na imagem abaixo para criação desse banco de dados no DBeaver!
Como criar CRUD Básico com NestJS, GraphQL e MySQL Luby Software
Como criar CRUD Básico com NestJS, GraphQL e MySQL 4

Configurando o GraphQL

Documentações de referência para projeto CRUD: https://docs.nestjs.com/graphql/quick-start, https://www.npmjs.com/package/graphql, https://www.npmjs.com/package/@nestjs/apollo, https://www.npmjs.com/package/apollo-server-express e https://www.npmjs.com/package/@nestjs/graphql.

  1. Instalação da dependências: yarn add @nestjs/graphql @nestjs/apollo graphql graphql-tools apollo-server-express
  2. Dentro do diretório src, vamos modificar o arquivo app.module.ts novamente, com a nova funcionalidade do GraphQLModule:
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm'
//importações para utilização do graphql
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { join } from 'path';
@Module({
imports: [
TypeOrmModule.forRoot({
type: "mysql",
host: "localhost",
port: 3306,
username: "root",
password: "",
database: "graphql_database",
entities: [
"dist/**/*.entity{.ts,.js}"
],
synchronize: true
}),
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule { }

Adicione GraphQLModule dentro do array de imports: []. Conforme o código supracitado! Assim, vamos utilizar o autoSchemaFile para fazer a geração do arquivo de schema.gql com as tipagens de forma automática e utilizar o servidor do Apollo para utilização do GraphQL.

Criando o Module, Service, Resolver e Entity de Users

  1. Comando para criação do modulo: nest g module user

Dessa forma, a imagem abaixo descreve o que você deve visualizar de saída.

Como criar CRUD Básico com NestJS, GraphQL e MySQL Luby Software
Como criar CRUD Básico com NestJS, GraphQL e MySQL 5

O comando irá instanciar automaticamente o módulo de usuário e criar o arquivo. Assim, o mesmo acontecerá para os próximos passos.

  1. Comando para criação do serviço: nest g s user
  2. Comando para criação do resolver: nest g r user
  3. Vamos criar nosso arquivo de entidade no caminho src/user com o seguinte nome user.entity.ts
Como criar CRUD Básico com NestJS, GraphQL e MySQL Luby Software
Como criar CRUD Básico com NestJS, GraphQL e MySQL 6
  1. Na entidade, vamos especificar todas as colunas que teremos em nossa tabela de users no banco de dados.

Configurando nossa entidade de Usuários

Documentações de referência para projeto CRUD: https://docs.nestjs.com/graphql/resolvers e https://docs.nestjs.com/graphql/cli-plugin.

As entidades se assemelham bastante com a estrutura de migrations. Então, é nesse arquivo que definimos como vai ficar estruturado as colunas da tabela em nosso banco de dados!

  1. Vamos adicionar ao arquivo que criamos na última etapa do tópico anterior (src/user/user.entity.ts), o seguinte trecho de código:
// importações
import { Field, ID, ObjectType } from '@nestjs/graphql';
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@ObjectType() //Informa que é um objeto
@Entity() //Especifica ao código que essa classe se trata de uma entidade
export class User {
@PrimaryGeneratedColumn() // Especifica ao NestJS que a coluna id é uma coluna de chave primaria que é gerada automaticamente
@Field(() => ID) // Informa ao graphql o tipo da coluna
id: string; // tipagem da coluna
@Column()
name: string;
@Column()
email: string;
}
  1. Para não precisar especificar @Field() para colunas de tipos comum e deixar o código mais limpo, podemos utilizar o seguinte trecho de código no arquivo nest-cli.json na raiz do nosso projeto.
{
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"plugins": [
{
"name": "@nestjs/graphql/plugin",
"options": {
"typeFileNameSuffix": [
".input.ts",
".args.ts",
".entity.ts",
".type.ts"
]
}
}
]
}
}

DTO e Validators

Documentação de referência para projeto CRUD: https://docs.nestjs.com/techniques/validation.

  1. Instalação da lib para validação: yarn add class-validator
  2. Instalação da lib para transformação da classe: yarn add class-transformer
  3. Dentro do caminho src/user, crie uma pasta e nomeie como dto e adicione dois arquivos dentro desta pasta chamada createuser.input.ts e update-user.input.ts
  4. Dentro do arquivo create-user.input.ts, adicione o seguinte trecho de código:
// importações
import { InputType } from "@nestjs/graphql";
import { IsEmail, IsNotEmpty, IsString } from "class-validator";
@InputType() //Define que essa classe é do tipo input, que são os valores que serão recebidos pelo endpoint
export class CreateUserInput {
@IsString()// Validação do tipo do input
@IsNotEmpty({ message: "Campo de name obrigatório" })//Validação para não aceitar o valor vazio para chave
name: string; //Tipagem da coluna
@IsEmail()// Validação do tipo do input
@IsNotEmpty({ message: "Campo de email obrigatório" })//Validação para não aceitar o valor vazio para chave
email: string; //Tipagem da coluna
}

Então, dentro do arquivo update-user.input.ts, adicione o seguinte trecho de código:

// importações
import { InputType } from "@nestjs/graphql";
import { IsEmail, IsNotEmpty, IsOptional, IsString } from "class-validator";
@InputType() //Define que essa classe é do tipo input, que são os valores que serão recebidos pelo endpoint
export class UpdateUserInput {
@IsString()// Validação do tipo do input
@IsNotEmpty({ message: "Campo de name obrigatório" })//Validação para não aceitar o valor vazio para chave
@IsOptional()// Define o campo como opcional
name?: string; //Tipagem da coluna
@IsEmail()// Validação do tipo do input
@IsNotEmpty({ message: "Campo de email obrigatório" })//Validação para não aceitar o valor vazio para chave
@IsOptional()// Define o campo como opcional
email?: string; //Tipagem da coluna
}

6. Adicione, no arquivo src/main.ts, o uso global das validações:

import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe()) //Para utilizar as validações globalmente
await app.listen(3000);
}
bootstrap();

Implementando o Service de User

Documentação de referência para projeto CRUD: https://docs.nestjs.com/providers#services

Service é o arquivo responsável por conter todas nossas funções que faram comunicação direta com o banco. Além disso, ele se assemelha muito aos controllers em outros frameworks.

Portanto, vamos modificar o arquivo src/user/user.service.ts com o seguinte trecho de código:

// importações
import { Injectable, InternalServerErrorException, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { CreateUserInput } from './dto/create-user.input';
import { UpdateUserInput } from './dto/update-user.input';
import { User } from './user.entity'
@Injectable() // para fazer injeção de dependências no nestjs
export class UserService {
//injeta o repositório utilizando a entidade de usuário
constructor(
@InjectRepository(User)
private userRepository: Repository<User>
) { }
//método para listagem de usuários
async findAllUsers(): Promise<User[]> {
const users = await this.userRepository.find()
return users
}
//método para trazer um usuário por id
async findUserById(id: string): Promise<User> {
const user = await this.userRepository.findOneBy({ id })
if (!user) {
throw new NotFoundException("Usuário não encontrado")
}
return user
}
//método para criar um usuário
async createUser(data: CreateUserInput): Promise<User> {
const user = this.userRepository.create(data);
const userSaved = await this.userRepository.save(user)
if (!userSaved) {
throw new InternalServerErrorException('Falha na criação do usuário')
}
return userSaved
}
//método para alterar um usuário
async updateUser(id: string, data: UpdateUserInput): Promise<User> {
const user = await this.findUserById(id);
await this.userRepository.update(user, { ...data });
const userUpdated = this.userRepository.create({ ...user, ...data })
return userUpdated;
}
//método para exclusão de um usuário
async deleteUser(id: string): Promise<boolean> {
const user = await this.findUserById(id);
const deleted = await this.userRepository.delete(user);
if (deleted) {
return true;
}
return false;
}
}

Implementando o Resolver de User e importando o TypeORM para o módulo de User

Documentação de referência para projeto CRUD: https://docs.nestjs.com/graphql/resolvers#resolvers

Os Resolvers fornecem instruções para transformar uma operação do GraphQL (@Query @Mutation) em dados. Assim, aqui ficará definido o que uma função recebe e o que ela retorna!

  1. Vamos modificar o arquivo src/user/user.resolver.ts com o seguinte trecho de código:
// importações
import { Args, Mutation, Resolver, Query } from '@nestjs/graphql';
import { CreateUserInput } from './dto/create-user.input';
import { UpdateUserInput } from './dto/update-user.input';
import { User } from './user.entity';
import { UserService } from './user.service';
@Resolver('User')
export class UserResolver {
//Ejetar nosso userService
constructor(private userService: UserService) { }
@Query(() => [User]) //informa ao graphql que esse método vai retornar um array de usuários e que não há modificação do banco com ela
async users(): Promise<User[]> {
const users = await this.userService.findAllUsers()
return users
}
@Query(() => User) //informa ao graphql que esse método vai retornar um usuário em especifico e que não há modificação do banco
async user(@Args('id') id: string): Promise<User> {
const user = await this.userService.findUserById(id)
return user
}
@Mutation(() => User) //informa ao graphql que esse método vai modificar o estado no nosso banco de dados
async createUser(@Args('data') data: CreateUserInput): Promise<User> {
const user = await this.userService.createUser(data)
return user
}
@Mutation(() => User) //informa ao graphql que esse método vai modificar o estado no nosso banco de dados
async updateUser(
@Args('id') id: string,
@Args('data') data: UpdateUserInput
): Promise<User> {
const user = this.userService.updateUser(id, data);
return user;
}
@Mutation(() => Boolean) //informa ao graphql que esse método vai modificar o estado no nosso banco de dados
async deleteUser(
@Args('id') id: string
): Promise<boolean> {
const deleted = await this.userService.deleteUser(id);
return deleted;
}
}

2. Vamos modificar o arquivo src/user/user.module.ts com o seguinte trecho de código:

import { Module } from '@nestjs/common';
import { UserService } from './user.service';
import { UserResolver } from './user.resolver';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './user.entity';
@Module({
imports: [
TypeOrmModule.forFeature([User])
],
providers: [UserService, UserResolver]
})
export class UserModule { }

Testando nossos endpoints

  1. Comando para execução do servidor: yarn run start:dev

Com isso, a saída deve se apresentar como na imagem abaixo:

Como criar CRUD Básico com NestJS, GraphQL e MySQL Luby Software
Como criar CRUD Básico com NestJS, GraphQL e MySQL 7
  1. Cole o seguinte endereço no seu navegador: http://localhost:3000/graphql

Dessa forma, após colar o endereço supracitado no navegador, a seguinte página deve aparecer:

Como criar CRUD Básico com NestJS, GraphQL e MySQL Luby Software
Como criar CRUD Básico com NestJS, GraphQL e MySQL 8

Esse é o playground do graphql. Ou seja, a ferramenta que auxilia em nossas requisições!

  1. Para utilizar o playground, vamos primeiro fazer uma listagem de todos os usuários! Digite o código abaixo para fazer essa requisição:
query{
users{
id
name
email
}
}

Assim, ao fazer a consulta na aba esquerda, a aba direita da ferramenta deve exibir o seguinte resultado:

Como criar CRUD Básico com NestJS, GraphQL e MySQL Luby Software
Como criar CRUD Básico com NestJS, GraphQL e MySQL 9

Isso acontece porque não temos nenhum usuário registrado.

  1. Para registrar um usuário, crie uma nova aba no playground e cole o seguinte trecho de código.
mutation {
createUser(
data: {
name: "Edith Silva"
email: "edith@email.com"
}
) {
id
name
email
}
}

Dessa forma, a resposta deve aparecer como na imagem abaixo:

Como criar CRUD Básico com NestJS, GraphQL e MySQL Luby Software
Como criar CRUD Básico com NestJS, GraphQL e MySQL 10

Então, à essa altura, já conseguimos listar o usuário criado!

  1. Agora é só você criar mais 3 novas abas, uma para alterar, outra para mostrar pelo ID e outra para excluir, os Body’s estão disponíveis conforme o trecho de código abaixo:
// Em uma nova aba do playground, adicione o body abaixo para fazer uma busca pelo id
query{
user(id: "1"){
id
name
email
}
}
// Em uma nova aba do playground, adicione o body abaixo para fazer uma Alteração
mutation {
updateUser(id: "1", data: { email: "manoel@gmail.com" }) {
id
name
email
}
}
//Em uma nova aba do playground, adicione o body abaixo para fazer uma exclusão
mutation {
deleteUser(id: "1")
}

Veja também:

Entenda gerenciador de pacotes

Uma fração do CRUD

Assim encerramos nossa implementação de um CRUD básico de usuários, utilizando o NestJS, GraphQL e SGBD MySQL. O que foi ensinado nesse artigo é uma pequena fração de tudo que o CRUD essas demais tecnologias podem nos entregar!

Dessa forma, sugiro que a partir daqui, vocês explorem cada vez mais a própria documentação e qualquer dúvida, estou aberto para discussões através do Discord (Manoel Fernandes Neto#5644) ou Linkedin.

Autor: Manoel Fernandes Neto.

[adrotate banner=”5″]

O post Como criar CRUD Básico com NestJS, GraphQL e MySQL apareceu primeiro em Luby Software.

]]>
Testes Automatizados com AdonisJS e Japa https://luby.com.br/desenvolvimento/software/programacao/testes-automatizados-com-adonisjs-e-japa/ Thu, 21 Jul 2022 20:32:59 +0000 https://luby.com.br/?p=10248 Quando o assunto é frameworks para NodeJS, não é novidade que o AdonisJS é uma opção bem completa – especialmente para aplicações monolíticas. Afinal, ele oferece de forma nativa várias ferramentas que facilitam o processo de desenvolvimento, além de possuir uma documentação clara, objetiva e intuitiva. Em abril de 2022, houve uma release que deixou […]

O post Testes Automatizados com AdonisJS e Japa apareceu primeiro em Luby Software.

]]>
Quando o assunto é frameworks para NodeJS, não é novidade que o AdonisJS é uma opção bem completa – especialmente para aplicações monolíticas. Afinal, ele oferece de forma nativa várias ferramentas que facilitam o processo de desenvolvimento, além de possuir uma documentação clara, objetiva e intuitiva.

Em abril de 2022, houve uma release que deixou esse framework ainda mais incrível – principalmente se você curte desenvolver ‘à la’ TDD (Desenvolvimento Orientado a Testes):

Testes Automatizados com AdonisJS e Japa Luby Software
Testes Automatizados com AdonisJS e Japa 11

Agora o AdonisJS possui suporte para testes automatizados!

Antes desta release, o AdonisJS já suportava integração com testes automatizados, mas o desenvolvedor precisava realizar instalações e configurações à parte. Havia até um artigo na seção Cookbooks da documentação explicando quais dependências instalar e como configurar tudo para executar os testes.

Mas agora isso é passado, porque desde abril de 2022, toda aplicação inicializada traz arquivos com configurações padrão para testes, e a documentação possui uma seção dedicada aos testes automatizados.

[adrotate banner=”4″]

Conforme consta na descrição da release mostrada na imagem acima, o framework utilizado para executar os testes é o Japa. Então, vamos falar um pouco sobre ele destacando algumas features e explicar como o AdonisJS o utiliza.

AdonisJS + Japa

O Japa é um framework para testes que se descreve como sendo API-first e Node-only. Ou seja, ele é focado em testes para desenvolvimento de API`s no ambiente backend NodeJS. Esse framework tem a vantagem de ser extensível – o desenvolvedor pode instalar alguns plugins de acordo com as necessidades do projeto e até mesmo estender classes pré-existentes para atender às necessidades do projeto.

O Japa pode ser utilizado em qualquer projeto com NodeJS. Para isso, basta seguir as orientações de instalação e configuração da documentação (que também é de qualidade). Porém, ao criar um projeto AdonisJS, o desenvolvedor observará os seguintes arquivos-padrão:

tests/bootstrap.ts

Este arquivo armazenado dentro do diretório tests contém uma série de configurações que irão reger o processo de escrita e execução dos testes. Por exemplo, aqui cada desenvolvedor deve escolher quais plugins (suportados pelo Japa) serão utilizados durante os testes.

assert()

O Japa proporciona a liberdade de escolher plugins para escrever os testes utilizando a sintaxe de acordo com a preferência do desenvolvedor. Para aqueles que preferem usar a sintaxe do Chai (Assert), o Adonis adiciona o plugin assert() por padrão ao array plugins. Entretanto, se alguém optar pela sintaxe Jest, basta trocar o plugin por expect().

runFailedTests()

Outro plugin que vem definido por padrão é o runFailedTests(). Qual a sua função? Imagine que você escreveu 10 testes até o momento e os executou pela primeira vez.

Nessa primeira execução, dois testes falharam. Então, você faz alguns ajustes no código de produção e executa os testes pela segunda vez. Se runFailedTests() estiver no array de plugins, o Japa irá executar apenas os dois testes que falharam anteriormente. Caso desejar sempre executar todos os testes, basta remover o plugin do array.

apiClient()

Para testar os endpoints de uma API, o Japa oferece o plugin apiClient() – uma API completa, com inúmeras funções para simular requisições HTTP. É possível simular rotas protegidas por autenticação, rotas que esperam receber dados de um formulário, upload de arquivos, dados em JSON e muito mais. Vale a pena se familiarizar com esse plugin!

specReporter()

Também dentro do arquivo bootstrap.ts, mas desta vez dentro do array reporters, há um plugin do Japa chamado specReporter() registrado por padrão. Ele é responsável por apresentar, no terminal, informações detalhadas sobre o progresso e os resultados dos testes.

Esse plugin deve ser mantido! Se ele for retirado, não haverá nenhum erro de execução. Porém, também existirá nenhuma informação relacionada aos testes será exibida no terminal – a não ser uma mensagem padrão proveniente do Logger do AdonisJS.

Testes Automatizados com AdonisJS e Japa Luby Software
Testes Automatizados com AdonisJS e Japa 12

runnerHooks

Logo abaixo das configurações de reporters, existe um objeto chamado runnerHooks, que possui duas propriedades: a primeira é um array – setup, e a segunda também é um array – teardown.

Toda função adicionada ao array setup será executada antes de todos os testes iniciarem. Aqui pode ser interessante registrar a execução de migrations e seeders para o banco de dados ou a inicialização de um servidor HTTP, por exemplo. Já as funções contidas no array teardown serão chamadas somente após todos os testes executarem.

Aqui, podem ser registradas funções que limpam alterações sofridas pelo banco de dados durante os testes, por exemplo.

configureSuite

Por último, existe uma função chamada configureSuite – o local onde a documentação sugere o registro hooks para conjuntos (suites) específicos de testes. No exemplo abaixo, o servidor HTTP é iniciado apenas antes de o conjunto de testes funcionais ser executado.

Testes Automatizados com AdonisJS e Japa Luby Software
Testes Automatizados com AdonisJS e Japa 13

test.ts

Algo interessante de se notar é que todos os elementos (arrays, objetos e função) de configurações definidos no arquivo bootstrap.ts são exportados. Isso porque todos eles são importados pelo arquivo test.ts, que está no diretório raiz do projeto.

Testes Automatizados com AdonisJS e Japa Luby Software
Testes Automatizados com AdonisJS e Japa 14

Este arquivo carrega todas as configurações necessárias para iniciar a aplicação AdonisJS e executar os testes por meio do Japa, aplicando tudo o que definido no arquivo bootstrap.ts.

A própria documentação declara que raramente é necessário alterar esse arquivo. Dessa forma, tudo está pronto! Basta executar o comando $ node ace test para os testes iniciarem e o seguinte resultado aparecerá no terminal:

Testes Automatizados com AdonisJS e Japa Luby Software
Testes Automatizados com AdonisJS e Japa 15

.adonisrc.json

Este arquivo é responsável por diversas configurações do AdonisJS, mas será dado destaque apenas à parte que rege os testes automatizados. Nessa parte do arquivo é possível separar os testes da aplicação em grupos chamados suites, o que é útil para deixar o projeto bem organizado. Dentro do array suites, o desenvolvedor pode inserir objetos com as propriedades:

  • name (identificação do conjunto de testes);
  • files (array com paths relativos para executar arquivos específicos);
  • e o timeout (tempo máximo permitido para executar os testes).
Testes Automatizados com AdonisJS e Japa Luby Software
Testes Automatizados com AdonisJS e Japa 16

É claro que começar a escrever os testes a partir de uma aplicação recém criada é relativamente fácil. Mas o que dizer sobre os projetos AdonisJS iniciados antes do release em abril de 2022? E se adicionar testes automatizados a um desses projetos mais antigos, nos quais não havia arquivos para configuração de testes por padrão?

Adicionando testes a projetos antigos

Como mencionado no início do artigo, o AdonisJS possui uma documentação bem abrangente. Por isso, não é de se surpreender que um passo a passo para integrar testes automatizados a projetos anteriores ao release de abril de 2022 esteja disponível neste link.

Esse breve tutorial oficial orienta o desenvolvedor a seguir os seguintes passos:

1. Atualizar dependências do projeto que sejam relacionadas ao AdonisJS:

Todo pacote registrado no arquivo package.json que contenha @adonisjs em seu nome (ex:@adonisjs/lucid) precisa ser atualizado. Atualizar todas as dependências de um projeto de uma só vez pode ser perigoso, gerando problemas no funcionamento da aplicação.

Por isso, pode ser interessante usar o gerenciador de pacotes Yarn, que oferece a solução de atualizar dependências de forma interativa por meio do comando $ yarn upgradeinteractive --latest. Assim, é possível atualizar apenas o necessário, sempre tomando cuidado com pacotes que contenham breaking changes, marcadas em vermelho:

Testes Automatizados com AdonisJS e Japa Luby Software
Testes Automatizados com AdonisJS e Japa 17

2. Executar o comando node ace generate:manifest:

Este comando atualizará o arquivo ace-manifest.json, adicionando os comandos mais recentes da CLI utilizada pelo AdonisJS ao projeto.

3. Executar o comando node ace configure tests:

Neste passo, todos os arquivos de configuração necessários para executar os testes serão criados (os mesmos mencionados anteriormente), além de um teste-modelo pronto para ser executado.

Testes Automatizados com AdonisJS e Japa Luby Software
Testes Automatizados com AdonisJS e Japa 18

4. Mudar nomenclatura do ambiente de teste testing para test:

Por último, é necessário mudar o nome dado pelo AdonisJS ao ambiente de testes. Geralmente, apenas no arquivo env.ts é necessário aplicar essa mudança ao enum da propriedade NODE_ENV.

Porém, alguns projetos possuem o arquivo config/shield.ts, no qual o ambiente de testes também está nomeado como testing, exigindo a mudança para test.

Com isso, tudo está pronto para começar a escrever os testes e executá-los!

Conclusão

De fato, AdonisJS e Japa formam uma dupla poderosa que pode turbinar o processo de desenvolvimento orientado a testes automatizados. Ambos possuem documentações completas e assertivas.

O Japa proporciona liberdade para escolher a sintaxe dos testes e disponibiliza plugins poderosos, enquanto o AdonisJS carrega diversas funcionalidades nativas para validação, autenticação, ORM e muitas outras.

Conheça um pouco mais do universo de desenvolvimento com o AdonisJS com essa série de vídeos do Luber Manoel Fernandes Neto. E para aprender muito mais sobre tecnologia, fique ligado no blog da Luby!

Autor: João Victor Pereira Rodrigues.

[adrotate banner=”5″]

Veja também:

Poised Testing – Tudo sobre o assunto.

Testes automatizados com React.

Desenvolvimento de Software.

O post Testes Automatizados com AdonisJS e Japa apareceu primeiro em Luby Software.

]]>
Saiba como utilizar Theme Provider com styled-components https://luby.com.br/desenvolvimento/software/theme-provider-com-styled-components/ Wed, 20 Jul 2022 15:03:54 +0000 https://luby.com.br/?p=10032 Em um projeto de desenvolvimento de software, é comum seguir uma linha de padrões de estilo, tais como: cores, tamanhos, fontes, etc. Com o Styled-components, uma boa forma de organizar essas constantes é criando um arquivo de tema. Englobando todos os componentes filhos com o theme provider, você conseguirá acessar esses estilos em qualquer componente […]

O post Saiba como utilizar Theme Provider com styled-components apareceu primeiro em Luby Software.

]]>
Em um projeto de desenvolvimento de software, é comum seguir uma linha de padrões de estilo, tais como: cores, tamanhos, fontes, etc. Com o Styled-components, uma boa forma de organizar essas constantes é criando um arquivo de tema. Englobando todos os componentes filhos com o theme provider, você conseguirá acessar esses estilos em qualquer componente de estilização

Assim, poderá criar padrões que facilitam a manutenção do código. Por exemplo, podemos mudar uma cor de todo o projeto em apenas um arquivo.

Neste artigo, você verá como é fácil e mais efetivo utilizar os temas globais do styled-components.

[adrotate banner=”4″]

Styled-components

­Styled-components é uma biblioteca para React e React Native, que permite a criação de componentes previamente estilizados. Isso não apenas com CSS, mas também é utilizado Javascript nele, para passar variáveis, propriedades e temas padrões.

Dessa forma, podemos passar esses temas através de um Theme Provider, que utiliza a context API para englobar toda a aplicação. Ou seja, ao criá-lo, todos os componentes filhos herdarão suas propriedades automaticamente.

Iniciando o projeto

Para iniciar, temos um projeto com React e styled-components. Para utilizá-lo, vamos precisar ter previamente instalado em nossa máquina o Node JS e o Git. Posteriormente, basta cloná-lo e executá-lo em sua máquina realizando os seguintes comandos em seu terminal e em um local da sua preferência:

Após clonar, devemos abrir o local do projeto com:

  • cd .\React-Styled-Components-Ts-Boilerplate\

Após abrir o local do projeto, devemos instalar as dependências do projeto com:

  • npm install

E executá-lo com:

  • npm start

Modificando os temas

Primeiramente, iremos modificar o arquivo de tema. Nele vamos declarar um objeto com as constantes que iremos utilizar no nosso projeto.

Por isso, vamos modificar o arquivo chamado “Theme.ts” e estruturar da melhor forma para atender o nosso projeto:

Saiba como utilizar Theme Provider com styled-components Luby Software
Saiba como utilizar Theme Provider com styled-components 19
const Theme = {
  color: {
    background: "#141827",
    primary: {
      main: "#fffae3",
      contrastText: "#c1d9d0",
    },
    secundary: {
      main: "#736681",
      contrastText: "#62455b",
    },
  },

  border: {
    radius: "15px",
    style: "2px solid #736681",
  },

  font: {
    small: "0.5rem",
    default: "1rem",
    big: "2rem",
    bigger: "3rem",
  },
};

export default Theme;

Modificando o arquivo de declaração

Para utilizar os temas, precisamos modificar a interface padrão do styled-components, fazendo ele reconhecer as propriedades que colocamos no nosso arquivo.

Assim, vamos modificar o arquivo chamado “styled.d.ts”.

Saiba como utilizar Theme Provider com styled-components Luby Software
Saiba como utilizar Theme Provider com styled-components 20
import 'styled-components';

import Theme from './Theme'

export type ITheme = typeof Theme

declare module 'styled-components' {
  export interface DefaultTheme extends ITheme {}
}

Aqui, importamos nosso tema criado anteriormente e estendemos sua interface ao tema padrão o DefaultTheme.

Theme Provider

Agora, para poder utilizá-lo em todos os componentes, iremos englobar toda a aplicação com o Theme Provider.

No arquivo “index.tsx”, iremos colocar o Theme Provider como componente pai do app:

import ReactDOM from "react-dom/client";
import App from "./App";

import { ThemeProvider } from "styled-components";
import Theme from "./styles/Theme";

const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement);
root.render(
  <ThemeProvider theme={Theme}>
    <App />
  </ThemeProvider>
);

É sua escolha onde deverá colocar. Entretanto, para um tema global, é recomendado que seja no arquivo “index.tsx” ou no “app.tsx” da raiz. Pois são neles que todos os componentes filhos herdarão suas propriedades.

Exemplos

Já está tudo preparado no nosso projeto. Então, podemos utilizar os temas na estilização de nossos componentes.

Criaremos três componentes “Button.ts”, “Container.ts”, “Title.ts”:

Saiba como utilizar Theme Provider com styled-components Luby Software
Saiba como utilizar Theme Provider com styled-components 21

Button.ts:

import styled from "styled-components";
export const ButtonWithTheme = styled.button`
  color: ${(props) => props.theme.color.secundary.main};
  background-color: ${(props) => props.theme.color.secundary.contrastText};

  border: ${(props) => props.theme.border.style};
  border-radius: ${(props) => props.theme.border.radius};

  font-size: ${(props) => props.theme.font.big};
`;

Container.ts:

import styled from "styled-components";

export const ContainerTheme = styled.div`
  padding: 15px;
  background-color: ${(props) => props.theme.color.background};
  border-radius: ${props=>props.theme.border.radius};
`;
export const Container = styled.div`
  display: flex;
  justify-content: space-evenly;
  align-items: center;
  height: 100vh;
`;

Title.ts:

import styled from "styled-components";
export const TitleTheme = styled.h1`
  color: ${(props) => props.theme.color.primary.main};
  font-size: ${(props) => props.theme.font.bigger};
  -webkit-text-stroke-width: 1px;
  -webkit-text-stroke-color:
${props => props.theme.color.primary.contrastText}; 
`;

Como podemos ver, os temas são passados pelas props padrões do styled-components. Isso porque nós estendemos nossa interface ao DefaultTheme. Assim, permitindo usar em todos componentes criados.

Nosso código no “App.tsx”:

import {  ButtonWithTheme } from "./components/Button";
import { Container, ContainerTheme } from "./components/Container";
import {  TitleTheme } from "./components/Title";

function App() {
  return (
    <>
    <Container>
      <ContainerTheme>
        <TitleTheme>Título com Tema :D</TitleTheme>
        <ButtonWithTheme>Botão com Tema :D</ButtonWithTheme>
      </ContainerTheme>
      <div>
        <h1>Título sem tema :(</h1>
        <button>Botão sem tema :(</button>
      </div>
    </Container>
    </>
  );
}

export default App;

Temos como resultado:

Saiba como utilizar Theme Provider com styled-components Luby Software
Saiba como utilizar Theme Provider com styled-components 22

Theme Provider com variáveis

Para finalizar, iremos criar uma variação do nosso tema. Então, faremos o tema claro apenas trocando a ordem de algumas cores.

Vamos criar um arquivo chamado “LightTheme.ts” e iremos fazer um novo objeto que contenha as mesmas propriedades do primeiro tema. Para isso, atribuímos o tipo DefaultTheme. Assim, ele dará erro se tiver alguma propriedade faltando:

Saiba como utilizar Theme Provider com styled-components Luby Software
Saiba como utilizar Theme Provider com styled-components 23
import { DefaultTheme } from "styled-components";

const LightTheme: DefaultTheme = {};

export default LightTheme;

Neste momento, teremos que colocar as mesmas propriedades e atribuir da forma que preferirmos. Aqui no nosso projeto, vamos apenas inverter a ordem das cores já estabelecidas:

import Theme from "./Theme";

const LightTheme: DefaultTheme = {
  color: {
    background: Theme.color.primary.contrastText,
    primary: {
      main: Theme.color.background,
      contrastText: Theme.color.primary.main,
    },
    secundary: {
      main: Theme.color.secundary.contrastText,
      contrastText: Theme.color.secundary.main,
    },
  },

  border: {
    radius: "15px",
    style: "2px solid " + Theme.color.secundary.contrastText,
  },

  font: Theme.font,
};

Dessa forma, nosso projeto está pronto para ser utilizado em qualquer componente de nossa aplicação. Para o exemplo, vamos adicionar no “App.tsx” um novo Theme Provider.

Agora, temos dois provider, um externo com o tema antigo e um interno com o novo tema claro:

//Mantenha as importações anteriores e adicione o seguinte
import { ThemeProvider } from "styled-components";
import LightTheme from "./styles/LightTheme";

function App() {
  return (
    <>
      <Container>

        <ThemeProvider theme={LightTheme}>
          <ContainerTheme>
            <TitleTheme>Título com Tema Claro :D</TitleTheme>
            <ButtonWithTheme>Botão com Tema Claro!! :D</ButtonWithTheme>
          </ContainerTheme>
        </ThemeProvider>

        <ContainerTheme>
          <TitleTheme>Título com Tema Escuro :D</TitleTheme>
          <ButtonWithTheme>Botão com Tema Escuro :D</ButtonWithTheme>
        </ContainerTheme>
      </Container>
    </>
  );
}

export default App;
Saiba como utilizar Theme Provider com styled-components Luby Software
Saiba como utilizar Theme Provider com styled-components 24

Também podemos fazer o uso da mudança de estado com useState, para deixar nosso tema dinâmico:

//Manter restante do código acima
import Theme from "./styles/Theme";
import { useState } from "react";

function App() {
  const [isDarkTheme, setIsDarkTheme] = useState(true);

  const handleButton = () => {
    setIsDarkTheme(!isDarkTheme);
  };

  return (
    <>
      <ThemeProvider theme={isDarkTheme ? Theme : LightTheme}>
        <Container>
          <ContainerTheme>
            <TitleTheme>Título com Tema Variável</TitleTheme>
            <ButtonWithTheme onClick={handleButton}>
              Click Para mudar o tema
            </ButtonWithTheme>
          </ContainerTheme>
        </Container>
      </ThemeProvider>
    </>
  );
}
//Manter restante do código abaixo
Saiba como utilizar Theme Provider com styled-components Luby Software
Saiba como utilizar Theme Provider com styled-components 25

Leia também:
Saiba como fazer validação de formulário

Autor: Alexandre Roberto Lima da Silva.

[adrotate banner=”5″]

O post Saiba como utilizar Theme Provider com styled-components apareceu primeiro em Luby Software.

]]>
Como aplicar Imutabilidade evitando bugs? https://luby.com.br/desenvolvimento/software/imutabilidade/ Tue, 19 Jul 2022 16:08:42 +0000 https://luby.com.br/?p=9991 Basicamente, a imutabilidade é uma estrutura ou algo que não pode ser alterado. Na programação, esse conceito é aplicado a objetos e variáveis, principalmente em programação orientada a objetos, durante a criação ou quando um objeto está sendo instanciado. Pelo fato de não poder ser alterado, automaticamente pensamos em utilizar constantes (const). Porém, não é […]

O post Como aplicar Imutabilidade evitando bugs? apareceu primeiro em Luby Software.

]]>
Basicamente, a imutabilidade é uma estrutura ou algo que não pode ser alterado. Na programação, esse conceito é aplicado a objetos e variáveis, principalmente em programação orientada a objetos, durante a criação ou quando um objeto está sendo instanciado.

Pelo fato de não poder ser alterado, automaticamente pensamos em utilizar constantes (const). Porém, não é bem assim! Uma variável declarada com constante não significa que o valor é imutável, mas apenas que a variável não pode ser alterada. Para entendermos mais, vamos nos aprofundar sobre os tipos de variáveis que existem no JavaScript e como se comportam em relação a imutabilidade.

[adrotate banner=”4″]

Tipos em JavaScript

Em Javascript, temos os tipos primitivos como:

  • Boolean;
  • Number;
  • BigInt;
  • String;
  • Null;
  • Undefined;
  • Symbol.

Tipos primitivos

Os tipos primitivos são dados que não são representados através de um objeto. Além disso, todos os primitivos são imutáveis. Mas, se não são representados por um objeto, como conseguimos acessar algumas propriedades como: “.length” e “.toString”?

Isso é possível porque os tipos primitivos, com exceção do null e undefined, possuem um objeto wrappers que permite acessar algumas propriedades.

Quando chamamos os métodos como “.length” e .”tostring” nos tipos primitivos como number e string, por baixo dos panos, o JavaScript cria um objeto temporário por volta da variável, instância, método específico e em seguida a instância é excluída. Com isso, conseguimos utilizar métodos em variáveis do tipo primitivo.

No JavaScript podemos comparar variáveis através do operador de igualdade (‘==’) ou com o operador de identidade ‘===’ . A diferença é que o operador de igualdade irá converter as variáveis para o mesmo tipo antes de comparar os valores. Já o operador de identidade irá verificar se as variáveis são do mesmo tipo
e valor sem realizar conversões.

Comparação

Quando tentamos comparar tipos primitivos, o JavaScript compara o tipo e o valor, como no exemplo a seguir:

Como aplicar Imutabilidade evitando bugs? Luby Software
Como aplicar Imutabilidade evitando bugs? 26

Sabendo que cada variável ocupa uma posição única de memória, ao compararmos os valores das variáveis a e b, como no exemplo/imagem a seguir, percebemos que o JavaScript considera como verdadeiro (true) o resultado da comparação entre as duas variáveis.

Como aplicar Imutabilidade evitando bugs? Luby Software
Como aplicar Imutabilidade evitando bugs? 27

Além dos tipos primitivos, temos os tipos Objeto e Array. Se utilizarmos os operadores de igualdade e identidade para objetos e arrays, obteremos falso (false) na saída em todas as comparações. Isso porque o JavaScript irá comparar a referência na memória que cada objeto ou array ocupa, e não o tipo e o valor.

Como aplicar Imutabilidade evitando bugs? Luby Software
Como aplicar Imutabilidade evitando bugs? 28

Para ilustrar a relação de igualdade entre os tipos Objeto e Array, considere as variáveis x (do tipo objeto), y (do tipo objeto) e z (uma cópia de x), como mostra a imagem logo abaixo.

Apesar das variáveis x e y serem do mesmo tipo, ao utilizarmos o operador de identidade, temos “false” como resultado. Pois fazem referência a diferentes posições de memória:

  • x aponta para o endereço 0x01;
  • e y para o endereço 0x02.

Entretanto, ao compararmos z e x, teremos um resultado verdadeiro (true), porque z e x apontam para a mesma referência na memória.

Como aplicar Imutabilidade evitando bugs? Luby Software
Como aplicar Imutabilidade evitando bugs? 29

Aplicando imutabilidade e evitando bugs

Durante o processo de desenvolvimento, é comum a necessidade de manipular variáveis do tipo objeto e array. Algo como copiar alguns desses tipos de variáveis aparenta ser uma tarefa simples. Porém, quando não é aplicado o conceito de imutabilidade (no qual uma variável não pode ser alterada diretamente), isso pode causar alguns bugs em nossa aplicação.

Podemos iniciar uso da imutabilidade utilizando const para declarar nossa variáveis. Então, vamos ver isso na prática!

Imaginemos que possuímos uma variável “pessoa”, que é um objeto e possui as seguintes propriedades:

Como aplicar Imutabilidade evitando bugs? Luby Software
Como aplicar Imutabilidade evitando bugs? 30

Agora, queremos copiar esse objeto para uma segunda variável chamada pessoa2 e alterar a profissão para UI/UX e executar um console log para analisarmos nossa saídas.

Como aplicar Imutabilidade evitando bugs? Luby Software
Como aplicar Imutabilidade evitando bugs? 31

Como podemos observar na imagem, o objeto realmente foi copiado. Porém, ao alterar a propriedade “profissao” da pessoa2, a profissão da pessoa também foi alterada.

Isso aconteceu porque, ao criar o objeto pessoa, alocamos um espaço na memória e, como objetos e array trabalham com referência de memória, ao copiar o objeto, estamos na verdade copiando o seu endereço de memória e não o seu conteúdo.

Como aplicar Imutabilidade evitando bugs? Luby Software
Como aplicar Imutabilidade evitando bugs? 32

Como podemos resolver isso?

Para copiar objetos e arrays, podemos utilizar o spread operator, representado por três pontinhos (…). Essa funcionalidade foi adicionada ao JavaScript no EcmaScript 2015. Assim, o spread tira uma cópia rasa (Shallow copy) do objeto ou array, criando um novo objeto ou array e gerando uma nova referência na memória.

Vamos ver como fica:

Como aplicar Imutabilidade evitando bugs? Luby Software
Como aplicar Imutabilidade evitando bugs? 33

Para copiarmos o objeto e alterar alguma de suas propriedades, podemos fazer isso de diversas maneiras. Duas delas são:

Como aplicar Imutabilidade evitando bugs? Luby Software
Como aplicar Imutabilidade evitando bugs? 34

Agora, quando queremos copiar objetos ou array alinhados como objetos dentro de objetos, precisamos fazer uma cópia profunda (deep copy) desse objeto.

Imaginemos que possuímos um objeto pessoa que tem um array de idiomas e queremos copiar esse objeto. Assim, faríamos da seguinte forma:

Como aplicar Imutabilidade evitando bugs? Luby Software
Como aplicar Imutabilidade evitando bugs? 35

Dessa forma, conseguimos copiar o objeto de forma correta e garantir que, ao alterar o segundo objeto, iremos manter a imutabilidade do primeiro objeto que foi copiado e evitaremos bugs em nossa aplicação.

Sempre que for preciso alterar um objeto ou array, precisamos criar um novo com os valores atualizados e substituir o anterior.

Veja também:

O que é Injeção e Inversão de dependências?

Autor: Anderson Pablo.

[adrotate banner=”5″]

O post Como aplicar Imutabilidade evitando bugs? apareceu primeiro em Luby Software.

]]>
POISED Testing: o que é e como utilizar? https://luby.com.br/desenvolvimento/software/poised-testing/ Thu, 14 Jul 2022 14:40:08 +0000 https://luby.com.br/?p=9712 Já ouviu falar sobre modelos heurísticos? Resumidamente, são métodos que nos ajudam a entender e lembrar de algo rapidamente, como atalhos mentais. Por isso, no caso do tema que vamos falar hoje: POISED Testing, esses modelos irão ajudar muito! O método heurístico de representatividade é utilizado como base para criar e pensar nossos testes de […]

O post POISED Testing: o que é e como utilizar? apareceu primeiro em Luby Software.

]]>
Já ouviu falar sobre modelos heurísticos? Resumidamente, são métodos que nos ajudam a entender e lembrar de algo rapidamente, como atalhos mentais. Por isso, no caso do tema que vamos falar hoje: POISED Testing, esses modelos irão ajudar muito!

O método heurístico de representatividade é utilizado como base para criar e pensar nossos testes de API.

[adrotate banner=”4″]
O que é POISED?

Primeiramente, vamos dar uma olhada no que isso significa e como pode nos ajudar de fato! O significado das siglas de POISED Testing é:

  • P – Parameters (Parâmetros);
  • O – Outputs (Saídas);
  • I – Interoperability (Interoperabilidade);
  • S – Security (Segurança);
  • E – Errors (Erros);
  • D – Data (Dados).

O que cada uma dessas etapas significa?

Bom, visto que agora sabemos o que cada uma das letras de POISED Testing representa, vamos entender melhor a função de cada uma.

Parameters (Parâmetros)

Esta é a etapa em que você cria seus testes baseados nos parâmetros que a API a ser testada pode enviar. Isso pode funcionar tanto nos headers, parâmetros de URL e parâmetros no envio de dados, como o body de uma request com método POST.

Por exemplo:  

  • Uma URL aceita ser enviado um header com um tipo de “content-type” x ,y,z e você envia um tipo não aceito;
  • Uma URL precisa de um header específico para saber para qual parte da aplicação enviar e você não passa nesse header obrigatório;
  • Um body de um request POST, para fazer um login num portal, precisa de campos obrigatórios e tipados por exemplo:
   		 {
	“email”: “” ,
	"password": 12345678
 }

Aqui você deveria ter passado um e-mail válido e passou uma string vazia. Além disso, na senha, deveria ter sido uma string e você passou um numérico qualquer.

Podemos ficar horas vendo tipos de parâmetros. Entretanto, com esses básicos já dá para entender e ir mais além do que seria o P desse modelo!

Outputs (Saídas)

Essa etapa será onde você criará seus testes baseados nas respostas das requests, validará se são coerentes, se estão corretas de acordo com o tipo de request e o status code recebido (response body x status code), logs feitos no console ou no servidor.

Por exemplo:

  • Você envia uma requisição do método DELETE e recebeu status code 200 ou 204, mas no corpo da resposta recebeu “criado”;
  • Você envia uma requisição do método POST e recebe um status code 200 e com o corpo da resposta vazio;
  • Validar se os logs apresentados no console ou servidor são coerentes ou se possui o mínimo de informação relacionada.

Em tese, o Output é onde você cria seus testes para validar a coerência das respostas X o que foi requisitado.

Interoperability (Interoperabilidade)

Aqui é uma etapa muito importante, em que você cria testes para validar e checar a Interoperabilidade da comunicação das APIs, onde você cria testes de contrato, checa a idempotência da API, entre outros.

Além disso, nesta etapa, também pode ser pensado e criado testes de performance para entender qual a performance da sua API, quando muito exigida ou chamada por outros serviços ou outras APIs.

Por exemplo:

  • Criar teste de contrato para, sempre que uma API precise, chamar os requisitos básicos e predefinidos como corretos, sendo atendidos e validados em seu comportamento. Por exemplo, o que uma API espera de parâmetros no body? Quais os tipos desses parâmetros? Quais as saídas? É importante não confundir com o teste de schema, onde é validado somente os tipos do schema.
  • Validar a idempotência da API. Verificar se, mesmo ela sendo chamada n* x vezes por outra API ou outras, aquele comportamento esperado continua sendo o mesmo sempre.
  • Criar testes de performance para latência e/ou saber o tempo de resposta de cada request depois de ter sido carregada com muitas requests.

Security (Segurança)

Uma das partes mais importantes do nosso modelo é criar testes e pensar estratégias de teste para cobrir possíveis cenários ou gaps de segurança na API. Por exemplo:

  • Validar que, somente com informações corretas, você consegue chamar com sucesso os endpoints que precisam de autorização e autenticação, como tokens, cookies ou até mesmo senhas;
  • Autenticar tempo de expiração das credenciais;
  • Validar se é possível, por exemplo, ao invés de mandar a autenticação correta, você consegue mandar algum script de JavaScript no campo;
  • Confirmar possíveis mensagens de respostas que contenham mais informação que o necessário ou logs que contenham informações internas, como logar o erro do banco de dados diretamente.

Errors (Erros)

Nesta etapa, podemos pensar sobre como validar as mensagens de erro (já vimos um pouco sobre isso nos tópicos Outputs e Security). Por exemplo:

  • Pensar se estão de acordo com o contexto, requisição, ambiente e etc.;
  • Verificar as mensagens de erro X o status code da resposta;
  • Verificar se nos passam o real problema que aconteceu (pensando sempre na segurança, como dito acima).

Data (Dados)

Nesta fase, pensamos como validar os dados. Por exemplo:

  • Validar as estruturas dos dados das requests, no body ou parâmetros;
  • Validar os dados quando executamos alguma requisição que altere dados. Por exemplo, quando fazemos um delete, update ou created. Os dados foram corretamente atualizados ou deletados? Após as alterações, a estrutura continua a mesma? E por aí vai…

Pensando nisso, é importante lembrar:

  • Precisamos sempre ter contato e conhecimento do código base para poder criar os testes com mais precisão e sempre com base na documentação;
  • Além disso, é preciso checar também os testes unitários, para não cairmos no problema testes duplicados em camadas diferentes.

Conclusão

Passamos por um overview sobre o POISED Testing, para nos dar ideias e nos guiar quando pensarmos sobre criação de testes de API. Como falamos acima, este é um modelo heurístico que usamos para apoio.

Existem alguns outros modelos interessantes, segue aqui uma lista para você checar, se tiver interesse!

  • VADER
  • BINMEN

Autor: Francisco Antônio Navarro Moral.

[adrotate banner=”5″]

Leia também:

Bot Para testes: Como executar.

Testes automatizados com adonis JS.

O post POISED Testing: o que é e como utilizar? apareceu primeiro em Luby Software.

]]>
Criação de uma API Mocking com MirageJS https://luby.com.br/desenvolvimento/software/programacao/api/mocking-com-miragejs/ Wed, 13 Jul 2022 15:38:33 +0000 https://luby.com.br/?p=9691 Neste artigo, iremos abordar um recurso que todo Dev Front-end gostaria de ter disponível desde o começo do desenvolvimento de uma aplicação Front- end: uma API Mocking para fazer a integração dos dados. [adrotate banner=”4″] Como todo início do desenvolvimento de uma aplicação web completa (back-end e frontend) nem sempre alguma destas partes estará disponível […]

O post Criação de uma API Mocking com MirageJS apareceu primeiro em Luby Software.

]]>
Neste artigo, iremos abordar um recurso que todo Dev Front-end gostaria de ter disponível desde o começo do desenvolvimento de uma aplicação Front- end: uma API Mocking para fazer a integração dos dados.

[adrotate banner=”4″]

Como todo início do desenvolvimento de uma aplicação web completa (back-end e frontend) nem sempre alguma destas partes estará disponível com antecedência para fazer a integração. Assim, é bastante comum em alguns projetos começarem o desenvolvimento pelo front-end (principalmente em casos onde você estará trabalhando sozinho no projeto), ou os dois ao mesmo tempo.

Dessa forma, como produtividade é muito importante, a equipe de front-end não quer ficar parada. Assim, pode seguir com a implementação com dados estáticos através de arquivos JSON ou armazenado em uma variável até que o back-end comece a fornecer uma API com dados reais que o front-end precise.

 

Vantagens e Desvantagens da API Mocking

A desvantagem de usar dados estáticos é que pode dificultar um pouco em apresentar cenários de dados. Por exemplo: em um momento podemos ter uma lista de usuários vazia, com 10, com 100, com 1000 e assim por diante e ficar alterando esses valores estaticamente não traz um dinamismo esperado.

A vantagem de utilizar uma API Mocking é que conseguiremos apresentar cenários de forma muito fácil, preparar o formato dos objetos (JSON) com as propriedades esperadas pelo front-end. Assim, o back-end pode reaproveitar e utilizar na criação da API, trazendo agilidade no desenvolvimento. Isso porque ele já saberá como front-end espera que os dados sejam enviados, testar solicitações HTTP (GET, POST, DELETE, PUT e PATCH) e apresentar mensagens de sucesso ou erros destas solicitações.

O que é o MirageJS?

Segundo a própria definição da documentação: “O Mirage JS é uma biblioteca de simulação de API que permite criar, testar e compartilhar um aplicativo JavaScript completo e funcional sem precisar depender de nenhum serviço de back-end”.

Ou seja, o MirageJS é uma lib que cria um servidor local dentro do projeto front-end que irá interceptar as requisições que saem da aplicação front-end e responde com o conteúdo que foi configurado.

Vantagens de utilizar o MirageJS

  • Servidor local dentro do próprio projeto. Isso significa que, assim que o servidor de desenvolvimento da aplicação front-end subir, o MirageJS (e o servidor local) irá executar junto;
  • Hot Reload: alterações ou adições de novos recursos. Ao salvar, o servidor automaticamente será atualizado e as mudanças serão refletidas na aplicação rodando no navegador;
  • Debugar é muito fácil. Como o MirageJS é totalmente construído com Javascript, podemos utilizar a instrução debugger e analisar o ponto especificado pelo o dev-tools do navegador;
  • Um mesmo servidor tanto para ambiente de desenvolvimento quanto para ambiente de testes;
  • Rotas para lidar com solicitações HTTP;
  • Um banco de dados e modelos para armazenar dados e definir relacionamentos;
  • ORM embutido;
  • Utilização de factories e seeds.

Iniciando um projeto React e configurando o servidor do MirageJS

Sem mais delongas, primeiro vamos implementar uma aplicação simples para registrar e remover usuários, e também enviar requisições HTTP para o servidor local do MirageJS.

Então, primeiro vamos iniciar um projeto React com ViteJS (https://vitejs.dev/guide/#scaffolding-your-first-vite-project). Você pode fazer isso rodando algum dos comandos abaixo:

npm create vite@latest miragejs-demo
// or
yarn create vite miragejs-demo

Para facilitar o entendimento do código, iremos utilizar o React sem Typescript. Entretanto, se você estiver confortável com o TS, fique a vontade para utilizar e fazer as devidas tipagens.

No App.jsx, vamos montar uma estrutura básica com um formulário simples para registrarmos o nome do usuário e listagem.

import { useState } from "react";
function App() {
const [users, setUsers] = useState([]);
return (
<div>
<form>
<p>
<label htmlFor="user-register">Name: </label>
<input
type="text"
id="user-register"
placeholder="Enter username"
name="userName"
/>
</p>
<button type="submit">Register</button>
</form>
<h1>Users:</h1>
<ul>
{(!!users || users.length > 0) &&
users.map((user, index) => <li key={index}>{user.name}</li>)}
</ul>
</div>
);
}
export default App;
Criação de uma API Mocking com MirageJS Luby Software
Criação de uma API Mocking com MirageJS 36

Como podemos notar, nossa aplicação inicia com dados de usuários vazio no estado. Dessa forma, para termos algo apresentado em tela inicialmente, iremos criar o servidor do MirageJS e definir a primeira rota GET, que vai retornar alguns usuários para o front-end.

Antes de mais nada, precisamos instalar o MirageJS em nossa aplicação:

# Using Yarn
yarn add -D miragejs
# Using npm
npm install --save-dev miragejs

No main.jsx, vamos criar o servidor com uma rota do tipo GET /users. Então, quando o nosso front-end fizer uma solicitação GET para /api/users, o Mirage responderá com esses dados:

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { createServer } from "miragejs";
import "./index.css";
// Servidor local do MirageJS
createServer({
routes() {
this.namespace = "api";
this.get("/users", () => {
return {
users: [
{ id: 1, name: "John Doe" },
{ id: 2, name: "Jane Doe" },
{ id: 3, name: "Gabe" },
],
};
});
},
});
ReactDOM.createRoot(document.getElementById("root")).render(
<React.StrictMode>
<App />
</React.StrictMode>
);

Ótimo! Agora, o próximo passo é fazer o front-end enviar uma solicitação para buscar os dados dos usuários:

function App() {
const [isLoading, setIsLoading] = useState(true)
const [users, setUsers] = useState([])
useEffect(() => {
async function fetchUsers () {
const res = await fetch('http://localhost:3000/api/users')
const data = await res.json()
setUsers(data.users)
setIsLoading(false)
}
fetchUsers()
}, [])
if (isLoading) {
return <p>Loading...</p>
}
return (
//... restante do código aqui.
)

E voilà! Assim, nosso front-end agora inicia com informações vindas de uma API funcional.

Criação de uma API Mocking com MirageJS Luby Software
Criação de uma API Mocking com MirageJS 37

Ao abrir o console do dev-tools do seu navegador, você conseguirá analisar o request e response interceptado pelo o MirageJS:

Criação de uma API Mocking com MirageJS Luby Software
Criação de uma API Mocking com MirageJS 38

Criando models, seeds e rotas para registrar e deletar usuários

Bom, até aqui nossa aplicação já possui uma configuração inicial de uma API Mocking. Apesar de termos um servidor devolvendo informações, o cenário atual ainda é de dados estáticos, já que preenchemos objetos de forma fixa (hardcode) no retorno da rota /api/users e o nosso desejo é de ter algo dinâmico.

Dessa forma, vamos fazer uso da camada de dados do Mirage que vai nos ajudar a escrever uma implementação de servidor mais poderosa.

Primeiro, vamos criar uma model para os users:

createServer({
models: {
user: Model
},
//... restante do código aqui.
)}

Agora, vamos refatorar nossa rota /users para torna-la dinâmica e fazer uso do banco de dados em memoria do Mirage:

// ...restante do código aqui
routes() {
this.namespace = "api";
this.get("/users", (schema, request) => {
return schema.users.all();
}
});

É através do schema que a rota acessará a model user e responderá com todas as informações do banco de dados do Mirage, no momento da solicitação. Assim, se voltamos ao nosso app rodando no navegador, teremos aquele cenário com o estado inicialmente vazio.

Sem problemas! Com seeds, podemos iniciar nosso banco de dados com alguns dados iniciais:

createServer({
//... restante do código aqui
seeds(server) {
server.create("user", { name: "John Doe" });
server.create("user", { name: "Jane Doe" });
server.create("user", { name: "Gabe" });
},
});

Maravilha! Voltamos ao cenário onde temos uma listagem de usuários sendo apresentada em tela. Agora chegou o momento de registrarmos usuários!

Para começar, vamos definir nossa rota do tipo POST para criar/registrar um usuário no banco de dados do Mirage:

createServer({
//... restante do código aqui
routes() {
//... restante do código aqui
this.post("/users", (schema, request) => {
const user = JSON.parse(request.requestBody);
return schema.users.create(user);
});
},
//... restante do código aqui
});

Então, o próximo passo é enviar os dados do usuário do front-end para o servidor:

function App() {
//... restante do código aqui
async function handleSubmit(e) {
e.preventDefault();
setIsLoading(true);
const {
userName: { value: userName },
} = e.currentTarget;
const res = await fetch("https://localhost:3000/api/users", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
name: userName,
}),
});
const data = await res.json();
const registeredUser = data.user;
setUsers((state) => state.concat(registeredUser));
setIsLoading(false);
}
//... restante do código aqui
return (
<div>
<form onSubmit={handleSubmit}>{/* ... restante do código aqui */}</form>
</div>
);
}

Por isso, o que faremos a seguir é definir a rota para deletar usuários pelo o id enviado via params.

createServer({
//... restante do código aqui
routes() {
//... restante do código aqui
this.delete("/users/:id", (schema, request) => {
const id = request.params.id;
return schema.users.find(id).destroy();
});
},
//... restante do código aqui
});

Agora no App.jsx vamos definir uma função que irá enviar a solicitação para deletar o usuário com base no id:

async function handleDeleteUserById(id) {
setIsLoading(true);
const res = await fetch(`/api/users/${id}`, { method: "DELETE" });
if (res.ok) {
setUsers((state) => state.filter((item) => item.id !== id));
}
setIsLoading(false);
}

Ainda no App.jsx, vamos adicionar um button no JSX que irá disparar/executar a função handleDeleteUserById:

//... restante do código aqui.
<ul>
{(!!users || users.length > 0) &&
users.map((user) => (
<li key={user.id}>
{user.name}
<button onClick={() => handleDeleteUserById(user.id)}>Delete</button>
</li>
))}
</ul>

Agora temos uma configuração no servidor onde ele inicia com alguns dados e fará inserções e remoções de registros de forma dinâmica.

Conclusão

Essa foi uma breve e básica introdução sobre o MirageJS, mostrando seus recursos na prática com uma simples aplicação em React.

A ferramenta é muito mais do que foi mostrado aqui. O Mirage consegue criar uma API REST completa, uma camada de dados poderosa que facilita a manipulação dos dados no banco, seeds, factories, relacionamentos, ORM, testes, entre outros recursos.

Sugiro que visitem a documentação para aprenderem mais sobre a ferramenta, que será muito útil para o desenvolvimento de suas aplicações, principalmente para os devs front-end.

Autor: Gabriel Pinheiro da Silva.

[adrotate banner=”5″]

O post Criação de uma API Mocking com MirageJS apareceu primeiro em Luby Software.

]]>