Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails3 Google Maps testing with selenium

I'm trying to test a google maps app with Rails3. I'm using cucumber with capybara and selenium for JavaScript testing. I have a map where I wait for google maps to be loaded, and then send an ajax request to my server, where I get locations that I'm inserting into the map. I'm wondering if it's possible with selenium to wait until google maps is loaded, the ajax call to my server is finished and the marker are placed inside the map. The other issue is, how to select this marker within google maps. Are there any selectors?

Or should I go the other way, and use a JS testing framework like Jasmine to test if my classes are loaded and so on. I don't have any experience with Jasmine, so is it possible to test a google maps?

Maybe someone knows a solution, or a hint if it's not possible, or a workaround or... ;)

[UPDATE 1]

I've found out how to select markers in google maps. If you look at googles selenium tests you can check out what they are doing. For example selecting a marker:

waitForElementPresent   xpath=//img[contains(@src,'marker')]

But here comes the next problem. How do I select a specific marker? Is there a way inside the javascript google maps API to assign an ID to it, so that I can use #marker_1, #marker_2...?

And another strange thing is, that function like wait_for_element or wait_for_condition aren't available inside my cucumber step definitions. Are the google selenium tests using own function like that waitForElementPresent? Or are this standard selenium functions? I've found a lots of posts, where they always use something like

selenium.wait_for_condition
selenium.wait_for_element

or

@selenium.wait_for_condition
...

Inside my step definitions the selenium and the @selenium var a nil. How can I access this methods? I've also found this post, but it is from Oct. '08, so I think there must be a better solution (btw. this solution works on the first sight).

Like on this page, they give an overview of a few selenium methods how to wait for a condition or element. Is this still present? How can I use this functions?

[UPDATE 2]

Damn it, I've found out, that the selenium tests I mentioned above are for V2 of google maps, not for V3. I have tried it with

wait_until { page.has_xpath?("//img[contains(@src,'marker')]") }

But it doesn't work. The marker is visible on the map, but I get a timeout error, because with this XPath selector it is not found. I'm wondering if it is generally possible to select a marker out of the DOM.

I also tried to assign an additional attribute to the marker when I create it:

// marker is the marker returned by google maps after adding it to the map
$(marker).attr('id', "marker_1");

But when I try to access it with the jQuery selector $("#marker_1"), it doesn't find it. So, still no solution, yet.

like image 900
23tux Avatar asked Mar 17 '11 08:03

23tux


People also ask

What is wrong with Google Maps in selenium testing?

With the proliferation of browser technologies such as Canvas, Google kept optimizing Maps to handle more markers and more layers, faster than ever before. The downside to this (from the Selenium testing perspective) is that many of these optimizations break the normal pattern one uses when writing a Selenium test.

How to perform geolocation testing with Selenium WebDriver?

You also have to install Selenium WebDriver for Chrome from here. With installation of Selenium 4 (Alpha), Google Chrome, and Chrome WebDriver; your environment is all set for geolocation testing with Selenium. For mocking (or faking) the geolocation, you first need to supply the latitude and longitude of the mock location.

How to install selenium in Python with chrome WebDriver?

Create and activate your python virtual environment and install Selenium using, Now download the Google Chrome WebDriver, which is basically a piece of software that automatically runs the browser instance and over which Selenium will work. #Note: Download the same version as your Chrome Browser.

What are the input arguments of selenium webdriver method?

The input arguments to the method are command name (i.e. Emulation.setGeolocationOverride) and map of parameters (i.e. coordinates). Step 5 – We navigate to the target URL and use Selenium WebDriver APIs for performing a ‘click’ operation on the search button on the target URL.


2 Answers

What I do with mine is to execute the calls in your step definitions like so:

page.execute_script("launchmap()")

then check for their existence in the page..then do your normal ajax check in capybara. the marker will be contained in a div right? then if you call launchmap and create the markers, capybara SHOULD be able find your markers

UPDATE

found out about this plugin: http://vigetlabs.github.com/jmapping/examples/

it gives you semantic markup for your google maps(for graceful degradation) allowing you to actually check if a marker exists using capybara. hope it helps(dont have time to test it but it looks promising)

like image 151
corroded Avatar answered Oct 16 '22 00:10

corroded


I found a way to Integration test my Google map with RSpec and Capybara. I wanted to write a test to assert that the content I got from an internal JSON-feed ended up in form of markers and info windows on my map (Google Maps API V3) in a Rails 4 app.

The problem: Even when I ran the tests with Selenium Webdriver that supports JS, I didn't find a way to select the markers with Capybara to check for their content.

My solution: 1. I added a div with ID test-box to my HTML markup 2. I wrote three helper methods into my JS that had access to my maps markers and added the results to the test-box. 3. In Capybara I executed the helper methods and expected to find the expected content or values in the box.

The code:

HTML:

<div id="map-canvas"></div>
<div id="info-box"></div>

JS-helpers: in app/assets/javascripts/events.js

// Test helper methods
testInfo = function(){
  document.getElementById("info-box").innerHTML = markers[0].title;
};

testInfoCount = function(){
  document.getElementById("info-box").innerHTML = markers.length;
};

testInfoWindow = function(){
  document.getElementById("info-box").innerHTML = markers[0].title + ", " + markers[0].time;
};

"markers" in my code is an array I push in every marker after I have added it to the map. I can be sure that the content actually is on the map if it's in the markers array.

Test:

spec/features/map_feature_spec.rb:

require "rails_helper"

describe "Map", js: true do
  let!(:john){create(:user)}
  let!(:event1){create(:event, user: john)}
  let!(:event2){create(:event)}

  it "shows a marker for a geocoded event on front page" do
    visit '/'
    find('#main-map-canvas')
    page.execute_script('testInfo()')
    expect(page.find("div#info-box").text).to eq(event1.title)
  end

  it "shows a marker for each geocoded event on front page" do
    visit '/'
    find('#main-map-canvas')
    page.execute_script('testInfoCount()')
    expect(page.find("div#info-box").text).to eq("2")
  end


  it "shows a marker for an event on event's page" do
    visit "/events/#{event1.id}"
    expect(page).to have_css("#single-map-canvas")
    page.execute_script('testInfo()')
    expect(page.find("div#info-box").text).to eq(event1.title)
  end

  context "Tooltips" do
  let!(:event1){create(:event)}
  let!(:event2){create(:event)}

    it "shows title and date on frontpage" do
      visit "/"
      find('#main-map-canvas')
      page.execute_script('testInfoWindow()')
      expect(page.find("div#info-box")).to have_content("Pauls Birthday Party, #{event1.nice_date}")
    end

  end
end
  • To run the javascripts Selenium webdriver and Firefox need to be installed (''gem "selenium-webdriver"'' in your Gemfile)

  • I'm creating the test content (let!...) using Factory Girl.

  • Running the tests you will actually see the markers on the map and their content appears in the test-box.

like image 24
Thomas Strothjohann Avatar answered Oct 16 '22 01:10

Thomas Strothjohann