<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Neilton Seguins</title>
    <description>The latest articles on Forem by Neilton Seguins (@neiltonseguins).</description>
    <link>https://forem.com/neiltonseguins</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1036366%2F9a9bac13-68da-4980-8a37-f76c0bdd7935.JPG</url>
      <title>Forem: Neilton Seguins</title>
      <link>https://forem.com/neiltonseguins</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/neiltonseguins"/>
    <language>en</language>
    <item>
      <title>Criando um Chatbot com JavaScript e Gemini AI: criando o backend</title>
      <dc:creator>Neilton Seguins</dc:creator>
      <pubDate>Mon, 23 Dec 2024 18:05:41 +0000</pubDate>
      <link>https://forem.com/neiltonseguins/criando-um-chatbot-com-javascript-e-gemini-ai-criando-o-backend-3lf7</link>
      <guid>https://forem.com/neiltonseguins/criando-um-chatbot-com-javascript-e-gemini-ai-criando-o-backend-3lf7</guid>
      <description>&lt;p&gt;Salve! \o&lt;/p&gt;

&lt;p&gt;Dando continuidade a criação do nosso chatbot com Javascript e Gemini AI, vamos adicionar o "backend" do projeto. Da vez passada criamos o frontend, com HTML, CSS e Javascript, onde garantimos que a interface do usuário irá refletir uma conversa entre o usuário e o chatbot.&lt;/p&gt;

&lt;p&gt;Agora precisamos criar um servidor, configurando uma rota com &lt;a href="https://expressjs.com/pt-br/" rel="noopener noreferrer"&gt;express.js&lt;/a&gt; para nos comunicar com a &lt;a href="https://ai.google.dev/gemini-api/docs/get-started/tutorial?lang=node&amp;amp;hl=pt-br#multi-turn-conversations-chat" rel="noopener noreferrer"&gt;API do Gemini&lt;/a&gt;. Vamos lá! &lt;/p&gt;

&lt;h2&gt;
  
  
  Instalando as dependências do projeto
&lt;/h2&gt;

&lt;p&gt;Bom, vamos precisar do express.js, o &lt;a href="https://ai.google.dev/gemini-api/docs/get-started/tutorial?lang=node&amp;amp;hl=pt-br#multi-turn-conversations-chat" rel="noopener noreferrer"&gt;sdk do google gemini&lt;/a&gt; e para proteger nossa chave de API vou instalar o dotenv para trabalharmos com variáveis de ambiente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @google/generative-ai express dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora estamos prontos para criar nosso servidor adotando melhores práticas como usar variáveis de ambiente locais para proteger dados particulares.&lt;/p&gt;

&lt;p&gt;Para isso, vamos criar um arquivo na pasta raiz do projeto chamado de &lt;code&gt;server.js&lt;/code&gt;. Neste arquivo vamos começar importando as dependências e configurando os recursos necessários.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GoogleGenerativeAI&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@google/generative-ai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;genAI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GoogleGenerativeAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GOOGLE_GEMINI_API_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este código configura o express para servir arquivos estáticos da pasta "public" e aceita requisições com payload em JSON. Por isso colocamos os arquivos &lt;code&gt;index.html&lt;/code&gt;, &lt;code&gt;styles.css&lt;/code&gt; e &lt;code&gt;script.js&lt;/code&gt; nesta pasta. Também configuramos a aplicação para rodar na porta 3000.&lt;/p&gt;

&lt;p&gt;Utilizamos a biblioteca &lt;code&gt;@google/generative-ai&lt;/code&gt; para integrar a API do Gemini, autenticando-a com uma chave armazenada em uma variável de ambiente chamada &lt;code&gt;GOOGLE_GEMINI_API_KEY&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Mas onde conseguimos essa API Key? É o que vamos descobrir agora.&lt;/p&gt;

&lt;h2&gt;
  
  
  Chave de API do Gemini
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Obtendo a chave
&lt;/h3&gt;

&lt;p&gt;Para conseguir uma chave de API do Gemini, recomendo que você esteja logado em uma conta "@gmail.com". Após isso, &lt;a href="https://aistudio.google.com/app/apikey" rel="noopener noreferrer"&gt;acesse este link&lt;/a&gt; e você verá uma tela como esta: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi12zz50nuvh1lypspj82.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi12zz50nuvh1lypspj82.png" alt="A imagem mostra uma interface de usuário para configurar e testar uma API, apresentando um exemplo de comando cURL para enviar requisições à API. Há um botão destacado no canto inferior que permite criar uma chave de API, e o layout inclui um título, um exemplo de código e links para guias ou informações adicionais." width="800" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clique no botão de "Criar chave de API", indique um projeto no qual você usará esta chave e prontinho. Logo abaixo aparecerá sua chave e você poderá visualizá-la e até copiá-la para fazer o próximo passo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Protegendo sua chave de API
&lt;/h3&gt;

&lt;p&gt;Agora no seu projeto, crie um arquivo com o nome &lt;code&gt;.env.local&lt;/code&gt; ou só &lt;code&gt;.env&lt;/code&gt; na pasta raiz do seu projeto. Neste arquivo coloque sua chave de API da seguinte maneira:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GOOGLE_GEMINI_API_KEY="sua-chave-vai-aqui"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora salve o seu arquivo e pronto. Se você fez o passo anterior corretamente, sua chave de API estará funcionando. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;PS: atente-se ao plano que aparece na sua chave de API. O gemini oferece um plano gratuito com uma quantidade limitada de tokens que sua chave pode retornar. Se quiser maior quantidade de tokens, avalie assinar um plano pago. Vamos utilizar o plano gratuito, que mesmo limitado vai nos permitir trocar algumas mensagens com o chatbot.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Criando a rota /chat
&lt;/h2&gt;

&lt;p&gt;Agora com as dependências configuradas e chave de API em mãos, vamos abrir as portas de possibilidades do que podemos fazer com a inteligência artificial. &lt;/p&gt;

&lt;p&gt;No arquivo &lt;code&gt;server.js&lt;/code&gt; vamos criar a rota &lt;code&gt;/chat&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/chat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mensagem não pode estar vazia.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nossa rota é do tipo POST, pois irá receber uma mensagem no corpo, justamente a mensagem do usuário que irá interagir com o chat. Então, com essa mensagem nós utilizamos um pouco de programação defensiva (não faz mal pra ninguém um pouco de cuidado rs) e verificamos se não temos uma mensagem. Se não tivermos, um erro é devolvido como resposta e uma mensagem é lançada. &lt;/p&gt;

&lt;p&gt;Se tivermos a mensagem, aí sim iremos enviar ela como prompt para o modelo que escolhermos, da seguinte forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;genAI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getGenerativeModel&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gemini-1.5-flash&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startChat&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
      &lt;span class="na"&gt;generationConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;maxOutputTokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Erro ao processar mensagem.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como essa comunicação é um processo assíncrono, vamos usar try/catch para lidar com a resposta. Primeiro eu defino o modelo do Gemini que será usado (&lt;a href="https://ai.google.dev/gemini-api/docs?hl=pt-br" rel="noopener noreferrer"&gt;você pode conferir uma lista de modelos neste link&lt;/a&gt;). Neste caso optei pelo gemini-1.5-flash.&lt;/p&gt;

&lt;p&gt;O segundo passo é iniciar o chat. Então com o &lt;code&gt;model.startChat()&lt;/code&gt; eu posso iniciar a comunicação com o Gemini, configurando a quantidade máxima de tokens que quero na resposta (neste caso 100 tokens por resposta). &lt;/p&gt;

&lt;p&gt;Agora nós aguardamos esta resposta depois de enviar a mensagem para o modelo com &lt;code&gt;chat.sendMessage(message)&lt;/code&gt;. Quando tivermos a resposta, iremos devolver ela para quem fez a requisição, convertendo o formato de texto devolvido pelo modelo para JSON. &lt;/p&gt;

&lt;p&gt;E por fim mas não menos importante, se tivermos um erro podemos usá-lo dentro do &lt;code&gt;catch&lt;/code&gt; para lançar este erro no console, e também devolvendo um status 500, facilitando a vida do cliente que está consumindo esta "mini api". Beleza? &lt;/p&gt;

