Code Monkey home page Code Monkey logo

page-objectify's Introduction

page-objectify

Build Status

A Ruby page class generator (for use with the page-object gem)

Why?

Normally, Iโ€™d advise against using a gem like this, because the page class shouldn't necessarily contain methods for every single HTML element on the page. In fact, if the page we are modeling is anything like the Google home page, our page class should only have one or 2 methods (a.k.a. PageObject::Accessors) for HTML elements: the search box and the submit button.

However, recently, almost all of the tests I have been writing have been for non-public facing sites, used by specialized, internal users who are trained on the platform. As a result, we end up with fairly dense webpages, with multiple different features and HTML elements that need interacting with, all on a single page.

Ultimately, this is the specific use case I am writing this gem for. Also, I wanted to learn a bit more about how a Ruby AST -- abstract syntax tree -- works and how the unparser gem allows me to generate working Ruby code from a dynamically generated AST.

Changes

This gem will follow semantic versioning. See changelog for changes in each version.

Installation

Ensure this gem and watir-webdriver are both in your Gemfile:

gem "page-objectify"
gem "watir-webdriver"

And then execute:

$ bundle

Usage

The supported usage of this gem is to:

  • create a SomethingPageGenerator class that inherits from PageObjectify::Generator
  • write a SomethingPageGenerator#visit method that opens a browser and navigates to the page you want to generate a page class for.
  • initialize the generator class & call #generate! in some kind of Rake task (that is typically executed manually.)

Here's a complete example (using the Google homepage, which, as I mention above, is a horrible use case, but it works for a demo):

# Gemfile
gem "chromedriver-helper", "~> 1.0"
gem "page-objectify"
gem "watir-webdriver", "~> 0.9.1"
# /generators/google_page_generator.rb
require "page-objectify/generator"
require "watir-webdriver"

class GooglePageGenerator < PageObjectify::Generator
  def visit
    @browser = Watir::Browser.new :chrome
    @browser.goto "www.google.com"
    sleep 1 # Use `wait_for_ajax` instead of `sleep`, if jQuery is available on the page!
  end
end
# Rakefile
require "generators/google_page_generator"

namespace :generate do
  task :po do
    # Specifying file path is optional
    GooglePageGenerator.new(file: "path/to/pages-dir/google_page.rb").generate!
    # and any other pages you want to generate programmatically
  end
end

Then, upon executing the rake task $ bundle exec rake generate:po, the following file will be generated:

class GooglePage < BasePage
  div(:viewport, id: "viewport")
  div(:"doc-info", id: "doc-info")
  div(:cst, id: "cst")
  text_area(:csi, id: "csi")
  div(:searchform, id: "searchform")
  # etc.
end

Currently, only those HTML elements with a non-empty id attribute will have PageObject accessors generated for them.

For another example (using watir-webdriver and phantomjs via the phantomjs gem), see this integration test.

Debugging & Development

The default log level is 2. Set this to a lower level to see helpful DEBUG level prints, i.e.

PageObjectify::Logging.logger.level = 0

After checking out the repo, run bin/setup to install dependencies. Then, run rake test to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install.

Releasing

To release a new version, I must:

  1. Update the version number in version.rb.
  2. Run rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.
  3. Run rake changelog, which will auto-generate a changelog of the PRs merged/Issues resolved in the newest release.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/smoll/page-objectify.

page-objectify's People

Contributors

smoll avatar

Stargazers

Justin Watts avatar

page-objectify's Issues

Allow user to configure mapping of HTML ids to PO accessor names

According to this SO article the HTML5 spec is incredibly permissive.

If we allowed a regex or some other mapping, we would avoid a lot of problems like:

  • duplicate accessor names (e.g. HTML ids of some-thing and some_thing)
  • valid chars in HTML ids that are not valid in Ruby methods (dashes, colons, etc.)
  • capital letters might still be a special case; but since HTML ids are case-insensitive, simply downcasing them should be fine

Something like this should work:

