Back to Repositories

Testing Google Places Details API Integration in Geocoder

This test suite validates the Google Places Details functionality in the Geocoder gem, focusing on place information retrieval and response parsing. It ensures accurate handling of location details, components, and various Google Places API features.

Test Coverage Overview

The test suite provides comprehensive coverage of Google Places Details API integration:

  • Address component extraction and validation
  • Geolocation data accuracy (latitude/longitude)
  • Place metadata handling (ratings, reviews, types)
  • Contact information verification
  • URL construction and parameter handling
  • Error cases and empty results handling

Implementation Analysis

The testing approach employs Ruby’s Test::Unit framework with custom assertions for Google Places API responses. The implementation follows a structured pattern of individual test methods for each API field, with setup configuration for API keys and lookup initialization.

Key patterns include mock result handling, API configuration testing, and comprehensive field validation.

Technical Details

Testing tools and configuration:

  • GeocoderTestCase as the base test class
  • Custom lookup configuration for Google Places Details
  • API key management through set_api_key! helper
  • Query URL construction testing
  • Field filtering and language parameter support

Best Practices Demonstrated

The test suite exemplifies several testing best practices:

  • Isolated test methods for single responsibilities
  • Comprehensive edge case coverage
  • Clear test naming conventions
  • Proper test setup and teardown
  • Error handling validation
  • Configuration flexibility testing

alexreisner/geocoder

test/unit/lookups/google_places_details_test.rb

            
# encoding: utf-8
require 'test_helper'

class GooglePlacesDetailsTest < GeocoderTestCase

  def setup
    super
    Geocoder.configure(lookup: :google_places_details)
    set_api_key!(:google_places_details)
  end

  def test_google_places_details_result_components
    assert_equal "Manhattan", madison_square_garden.address_components_of_type(:sublocality).first["long_name"]
  end

  def test_google_places_details_result_components_contains_route
    assert_equal "Pennsylvania Plaza", madison_square_garden.address_components_of_type(:route).first["long_name"]
  end

  def test_google_places_details_result_components_contains_street_number
    assert_equal "4", madison_square_garden.address_components_of_type(:street_number).first["long_name"]
  end

  def test_google_places_details_street_address_returns_formatted_street_address
    assert_equal "4 Pennsylvania Plaza", madison_square_garden.street_address
  end

  def test_google_places_details_result_contains_place_id
    assert_equal "ChIJhRwB-yFawokR5Phil-QQ3zM", madison_square_garden.place_id
  end

  def test_google_places_details_result_contains_latitude
    assert_equal madison_square_garden.latitude, 40.750504
  end

  def test_google_places_details_result_contains_longitude
    assert_equal madison_square_garden.longitude, -73.993439
  end

  def test_google_places_details_result_contains_rating
    assert_equal 4.4, madison_square_garden.rating
  end

  def test_google_places_details_result_contains_rating_count
    assert_equal 382, madison_square_garden.rating_count
  end

  def test_google_places_details_result_contains_reviews
    reviews = madison_square_garden.reviews

    assert_equal 2, reviews.size
    assert_equal "John Smith", reviews.first["author_name"]
    assert_equal 5, reviews.first["rating"]
    assert_equal "It's nice.", reviews.first["text"]
    assert_equal "en", reviews.first["language"]
  end

  def test_google_places_details_result_contains_types
    assert_equal madison_square_garden.types, %w(stadium establishment)
  end

  def test_google_places_details_result_contains_website
    assert_equal madison_square_garden.website, "http://www.thegarden.com/"
  end

  def test_google_places_details_result_contains_phone_number
    assert_equal madison_square_garden.phone_number, "+1 212-465-6741"
  end

  def test_google_places_details_query_url_contains_placeid
    url = lookup.query_url(Geocoder::Query.new("some-place-id"))
    assert_match(/placeid=some-place-id/, url)
  end

  def test_google_places_details_query_url_contains_language
    url = lookup.query_url(Geocoder::Query.new("some-place-id", language: "de"))
    assert_match(/language=de/, url)
  end

  def test_google_places_details_query_url_always_uses_https
    url = lookup.query_url(Geocoder::Query.new("some-place-id"))
    assert_match(%r(^https://), url)
  end

  def test_google_places_details_query_url_omits_fields_by_default
    url = lookup.query_url(Geocoder::Query.new("some-place-id"))
    assert_no_match(/fields=/, url)
  end

  def test_google_places_details_query_url_contains_specific_fields_when_given
    fields = %w[formatted_address place_id]
    url = lookup.query_url(Geocoder::Query.new("some-place-id", fields: fields))
    assert_match(/fields=#{fields.join('%2C')}/, url)
  end

  def test_google_places_details_query_url_contains_specific_fields_when_configured
    fields = %w[business_status geometry photos]
    Geocoder.configure(google_places_details: {fields: fields})
    url = lookup.query_url(Geocoder::Query.new("some-place-id"))
    assert_match(/fields=#{fields.join('%2C')}/, url)
    Geocoder.configure(google_places_details: {})
  end

  def test_google_places_details_query_url_omits_fields_when_nil_given
    Geocoder.configure(google_places_details: {fields: %w[business_status geometry photos]})
    url = lookup.query_url(Geocoder::Query.new("some-place-id", fields: nil))
    assert_no_match(/fields=/, url)
    Geocoder.configure(google_places_details: {})
  end

  def test_google_places_details_query_url_omits_fields_when_nil_configured
    Geocoder.configure(google_places_details: {fields: nil})
    url = lookup.query_url(Geocoder::Query.new("some-place-id"))
    assert_no_match(/fields=/, url)
    Geocoder.configure(google_places_details: {})
  end

  def test_google_places_details_result_with_no_reviews_shows_empty_reviews
    assert_equal no_reviews_result.reviews, []
  end

  def test_google_places_details_result_with_no_types_shows_empty_types
    assert_equal no_types_result.types, []
  end

  def test_google_places_details_result_with_invalid_place_id_empty
    silence_warnings do
      assert_equal Geocoder.search("invalid request"), []
    end
  end

  def test_raises_exception_on_google_places_details_invalid_request
    Geocoder.configure(always_raise: [Geocoder::InvalidRequest])
    assert_raises Geocoder::InvalidRequest do
      Geocoder.search("invalid request")
    end
  end

  private

  def lookup
    Geocoder::Lookup::GooglePlacesDetails.new
  end

  def madison_square_garden
    Geocoder.search("ChIJhRwB-yFawokR5Phil-QQ3zM").first
  end

  def no_reviews_result
    Geocoder.search("no reviews").first
  end

  def no_types_result
    Geocoder.search("no types").first
  end

end