कैपीबारा अंबुजिटी रिज़ॉल्यूशन


97

मैं Capybara में अस्पष्टता कैसे हल करूं? किसी कारण से मुझे एक पृष्ठ में समान मूल्यों के साथ लिंक की आवश्यकता होती है, लेकिन त्रुटि मिलने के बाद से मैं परीक्षण नहीं बना सकता

Failure/Error: click_link("#tag1")
     Capybara::Ambiguous:
       Ambiguous match, found 2 elements matching link "#tag1"

डिज़ाइन के कारण मैं इसे टाल नहीं सकता। मैं ट्विटर पेज को दाईं ओर ट्वीट्स / टैग और पेज के बाईं ओर टैग के साथ फिर से बनाने की कोशिश कर रहा हूं। इसलिए यह अपरिहार्य होगा कि समान लिंक पृष्ठ एक ही पृष्ठ पर दिखाई दे।


क्या आप कृपया कुछ कोड भी पोस्ट कर सकते हैं?
हीना हुसैन

8
आपको पृष्ठ पर दो तत्वों को एक ही आईडी नहीं देनी चाहिए। यदि आपके पास समान लिंक होंगे, तो तत्वों को एक आईडी आवंटित न करें, इसके बजाय एक वर्ग का उपयोग करें।
क्रिस साल्जबर्ग

जवाबों:


147

मेरा समाधान है

first(:link, link).click

के बजाय

click_link(link)

6
यह Capybara उन्नयन गाइड में विस्तृत है यदि आपको यह समस्या थी तो आपको उपयोगी मिल सकता है।
रिची

1
जब तक आप पूरी तरह से करने के लिए Capybara 2.0 के रूप में ऐसा नहीं करते। नीचे दिए गए अपग्रेड गाइड में @ एंड्री का जवाब और नीचे अस्पष्ट मिलान की व्याख्या देखें।
जिम

4
विशेष रूप से, Capybara 2.0 में विशिष्ट प्रतीक्षा गति की मशीनों के पार चश्मा को सुनिश्चित करने या लगातार विफल रहने के लिए बुद्धिमान प्रतीक्षा तर्क है, जबकि केवल न्यूनतम आवश्यक समय की प्रतीक्षा कर रहा है। का प्रयोग firstके रूप में, इसके बाद के संस्करण का सुझाव दिया जब तक आप पूरी तरह से पता है कि तुम क्या कर रहे हैं, चश्मा है कि आप के लिए पारित लेकिन एक सीआई निर्माण में या एक सहयोगी की मशीन पर विफल में परिणाम की संभावना है।
जिम

1
एक अच्छी चर्चा के लिए देखें: robots.thoughtbot.com/…
jim

74

कैपीबारा का ऐसा व्यवहार जानबूझकर किया गया है और मेरा मानना ​​है कि इसे तय नहीं किया जाना चाहिए क्योंकि अधिकांश अन्य उत्तरों में सुझाव दिया गया है।

2.0 से पहले Capybara के संस्करणों ने अपवाद को बढ़ाने के बजाय पहला तत्व वापस कर दिया, लेकिन बाद में Capybara के अनुरक्षकों ने फैसला किया कि यह एक बुरा विचार है और इसे उठाना बेहतर है। यह तय किया गया था कि कई स्थितियों में पहला तत्व वापस लौटता है, उस तत्व को नहीं लौटाता है जिसे डेवलपर लौटना चाहता था।

यहां सबसे उत्क्रमित उत्तर का उपयोग करने firstया allइसके बजाय करने की सलाह देते हैं find:

  1. allऔर firstइस तरह के लोकेटर के साथ तत्व का इंतजार नहीं है, हालांकि पेज पर दिखाई देगा findप्रतीक्षा करता है
  2. all(...).first तथा first आपको इस स्थिति से नहीं बचाएंगे कि भविष्य में इस तरह के लोकेटर के साथ एक और तत्व पृष्ठ पर दिखाई दे सकता है और परिणामस्वरूप आपको गलत तत्व मिल सकता है

तो यह एक और, कम अस्पष्ट लोकेटर चुनने की सलाह दी जाती है : उदाहरण के लिए आईडी, क्लास या अन्य सीएसएस / xpath लोकेटर द्वारा चयनित तत्व ताकि केवल एक तत्व इसका मिलान करेगा।


