2012-06-12 49 views
14

नोट: मैंने this प्रश्न और उत्तर पढ़ा है, लेकिन किसी कारण से कोड मेरे लिए काम नहीं कर रहा है। (मुझे जो त्रुटि मिल रही है, उसके लिए नीचे देखें)आरएसपीसी परीक्षण विधियों को नष्ट कर देता है (रेल ट्यूटोरियल 3.2 सी। 9, एक्स 10)

रेल ट्यूटोरियल के अध्याय 9 से व्यायाम 10 आपको पूछता है: व्यवस्थापक उपयोगकर्ताओं को खुद को नष्ट करने से रोकने के लिए [उपयोगकर्ताओं के लिए] नष्ट करें क्रिया को संशोधित करें। (पहले एक परीक्षण लिखें।)

यहां मुश्किल हिस्सा इसका परीक्षण कर रहा है, क्योंकि एप्लिकेशन वर्तमान उपयोगकर्ता के लिए पहले से ही "हटाएं" लिंक छुपाता है, इसलिए आपको सीधे http अनुरोध करना होगा।

मुझे कोड मिल रहा है, और कोड के टुकड़े को हटाकर इसका परीक्षण किया गया है जो वर्तमान उपयोगकर्ता के लिए डिलीट लिंक छुपाता है। निश्चित रूप से, अगर मैं वर्तमान में लॉग-इन किए गए उपयोगकर्ता के लिए डिलीट लिंक पर क्लिक करता हूं, तो यह मुझे रीडायरेक्ट करता है और मुझे नोटिस संदेश देता है।

users_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 for destroy if no delete link से समाधान करने की कोशिश की, जिसे मैंने यहां कॉपी करने हूँ:

से user_pages_spec.rb

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 <top (required)>' 
    # ./spec/requests/user_pages_spec.rb:180:in `block (3 levels) in <top (required)>' 

यह त्रुटि प्राप्त तो, मेरे प्रश्न हैं: 1) यह कोड विफल होने से ऊपर क्यों है? 2) मैं अपने नियंत्रक में नष्ट कार्रवाई को कॉल करने के लिए "हटाएं" अनुकरण कैसे करूं?

पर्यावरण: मैक OSX माणिक 1.9.3p194 रेल परीक्षण के लिए 3.2.3

रत्न:
समूह: परीक्षण करना मणि 'rspec-रेल', '2.9.0' मणि 'capybara ',' 1.1.2 ' मणि' आरबी-फ़ेसेंट ',' 0.4.3.1 ',: आवश्यकता => झूठी मणि' उगलना ',' 1.0.3 ' मणि' गार्ड-स्पार्क ',' 0.3.2 ' मणि 'स्पार्क', '0.9.0' मणि 'factory_girl_rails', '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 <top (required)>' 
    # ./spec/requests/user_pages_spec.rb:190:in `block (3 levels) in <top (required)>' 

समाधान

मैंने इसे बाद में बाहर निकाला।

मुझे डेले अनुरोध जारी करने के लिए रैक :: टेस्ट का उपयोग करना पड़ा, लेकिन कैपिबरा और रैक :: टेस्ट एक ही मॉक सत्र साझा नहीं करता है, इसलिए मुझे इसे याद रखना था: remember_token और:! Sample_app_session कुकीज़ और उन्हें डाल दें मैन्युअल रूप से 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 

मैं अपने users_controller.rb और इस में मेरी before_filters के बाद एक force_ssl बयान था किसी भी तरह बातें बंद फेंक रहा था तो मैं नष्ट कार्रवाई करने के लिए नहीं मिला।

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/

+0

एक बात मैं सिर्फ खोज की है, जो मेरी समस्या बिल्कुल नहीं है, लेकिन एक * समस्या * जा सकता है कि लेट विधि आलसी है है, इसलिए मैं यह पंगा लेना कार्यप्रणाली को to_not उम्मीद कल्पना कर सकता। तो मैंने उपयोग करने के लिए कोड समायोजित किया! व्यवस्थापक उपयोगकर्ता बनाते समय। –

+0

आप जिस परिदृश्य का परीक्षण कर रहे हैं वह क्या है? व्यवस्थापक लॉग इन करता है, लिंक हटाया जाता है, लेकिन वह किसी भी तरह से हटाए गए अनुरोध को शिल्प करता है? (बस पूछना) –

+0