&lt;p&gt;Agora só falta indicar onde a nossa "mini api" irá rodar com o trecho de código abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Servidor rodando em http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nossa api irá rodar na porta que especificamos lá no início. O código completo do &lt;code&gt;server.js&lt;/code&gt; é mostrado abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GoogleGenerativeAI&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@google/generative-ai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;genAI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GoogleGenerativeAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GOOGLE_GEMINI_API_KEY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/chat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mensagem não pode estar vazia.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;genAI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getGenerativeModel&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gemini-1.5-flash&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startChat&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
      &lt;span class="na"&gt;generationConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;maxOutputTokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Erro ao processar mensagem.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Servidor rodando em http://localhost:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testando o chatbot
&lt;/h2&gt;

&lt;p&gt;Agora chegou o momento mais aguardado, o de testar nosso chatbot. Para isso, vamos abrir um terminal e digitar o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node server.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você deve receber a seguinte mensagem no terminal depois de rodar este comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Servidor rodando em http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora acessando a url &lt;code&gt;http://localhost:3000&lt;/code&gt; e escrevendo uma mensagem no input e pressionando o botão de enviar, a IA responde sua mensagem e ela é mostrada na tela.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fclydpszybq01dp4hnxbj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fclydpszybq01dp4hnxbj.png" alt="Interface de chat com duas mensagens: uma pergunta " width="755" height="680"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Muito legal, né?  &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Com isso a gente finaliza a criação de um chatbot usando JavaScript e a API do Google Gemini. Vimos como criar o frontend do zero, aplicar estilos, fazer manipulação do DOM. Criamos um servidor com express.js, usamos a api do gemini, configuramos uma rota POST para nos comunicarmos com o cliente da aplicação e conseguimos conversar com a IA de uma interface própria, desenvolvida por nós mesmos. &lt;/p&gt;




&lt;p&gt;Mas não é só isso que dá para fazer. Podemos personalizar e configurar este chatbot para diversas tarefas, desde ser um assistente de idiomas, até um professor virtual que tira suas dúvidas sobre matemática ou programação, vai depender de sua criatividade. &lt;/p&gt;

&lt;p&gt;Transformar uma IA em um assistente personalizado envolve treinamento do modelo, mais sobre como &lt;a href="https://ai.google.dev/gemini-api/docs/prompting-strategies?hl=pt-br" rel="noopener noreferrer"&gt;a forma que você quer que ele responda e se comporte&lt;/a&gt; do que sobre código propriamente dito. &lt;/p&gt;

&lt;p&gt;Vamos explorar um pouco disso em um próximo artigo. &lt;/p&gt;

&lt;p&gt;Até lá! &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>gemini</category>
      <category>ai</category>
      <category>backend</category>
    </item>
    <item>
      <title>Criando um Chatbot com JavaScript e Gemini AI: criando o frontend</title>
      <dc:creator>Neilton Seguins</dc:creator>
      <pubDate>Wed, 11 Dec 2024 14:09:33 +0000</pubDate>
      <link>https://forem.com/neiltonseguins/criando-um-chatbot-com-javascript-e-gemini-ai-364k</link>
      <guid>https://forem.com/neiltonseguins/criando-um-chatbot-com-javascript-e-gemini-ai-364k</guid>
      <description>&lt;p&gt;E aí, tudo bom? &lt;/p&gt;

&lt;p&gt;Eu estava olhando alguns projetos no &lt;a href="https://github.com/NeiltonSeguins" rel="noopener noreferrer"&gt;meu github&lt;/a&gt; e me deparei com um chatbot que criei recentemente usando o &lt;a href="https://ai.google.dev/gemini-api/docs?hl=pt-br" rel="noopener noreferrer"&gt;Google Gemini&lt;/a&gt;. A ideia era criar um assistente de idiomas, onde você conseguisse conversar com a IA para aprimorar suas habilidades no idioma que quisesse. &lt;/p&gt;

&lt;p&gt;Então pensei: " Porque não compartilhar como eu fiz este projeto com todo mundo? ". E é por isso que estou escrevendo aqui, para te mostrar como fiz cada parte. Então vamos começar pelo front-end da aplicação. &lt;/p&gt;

&lt;h2&gt;
  
  
  Iniciando um novo projeto
&lt;/h2&gt;

&lt;p&gt;Bom, para justificar algumas ações que vou tomar no projeto vou logo adiantando que iremos criar um "servidor" com &lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;express.js&lt;/a&gt;, onde forneceremos uma rota de api '/chat' que servirá para a comunicação entre o front-end e a &lt;a href="https://aistudio.google.com/apikey" rel="noopener noreferrer"&gt;API do Gemini&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Então, precisaremos iniciar nosso projeto com o comando &lt;code&gt;npm init -y&lt;/code&gt;. O resultado é um arquivo &lt;code&gt;package.json&lt;/code&gt; mais ou menos com essa cara:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chatbot-ia"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Error: no test specified&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; exit 1"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"keywords"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"license"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ISC"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E também, vamos precisar organizar nossos arquivos da seguinte forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;public
  |__ index.html
  |__ style.css
  |__ script.js
package.json 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Feito isso, vamos criar a parte visual do nosso chatbot. Vamos lá!&lt;/p&gt;

&lt;h2&gt;
  
  
  Criando o visual do Chat
&lt;/h2&gt;

&lt;p&gt;Como a ideia era fazer um projeto para um &lt;em&gt;live coding&lt;/em&gt; de 1h, resolvi criar uma interface bem simples usando HTML, CSS e JavaScript para o Chatbot. Sou bem ruim com design, então a fonte e as cores eu escolhi as que mais gosto. Então vamos lá, começando pelo HTML.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"pt-br"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Chatbot Assistente de Idiomas&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"preconnect"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://fonts.googleapis.com"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"preconnect"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://fonts.gstatic.com"&lt;/span&gt; &lt;span class="na"&gt;crossorigin&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt;
      &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://fonts.googleapis.com/css2?family=Roboto&amp;amp;display=swap"&lt;/span&gt;
      &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;
    &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"style.css"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"chat-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"chat-window"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"chat-box"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- As mensagens vão aparecer aqui --&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"input-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"chat-form"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"chat-form"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt;
            &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
            &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"user-input"&lt;/span&gt;
            &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Digite sua mensagem..."&lt;/span&gt;
            &lt;span class="na"&gt;autocomplete=&lt;/span&gt;&lt;span class="s"&gt;"off"&lt;/span&gt;
            &lt;span class="na"&gt;required&lt;/span&gt;
          &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"send-button"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Enviar&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"script.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E agora o CSS da página&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"Roboto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;min-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vh&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#f2f2f2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.chat-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;400px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0px&lt;/span&gt; &lt;span class="m"&gt;4px&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.chat-box&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;300px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;max-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;500px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;overflow-y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;16px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.chat-form&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;space-between&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.message&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;word-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;break-word&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.model&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#e0e0e0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#333&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;align-self&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex-start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex-start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.user&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#4caf50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;align-self&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex-end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex-end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.input-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#ddd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;#user-input&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#ddd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;outline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;#send-button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt; &lt;span class="m"&gt;15px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#4caf50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;#send-button&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#45a049&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O resultado disso deve ser uma tela parecida com a mostrada abaixo: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi13foin4q5hcv1pav2do.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi13foin4q5hcv1pav2do.png" alt="alt: Interface de chat com uma área em branco para mensagens, campo de texto com o placeholder " width="800" height="639"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Criando a lógica do cliente
&lt;/h2&gt;

&lt;p&gt;Nossa aplicação é um chatbot que irá se comunicar com a API do Gemini. Então, precisamos criar a lógica que irá fazer essa comunicação. Para ficar claro o que devemos fazer, vou listar abaixo: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pegar o que for digitado pelo usuário&lt;/li&gt;
&lt;li&gt;Fazer uma requisição POST para a rota '/chat' que iremos criar&lt;/li&gt;
&lt;li&gt;Exibir a mensagem do usuário e do modelo (a IA) na tela do chat&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Então vamos lá, primeiro vamos adicionar um &lt;a href="https://developer.mozilla.org/pt-BR/docs/Web/API/EventTarget/addEventListener" rel="noopener noreferrer"&gt;ouvinte de eventos&lt;/a&gt; para executar nossa lógica apenas depois que o conteúdo do DOM for totalmente carregado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// script.js&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DOMContentLoaded&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chatForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;chat-form&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chatWindow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;chat-window&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user-input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Criamos constantes para pegar os elementos que nos interessam, como o input onde o usuário digita, a janela onde irão aparecer as mensagens e o campo do formulário, pois vamos escutar quando ele for submetido e aí sim executar nossa lógica. &lt;/p&gt;

