Pergunta

Eu tenho um aplicativo Sinatra que exibe páginas somente leitura ou editáveis, dependendo se o usuário está logado.

O controlador define uma variável @can_edit, que é usado pelas visualizações para ocultar/mostrar links de edição.Como posso testar @can_edito valor em meus testes?Não tenho ideia de como chegar à instância atual do controlador em Rack::Test.

eu uso class_eval para esboçar o logged_in? método no controlador, mas estou tendo que recorrer à verificação last_response.body para meus links de edição para ver se @can_edit foi definido ou não.

Como posso testar o valor de @can_edit diretamente?

Foi útil?

Solução

Infelizmente não acho que isso seja possível sem modificar Rack::Test.Quando você faz uma solicitação durante o teste do aplicativo, Rack::Test faz o seguinte:

  1. adiciona a solicitação a uma lista de solicitações recentes
  2. cria uma nova instância do seu aplicativo e invoca seu call método
  3. adiciona a resposta do seu aplicativo a uma lista de respostas recentes

É fácil acessar o last_request e last_response, mas infelizmente nenhuma informação é salva sobre o estado do seu aplicativo enquanto ele está em execução.

Se você estiver interessado em hackear um patch Rack::Test para fazer isso, comece olhando rack-test/lib/rack/mock_session.rb na linha 30.É aqui que Rack::Test executa sua aplicação e recebe os valores de retorno padrão do aplicativo Rack (status, cabeçalhos, corpo).Meu palpite é que você também terá que modificar seu aplicativo para coletar e tornar acessíveis todas as suas variáveis ​​de instância.

De qualquer forma, é melhor testar os resultados e não os detalhes da implementação.Se você quiser ter certeza de que um link de edição não está visível, teste a presença do link de edição por ID do DOM:

assert last_response.body.match(/<a href="..." id="...">/)

Outras dicas

É possível com um pequeno hack. As instâncias do aplicativo Sinatra não estão disponíveis porque são criadas quando Sinatra :: Base#a chamada é chamada. Como Alex explicou. Este hack prepara uma instância à frente e deixa a próxima chamada agarrá -la.

require 'something/to/be/required'

class Sinatra::Base
  @@prepared = nil

  def self.onion_core
    onion = prototype
    loop do
      onion = onion.instance_variable_get('@app')
      return onion if onion.class == self || onion.nil?
    end
  end

  def self.prepare_instance
    @@prepared = onion_core
  end

  # Override
  def call(env)
    d = @@prepared || dup
    @@prepared = nil
    d.call!(env)
  end
end

describe 'An Sinatra app' do
  include Rack::Test::Methods

  def app
    Sinatra::Application
  end

  it 'prepares an app instance on ahead' do
    app_instance = app.prepare_instance    
    get '/foo'
    app_instance.instance_variable_get('@can_edit').should be_true
  end
end

Eu descobri essa técnica para zombar da instância que executa o teste atual em primeiro lugar.

Aqui está uma alternativa desagradável, mas viável

# app.rb - sets an instance variable for all routes
before do
  @foo = 'bar'
end

# spec.rb
it 'sets an instance variable via before filter' do
  my_app = MySinatraApplication
  expected_value = nil
  # define a fake route
  my_app.get '/before-filter-test' do
    # as previously stated, Sinatra app instance isn't avaiable until #call is performed
    expected_value = @foo
  end
  my_app.new.call({
    'REQUEST_METHOD' => 'GET',
    'PATH_INFO' => '/before-filter-test',
    'rack.input' => StringIO.new
  })
  expect(expected_value).to eq('bar')
end

Isso permite testar um sinatra antes de filtrar e/ou acessar variáveis ​​de instância criadas para o aplicativo base.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top