Flow is undefined - class inheritance issue? (Ruby Shoes) - ruby

I am following a sample located here in the samples folder on the official Shoes github repo. I saw that the programmer defined a class Book which inherited from Shoes. I have a relatively large program coming along with shoes that I'm porting for 3.x, and I wanted to split all of my different classes into smaller files to make it easier on me. I have a file like so
#this class essentially sets up user interface
class Interface < Shoes
def initialize
flow do
#shed = button "New"
#editbutton = button "Edit"
#employees = button "Employees"
#sdays = button "Special Days"
#makenote = button "Make Note"
#backbutton = button "Go Back"
end
end
end
My main file looks like so
$LOAD_PATH << "."
require 'loader' #all of these are other classes i have defined
require 'interface' #contains the interface class
require 'schutil'
Shoes.app title: "Baesler's Scheduling Application", width: 1024, height: 768, resizable: true do
Interface.new
end
First of all, in the sample I provided, the programmer never had to use a block with Shoes.app. I don't know how, but his class got initialized with shoes when it was ran. That was my original intention, but when I try that (the code above without ever calling Interface.init), nothing shows up in Shoes, but it does load. However, using the above code as-is, I get the following error:
NoMethodError: undefined method 'flow' for nil:NilClass
If it helps at all, I am using the Shoes 4 preview 3 gem and am running Windows 8.1 64 bit. What am I doing wrong? Is this a bug in the Shoes codebase, or am I doing this wrong? Any help would be greatly appreciated.

You are overwriting the initialize method which breaks the whole setup of shoes (it needs to get an app instance on which to call the flow method for instance).
You are also following a url sample without using any actual url calls.
A widget might suit your use case better.
Personally I rather resort to defining methods within an app and then calling those :)

Related

Unknown response for all methods and commands in ruby-asterisk

Testing ruby-asterisk manager interface with ruby version 1.9.3p0 and gem 1.8.11, for all command and methods its printing the the same output.
Anyone faced similar problem.
Code:
#!/usr/bin/env ruby
require 'ruby-asterisk'
#ami = RubyAsterisk::AMI.new("192.168.1.5",5038)
#ami.login("admin","passs")
puts #ami.command("sip show peers")
Output:
#<RubyAsterisk::Response:0x000000016af710>
Project URL
Problem solved. Didn’t check the readme RESPONSE OBJECT section.
It's working.
var = #ami.command(""sip show peers)
puts var.data
You are putting the Instance of the RubyAsterix. I think after haveing a brief look at the project that most/all of the instance methods returns the instance it self. The reason for doing it that way is that it makes it very easy to chain multiplie actions which makes for a nice syntax/usage.
I think you should remove the puts and allow the gem to display what it wants to display.

Using SitePrism with Rspec and Capybara feature specs

I recently discovered SitePrism via the rubyweekly email.
It looks amazing. I can see its going to be the future.
The examples I have seen are mostly for cucumber steps.
I am trying to figure out how one would go about using SitePrism with rspec.
Assuming #home_page for the home page, and #login_page for the login_page
I can understand that
#home_page.load # => visit #home.expanded_url
however, the part I am not sure about, is if I think click on for example the "login" link, and the browser in Capybara goes to the login page - how I can then access an instance of the login page, without loading it.
#home_page = HomePage.new
#home_page.load
#home.login_link.click
# Here I know the login page should be loaded, so I can perhaps do
#login_page = LoginPage.new
#login_page.should be_displayed
#login_page.email_field.set("some#email.com")
#login_page.password_field.set("password")
#login_page.submit_button.click
etc...
That seems like it might work. So, when you know you are supposed to be on a specific page, you create an instance of that page, and somehow the capybara "page" context, as in page.find("a[href='/sessions/new']") is transferred to the last SitePrism object?
I just feel like I am missing something here.
I'll play around and see what I can figure out - just figured I might be missing something.
I am looking through the source, but if anyone has figured this out... feel free to share :)
What you've assumed turns out to be exactly how SitePrism works :) Though you may want to check the epilogue of the readme that explains how to save yourself from having to instantiate page objects all over your test code. Here's an example:
# our pages
class Home < SitePrism::Page
#...
end
class SearchResults < SitePrism::Page
#...
end
# here's the app class that represents our entire site:
class App
def home
Home.new
end
def results_page
SearchResults.new
end
end
# and here's how to use it:
#first line of the test...
#app = App.new
#app.home.load
#app.home.search_field.set "sausages"
#app.home.search_button.click
#app.results_page.should be_displayed

How much should interfaces of elements in Page Objects be abstracted?