&lt;p&gt;Continuando, vamos para o segundo passo que é fazer a requisição para a rota que criaremos enviando a mensagem do usuário.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;chatForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;userMessage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;addMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;modelResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/chat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userMessage&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;modelResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;addMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;model&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;addMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;model&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Erro: Resposta inválida do modelo.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;addMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;model&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Erro: Não foi possível processar sua mensagem.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;userInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste código, estamos escutando o evento de submit no elemento de formulário. Então, de início usamos o &lt;code&gt;preventDefault&lt;/code&gt; para evitar que a página faça &lt;em&gt;reload&lt;/em&gt; sempre que enviarmos uma mensagem. Depois pegamos o que o usuário digitou, removendo os espaços em branco da mensagem, do início e fim com o &lt;code&gt;trim()&lt;/code&gt; e verificamos se a mensagem não é vazia, em branco. Se a mensagem for vazia a gente para nosso processo aí mesmo.&lt;/p&gt;

&lt;p&gt;Agora, se tivermos a mensagem do usuário, exibimos ela na tela usando a função &lt;code&gt;addMessage()&lt;/code&gt;. Esta função é definida da seguinte forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;addMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messageDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;messageDiv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`message &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;messageDiv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;chatWindow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messageDiv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;chatWindow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollTop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chatWindow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollHeight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Basicamente ela recebe quem enviou a mensagem e o texto da mensagem e exibe essa informação no chat, adicionando os estilos corretos do usuário e do &lt;em&gt;model&lt;/em&gt;, o modelo de IA. &lt;/p&gt;

&lt;p&gt;Beleza, agora voltando para a lógica da nossa requisição se tivermos uma mensagem do usuário precisamos fazer uma requisição POST usando o &lt;a href="https://developer.mozilla.org/pt-BR/docs/Web/API/Fetch_API/Using_Fetch" rel="noopener noreferrer"&gt;fetch API&lt;/a&gt;, e o corpo dessa requisição é a mensagem do usuário. &lt;/p&gt;

&lt;p&gt;Por fim, se tivermos uma resposta dessa requisição iremos exibir a mensagem do modelo no chat. Caso contrário, pegamos o erro e exibimos no console, com o &lt;code&gt;console.error()&lt;/code&gt; ou exibimos uma mensagem no próprio chat de forma customizada. E para melhorar a usabilidade do chat, limpamos o input de mensagem do usuário com o &lt;code&gt;userInput.value = "";&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;O arquivo &lt;code&gt;script.js&lt;/code&gt; fica com essa cara:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// script.js&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DOMContentLoaded&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chatForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;chat-form&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chatWindow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;chat-window&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user-input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;chatForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;userMessage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;addMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;modelResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/chat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userMessage&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;modelResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;addMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;model&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;addMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;model&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Erro: Resposta inválida do modelo.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;addMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;model&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Erro: Não foi possível processar sua mensagem.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;userInput&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;addMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messageDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;messageDiv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`message &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;messageDiv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;chatWindow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messageDiv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;chatWindow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollTop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;chatWindow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollHeight&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;E com isso a gente finaliza a parte do front-end do chatbot. O próximo passo será criar o nosso "servidor", realizar a comunicação com a API do Gemini e conversar com ele sobre a vida, o universo e tudo mais! &lt;/p&gt;

&lt;p&gt;Até uma próxima!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>gemini</category>
      <category>ai</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Onde eu colaborei no 11 Hacktoberfest</title>
      <dc:creator>Neilton Seguins</dc:creator>
      <pubDate>Mon, 28 Oct 2024 16:12:19 +0000</pubDate>
      <link>https://forem.com/neiltonseguins/onde-eu-colaborei-no-11deg-hacktoberfest-499h</link>
      <guid>https://forem.com/neiltonseguins/onde-eu-colaborei-no-11deg-hacktoberfest-499h</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest"&gt;2024 Hacktoberfest Writing challenge&lt;/a&gt;: Contributor Experience&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;E aí, pessoal! Tudo bom? &lt;/p&gt;

&lt;p&gt;Todos os anos no mês de outubro rola uma competição muito legal e saudável no mundo tech: o Hacktoberfest. Este evento celebra a colaboração em projetos open source pelo mundo inteiro. Então se você gosta de colaborar em projetos no github é uma ótima oportunidade para encontrar repositórios onde você possa deixar uma pull request de qualidade.&lt;/p&gt;

&lt;p&gt;Aproveitando que o mês está acabando, vou deixar aqui minha experiência e onde eu consegui colaborar na edição deste ano. Vamos lá!&lt;/p&gt;

&lt;h2&gt;
  
  
  TechGuide.sh
&lt;/h2&gt;

&lt;p&gt;Minhas duas primeiras contribuições foram no repositório do &lt;a href="https://github.com/alura/techguide" rel="noopener noreferrer"&gt;techguide.sh&lt;/a&gt; que é um projeto muito bacana criado pela &lt;a href="https://www.alura.com.br/" rel="noopener noreferrer"&gt;Alura&lt;/a&gt; e desenvolvido pensando na comunidade. O tech guide ajuda pessoas a descobrirem que área desejam seguir, dá sugestões de conteúdos da comunidade e destaca em cada área de conhecimento um "T" do que é chamado de "Dev em T".&lt;/p&gt;

&lt;p&gt;O Dev em T é a ideia de que você precisa ser um profissional especialista em uma área (a barra vertical do T), mas que conhece bem áreas correlatas a sua (a barra horizontal do T). Por exemplo, uma pessoa que é dev frontend deve conhecer um pouco da área de UX designer e de DevOps e backend. Não de forma profunda, mas o suficiente para se comunicar e entender bem o projeto como um todo, poder participar e dar sugestões, feedbacks, etc.&lt;/p&gt;

&lt;p&gt;Já sou colaborador no tech guide então foi fácil fazer minhas PR's e fiquei muito feliz de contribuir sabendo que estou ajudando outras pessoas a seguirem o seu próprio caminho na área tech. &lt;/p&gt;

&lt;h2&gt;
  
  
  Eventos Tech Brasil
&lt;/h2&gt;

&lt;p&gt;Minha terceira contribuição foi no repositório &lt;a href="https://github.com/Abacatinhos/agenda-tech-brasil" rel="noopener noreferrer"&gt;agenda-tech-brasil&lt;/a&gt; da &lt;a class="mentioned-user" href="https://dev.to/pachicodes"&gt;@pachicodes&lt;/a&gt; que reúne eventos tech de todo o Brasil que ainda vão acontecer. A Pachi ainda tem uma &lt;a href="https://www.linkedin.com/pulse/eventos-dessa-semana-28-de-outubro-3-novembro-pachi-parra-auo2f/" rel="noopener noreferrer"&gt;newsletter semanal no Linkedin&lt;/a&gt; onde compartilha os principais eventos que vão acontecer durante a semana. &lt;/p&gt;

&lt;p&gt;Repositórios assim são de muita importância e utilidade, pois é difícil acompanhar os mais diversos eventos tech que acontecem no país, e centralizar isto em um lugar só facilita a vida de quem tá procurando eventos para participar e se engajar na comunidade. &lt;/p&gt;

&lt;p&gt;Fiquei contente que consegui contribuir neste repositório com um evento importante da minha cidade, e vou ficar atento para adicionar os próximos que surgirem. &lt;/p&gt;

&lt;h2&gt;
  
  
  Diciotech
&lt;/h2&gt;

&lt;p&gt;Minha quarta contribuição foi &lt;a href="https://github.com/levxyca/diciotech" rel="noopener noreferrer"&gt;no repositório da Diciotech&lt;/a&gt;. Este projeto é realmente necessário. Sabe aquele monte de termos técnicos que você ouve por aí na tecnologia, como framework, LLM, Code Smells, Deploy, etc? Pois bem, este projeto tem o objetivo de desmistificar e esclarecer o significado destes termos. &lt;/p&gt;

&lt;p&gt;É o segundo ano que deixo um PR neste repositório e sempre adicionando termos relacionados ao Frontend, que é o que sou atualmente. O projeto &lt;a href="https://diciotech.netlify.app/" rel="noopener noreferrer"&gt;Diciotech&lt;/a&gt; é coordenado pela &lt;a class="mentioned-user" href="https://dev.to/levxyca"&gt;@levxyca&lt;/a&gt;, tem um designer muito bonito, simples, tema dark e filtro para facilitar a busca por termos específicos. Usa somente HTML, CSS e JavaScript, então é ótimo para iniciantes que desejam contribuir também. &lt;/p&gt;




&lt;h2&gt;
  
  
  Menção honrosa
&lt;/h2&gt;

