Testando views em RSpec Rails
Tags: rails, rspec, testing
Published: 2022-12-09 14:26:22

Até agora, nós testamos o model e request, ainda falta views, system, mailer, channel e routes.

Também existe outros, como controller, feature, helper, job e mailbox, porém alguns deles estão obsoleta ou é trivial para gente.

O nosso foco é Views.

Mas o que é que vamos testar nele?

Bem, o conteúdo.

Nós vamos testar se a view está de fato com informação que precisamos.

Lembre-se que esse teste não testa o javascript.

Mas talvez você se pergunte de o por quê desse teste.

Bem, vamos criar um situação aqui, imagine que você tem um e-commerce e então um usuário clica em um produto chamado "Camiseta de Boku no hero" e ele é redirecionado para outra página que tem mais detalhes sobre essa camiseta, porém o usuário descobre que a página está com informação errada, porque produto não é o que ele escolheu, pois o nome do produto está "Camiseta de Boku no pico" e convenhamos que isso é problemático.

Então, o que aconteceu?

Depende, existe muitos fatores que pode ter ocorrido para causar esse problema.

Mas como evitaria esse problema?

Bem, testando.

Se tivesse testado que o conteúdo está correto, talvez descobriria a fonte do problema, mas não, você decidiu que esse teste é irrelevante.

Bem, chega de papo, vamos construir a aplicação.

A nossa aplicação só vai ter um controller e um model, que é o produto, só isso.

Se quiser acompanhar a gente, basta executar os comandos abaixo.

```bash
rails new teste_views --skip-test
cd teste_views
rails db:create db:migrate
echo 'gem "rspec-rails", group: [:development, :test]' >> Gemfile
bundle install
rails g rspec:install
```

Bem, com a aplicação criada, vamos criar o model e o controller.

```bash
rails g model Produto nome preco:float descricao:text
rails db:migrate
rails g controller Produtos index
```

O nosso controller só vai ter uma action, pois, no nosso caso, não será necessário ter os `show`, `new`, `create` etc.

O nosso model tem nome, preço e descrição, e são eles que tem a informação que nós queremos testar.

Vamos para `spec/views/produtos/index.html.erb_spec.rb` e adiciona o teste.

```ruby
# spec/views/produtos/index.html.erb_spec.rb
require 'rails_helper'

RSpec.describe "produtos/index.html.erb", type: :view do
  it "Deve mostrar todos os produtos" do
    Produto.create(
      nome: "Camiseta de Boku no hero",
      preco: 100,
      descricao: "Uma camiseta de Midoriya"
    )

    Produto.create(
      nome: "Camiseta de One piece",
      preco: 100,
      descricao: "Uma camiseta de Zoro"
    )

    assign(:produtos, Produto.all)

    render

    expect(rendered).to match "Camiseta de Boku no hero"
    expect(rendered).to match "Camiseta de One piece"
  end

  it "Não deve ter os produtos" do
    assign(:produtos, Produto.all)

    render

    expect(rendered).not_to match "Camiseta de Boku no hero"
    expect(rendered).not_to match "Camiseta de One piece"
  end
end
```

Bem, é pequeno, o teste.

E de fato, é pequeno, porque não tem muito o que testar além do conteúdo.

Bem, vamos analisar o código, o que podemos ver de coisas novas, se você acompanha essa série que fiz, são:

- `assign`
- `render`
- `rendered`
- `match`

Vamos de cada vez.

Eu não sei se você lembra do método `assigns` que usamos no teste de request, apesar de ter nome iguais, o que difere é a letra `s` no final, e a funcionalidade deles são diferentes.

O `assigns` pega o valor da variável de instância do controller, enquanto o `assign` atribui para uma variável de instância do controller.

Agora vamos ver os argumentos que eu passei, no primeiro argumento, eu passei um symbol do nome da variável, isso significa que ele vai atribuir o valor para o `@produtos`, e o segundo argumento é o valor e eu coloquei uma array de produtos.

Não tem muito segredo nesse método, então é isso.

O `render` é o método que renderizar a página, ou seja, ele vai criar a página web.

O `rendered` é a página renderizada pelo o `render`.

E o match é o método de busca de string em uma string.

Pronto, com explicação dada, vamos rodar o teste.

```bash
rspec

Finished in 0.55462 seconds (files took 4.11 seconds to load)
6 examples, 1 failure, 2 pending

Failed examples:

rspec ./spec/views/produtos/index.html.erb_spec.rb:4 # produtos/index.html.erb Deve mostrar todos os produtos
```

É obvio que falhou, porque não fizemos nada com a view e o controller.

Vamos primeiro para o controller, vá para `app/controllers/produtos_controller.rb`

```ruby
class ProdutosController < ApplicationController
  def index
    @produtos = Produto.all
  end
end
```

Pronto, agora vamos para o `app/views/produtos/index.html.erb` e colocar os produtos.

```erb
# app/views/produtos/index.html.erb

<%= @produtos.each do |produto| %>
	<%= produto.nome %>
<% end %>
```

Vamos rodar o teste.

```bash
rspec

Finished in 0.60784 seconds (files took 5.35 seconds to load)
6 examples, 0 failures, 2 pending
```

Sem nenhuma falha.

E é isso, nós acabamos por aqui.

Como eu não tenho nada o que falar, tchau!