यहाँ एक नोट के रूप में कुछ लोकेटर हैं जिन्हें मैं आमतौर पर अस्पष्टता का समाधान करते समय उपयोगी मानता हूं:

  • find('ul > li:first-child')

    यह first('ul > li')तब तक अधिक उपयोगी है, जब तक यह पहले liपृष्ठ पर दिखाई देगा।

  • click_link('Create Account', match: :first)

    यह first(:link, 'Create Account').clickउस पेज से कम से कम एक क्रिएट अकाउंट लिंक दिखाई देगा जब तक यह बेहतर होगा। हालाँकि मेरा मानना ​​है कि अद्वितीय लोकेटर चुनना बेहतर है जो पृष्ठ पर दो बार दिखाई नहीं देता है।

  • fill_in('Password', with: 'secret', exact: true)

    exact: true Capybara को केवल सटीक मिलान खोजने के लिए कहता है, अर्थात "पासवर्ड पुष्टिकरण" नहीं मिल रहा है


7
यह शीर्ष उत्तर होना चाहिए। हमेशा एक चयनकर्ता का उपयोग करने का प्रयास करें जो कैपिबारा में अंतर्निहित प्रतीक्षा क्षमताओं का उपयोग करेगा।
tgf

धन्यवाद। मैंने उपयोग करने की कोशिश की: पहले लेकिन एहसास हुआ कि केवल jQuery में काम करता है। मैं जो देख रहा था वह है: पहला बच्चा
ओवरलोड

25

उपरोक्त समाधान महान काम करता है, लेकिन उन जिज्ञासुओं के लिए आप निम्न सिंटैक्स का भी उपयोग कर सकते हैं।

click_link(link_name, match: :first)

आपके द्वारा यहां और अधिक जानकारी प्राप्त की जा सकती है:

http://taimoorchangaizpucitian.wordpress.com/2013/09/06/capybara-click-link-different-cases-and-solutions/


24

नई उत्तर:

आप कुछ इस तरह की कोशिश कर सकते हैं

all('a').select {|elt| elt.text == "#tag1" }.first.click

ऐसा करने का एक तरीका हो सकता है जो उपलब्ध Capybara सिंटैक्स का बेहतर उपयोग करता है - कुछ की तर्ज पर all("a[text='#tag1']").first.clickलेकिन मैं सही सिंटैक्स ऑफ हैंड के बारे में नहीं सोच सकता और मुझे उपयुक्त दस्तावेज नहीं मिल सकता है। यही कारण है कि ने कहा कि यह एक अजीब स्थिति का एक सा के साथ शुरू, दो होने है <a>ही साथ टैग id, classऔर पाठ। क्या कोई मौका है कि वे अलग-अलग डिवीजन के बच्चे हैं, क्योंकि तब आप अपने find withinडोम के उपयुक्त सेगमेंट कर सकते थे। (यह आपके HTML स्रोत को थोड़ा देखने में मदद करेगा)।


पुराने उत्तर: (जहां मुझे लगा कि '# टैग 1' का अर्थ तत्व idका "टैग 1" था)

आप किस लिंक पर क्लिक करना चाहते हैं? यदि यह पहला (या इससे कोई फर्क नहीं पड़ता), तो आप कर सकते हैं

find('#tag1').click

नहीं तो आप कर सकते हैं

all('#tag1')[1].click

दूसरा क्लिक करने के लिए।


पहले समाधान पर काम हो सकता है लेकिन अब समस्या यह है कि शायद यह एक सीएसएस आईडी के लिए गलत है --------- विफलता / त्रुटि: ढूँढें ('# tag1') # # या सभी पर क्लिक करें ('#) tag1 ') [0] .click Capybara :: ElementNotFound: css "# tag1" खोजने में असमर्थ
neilmarion

find('#tag1')इसका मतलब है कि आप आईडी के साथ केवल एक तत्व ढूंढना चाहते हैं tag1। अपवाद को उठाया जाता है tag1क्योंकि पेज पर आईडी के साथ कई तत्व हैं
आंद्रेई बोटालोव

आप कर सकते हैं all(:xpath, '//a[text()="#tag1"]').first.click
शुहेई कागवा

9

आप यह सुनिश्चित कर सकते हैं कि आप पहले वाले का उपयोग करें match:

find('.selector', match: :first).click