&lt;p&gt;Também colaborei no repositório &lt;a href="https://github.com/mateushsx/algorithms-js" rel="noopener noreferrer"&gt;Algorithms-js&lt;/a&gt; que apesar de não ser participante no Hacktoberfest contém uma ideia interessante: um banco de algoritmos importantes na linguagem JavaScript.&lt;/p&gt;

&lt;p&gt;Neste repositório deixei duas PR's, as duas focadas em algoritmos de ordenação. A primeira eu inseri o algoritmo de &lt;strong&gt;&lt;a href="https://github.com/mateushsx/algorithms-js/tree/master/algorithms/sorting/selection-sort" rel="noopener noreferrer"&gt;Selection Sort&lt;/a&gt;&lt;/strong&gt; e sua análise de desempenho em notação BigO. E na segunda PR eu adicionei o algoritmo de &lt;strong&gt;&lt;a href="https://github.com/mateushsx/algorithms-js/tree/master/algorithms/sorting/quicksort" rel="noopener noreferrer"&gt;Quick Sort&lt;/a&gt;&lt;/strong&gt; que é um dos meus preferidos por sua lógica simples, porém complexa, e seu ótimo desempenho. &lt;/p&gt;

&lt;p&gt;Essas duas contribuições foram importantes pra mim, pois demonstraram minha evolução ao implementar algoritmos de busca e ordenação. Além de escrever um código limpo e bem documentado, aprovado sem quase nenhuma alteração.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Esse foi meu mês de outubro como participante do 11° Hacktoberfest. Foi desafiador colaborar em repositórios diferentes, escrever algoritmos complexos, simplificar a linguagem tech para todas as pessoas e compartilhar eventos do meu estado com o Brasil todo. &lt;/p&gt;

&lt;p&gt;É satisfatório contribuir com projetos open source. Sou muito fã de quem não privatiza o conhecimento e se empenha em disponibilizar suas ideias e projetos com a comunidade sem cobrar nada. Em muitas situações da minha vida fui salvo pro projetos open source, na graduação e no trabalho principalmente. Por isso sempre que posso colaboro com projetos que fazem sentido pra mim. &lt;/p&gt;

&lt;p&gt;E foi isso! Já espero ansioso pelo próximo ano. Quero conhecer cada vez mais projetos incríveis. &lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hacktoberfest</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Rick and Morty e Closures: o que essas coisas tem em comum?</title>
      <dc:creator>Neilton Seguins</dc:creator>
      <pubDate>Wed, 23 Oct 2024 14:31:22 +0000</pubDate>
      <link>https://forem.com/neiltonseguins/rick-and-morty-e-clorsures-o-que-essas-coisas-tem-em-comum-3jpb</link>
      <guid>https://forem.com/neiltonseguins/rick-and-morty-e-clorsures-o-que-essas-coisas-tem-em-comum-3jpb</guid>
      <description>&lt;p&gt;E aí, tudo bom? Espero que sim! &lt;/p&gt;

&lt;p&gt;Eu estava tentando resolver alguns problemas de programação no &lt;a href="https://leetcode.com/explore/" rel="noopener noreferrer"&gt;Leetcode&lt;/a&gt; e em um dos desafios eu me deparei com um conceito muito importante em programação que muitas pessoas tem dificuldade em entender. &lt;/p&gt;

&lt;p&gt;Então resolvi escrever aqui tentando explicar da melhor forma possível como &lt;em&gt;closures&lt;/em&gt; funcionam no JavaScript. Vem comigo!&lt;/p&gt;

&lt;h2&gt;
  
  
  O Problema
&lt;/h2&gt;

&lt;p&gt;Eu estava trabalhando em um desafio chamado "Counter" onde eu precisava criar uma função &lt;code&gt;counter&lt;/code&gt; que retornasse inicialmente o número inteiro &lt;code&gt;n&lt;/code&gt; e, a cada chamada subsequente, retornasse 1 unidade a mais do que o valor anterior. Por exemplo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;counter(10)&lt;/code&gt; retorna &lt;code&gt;10&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;counter()&lt;/code&gt; (chamado novamente) retorna &lt;code&gt;11&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;counter()&lt;/code&gt; (chamado novamente) retorna &lt;code&gt;12&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O problema dá algumas dicas, entre elas que podemos usar &lt;strong&gt;&lt;em&gt;funções que retornam outras funções&lt;/em&gt;&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Este é o conceito de &lt;strong&gt;closures&lt;/strong&gt;. Então segui a dica e fui por este caminho. Aqui está a solução que cheguei:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;createCounter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;contador&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;resultado&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;contador&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;contador&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;resultado&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse código define uma função chamada &lt;code&gt;createCounter&lt;/code&gt; que retorna uma outra função (closure), capaz de armazenar e manipular uma variável local (no caso, o contador). &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O contador começa com o valor de &lt;code&gt;n&lt;/code&gt; passado quando você chama &lt;code&gt;createCounter()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Cada vez que você executa a função, a função interna (retornada) acessa o valor atual de contador, o retorna, e então o incrementa.&lt;/li&gt;
&lt;li&gt;Isso permite que o contador "lembre" de onde parou, graças ao closure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Neste último passo é onde percebemos o verdadeiro poder de uma closure. Uma closure é quando uma função retorna outra função que &lt;strong&gt;tem acesso a variáveis externas&lt;/strong&gt; e &lt;strong&gt;mantém seu estado entre chamadas&lt;/strong&gt;. É como ter um pequeno "esconderijo" dentro da minha função onde eu posso armazenar informações e acessá-las posteriormente.&lt;/p&gt;

&lt;h2&gt;
  
  
  E onde o Rick e Morty entra nessa história?
&lt;/h2&gt;

&lt;p&gt;A série &lt;a href="https://www.imdb.com/title/tt2861424/?language=pt-br" rel="noopener noreferrer"&gt;Rick and Morty&lt;/a&gt; brinca com viagens interdimensionais, outras civilizações e faz críticas e propõe reflexões sobre muitas questões existenciais para o ser humano. &lt;/p&gt;

&lt;p&gt;Se você não conhece a série aqui vai um breve resumo: O Rick Sanchez, personagem principal da obra, é um cientista que desenvolve todas as maluquices tecnológicas e costuma levar em suas aventuras seu neto Morty. Uma das invenções mais famosas do velho é o portal interdimensional, que permite que ele viaje entre realidades e dimensões. Para saber mais, você vai ter que assistir a série (risos).&lt;/p&gt;

&lt;p&gt;Onde você quer chegar, Neilton? &lt;/p&gt;

&lt;p&gt;Bom, imagina que o Rick desenvolve uma mochila interdimensional para o Morty, que dá acesso a uma dimensão específica. Nessa dimensão, o Rick coloca algumas ferramentas importantes. Morty pode carregar a mochila para qualquer lugar — seja para a escola, para passear, ou até para uma viagem intergaláctica — e, mesmo longe de Rick, ele ainda terá acesso a tudo o que foi guardado lá. &lt;/p&gt;

&lt;p&gt;A melhor parte? Morty pode abrir a mochila e pegar as ferramentas sempre que quiser usar ou até modificar o que está lá dentro. E não importa onde ele esteja, o que foi guardado continua acessível. &lt;/p&gt;

&lt;p&gt;E como esse exemplo se conecta com as closures? &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rick é a &lt;em&gt;função externa&lt;/em&gt;, que cria o &lt;strong&gt;escopo&lt;/strong&gt; (dimensão) e as &lt;strong&gt;variáveis&lt;/strong&gt; (ferramentas) que podem ser acessadas depois.&lt;/li&gt;
&lt;li&gt;O Morty com a mochila representa a &lt;em&gt;função interna&lt;/em&gt;, que pode acessar e modificar as variáveis da função externa.&lt;/li&gt;
&lt;li&gt;A dimensão representa o &lt;em&gt;escopo léxico&lt;/em&gt; da função externa, ou seja, as variáveis que foram criadas dentro da função externa e são acessadas pela função interna, mesmo após a função externa ser executada.&lt;/li&gt;
&lt;li&gt;O fato de Morty poder acessar as coisas da dimensão de qualquer lugar reflete a &lt;em&gt;persistência do escopo&lt;/em&gt;: mesmo após a função externa ser finalizada, a função interna mantém o acesso às variáveis do escopo original.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Closures são poderosos recursos em programação. Entre as principais vantagens de usar closures, eu destaco o encapsulamento e a memoização. O encapsulamento porque o valor só pode ser acessado através da closure (função interna) e a memoização pela capacidade de preservar o valor das variáveis entre chamadas. &lt;/p&gt;




