Метод тестового уничтожения RSpec (Rails Tutorial 3.2 Ch. 9, пр. 10)

Примечание :Я прочитал этот вопрос и ответ, но по какой-то причине код у меня не работает. (см. ниже ошибку, которую я получаю)

Упражнение 10 из Главы 9 Учебника по Rails просит вас :Изменить действие уничтожения [для пользователей], чтобы пользователи-администраторы не могли уничтожить себя. (Сначала напишите тест.)

Сложность здесь заключается в том, чтобы протестировать его, потому что приложение уже скрывает ссылку «удалить» для текущего пользователя, поэтому вам нужно выполнить HTTP-запрос напрямую.

Я заставил код работать и протестировал его, удалив часть кода, которая скрывает ссылку удаления для текущего пользователя. Конечно,если я нажимаю на ссылку удаления для текущего пользователя -, он перенаправляет меня и дает мне уведомление.

От пользователей _controller.rb

  def destroy
    @user = User.find(params[:id])
    if current_user?(@user)
      redirect_to users_path, notice: "You can't destroy yourself."
    else
      @user.destroy
      flash[:success] = "User destroyed."
      redirect_to users_path
    end
  end

Проблема, с которой я сталкиваюсь, заключается в написании тестов для этого, которые будут отправлять запрос на удаление и вызывать метод уничтожения. Я попробовал решение из Rspec test для уничтожения, если нет ссылки на удаление , которое я копирую здесь:

Из пользовательских _страниц _спец.рб

 describe "destroy" do
    let(:admin) { FactoryGirl.create(:admin) }

    it "should not allow the admin to delete herself" do
      sign_in admin
      #expect { delete user_path(admin), method: :delete }.should change(User, :count)
      expect { delete :destroy, :id => admin.id }.should_not change(User, :count)
    end
  end

Но когда я запускаю это, я получаю эту ошибку от RSpec

Failures:

  1) User Pages destroy should not allow the admin to delete herself
     Failure/Error: expect { delete :destroy, :id => admin.id }.should_not change(User, :count)
     ArgumentError:
       bad argument (expected URI object or URI string)
     #./spec/requests/user_pages_spec.rb:180:in `block (4 levels) in '
     #./spec/requests/user_pages_spec.rb:180:in `block (3 levels) in '

Итак, мои вопросы :1 )Почему приведенный выше код не работает? 2 )Как имитировать «удаление», чтобы вызвать действие уничтожения в моем контроллере?

Окружающая среда :Mac OS X рубин 1.9.3p194 Рельсы 3.2.3

Драгоценные камни для тестирования:
группа :тест делать gem 'rspec -рельсы', '2.9.0' драгоценный камень «капибара», «1.1.2» gem 'rb -fsevent', '0.4.3.1', :требуют => ложь драгоценный камень «рычание», «1.0.3» драгоценный камень 'охрана -спорк', '0.3.2' гем 'спорк', '0.9.0' gem 'фабрика _девушка _рельсы', '1.4.0' конец

Подробнее Я пробовал тонну способов, чтобы попытаться имитировать нажатие на ссылку удаления, и ни один из них не работает. Я использовал драгоценный камень отладчика, чтобы увидеть, вызывается ли метод уничтожения. В тесте, который щелкает ссылку для удаления другого пользователя, вызывается метод уничтожения, и он работает нормально:

it "should be able to delete another user" do
  expect { click_link('delete') }.to change(User, :count).by(-1)
end

Но ничто из того, что я пытался сгенерировать запрос на удаление напрямую, не помогло вызвать метод уничтожения.

Спасибо за вашу помощь!

Уилл

**ОБНОВЛЕНИЕ**

Я попробовал предложение DVG:

describe "destroy" do
    let(:admin) { FactoryGirl.create(:admin) }

    it "should not allow the admin to delete herself" do
      sign_in admin
      #expect { delete user_path(admin), method: :delete }.should change(User, :count)
      expect { delete :destroy, :id => admin }.to_not change(User, :count)
    end
  end

И получил эту ошибку:

6) User Pages destroy should not allow the admin to delete herself
     Failure/Error: expect { delete :destroy, :id => admin }.to_not change(User, :count)
     ArgumentError:
       bad argument (expected URI object or URI string)
     #./spec/requests/user_pages_spec.rb:190:in `block (4 levels) in '
     #./spec/requests/user_pages_spec.rb:190:in `block (3 levels) in '

РЕШЕНИЕ

Я понял это после FOREVER.

Мне пришлось использовать Rack ::Test для выдачи запроса DELETE, но Capybara и Rack ::Test не используют один и тот же MockSession, поэтому мне пришлось вытащить токен :запомнить _и :!sample _приложение _файлы cookie сеанса и поместите их в запрос DELETE вручную.Вот что сработало. (другая проблема, с которой я столкнулся, описанная ниже, заключалась в том, что у меня было выражение force _ssl, которое не позволяло вызвать мое действие по уничтожению.

describe "destroy" do
    let!(:admin) { FactoryGirl.create(:admin) }

    before do
      sign_in admin
    end

    it "should delete a normal user" do
      user = FactoryGirl.create(:user)
      expect { delete user_path(user), {},
       'HTTP_COOKIE' => "remember_token=#{admin.remember_token},
        #{Capybara.current_session.driver.response.headers["Set-Cookie"]}" }.
        to change(User, :count).by(-1)
    end

    it "should not allow the admin to delete herself" do
      expect { delete user_path(admin), {},
       'HTTP_COOKIE' => "remember_token=#{admin.remember_token},
        #{Capybara.current_session.driver.response.headers["Set-Cookie"]}" }.
       to_not change(User, :count)
    end
  end

У меня было выражение force _ssl после моих фильтров before _в моих пользователях _controller.rb, и это каким-то образом сбивало ситуацию, поэтому я так и не добрался до действия уничтожения.

class UsersController < ApplicationController
  before_filter :signed_in_user,  only: [:edit, :update, :index]
  before_filter :existing_user,   only: [:new, :create]
  before_filter :correct_user,    only: [:edit, :update]
  before_filter :admin_user,      only: :destroy

  #force_ssl

  def index
    @users = User.paginate(page: params[:page])
  end

  def show 
    @user = User.find(params[:id])
    @microposts = @user.microposts.paginate(page: params[:page])
  end

  def destroy
    @user = User.find(params[:id])
    if current_user?(@user)
      redirect_to users_path, notice: "You can't destroy yourself."
    else
      @user.destroy
      flash[:success] = "User destroyed."
      redirect_to users_path
    end
  end

Они помогли найти решение

https://gist.github.com/484787

http://collectiveidea.com/blog/archives/2012/01/05/capybara-cucumber-and-how-the-cookie-crumbles/

15
задан Community 23 May 2017 в 12:01
поделиться