लेकिन महत्वपूर्ण रूप से, आप शायद ऐसा नहीं करना चाहते हैं , क्योंकि इससे डुप्लिकेट-आउटपुट कोड गंध की अनदेखी करने वाले भंगुर परीक्षण हो सकते हैं, जिसके परिणामस्वरूप गलत सकारात्मकता होती है जो काम करना जारी रखें जब उन्हें विफल होना चाहिए था, क्योंकि आपने एक मिलान हटा दिया था तत्व लेकिन परीक्षण खुशी से दूसरे को मिला।

बेहतर शर्त का उपयोग करना है within:

within('#sidebar') do
  find('.selector).click
end

यह सुनिश्चित करता है कि आप उस तत्व को ढूंढ रहे हैं जिसे आप खोजने की उम्मीद करते हैं, जबकि अभी भी कैपिबारा के ऑटो-वेट और ऑटो-रिट्री क्षमताओं का लाभ उठाते हैं (जो आप उपयोग करते हैं तो आप खो देते हैं find('.selector').click), और यह बहुत स्पष्ट करता है कि इरादा क्या है।


7

यहाँ ज्ञान के मौजूदा शरीर में जोड़ने के लिए:

JS परीक्षणों के लिए, Capybara को दो धागे (एक RSpec के लिए, एक रेल के लिए) और दूसरी प्रक्रिया (ब्राउज़र) सिंक में रखना है। यह सबसे मिलान और नोड-खोजने के तरीकों में प्रतीक्षा (कॉन्फ़िगर अधिकतम प्रतीक्षा समय तक) के द्वारा करता है।

Capybara में वे विधियाँ भी हैं जो मुख्य रूप से प्रतीक्षा नहीं करती हैं Node#all। उनका उपयोग करना आपके चश्मे के बारे में बताने जैसा है कि आप चाहते हैं कि वे रुक-रुक कर विफल हों।

स्वीकृत उत्तर बताता है page.first('selector')। यह अवांछनीय है, कम से कम जेएस चश्मा के लिए, क्योंकि Node#firstउपयोग करता हैNode#all

अगर आप कैपिबारा को इस तरह कॉन्फ़िगर करते हैं , तो Node#first यह इंतजार करेगा :

# rails_helper.rb
Capybara.wait_on_first_by_default = true

यह विकल्प Capybara 2.5.0 में जोड़ा गया था और डिफ़ॉल्ट रूप से गलत है।

जैसा कि आंद्रेई ने उल्लेख किया है, आपको इसके बजाय उपयोग करना चाहिए

find('selector', match: :first)

या अपना चयनकर्ता बदलें। कॉन्फ़िगरेशन या ड्राइवर की परवाह किए बिना या तो अच्छी तरह से काम करेगा।

चीजों को और जटिल करने के लिए, कैपिबारा के पुराने संस्करणों में (या एक सक्षम विकल्प के साथ), #findखुशी से अस्पष्टता को नजरअंदाज कर देगा और बस पहले मिलान चयनकर्ता को वापस कर देगा। यह या तो महान नहीं है, क्योंकि यह आपके चश्मे को कम स्पष्ट करता है, जिसकी मैं कल्पना करता हूं कि अब डिफ़ॉल्ट व्यवहार क्यों नहीं है। मैं बारीकियों को छोड़ दूँगा क्योंकि वे पहले ही ऊपर चर्चा कर चुके हैं।

और अधिक संसाधनों:


5

इस पोस्ट के कारण , आप इसे "मैच" विकल्प के माध्यम से ठीक कर सकते हैं:

Capybara.configure do |config|
  config.match = :prefer_exact
end

2

उपरोक्त सभी विकल्पों पर विचार करते हुए, आप इसे भी आजमा सकते हैं

find("a", text: text, match: :prefer_exact).click

यदि आप ककड़ी का उपयोग कर रहे हैं, तो आप भी इसका अनुसरण कर सकते हैं

आप पाठ को परिदृश्य चरणों से एक पैरामीटर के रूप में पारित कर सकते हैं जो फिर से पुन: उपयोग करने के लिए सामान्य कदम हो सकता है

कुछ इस तरह When a user clicks on "text" link

और स्टेप डेफिनिशन में When(/^(?:user) clicks on "([^"]*)" (?:link)$/) do |text|

इस तरह, आप कोड की पंक्तियों को छोटा करके उसी चरण का पुनः उपयोग कर सकते हैं और नए ककड़ी परिदृश्यों को लिखना आसान होगा


0

ककड़ी में अस्पष्ट त्रुटि से बचने के लिए।

समाधान 1

first("#tag1").click

समाधान २

Cucumber features/filename.feature --guess
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.