&lt;p&gt;Imagem gerada por IA: &lt;a href="https://designer.microsoft.com/image-creator?scenario=texttoimage" rel="noopener noreferrer"&gt;https://designer.microsoft.com/image-creator?scenario=texttoimage&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prompt: Generate an image where Rick from Rick and Morty is handing Morty a glowing dimensional pocket device. Morty is pulling objects out of the pocket, like tools and gadgets, while Rick casually explains the mechanics of it in a lab. The pocket represents a closure, containing floating items that Morty can keep accessing, even after Rick steps away.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;E aí, deu para entender o que são closures e como elas são importantes em programação? As vezes eu queria ter uma mochila como essa do Morty para guardar coisas úteis ou simplesmente para me teleportar para uma outra dimensão (risos).&lt;/p&gt;

&lt;p&gt;Se gostou do conteúdo, comenta e compartilha aí, vai! Dá essa força se você acha que este artigo irá ajudar outras pessoas.&lt;/p&gt;

&lt;p&gt;Até a próxima!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>development</category>
      <category>programming</category>
    </item>
    <item>
      <title>Onde contribuir no #Hacktoberfest 2024</title>
      <dc:creator>Neilton Seguins</dc:creator>
      <pubDate>Thu, 03 Oct 2024 17:06:16 +0000</pubDate>
      <link>https://forem.com/neiltonseguins/onde-contribuir-no-hacktoberfest-2024-j6o</link>
      <guid>https://forem.com/neiltonseguins/onde-contribuir-no-hacktoberfest-2024-j6o</guid>
      <description>&lt;p&gt;Se você é uma pessoa desenvolvedora, já deve ter ouvido falar do &lt;strong&gt;Hacktoberfest&lt;/strong&gt;, né? Um evento que rola todo mês de outubro e nos convida a fazer algo que, além de gratificante, ajuda o mundo da tecnologia a crescer: &lt;strong&gt;contribuir com projetos open source&lt;/strong&gt;! &lt;/p&gt;

&lt;p&gt;Mas se você está se perguntando por onde começar ou em quais repositórios mandar aquela &lt;em&gt;pull request (PR)&lt;/em&gt; caprichada, eu tô aqui pra te ajudar. Vamos nessa?&lt;/p&gt;

&lt;h2&gt;
  
  
  O que é o Hacktoberfest?
&lt;/h2&gt;

&lt;p&gt;Se você não sabe, o &lt;a href="https://hacktoberfest.com/" rel="noopener noreferrer"&gt;Hacktoberfest&lt;/a&gt; é um evento organizado pela &lt;a href="https://www.digitalocean.com/" rel="noopener noreferrer"&gt;DigitalOcean&lt;/a&gt; e &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, que incentiva desenvolvedores do mundo todo a colaborar com projetos de código aberto. &lt;/p&gt;

&lt;p&gt;Para participar é muito simples, é só se inscrever no site do &lt;a href="https://hacktoberfest.com/" rel="noopener noreferrer"&gt;Hacktoberfest&lt;/a&gt;, você pode usar suas contas do Github e Gitlab para issso, e fazer pelo menos 4 contribuições válidas em repositórios que possuem a #hacktoberfest, repositórios de código aberto. &lt;/p&gt;

&lt;p&gt;O que você ganha com isso? Além de &lt;strong&gt;conhecimento&lt;/strong&gt; e &lt;strong&gt;experiência&lt;/strong&gt;, este ano de 2024 você pode ganhar uma camiseta incrível! Ano passado eu consegui plantar uma árvore na Tanzânia em um projeto de conservação e biodiversidade e achei isso muito legal, pois nunca pensei que escrever código poderia me fazer salvar espécies nativas de outros países!!&lt;/p&gt;

&lt;p&gt;E para te ajudar a contribuir este ano vou te mostrar alguns repositórios para você deixar sua PR. Vem comigo!&lt;/p&gt;

&lt;h2&gt;
  
  
  1. TypeScript cheatsheets for React
&lt;/h2&gt;

&lt;p&gt;Você curte React e está aprendendo TypeScript? &lt;a href="https://github.com/typescript-cheatsheets/react" rel="noopener noreferrer"&gt;Este repositório&lt;/a&gt; é ótimo para você! Ele reúne &lt;em&gt;cheatsheets&lt;/em&gt; (guias rápidos) de TypeScript aplicados ao React. Se você já passou pelo dilema de "como tipar isso aqui no React?", esses &lt;em&gt;cheatsheets&lt;/em&gt; são uma mão na roda. &lt;/p&gt;

&lt;p&gt;Agora, se você já manja dos "paranauês" de TypeScript e quer contribuir,  este repositório é uma excelente oportunidade para testar seus conhecimentos e compartilhar o que você sabe. &lt;/p&gt;

&lt;h2&gt;
  
  
  2. Developer roadmap (&lt;em&gt;roadmap.sh&lt;/em&gt;)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/kamranahmedse/developer-roadmap" rel="noopener noreferrer"&gt;Este repositório&lt;/a&gt; é bem popular, pois dá uma visão do caminho a seguir na sua carreira de pessoa desenvolvedora. Este projeto traça mapas de aprendizado que guiam desenvolvedores em várias áreas (frontend, backend, DevOps, etc.). &lt;/p&gt;

&lt;p&gt;Se você curte criar conteúdos visuais ou quer ajudar a estruturar esse roadmap para outros devs, esse é o lugar certo! Aqui dá pra contribuir com melhorias no roadmap ou sugerir novas skills que podem ser importantes.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Tech Guide by Alura
&lt;/h2&gt;

&lt;p&gt;O &lt;a href="https://techguide.sh/" rel="noopener noreferrer"&gt;Tech Guide&lt;/a&gt; é inspirado no &lt;a href="https://roadmap.sh/" rel="noopener noreferrer"&gt;roadmap.sh&lt;/a&gt; e reúne conteúdos valiosos sobre várias áreas da tecnologia, ajudando a galera a se situar no mundão do desenvolvimento. A principal diferença é que o Tech Guide apresenta os mapas de aprendizado usando a filosofia do &lt;strong&gt;Dev em T&lt;/strong&gt;, que diz que você deve ser especialista em uma tecnologia mas conhecer o suficiente outras que estão relacionadas (pense no T, a barra vertical é sua especialidade, as "pontinhas" do T são as áreas relacionadas). &lt;/p&gt;

&lt;p&gt;Quer melhorar a documentação, sugerir novos conteúdos ou revisar algo? As oportunidades de contribuição aqui são ótimas, e você ainda fortalece a comunidade tech no Brasil. Tá esperando o que? &lt;a href="https://github.com/alura/techguide" rel="noopener noreferrer"&gt;Clique aqui neste link se quiser contribuir&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Algorithms in JavaScript
&lt;/h2&gt;

&lt;p&gt;Se você curte desafios de algoritmos e adora resolver problemas com JavaScript, &lt;a href="https://github.com/mateushsx/algorithms-js" rel="noopener noreferrer"&gt;esse repositório é pra você&lt;/a&gt;! Ele contém implementações de algoritmos e estruturas de dados em JavaScript, o que é perfeito para quem está estudando e quer praticar ou ensinar outras pessoas. &lt;/p&gt;

&lt;p&gt;Ainda é um projeto com poucos algoritmos disponíveis, então se você conhece um algoritmo que ainda não está lá, é sua chance de brilhar!&lt;/p&gt;

&lt;h2&gt;
  
  
  5. DicioTech
&lt;/h2&gt;

&lt;p&gt;Aqui está uma contribuição super divertida e inclusiva! O &lt;a href="https://diciotech.netlify.app/" rel="noopener noreferrer"&gt;DicioTech&lt;/a&gt; é um dicionário de termos técnicos de tecnologia, mas com uma pegada leve e acessível para todos. &lt;/p&gt;

&lt;p&gt;Se você já se perdeu entre siglas, tecnologias, nomes técnicos demais, frameworks e gírias tech, este projeto ajuda a desmistificar tudo isso. Quer adicionar um termo novo ou melhorar as definições? Vai fundo, a comunidade agradece! O &lt;a href="https://github.com/levxyca/diciotech" rel="noopener noreferrer"&gt;link para este repositório&lt;/a&gt; se encontra aqui!&lt;/p&gt;




&lt;p&gt;Estes são apenas alguns dos repositórios legais que encontrei e que já contribuí anos antes que podem te ajudar no desafio de cumprir as 4 PR no mês de outubro. E se você não é pessoa desenvolvedora e quer participar o evento é bastante inclusivo e você consegue contribuir com documentação, tradução de documentação, revisão de textos e muito mais. As possibilidades são muitas então fique a vontade.&lt;/p&gt;

