Usando shared_examples de Rspec para especificar um novo comportamento

Suponha que temos um CartController e uma especificação correspondente. No momento, apenas usuários logados podem adicionar itens a seus carrinhos, e queremos oferecer suporte a carrinhos para usuários convidados.

Até agora, a especificação pode ser assim:

describe CartController do
let(:user) { create(:user) }
let(:item) { create(:item) }
let(:response_items) { JSON.parse(response["items"]) }

describe
:index do
it
"returns items in the cart" do
user
.cart.add(item)

get :index

response_items
[0]["id"].should == item.id
end
end

describe
:create do
it
"adds an item to the cart" do
post
:create, id: item.id

response_items
[0]["id"].should == item.id
end
end

describe
:destroy do
it
"removes an item from the cart" do
user
.cart.add(item)

delete :destroy, id: item.id

response_items
.should be_empty
end
end
end

Agora, para adicionar suporte para carrinhos de convidados, pode ser tentador adicionar coisas como:

it "adds an item to the cart when user is a guest"
it
"removes an item to the cart when user is a guest"

Mas isso vai acabar repetindo muitas das especificações anteriores. É importante isolar o que está realmente mudando, que é o usuário. Então, vamos configurar alguns blocos de contexto para os dois cenários:

context "signed in user" do
let(:user) { create(:user) }
end

context
"guest user" do
let(:user) { User.new }
end

Agora, precisamos apenas de nossas especificações anteriores para executar nesses dois contextos. Podemos fazer isso movendo-os para exemplos compartilhados e executando esses exemplos em nossos contextos:

shared_examples "cart requests" do
describe
:index
describe
:create
describe
:destroy
end

context
"signed in user" do
let(:user) { create(:user) }

it_behaves_like
"cart requests"
end

context
"guest user" do
let(:user) { User.new }

it_behaves_like
"cart requests"
end

Com essa abordagem, adicionamos uma nova camada de comportamento às nossas especificações com muito pouca repetição ou código real.

E o mais importante, como reutilizamos as especificações anteriores, podemos ter certeza de que todas as funcionalidades de um usuário real também estão disponíveis para usuários convidados.