I have a page object called LineItemsPage
class LineItemsPage
attr_accessor :add_line_item_button
def initialize(test_env)
#browser = test_env[:browser]
#action_bar = #browser.div(:id => 'lineitems_win').div(:class => 'window-body').div(:class => 'actionbar')
#add_line_item_button = #action_bar.img(:class => 'button add')
end
def method_missing(sym, *args, &block)
#browser.send sym, *args, &block
end
end
I use it like so:
When /^I click on Add Item and enter the following values:$/ do |table|
#line_items_page = LineItemsPage.new(#test_env)
#line_items_page.add_line_item_button.when_present.click
end
I'm wondering if I should be abstracting the click, by adding something like the following to my LineItemsPage class:
def add_item
self.add_line_item_button.when_present.click
end
And then using it like so:
#line_items_page.add_item
I'm looking for best practices, either with regards to Page Object in particular or Ruby in general. I feel that encapsulating the interface by using add_item() is going a bit far, but I'm wondering if I'm unaware of issues I might run into down the road if I don't do that.
Personally, I try to make my page object methods be in the domain language with no reference to the implementation.
I used to do something like #line_items_page.add_line_item_button.when_present.click, however it has caused problems in the following scenarios:
1) The add line item was changed from a button to a link.
2) The process for adding a line item has changed - say its now done by a right-click or it has become a two step process (like open some dropdown and then click the add line).
In either case, you would have to locate all the places you add line items and update them. If you had all the logic in the add_item page object method, you would only have to update the one place.
From an implementation perspective, I have found that Cheezy's page object accessors work pretty well. However, for image buttons (or any of your app's custom controls), I would add additional methods to the PageObject::Accessors module. Or if they are one off controls, you can add the methods directly to the specific page object.
Update - Reply to Comment Regarding Some Starting Points:
I have not come across too much documentation, but here are a couple links that might help:
1) The Cheezy Page Object project wiki - Gives a simple example to get started
2) Cheezy's blog posts where the page object gem first started. Note that the content here might not be exactly how the gem is currently implemented, but I think it gives a good foundation to understanding what he is trying to achieve. This in turn makes it easier to understand what is happening when you have to open up and modify the gem to fit you needs.

PageObject with Ruby - set text in a text field only works in the main file

I'm automating a site that has a page with a list of options selected by a radio button. When selecting one of the radios, a text field and a select list are presented.
I created a file (test_contracting.rb) that is the one through which I execute the test (ruby test_contracting.rb) and some other classes to represent my page.
On my class ContractPage, I have the following element declaration:
checkbox(:option_sub_domain, :id => "option_sub_domain")
text_field(:domain, :id => "domain_text")
select_list(:tld, :id => "domain_tld")
I've created in the ContractPage a method that sets the configuration of the domain like this:
def configure_domain(config={})
check_option_sub_domain
domain = config[:domain]
tld = config[:tld]
end
When I call the method configure_domain from the test_contracting.rb, it selects the radio button, but it doesn't fill the field with the values. The params are getting into the method correctly. I've checked it using "puts". Even if I change the params to a general string like "bla" it doesnt work. The annoying point is that if on test_contracting.rb I call the exact same components, it works.
my_page_instance = ContractPage.new(browser)
my_page_instance.domain = "bla"
my_page_instance.tld = ".com"
What I found to work was to in the configure_domain method, implement the following:
domain_element.value = config[:domain]
tld_element.send_keys config[:locaweb_domain]
Then it worked.
The documentation for the PageObjects module that I'm using as reference can be found here: http://rubydoc.info/github/cheezy/page-object/master/PageObject/Accessors#select_list-instance_method
Do you guys have any explation on why the method auto generated by the pageobject to set the value of the object didnt work in this scope/context ?
By the way, a friend tried the same thing with Java and it failed as well.
In ruby all equals methods (methods that end with the = sign) need to have a receiver. Let me show you some code that will demonstrate why. Here is the code that sets a local variable to a value:
domain = "blah"
and here is the code that calls the domain= method:
domain = "blah"
In order for ruby to know that you are calling a method instead of setting a local variable you need to add a receiver. Simply change your method above to this and it will work:
def configure_domain(config={})
check_option_sub_domain
self.domain = config[:domain]
self.tld = config[:tld]
end
I'm pretty new to this world of Selenium and page objects but maybe one of my very recent discoveries might help you.
I found that that assignment methods for the select_list fields only worked for me once I started using "self" in front. This is what I have used to access it within my page object code. e.g., self.my_select_list="my select list value"
Another note - The send_keys workaround you mention is clever and might do the trick for a number of uses, but in my case the select list values are variable and may have several options starting with the same letter.
I hope something in here is useful to you.
UPDATE (Jan 3/12)
On diving further into the actual Ruby code for the page object I discovered that the select_list set is also using send_keys, so in actuality I still have the same limitation here as the one I noted using the send_keys workaround directly. sigh So much to learn, so little time!

Qt QLineEdit custom validation in ruby

I am trying to implement QLineEdit's text which is all capital letters no matter what user types in. I have found several solutions, none of them working in Ruby. In brief I have QLineEdit object searchEdit and this code:
class UpcaseValidator < Qt::Validator
def validate(input,pos)
input.upcase!
Qt::Validator::Acceptable
end
end
...
def initialize(parent = nil)
uppercaseValidator = UpcaseValidator.new;
searchEdit.setValidator(uppercaseValidator)
...
The validate method gets triggered correctly whenever user types in the input field, but it is not getting uppercased. Seems to me that changing input variable within validate does not get propagated back to the searchEdit object.
Thanks for any help, even pointing me out to some good docs about Qt Ruby bindings.
QValidator has a method called 'fixup()', which will probably do what you want :)

Resources