&lt;p&gt;Conhece outros repositórios abertos que aceitam a colaboração? Já deixa aí nos comentários que você estará ajudando outras pessoas nesse desafio super legal. &lt;/p&gt;

&lt;p&gt;Grande abraço e até a próxima!&lt;/p&gt;




&lt;p&gt;Imagem de capa gerada por IA: &lt;a href="https://designer.microsoft.com/image-creator" rel="noopener noreferrer"&gt;https://designer.microsoft.com/image-creator&lt;/a&gt;&lt;br&gt;
Prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"&lt;em&gt;Ilustração em bloco de cores simples de um panda usando um moletom verde, sentado em um quarto escuro com luzes neon verdes e pretas, cercado por vários monitores com telas de código. O fundo tem uma vibe digital, estilo cyberpunk, com referências sutis a hacking e programação, com o código exibido em tons suaves de verde e preto.&lt;/em&gt;"&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>hacktoberfest</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Conhecendo objetos em JavaScript</title>
      <dc:creator>Neilton Seguins</dc:creator>
      <pubDate>Mon, 16 Sep 2024 16:32:36 +0000</pubDate>
      <link>https://forem.com/neiltonseguins/conhecendo-objetos-em-javascript-233</link>
      <guid>https://forem.com/neiltonseguins/conhecendo-objetos-em-javascript-233</guid>
      <description>&lt;p&gt;Você já se deparou com a necessidade de guardar um conjunto de informações complexas em seu código JavaScript? Por exemplo, você precisa armazenar dados de um usuário em um banco de dados, como nome, idade e endereço. Que estrutura do JavaScript você usaria para esta missão?&lt;/p&gt;

&lt;p&gt;Neste artigo, vamos conhecer como os objetos podem ser úteis em tarefas como essa e entender o que é essa importante coleção de dados no JavaScript. &lt;/p&gt;

&lt;p&gt;Vem comigo!&lt;/p&gt;

&lt;h2&gt;
  
  
  Um "armário" para seus dados
&lt;/h2&gt;

&lt;p&gt;Pensa no armário da sua casa. Se você for organizado, cada gaveta vai servir para guardar algum tipo de item da sua casa, como chaves, ferramentas, remédios, etc. Se pensarmos em objetos no JavaScript, cada gaveta representa uma propriedade (&lt;strong&gt;chave&lt;/strong&gt;) e o conteúdo dentro dela, o &lt;strong&gt;valor&lt;/strong&gt; associado a essa propriedade.  Na gaveta de chaves você terá as chaves do seu carro, casa, moto. E na gaveta de ferramentas você poderá guardar uma chave inglesa, martelo, furadeira, etc.&lt;/p&gt;

&lt;p&gt;Os &lt;strong&gt;objetos armazenam informações organizadas em pares chave-valor&lt;/strong&gt;. Exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;usuario&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;nome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ana&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;idade&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cidade&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;São Paulo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nesse exemplo, &lt;code&gt;usuario&lt;/code&gt; é um objeto que guarda informações sobre um usuário. As chaves são &lt;code&gt;nome&lt;/code&gt;, &lt;code&gt;idade&lt;/code&gt; e &lt;code&gt;cidade&lt;/code&gt;, e os valores correspondentes são "Ana", 25 e "São Paulo".&lt;/p&gt;

&lt;h2&gt;
  
  
  Acessando as informações do objeto
&lt;/h2&gt;