REGEX_MAPPING = {
  "\d" => '_\1'
}
SomePageGenerator.new(regex_mapping: REGEX_MAPPING).generate!

# and

STRING_MAPPING = {
  "-" => "_"
}
SomePageGenerator.new(string_mapping: STRING_MAPPING).generate!

And somewhere in dom_to_ruby.rb I think:

method_name = element[:id]
@config.string_mapping.each { |k,v| method_name.sub!(k, v) }
@config.regex_mapping.each { |k,v| method_name.sub!(/#{k}/, v) }

# Partial AST:
          s(:sym, method_name.to_sym),
# ...

Ref: http://stackoverflow.com/a/15061201

Write a more complex cucumber example, e.g. for a page behind authentication or that includes a modal not initially in the markup

Steps:

  1. Write a tiny fixture app that displays a login form, start the app from the test runner
  2. Write the Generator class as usual
  3. Write an Authentication module with a callable instance method, e.g. #authenticate
  4. Include the module in Generator class, and call #authenticate inside the #visit method
  5. Assert that the page generates as expected

The module from (3) should actually be reusable as a Cucumber World helper too!

Add tbody and thead to list of ignored tags

Log:

W, [2015-11-11T00:52:22.097984 #6438]  WARN -- PageObjectify::Logging: Tag thead is not supported! This may be a bug in the PageObjectify gem, please report it! :)
W, [2015-11-11T00:52:22.098222 #6438]  WARN -- PageObjectify::Logging: Tag tbody is not supported! This may be a bug in the PageObjectify gem, please report it! :)

Don't try to generate accessors for invalid tags, and write tests for it

For example, seeing this output when attempting to generate for a page with <script id="something"></script> tags:

W, [2015-11-09T17:27:22.376226 #73458]  WARN -- PageObjectify::Logging: Tag script is not supported! This may be a bug in the PageObjectify gem, please report it! :)
W, [2015-11-09T17:27:22.376313 #73458]  WARN -- PageObjectify::Logging: Tag script is not supported! This may be a bug in the PageObjectify gem, please report it! :)

HTML id with dashes should be converted into valid PO accessor method names

At the moment, the following is being generated:

# pages/some_page.rb

div(:"general-footer", id: "general-footer")

general-footer and general-footer_element are not valid method names (Ref: http://stackoverflow.com/a/10542599)

It could instead be:

# pages/some_page.rb

div(:general_footer, id: "general-footer")

Considerations:

This would mean that the following would override one another:

# pages/some_page.rb

div(:general_footer, id: "general-footer")
div(:general_footer, id: "general_footer")

Generator raises NameError: uninitialized constant PageObjectify::VERSION when writing timestamped code comment

See this backtrace when attempting to invoke generator from a Rake task:

$ rake generate:qa
warning: parser/current is loading parser/ruby22, which recognizes
warning: 2.2.3-compliant syntax, but you are running 2.2.1.
warning: please see https://github.com/whitequark/parser#compatibility-with-ruby-mri.
W, [2015-11-10T09:19:43.620167 #81702]  WARN -- PageObjectify::Logging: Tag script is not supported! This may be a bug in the PageObjectify gem, please report it! :)
W, [2015-11-10T09:19:43.620253 #81702]  WARN -- PageObjectify::Logging: Tag script is not supported! This may be a bug in the PageObjectify gem, please report it! :)
rake aborted!
NameError: uninitialized constant PageObjectify::VERSION
/Users/smollah/.rvm/gems/ruby-2.2.1/gems/page-objectify-0.0.2/lib/page-objectify/generator.rb:62:in `write_to_disk'
/Users/smollah/.rvm/gems/ruby-2.2.1/gems/page-objectify-0.0.2/lib/page-objectify/generator.rb:32:in `generate!'
/Users/smollah/workspace/pipeline_poc/lib/tasks/generate.rake:6:in `block (2 levels) in <top (required)>'
Tasks: TOP => generate:qa
(See full trace by running task with --trace)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.