E
E
Evgeniy Trebin2016-02-07 14:57:27
Ruby on Rails
Evgeniy Trebin, 2016-02-07 14:57:27

RSpec How to access or stub a controller helper method in a view spec?

Decided to try decent_exposure gem . It allows you to shorten the code in CRUD controllers, but instead of @article and @articles variables, it creates helper methods with appropriate names. But I don’t understand how to access such methods in the view or create a stub for them
Rspec 3.4, Rails 4.2.5
Account::ArticlesController

class Account::ArticlesController < Account::BaseController
  expose(:articles) { current_user.articles }
  expose(:article, attributes: :article_params)

  # POST /account/articles
  # POST /account/articles.json
  def create
    respond_to do |format|
      if article.save
        format.html { redirect_to account_article_url(article), notice: 'Article was successfully created.' }
        format.json { render :show, status: :created, location: account_article_url(article) }
      else
        format.html { render :new }
        format.json { render json: article.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /account/articles/1
  # PATCH/PUT /account/articles/1.json
  def update
    respond_to do |format|
      if article.update(article_params)
        format.html { redirect_to account_article_url(article), notice: 'Article was successfully updated.' }
        format.json { render :show, status: :ok, location: account_article_url(article) }
      else
        format.html { render :edit }
        format.json { render json: article.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /account/articles/1
  # DELETE /account/articles/1.json
  def destroy
    respond_to do |format|
      if article.destroy
        format.html { redirect_to account_articles_url, notice: 'Article was successfully destroyed.' }
        format.json { head :no_content }
      else
        format.html { redirect_to account_articles_url, notice: 'Article was not destroyed.' }
        format.json { render json: article.errors, status: :unprocessable_entity }
      end
    end
  end

  private

  def article_params
    params.require(:article).permit(:title, :announce, :content, :is_published, :published_at)
  end

end

action view new
= form_for [:account, article], html: { class: "form-horizontal", role: "form" } do |f|
  -if article.errors.any?
    .alert.alert-danger.alert-dismissable{role: "alert"}
      %button.close{type: "button", data: {dismiss: "alert"} }
        %span{aria: {hidden: "true"} } &times;
        %span.sr-only Close
      %h4= "#{pluralize(article.errors.count, "error")} prohibited this article from being saved:"

      %ul
        - article.errors.full_messages.each do |msg|
          %li= msg

  .form-group
    .col-sm-offset-2.col-sm-10
      = f.submit class: 'btn btn-primary'

spec for the new view
require 'rails_helper'

RSpec.describe 'account/articles/new', type: :view do

  before do
    allow(view).to receive(:article).and_return(build(:article))
  end

  it 'renders new article form' do
    render
    expect(rendered).to match %Q{form[action=#{account_articles_path}][method=post]}
  end
end

Mistake
account/articles/new renders new article form
     Failure/Error: allow(view).to receive(:article).and_return(build(:article))

If this is removed
allow(view).to receive(:article).and_return(build(:article))

Therefore, the method is not defined
Failure/Error: = form_for [:account, article], html: { class: "form-horizontal", role: "form" } do |f|
     
     ActionView::Template::Error:
       undefined local variable or method `article' for #<#<Class:0x007fbb32b4ad30>:0x007fbb35c846a8>

Answer the question

In order to leave comments, you need to log in

1 answer(s)
E
Evgeniy Trebin, 2016-02-08
@evgeniy_trebin

require 'rails_helper'

RSpec.describe 'account/articles/new', type: :view do

  it 'renders new article form' do
    stub_article { Article.new }
    render
    expect(rendered).to match(%r{form.+id="new_article".+action=\"#{account_articles_path}".+accept-charset=\"UTF-8\".+method=\"post\"})
  end

  def stub_article(&block)
    controller.singleton_class.class_exec(block) do
      helper_method :article
      define_method :article do
        block.call
      end
    end
  end

end

or an easier way
require 'rails_helper'

RSpec.describe 'account/articles/new', type: :view do

  it 'renders new article form' do
    def view.article
      Article.new
    end
    render
    expect(rendered).to match %r{form.+id="new_article".+action=\"#{account_articles_path}".+accept-charset=\"UTF-8\".+method=\"post\"}
  end

end

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question