अच्छा सवाल है। ज्यादातर जवाब यह है कि यह रेल ट्यूटोरियल में एक अभ्यास था। यह पता चला कि यह एक अच्छा अभ्यास था, क्योंकि मैंने कुकीज़, http अनुरोध, कैपिबरा और रैक :: टेस्ट के बारे में सभी प्रकार की चीजें सीखीं। मुझे लगता है कि मैं परिदृश्य का परीक्षण कर सकता हूं जहां हटाए गए लिंक को छिपाने के लिए कोड विफल रहता है और मैं चाहता हूं कि मेरे नियंत्रक का बैक-अप हो। –

उत्तर

5

आप rspec-रेल अनुरोध चश्मा जो एकीकरण परीक्षण कर रहे हैं और एक नकली ब्राउज़र और नियंत्रक चश्मा जो परीक्षण अलगाव में नियंत्रक में क्रियान्वित कर रहे हैं भ्रमित कर रहे हैं। delete(action, *args) (और get, post और इसी तरह) - एक्शनकंट्रोलर :: टेस्टकेस से अनुरोध अनुकरण करने का एक तरीका है, इसलिए यह आपके परीक्षण में उपलब्ध नहीं है।

तो आपका एकमात्र विकल्प ब्राउज़र में एक क्लिक अनुकरण करना है। मुझे नहीं पता कि आप अपना डिलीट लिंक कैसे छिपाते हैं, अगर एचटीएमएल वहां है लेकिन छुपा हुआ है तो आपको इसे क्लिक करने में सक्षम होना चाहिए। यदि यह वहां नहीं है (दृश्य उत्पन्न करते समय सर्वर पक्ष पर हटा दिया गया है) तो आप कैपिबरा के page.execute_script का उपयोग कर सकते हैं (लेकिन आपको इस उदाहरण के लिए जावास्क्रिप्ट को सक्षम करना होगा :js => true)। आप या तो लिंक वापस जोड़ सकते हैं:

page.execute_script("$('body').append("<a href="https://stackoverflow.com/users/1" data-method="delete" rel="nofollow">Destroy</a>")") 

या ajax फोन करना:

page.execute_script("$.ajax({type:'DELETE',url:'/users/1'})") 

का परीक्षण नहीं किया था, लेकिन कुछ इस तरह काम करना चाहिए।

3

इस प्रयास करें:

expect { delete :destroy, :id => admin }.to_not change(User, :count) 
+0

कोशिश की, एक ही त्रुटि (ऊपर देखें) –

+0

यह मेरे लिए काम किया। धन्यवाद! –

6

मैं निम्नलिखित का उपयोग कर इस एक ही समस्या हल हो:

describe "should not be able to delete themselves" do 
    it { expect { delete user_path(admin) }.not_to change(User, :count) } 
end 
+1

मुझे लगता है कि यह केवल नियंत्रक परीक्षणों में काम करता है, न कि एकीकरण परीक्षण। – Dean

+0

यह परीक्षण गुजरता है, इसके बावजूद मैंने मैन्युअल रूप से इसका परीक्षण किया और यह काम नहीं करता है। (यह असफल होना चाहिए) –

6

CallumD के समाधान मेरे लिए काम किया है, और सबसे तकनीक माइकल हार्टल के शेष ट्यूटोरियल में सिफारिश के अनुरूप लग रहा था।

it "should not be able to delete itself" do 
    expect { delete user_path(admin) }.not_to change(User, :count) 
end 
+1

मैं सहमत हूं। मैने भी वही कीया। – KMcA

5

यह है कि मैं क्या साथ समाप्त हो गया है (Rspec 3.2): लेकिन मैं एक छोटे से वाक्य रचना में इसे और अधिक एक ही ट्यूटोरियल में अन्य चश्मा के अनुरूप बनाने के लिए ऊपर मजबूत करने के लिए चाहता था

describe 'DELETE destroy' do 
    before :each do 
    delete :destroy, { id: current_partner_role } 
    end 

    it 'destroys role' do 
    expect(assigns(:role).destroyed?).to be true 
    end 

"नष्ट किया हुआ?" विधि स्वयं रेल द्वारा spec-ed है इसलिए IMHO इसे भरोसा करना ठीक होना चाहिए।

https://github.com/rails/rails/blob/5142d5411481c893f817c1431b0869be3745060f/activerecord/lib/active_record/persistence.rb#L91