&lt;p&gt;Para acessar uma propriedade do objeto, você utiliza a notação de ponto (&lt;code&gt;.&lt;/code&gt;) ou colchetes (&lt;code&gt;[]&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;usuario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nome&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Saída: Ana&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;usuario&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;idade&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// Saída: 25&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A notação de colchetes é útil quando você precisa acessar uma propriedade cujo nome é armazenado em uma variável:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;propriedade&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cidade&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;usuario&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;propriedade&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// Saída: São Paulo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Adicionando e modificando propriedades
&lt;/h2&gt;

&lt;p&gt;Você pode adicionar novas propriedades a um objeto ou modificar o valor de uma propriedade existente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;usuario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;profissao&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Desenvolvedora&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Adiciona uma nova propriedade&lt;/span&gt;
&lt;span class="nx"&gt;usuario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;idade&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;26&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Modifica o valor da propriedade 'idade'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Objetos e arrays: trabalhando em conjunto
&lt;/h2&gt;

&lt;p&gt;Objetos podem conter arrays como valores de suas propriedades, permitindo que você organize dados relacionados de forma eficiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;usuario&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;nome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;João&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;idades&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// Armazena as idades do João ao longo dos anos&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;usuario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;idades&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// Saída: 21&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora que você já conhece objetos no JavaScript, tenho certeza que conseguirá trabalhar melhor com as coleções de dados em suas aplicações. Por exemplo, se você precisa de informações de um usuário que preenche um formulário, objetos podem armazenar esses dados em uma única coleção. &lt;/p&gt;

&lt;p&gt;Explore a &lt;a href="https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/Objects/Basics" rel="noopener noreferrer"&gt;documentação oficial do JavaScript&lt;/a&gt; para aprofundar seus conhecimentos sobre objetos e descobrir suas infinitas possibilidades.&lt;/p&gt;

&lt;p&gt;Já sabia que era possível fazer isso com objetos? Este artigo te ajudou de alguma forma, deixe seu comentário para que eu possa saber o que você achou. &lt;/p&gt;

&lt;p&gt;Imagem gerada por IA:  &lt;a href="https://designer.microsoft.com/image-creator" rel="noopener noreferrer"&gt;https://designer.microsoft.com/image-creator&lt;/a&gt;&lt;br&gt;
Prompt: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Uma ilustração plana de uma mulher negra com um um moletom azul e uma xícara de café em uma quarto escuros com luzes de led neon na cor rosa com um computador gamer, programando algum código em cores macias e pastel.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>programacao</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>objetos</category>
    </item>
    <item>
      <title>Testes no Front-end: métodos de consulta do RTL</title>
      <dc:creator>Neilton Seguins</dc:creator>
      <pubDate>Mon, 06 Mar 2023 15:30:00 +0000</pubDate>
      <link>https://forem.com/neiltonseguins/testes-no-front-end-metodos-de-consulta-do-rtl-4obf</link>
      <guid>https://forem.com/neiltonseguins/testes-no-front-end-metodos-de-consulta-do-rtl-4obf</guid>
      <description>&lt;p&gt;Neste artigo, vamos explorar os principais métodos de consulta disponíveis na biblioteca React testing Library e entender a diferença entre eles.&lt;/p&gt;

&lt;h2&gt;
  
  
  React Testing Library (RTL)
&lt;/h2&gt;

&lt;p&gt;O &lt;a href="https://testing-library.com/docs/react-testing-library/intro/" rel="noopener noreferrer"&gt;React Testing Library&lt;/a&gt; é uma biblioteca popular para escrever testes automatizados em aplicações React. Uma das principais funcionalidades dessa biblioteca é a capacidade de &lt;strong&gt;consultar elementos na tela e realizar interações com eles&lt;/strong&gt;, como clique de botões e preenchimento de formulários.&lt;/p&gt;

&lt;p&gt;Existem vários métodos de consulta disponíveis no React Testing Library, e cada um deles tem sua finalidade específica. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;getBy&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;O método &lt;code&gt;getBy&lt;/code&gt; é usado para obter um elemento com base em um seletor. Ele retorna o primeiro elemento que corresponde ao seletor especificado. Se nenhum elemento corresponder ao seletor, o getBy irá lançar um erro.&lt;/p&gt;

&lt;p&gt;Podemos fazer essas consultas usando um método que começa com um &lt;strong&gt;prefixo indicando o tipo de consulta&lt;/strong&gt; e um &lt;strong&gt;sufixo que indica qual o tipo de seletor&lt;/strong&gt; estaremos usando para esta consulta.&lt;/p&gt;

&lt;p&gt;Exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;deve exibir o título da página&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;titulo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Meu Título&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;titulo&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste exemplo, estamos buscando o elemento que contém o texto "Meu Título" na tela usando o &lt;code&gt;getByText&lt;/code&gt;. Se o elemento não for encontrado, o teste irá falhar.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;queryBy&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;O método queryBy é semelhante ao getBy, mas não lança um erro se o elemento não for encontrado. Em vez disso, ele retorna null.&lt;/p&gt;

&lt;p&gt;Exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;deve exibir o título da página&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;titulo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;queryByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Meu Título&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;titulo&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste exemplo, estamos buscando o elemento que contém o texto "Meu Título" na tela usando o &lt;code&gt;queryByText&lt;/code&gt;. Se o elemento for encontrado, o teste irá passar, pois estamos verificando se o título está presente na tela usando o método &lt;code&gt;toBeInTheDocument()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Esse tipo de consulta é muito útil quando queremos verificar se um elemento &lt;strong&gt;não está presente&lt;/strong&gt;, pois ele retorna null e não um erro imediatamente. Então você consegue utilizar o retornado com utilitários do jest, como o &lt;code&gt;not.toBeInTheDocument()&lt;/code&gt; para verificar se elementos não estão presentes.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;findBy&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;O método findBy é usado para obter um elemento &lt;strong&gt;&lt;em&gt;assíncrono&lt;/em&gt;&lt;/strong&gt; com base em um seletor. Ele aguarda até que o elemento seja encontrado ou até que expire o tempo limite especificado. Se o elemento não for encontrado, o findBy irá lançar um erro.&lt;/p&gt;

&lt;p&gt;Exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;deve exibir o título da página&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;titulo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Meu Título&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;titulo&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste exemplo, estamos buscando o elemento que contém o texto "Meu Título" na tela usando o &lt;code&gt;findByText&lt;/code&gt;. O teste irá aguardar até que o elemento seja encontrado ou até que o tempo limite especificado seja atingido.&lt;/p&gt;

&lt;p&gt;Note que tivemos que usar async await para aguardar que a promise fosse resolvida, e só assim continuar o nosso teste. Essa &lt;em&gt;query&lt;/em&gt; é muito útil quando você precisar testar componentes que renderizam dados provenientes de API's, ou elementos que carregam em uma outra página ao você visitá-los.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;getAllBy&lt;/code&gt;, &lt;code&gt;queryAllBy&lt;/code&gt; e &lt;code&gt;findAllBy&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Os métodos &lt;code&gt;getAllBy&lt;/code&gt; e &lt;code&gt;queryAllBy&lt;/code&gt; são usados para obter uma lista de elementos com base em um seletor. O &lt;code&gt;getAllBy&lt;/code&gt; irá lançar um erro se nenhum elemento corresponder ao seletor, enquanto o &lt;code&gt;queryAllBy&lt;/code&gt; retorna uma lista vazia se nenhum elemento for encontrado. &lt;/p&gt;

&lt;p&gt;Da mesma forma, temos o &lt;code&gt;findAllBy&lt;/code&gt; que aguarda uma promisse ser resolvida, ou seja, ao menos um elemento aparecer em tela e se ele existir o método retorna uma lista desses elementos encontrados.&lt;/p&gt;

&lt;p&gt;Exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;deve exibir todos os itens da lista&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ItemList&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAllByTestId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;item&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste teste estamos fazendo uma consulta a vários elementos que possuem um test-id de item. Se encontrados, eles serão retornados e armazenados na variável items como um array desses itens. Se não encontrados o teste irá falhar.&lt;/p&gt;




&lt;p&gt;Tranquilo!? Estes são os métodos de consulta disponíveis na API do React Testing Library. O conhecimento sobre cada método, o que cada um retorna nos dá uma visão muito boa sobre quais situações eles seriam adequados ao testar nossas aplicações. &lt;/p&gt;

&lt;p&gt;Por exemplo, se você quiser que um teste falhe caso nenhum elemento seja encontrado é bom usar o &lt;code&gt;getBy&lt;/code&gt;. Se for o caso em que você precisa aguardar o elemento aparecer na tela depois de um tempo, você pode usar o &lt;code&gt;findBy&lt;/code&gt;, ou se quiser uma lista desses elementos pode usar &lt;code&gt;findAllBy&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Deu para notar que cada um desses métodos de consulta utilizam um seletor, que identifica o que estamos consultando, por exemplo, o &lt;code&gt;getByText&lt;/code&gt; ou &lt;code&gt;queryByText&lt;/code&gt; vai buscar um elemento pelo seu texto. O &lt;code&gt;getByTestId&lt;/code&gt; busca um elemento pelo seu &lt;code&gt;data-test&lt;/code&gt;, e por aí vai. &lt;a href="https://testing-library.com/docs/queries/about/#types-of-queries" rel="noopener noreferrer"&gt;Se você quiser conhecer mais sobre cada um desses métodos pode clicar aqui e acessar a documentação do React Testing Library&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Grande abraço e até a próxima! &lt;/p&gt;

</description>
      <category>testing</category>
      <category>react</category>
      <category>javascript</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Testes no Front-end: Escrevendo seu primeiro teste</title>
      <dc:creator>Neilton Seguins</dc:creator>
      <pubDate>Thu, 02 Mar 2023 15:30:00 +0000</pubDate>
      <link>https://forem.com/neiltonseguins/testes-no-front-end-escrevendo-seu-primeiro-teste-go4</link>
      <guid>https://forem.com/neiltonseguins/testes-no-front-end-escrevendo-seu-primeiro-teste-go4</guid>
      <description>&lt;p&gt;No último artigo eu falei um pouco sobre testes no front-end, os motivos de testar suas aplicações, tipos de testes e principais ferramentas para isso. &lt;/p&gt;

&lt;p&gt;Neste artigo iremos escrever nosso primeiro teste para um componente de uma aplicação React. Vamos lá!&lt;/p&gt;

&lt;h2&gt;
  
  
  Criando o componente
&lt;/h2&gt;

&lt;p&gt;Suponha que precisamos testar o seguinte componente React chamado "Counter", que exibe um contador que é incrementado sempre que um botão é clicado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;incrementCount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Contador: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;incrementCount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Incrementar&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse componente não recebe nenhuma &lt;em&gt;prop&lt;/em&gt;, ele tem apenas um estado, o contador (count) que é incrementado sempre que o botão "Incrementar" é clicado. &lt;/p&gt;

&lt;p&gt;Perfeito! Então vamos criar um teste para este componente.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testando o componente &lt;code&gt;&amp;lt;Counter /&amp;gt;&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Para testar componentes React eu vou usar o &lt;a href="https://jestjs.io/pt-BR/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt; e o &lt;a href="https://testing-library.com/" rel="noopener noreferrer"&gt;Testing Library&lt;/a&gt;. O Jest é bem fácil de usar e servirá para fazermos asserções sobre nosso código, enquanto que o Testing Library serve para para facilitar a renderização dos componentes e a interação com eles. &lt;/p&gt;

&lt;p&gt;Se você criou sua aplicação React com o Create React App (CRA) é provável quee já tenha tanto o jest como os recursos do React Testing Library no seu projeto. Se não, se você usou o Vite por exemplo, pode ser que precise instalar essas dependências. Para instalar é bem simples, é só digitar no seu terminal&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; jest @testing-library/react @testing-library/jest-dom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ambiente preparado, então vamos ao teste. &lt;/p&gt;

&lt;p&gt;Vamos criar um arquivo de teste para o componente Counter, com o nome &lt;code&gt;Counter.test.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;userEvent&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/user-event&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/jest-dom/extend-expect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Counter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Counter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Deve renderizar o contador sem erros&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;textoContador&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Contador: 0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;textoContador&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Deve incrementar o contador quando o botão é clicado&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Counter&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;botaoIncrementar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Incrementar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;novoTextoContador&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Contador: 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;userEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;botaoIncrementar&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;novoTextoContador&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tá, mas o que significa cada linha deste teste? Vou explicar.&lt;/p&gt;

&lt;p&gt;Primeiro precisamos fazer as importações dos utilitários que iremos precisar. Para renderizar nosso componente importamos o &lt;code&gt;render&lt;/code&gt;, para observar o que foi renderizado utilizamos &lt;code&gt;screen&lt;/code&gt; e para fazer consultas aos elementos desse componente utilizamos o &lt;code&gt;getByText()&lt;/code&gt;. Não se preocupe com essas funções e utilitários agora, irei  trazer explicações mais detalhadas sobre cada um em outros artigos.&lt;/p&gt;

&lt;p&gt;Para agrupar e organizar melhor os testes deste componente, eu utilizo o &lt;code&gt;describe&lt;/code&gt; e dou uma descrição que nada mais é que o nome do componente, mas você pode fazer descrições mais detalhadas. &lt;/p&gt;

&lt;p&gt;O teste em si mesmo, só começa quando declaramos ele, com o &lt;code&gt;it()&lt;/code&gt;. O &lt;code&gt;it&lt;/code&gt; recebe dois parâmetros, que é a descrição do cenário de teste e uma função que executará o teste. &lt;/p&gt;

&lt;p&gt;Como boa prática, eu gosto de seguir uma ordem ao escrever um cenário de teste.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Renderizo o componente que estou testando com o render;&lt;/li&gt;
&lt;li&gt;Faço uma consulta a um elemento usando o &lt;code&gt;screen&lt;/code&gt; e uma &lt;em&gt;query&lt;/em&gt; de consulta, neste caso o &lt;code&gt;getByText()&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Faço uma asserção, que é a comparação entre o que eu espero e o que eu recebo no meu teste;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Neste primeiro teste eu tenho dois cenários: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O primeiro verifica se o componente &lt;code&gt;&amp;lt;Counter /&amp;gt;&lt;/code&gt; é renderizado sem erros e se o contador é iniciado com o valor 0.&lt;/li&gt;
&lt;li&gt;O segundo simula um clique no botão "Incrementar" e verifica se o contador é incrementado corretamente.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O clique no botão é realizado utilzando o utilitário &lt;code&gt;userEvent&lt;/code&gt;, que possui uma grande quantidade de eventos que simulam interações com a página, como digitar em campos de texto, selecionar opções em um select, etc.&lt;/p&gt;

&lt;p&gt;Como outra boa prática eu gosto de salvar o que é retornado das consultas em variáveis e dar nome à elas que sejam significativos. Por exemplo, eu  usei o &lt;em&gt;textoContador&lt;/em&gt; para receber o que foi retornado de resultado da minha consulta a este elemento. E chamei de &lt;em&gt;botaoIncrementar&lt;/em&gt; o botão que obtemos ao fazer a consulta pelo seu texto também. &lt;/p&gt;

&lt;p&gt;Você pode perceber que ao fazer isso, fica bem mais simples de ler o teste, por exemplo, nesta asserção:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;textoContador&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ao ler eu claramente sei o que esse teste faz, que é: "Espero que o texto do contador esteja no documento". &lt;/p&gt;

&lt;h2&gt;
  
  
  Executando os testes
&lt;/h2&gt;

&lt;p&gt;Para executar os testes de sua aplicação é bem simples, é só digitar em um terminal&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este script vem como padrão ao iniciar a aplicação com o CRA.&lt;/p&gt;




&lt;p&gt;E prontinho! Em menos de cinco minutos você escreveu o que chamamos de &lt;strong&gt;testes de unidade&lt;/strong&gt; para um componente React. Este tipo de teste é simples, onde estamos &lt;em&gt;testando uma unidade&lt;/em&gt;, no caso um componente, que é uma função, e como esse componente tem sua própria responsabilidade, que é renderizar o contador e incrementá-lo ao clicar em um botão, ele pode ser facilmente testado com testes esse. &lt;/p&gt;

&lt;p&gt;Dependendo do projeto, pode ser necessário escrever testes mais complexos e abrangentes para garantir a qualidade do código. &lt;/p&gt;

&lt;p&gt;Maneiro né? Se está gostando dessa série de artigos sobre testes no Front-end comenta aí o que tem achado e se esse conteúdo tem te ajudade de alguma forma!&lt;/p&gt;

&lt;p&gt;Até a próxima!&lt;/p&gt;

</description>
      <category>testing</category>
      <category>react</category>
      <category>javascript</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Testes no Front-end: por que, como e quais tipos usar</title>
      <dc:creator>Neilton Seguins</dc:creator>
      <pubDate>Wed, 01 Mar 2023 15:15:35 +0000</pubDate>
      <link>https://forem.com/neiltonseguins/testes-no-front-end-por-que-como-e-quais-tipos-usar-11jp</link>
      <guid>https://forem.com/neiltonseguins/testes-no-front-end-por-que-como-e-quais-tipos-usar-11jp</guid>
      <description>&lt;p&gt;Testes são fundamentais em qualquer tipo de aplicação, e com o front-end não é diferente. Afinal, testar as funcionalidades e a usabilidade da sua aplicação web ajuda a &lt;strong&gt;garantir&lt;/strong&gt; que ela esteja funcionando corretamente, sem bugs, e que a experiência do usuário esteja satisfatória.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tipos de testes no Front-end
&lt;/h2&gt;

&lt;p&gt;Existem diversos tipos de testes que podem ser utilizados em aplicações front-end. Entre os mais comuns, podemos destacar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Testes Unitários&lt;/strong&gt;: São testes que avaliam &lt;strong&gt;pequenas partes do código&lt;/strong&gt;, como funções e métodos. Esses testes garantem que essas partes do código funcionem corretamente. O &lt;a href="https://jestjs.io/pt-BR/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt; é uma das ferramentas mais comuns para testes unitários.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Testes de Integração&lt;/strong&gt;: São testes que avaliam a &lt;strong&gt;integração entre as partes da aplicação&lt;/strong&gt;. Eles garantem que os diferentes componentes se comuniquem corretamente e que a aplicação como um todo funcione corretamente.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Testes End-to-End&lt;/strong&gt;: São testes que &lt;strong&gt;simulam a interação de um usuário com a aplicação&lt;/strong&gt;. Eles garantem que a aplicação funcione corretamente do ponto de vista do usuário final. O &lt;a href="https://www.cypress.io/" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt; é uma das ferramentas mais comuns para testes end-to-end.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Ferramentas de Testes
&lt;/h2&gt;

&lt;p&gt;Existem muitas ferramentas de testes para aplicações de Front-end. Algumas das mais comuns são:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://jestjs.io/pt-BR/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt;: É um framework de testes criado pelo Facebook. Ele é rápido e fácil de usar e tem uma boa documentação. É comumente usado para testes unitários e de integração em aplicações React.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://testing-library.com/" rel="noopener noreferrer"&gt;Testing Library&lt;/a&gt;: É uma biblioteca que ajuda a testar as interações do usuário com a aplicação. É fácil de usar e tem uma abordagem mais voltada para o usuário final.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.cypress.io/" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt;: É uma ferramenta de teste de integração que simula a interação do usuário com a aplicação. É útil para testes de ponta a ponta, onde você deseja testar a aplicação como um todo.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://pptr.dev/" rel="noopener noreferrer"&gt;Puppeteer&lt;/a&gt;: É uma biblioteca que controla um navegador Chrome para testar a aplicação. É útil para testes de aceitação, onde você deseja testar a aplicação como um usuário final faria.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://enzymejs.github.io/enzyme/" rel="noopener noreferrer"&gt;Enzyme&lt;/a&gt;: É uma biblioteca de testes que fornece utilitários para interagir com componentes React e verificar o seu estado. Ele é amplamente utilizado para testes unitários e de integração em aplicações React, e oferece uma sintaxe simples e fácil de entender para testar componentes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=""&gt;Mocha&lt;/a&gt;: É um framework de teste de JavaScript que suporta testes assíncronos e síncronos, bem como testes de unidade e integração. Ele também oferece uma ampla variedade de recursos, incluindo hooks para configurar testes, relatórios detalhados e suporte a múltiplos ambientes de execução.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cada ferramenta possui vantagens e desvantagens ao testar suas aplicações. Independentemente da ferramenta escolhida, o importante é que as aplicações sejam testadas regularmente e com cuidado. Testes bem escritos podem ajudar a detectar bugs antes que eles se tornem um problema sério, melhorar a qualidade do código e facilitar a manutenção da aplicação.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mas por que testar as aplicações Front-end?
&lt;/h2&gt;

&lt;p&gt;Testar aplicações front-end é importante porque elas são a interface principal entre os usuários e o sistema. É fundamental garantir que a interface do usuário funcione conforme o esperado. &lt;/p&gt;

&lt;p&gt;Além disso, as aplicações front-end estão sujeitas a uma grande variedade de dispositivos, navegadores e sistemas operacionais. Testes podem ajudar a garantir que a aplicação funcione corretamente em todos os ambientes possíveis.&lt;/p&gt;




&lt;p&gt;Bom, essa foi apenas uma breve introdução sobre testes no Front-end, espero que em breve eu possa trazer mais assuntos sobre este tema tão rico e importante no desenvolvimento de software!&lt;/p&gt;

&lt;p&gt;Espero que vocês tenham curtido a leitura e até a próxima!!&lt;/p&gt;

</description>
      <category>testing</category>
      <category>frontend</category>
      <category>react</category>
    </item>
  </channel>
</rss>
