tube 0.2.5 → 0.3.0pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8146af96982affbf00a37dfac0b79cb8e7cd5175
4
+ data.tar.gz: dbc5fca47bfe1813d1fd46f54569c66871e60a66
5
+ SHA512:
6
+ metadata.gz: 52ea0e16ce2840d5afbb9e0b7f5fb7a9731168291c9bb8bd818ccf91e24627e2c3279c8bee936989fe483e03d36342a1b5f019c35f92947346e6df5ba05c4357
7
+ data.tar.gz: 030c5bc541b2c5517f3e1d8c34af46cc9b4bb59cc6abdf7115606237cd342bdba0a3a2cf8fde3b8ecec2714892cadf9f7bf7c0649a5d0bbbb0e38bc756f58316
data/README.rdoc CHANGED
@@ -1,13 +1,20 @@
1
1
  = Tube/Status
2
2
 
3
- A simple MIT licensed Ruby library to access the status of the London Underground network as displayed on the Transport for London {Live travel news}[http://www.tfl.gov.uk/tfl/livetravelnews/realtime/tube/default.html] page.
3
+ A simple MIT licensed Ruby library to access the status of the London
4
+ Underground network as returned by the Transport for London
5
+ {API}[http://api.tfl.gov.uk].
6
+
7
+ Before the API was available this library scraped the data from the TFL
8
+ website, at the moment the code has been updated to retain mostly the same Ruby
9
+ API, while calling the new TFL API, rather than scrape the website. In the
10
+ future this library may change to better match what TFL now make available.
4
11
 
5
12
  == Installation
6
13
 
7
14
  $ gem install tube
8
15
 
9
16
  == Examples
10
- require 'tube/status'
17
+ require "tube/status"
11
18
 
12
19
  status = Tube::Status.new
13
20
 
@@ -32,5 +39,3 @@ A simple MIT licensed Ruby library to access the status of the London Undergroun
32
39
  status.reload
33
40
  status.updated.strftime("%I:%M%p")
34
41
  #=> "05:00PM"
35
-
36
- See the {documentation}[http://sourcetagsandcodes.com/codes/tube_status/doc/] for more details.
data/lib/tube/line.rb CHANGED
@@ -12,7 +12,7 @@ module Tube # :nodoc:
12
12
  #
13
13
  # Create a new Line.
14
14
  #
15
- def initialize( id, name, status, problem, message=nil )
15
+ def initialize(id, name, status, problem, message=nil)
16
16
  @id = id
17
17
  @name = name
18
18
  @status = status
@@ -21,4 +21,4 @@ module Tube # :nodoc:
21
21
  end
22
22
 
23
23
  end
24
- end
24
+ end
data/lib/tube/station.rb CHANGED
@@ -11,10 +11,10 @@ module Tube # :nodoc:
11
11
  #
12
12
  # Create a new Station.
13
13
  #
14
- def initialize( name, message )
14
+ def initialize(name, message)
15
15
  @name = name
16
16
  @message = message
17
17
  end
18
18
 
19
19
  end
20
- end
20
+ end
data/lib/tube/status.rb CHANGED
@@ -1,22 +1,17 @@
1
- require 'open-uri'
2
-
3
- require "#{File.dirname( __FILE__ )}/status_parser"
4
- require "#{File.dirname( __FILE__ )}/line"
5
- require "#{File.dirname( __FILE__ )}/station"
1
+ require File.expand_path("../tfl_client", __FILE__)
2
+ require File.expand_path("../line", __FILE__)
3
+ require File.expand_path("../station", __FILE__)
6
4
 
7
5
  module Tube # :nodoc:
8
6
 
9
- # Models the status of the London Underground network as displayed on
10
- # http://www.tfl.gov.uk/tfl/livetravelnews/realtime/tube/default.html.
7
+ # Models the status of the London Underground network as returned by
8
+ # http://api.tfl.gov.uk.
11
9
  #
12
- # It is a very thin abstraction over the tfl website, as a result the access
13
- # to data on stations is somewhat different to lines due to the differing
14
- # presentation.
15
- # However it is very dynamic, for example should the East London line return
16
- # it will show up in the lines array automatically.
10
+ # Before TFL made an API available this library scraped the TFL website, due
11
+ # to this the API provided doesn't (currently) match the TFL API very well.
17
12
  #
18
13
  # ==Example Usage
19
- # require 'tube/status'
14
+ # require "tube/status"
20
15
  #
21
16
  # status = Tube::Status.new
22
17
  #
@@ -50,28 +45,28 @@ module Tube # :nodoc:
50
45
  # Request and parse the status of the London Underground network from the
51
46
  # tfl.gov.uk "Live travel news" page.
52
47
  #
53
- def initialize( url=
54
- "http://www.tfl.gov.uk/tfl/livetravelnews/realtime/tube/default.html" )
55
- results = Tube::StatusParser.parse( open( url ).read )
56
- @updated = results[:updated]
48
+ def initialize(app_id=nil, app_key=nil, host="api.tfl.gov.uk", port=80)
49
+ client = TFLClient.new(app_id, app_key, host, port)
50
+ line_details = client.line_mode_status(modes: %W{tube dlr overground})
51
+ station_details = client.stop_point_mode_disruption(modes: %W{tube dlr overground})
52
+
53
+ @updated = Time.now
57
54
 
58
- @lines = results[:lines].map do |line|
59
- id = line[:html_class].to_sym
60
- name = line[:name]
61
- status = line[:status][:headline]
62
- problem = line[:status][:problem]
63
- message = line[:status][:message]
55
+ @lines = line_details.map do |line|
56
+ id = line["id"].to_sym
57
+ name = line["name"]
58
+ status_details = line["lineStatuses"].first
59
+ status = status_details["statusSeverityDescription"]
60
+ problem = status_details["statusSeverity"] > 10
61
+ message = status_details["reason"]
64
62
 
65
- Line.new( id, name, status, problem, message )
63
+ Line.new(id, name, status, problem, message)
66
64
  end
67
65
 
68
- @station_groups = results[:station_groups].inject( {} ) do |memo, group|
69
- stations = group[:stations].map do |station|
70
- Station.new( station[:name], station[:message] )
71
- end
72
-
73
- memo[group[:name]] = stations
74
- memo
66
+ @station_groups = {}
67
+ station_details.each do |detail|
68
+ station = Station.new(detail["commonName"], detail["description"])
69
+ (@station_groups[detail["type"]] ||= []).push(station)
75
70
  end
76
71
 
77
72
  self
@@ -0,0 +1,56 @@
1
+ require "net/http"
2
+ require "json"
3
+
4
+ module Tube
5
+ class TFLClient
6
+
7
+ attr_reader :app_id, :app_key, :host, :port
8
+
9
+ def initialize(app_id, app_key, host="api.tfl.gov.uk", port=80)
10
+ @app_id = app_id
11
+ @app_key = app_key
12
+ @host = host
13
+ @port = port
14
+ end
15
+
16
+ def self.def_request(name, method, path)
17
+ define_method(name) do |params, body=nil, headers=nil|
18
+ request(method, path, params, body, headers)
19
+ end
20
+ end
21
+ private_class_method :def_request
22
+
23
+ def_request :line_mode_status, :get, "/Line/Mode/{modes}/Status"
24
+ def_request :stop_point_mode_disruption, :get, "/StopPoint/Mode/{modes}/Disruption"
25
+
26
+ def request(method, path, params, body=nil, headers=nil)
27
+ path = format_path(path, params)
28
+ Net::HTTP.start(host, port) do |http|
29
+ req = Net::HTTP.const_get(method.capitalize).new(path, headers)
30
+ req.body = body if req.request_body_permitted?
31
+ res = http.request(req)
32
+ JSON.parse(res.body)
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def format_path(path, params)
39
+ path = path.dup
40
+ params = {"app_id" => app_id, "app_key" => app_key}.merge(params)
41
+ params.reject! do |key, value|
42
+ key = lower_camel_case(key)
43
+ value = value.join(",") if value.respond_to?(:join)
44
+ path.sub!("{#{key}}", value.to_s)
45
+ end
46
+ path << "?" << params.map {|kv| kv.join("=")}.join("&")
47
+ end
48
+
49
+ def lower_camel_case(string)
50
+ parts = string.to_s.split("_")
51
+ first = parts.shift
52
+ parts.map(&:capitalize).unshift(first.downcase).join("")
53
+ end
54
+
55
+ end
56
+ end
metadata CHANGED
@@ -1,27 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tube
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
5
- prerelease:
4
+ version: 0.3.0pre
6
5
  platform: ruby
7
6
  authors:
8
7
  - Matthew Sadler
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-07-20 00:00:00.000000000Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: nokogiri
16
- requirement: &2153504660 !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: 1.4.1
22
- type: :runtime
23
- prerelease: false
24
- version_requirements: *2153504660
11
+ date: 2014-04-08 00:00:00.000000000 Z
12
+ dependencies: []
25
13
  description: A simple Ruby library to access the status of the London Underground
26
14
  network.
27
15
  email: mat@sourcetagsandcodes.com
@@ -30,39 +18,34 @@ extensions: []
30
18
  extra_rdoc_files:
31
19
  - README.rdoc
32
20
  files:
21
+ - README.rdoc
33
22
  - lib/tube/line.rb
34
23
  - lib/tube/station.rb
35
24
  - lib/tube/status.rb
36
- - lib/tube/status_parser.rb
37
- - test/dummy.html
38
- - test/status_parser_test.rb
39
- - examples/service_board.rb
40
- - README.rdoc
25
+ - lib/tube/tfl_client.rb
41
26
  homepage: http://github.com/matsadler/tube
42
27
  licenses: []
28
+ metadata: {}
43
29
  post_install_message:
44
30
  rdoc_options:
45
- - --main
31
+ - "--main"
46
32
  - README.rdoc
47
33
  require_paths:
48
34
  - lib
49
35
  required_ruby_version: !ruby/object:Gem::Requirement
50
- none: false
51
36
  requirements:
52
- - - ! '>='
37
+ - - ">="
53
38
  - !ruby/object:Gem::Version
54
39
  version: '0'
55
40
  required_rubygems_version: !ruby/object:Gem::Requirement
56
- none: false
57
41
  requirements:
58
- - - ! '>='
42
+ - - ">"
59
43
  - !ruby/object:Gem::Version
60
- version: '0'
44
+ version: 1.3.1
61
45
  requirements: []
62
46
  rubyforge_project:
63
- rubygems_version: 1.8.7
47
+ rubygems_version: 2.2.0
64
48
  signing_key:
65
- specification_version: 3
49
+ specification_version: 4
66
50
  summary: Access the status of the London Underground network.
67
- test_files:
68
- - test/status_parser_test.rb
51
+ test_files: []
@@ -1,39 +0,0 @@
1
- require 'rubygems'
2
- require 'tube/status'
3
- require 'terminal_color/ansi'
4
-
5
- class String
6
- include Terminal::Color::ANSI
7
- end
8
-
9
- LINE_COLORS = {
10
- :bakerloo => [:bright_white, :red_bg],
11
- :central => [:white, :bright_red_bg],
12
- :circle => [:blue, :bright_yellow_bg],
13
- :district => [:bright_white, :green_bg],
14
- :hammersmithandcity => [:blue, :bright_magenta_bg],
15
- :jubilee => [:bright_white, :bright_black_bg],
16
- :metropolitan => [:bright_white, :magenta_bg],
17
- :northern => [:bright_white, :black_bg],
18
- :piccadilly => [:bright_white, :blue_bg],
19
- :victoria => [:bright_white, :bright_blue_bg],
20
- :waterlooandcity => [:blue, :bright_cyan_bg],
21
- :dlr => [:bright_white, :cyan_bg],
22
- :overground => [:bright_white, :yellow_bg]
23
- }
24
- STATUS_COLOR = [:blue, :bright_white_bg]
25
- PROBLEM_COLOR = STATUS_COLOR + [:negative]
26
-
27
- status = Tube::Status.new
28
-
29
- longest_name = status.lines.map {|l| l.name.length}.max
30
- longest_status = status.lines.map {|l| l.status.length}.max
31
- formatted_time = status.updated.strftime("%I:%M%p").downcase.sub(/^0/, "")
32
-
33
- puts " Live travel news".style(:bold), " Last update: #{formatted_time}", ""
34
- status.lines.each do |line|
35
- print " "
36
- printf(" %-#{longest_name}s ".color(*LINE_COLORS[line.id]), line.name)
37
- status_color = if line.problem? then PROBLEM_COLOR else STATUS_COLOR end
38
- printf(" %-#{longest_status}s \n".color(*status_color), line.status)
39
- end
@@ -1,141 +0,0 @@
1
- require 'time'
2
- require 'date'
3
- require 'rubygems'
4
- require 'nokogiri'
5
-
6
- module Tube # :nodoc:
7
- module StatusParser # :nodoc:
8
- extend self
9
-
10
- def parse( html_doc )
11
- html_doc.gsub!( /&nbsp;/, " " )
12
- doc = Nokogiri::HTML( html_doc )
13
-
14
- updated_element = doc.at_css( "div.hd-row > h2" )
15
- updated = parse_updated( updated_element )
16
-
17
- service_board = doc.at_css( "#service-board" )
18
-
19
- line_elements = service_board.css( "ul#lines > li.ltn-line" )
20
- lines = line_elements.map( &method( :parse_line ) )
21
-
22
- station_group_elements = service_board.css( "ul#stations > li" )
23
- station_groups = station_group_elements.map(&method(:parse_station_group))
24
-
25
- {:updated => updated, :lines => lines, :station_groups => station_groups}
26
- end
27
-
28
- def parse_updated( updated_element )
29
- time_text = updated_element.content.match( /(\d?\d:\d\d)/ )[0]
30
- time_zone = if is_bst? then "+0100" else "+0000" end
31
-
32
- Time.parse( "#{time_text} #{time_zone}" )
33
- end
34
-
35
- def parse_line( line_element )
36
- name_element = line_element.at_css( "h3.ltn-name" )
37
- name = name_element.content
38
- html_class = name_element["class"].split.first
39
- status = parse_status( line_element.at_css( "div.status" ) )
40
-
41
- {:name => name, :html_class => html_class, :status => status}
42
- end
43
-
44
- def parse_status( status_element )
45
- header = status_element.at_css( "h4.ltn-title" )
46
-
47
- if header
48
- headline = header.content.strip
49
- message = parse_status_message( status_element.css("div.message > p") )
50
- else
51
- headline = status_element.content.strip
52
- end
53
- problem = status_element["class"].split.include?( "problem" )
54
-
55
- {:headline => headline, :problem => problem, :message => message}
56
- end
57
-
58
- def parse_station_group( station_group_element )
59
- name = station_group_element.at_css( "h3" ).content
60
-
61
- station_elements = station_group_element.css( "ul > li.ltn-station" )
62
-
63
- stations = station_elements.map do |station_element|
64
- parse_station( station_element )
65
- end
66
-
67
- {:name => name, :stations => stations}
68
- end
69
-
70
- def parse_station( station_element )
71
- name = station_element.at_css( "h4.ltn-name" ).content.strip
72
- message = parse_status_message( station_element.css( "div.message > p" ) )
73
-
74
- {:name => name, :message => message}
75
- end
76
-
77
- def parse_status_message( messages )
78
- text_messages = messages.map do |message|
79
- if message.children
80
- message.children.select {|child| child.text?}.join( " " )
81
- end
82
- end.compact
83
- text_messages.reject! {|m| m.empty?}
84
-
85
- text_messages.map {|m| m.gsub( /\s+/, " " ).strip}.join( "\n" )
86
- end
87
-
88
- private
89
-
90
- # :call-seq: is_bst? -> bool
91
- #
92
- # Is British Summer Time currently in effect.
93
- #
94
- def is_bst?
95
- bst_start = last_sunday_of_month( "march" )
96
- bst_end = last_sunday_of_month( "october" )
97
-
98
- one_hour = 3600
99
-
100
- bst_start = Time.gm( bst_start.year, bst_start.month, bst_start.day )
101
- bst_start += one_hour
102
-
103
- bst_end = Time.gm( bst_end.year, bst_end.month, bst_end.day )
104
- bst_end += one_hour
105
-
106
- bst = (bst_start..bst_end)
107
- if bst.respond_to?(:cover?)
108
- bst.cover?( Time.now.getgm )
109
- else
110
- bst.include?( Time.now.getgm )
111
- end
112
- end
113
-
114
- # :call-seq: last_sunday_of_month(month_name) -> date
115
- #
116
- def last_sunday_of_month( month )
117
- start_of_next_month = Date.parse( next_month_name( month ) )
118
-
119
- week_day = start_of_next_month.wday
120
-
121
- distance_from_sunday = if week_day == 0 then 7 else week_day end
122
- start_of_next_month - distance_from_sunday
123
- end
124
-
125
- # :call-seq: next_month_name(month_name) -> string
126
- #
127
- def next_month_name( month )
128
- index = Date::MONTHNAMES.index( month.capitalize )
129
- index ||= ABBR_MONTHNAMES.index( month.capitalize )
130
-
131
- index += 1
132
-
133
- if index >= 12
134
- index = 1
135
- end
136
-
137
- Date::MONTHNAMES[index]
138
- end
139
-
140
- end
141
- end
data/test/dummy.html DELETED
@@ -1,145 +0,0 @@
1
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
- <head>
5
- <title>Service update now &#124; Transport for London</title>
6
- <!-- Transport for London website template version 1.7 -->
7
-
8
- <meta http-equiv="content-type" content="text/html;charset=utf-8" />
9
- </head>
10
- <body class="template-6">
11
- <!-- <lm>Sun, 15 Nov 2009 12:12:20 GMT</lm> -->
12
-
13
- <div id="container" class="live-travel-news">
14
- <div id="main-content">
15
- <h1>Live travel news</h1>
16
-
17
- <div class="hd-row">
18
- <h2>
19
- Service update at 12:12
20
- <a href="later.html" id="works_later" class="alert">
21
- View engineering works planned for <strong>later today</strong>
22
- </a>
23
- </h2>
24
-
25
- <div id="closures-email">
26
- <h3>
27
- <a class="iframe closures-eml-lnk" href="/plannedworks">
28
- Weekend closures email
29
- </a>
30
- </h3>
31
- <p>Get advance warning of weekend closures</p>
32
- </div>
33
- </div>
34
-
35
- <div class="short-form">
36
- <div class="clear"></div>
37
- </div>
38
-
39
- <div id="service-board">
40
- <h2>Tube lines</h2>
41
- <ul id="lines">
42
- <li class="ltn-line">
43
- <h3 class="central ltn-name">Central</h3>
44
- <div class="status">Good service</div>
45
- </li>
46
-
47
- <li class="ltn-line">
48
- <h3 class="district ltn-name">District</h3>
49
- <div class="problem status">
50
- <h4 class="ltn-title">Part closure</h4>
51
- <div class="message">
52
- <p>Rail replacement bus</p>
53
- <p>Service A: details...</p>
54
- <dl class="linklist">
55
- <dd>
56
- <a href="http://journeyplanner.tfl.gov.uk/">Replan your journey</a>
57
- </dd>
58
- </dl>
59
- </div>
60
- </div>
61
- </li>
62
-
63
- <li class="ltn-line">
64
- <h3 class="waterlooandcity ltn-name">Waterloo &amp; City</h3>
65
- <div class="problem status">
66
- <h4 class="ltn-title">Planned closure</h4>
67
- <div class="message">
68
- <p>Closed Sunday.</p>
69
- <dl class="linklist">
70
- <dd>
71
- <a href="http://journeyplanner.tfl.gov.uk/">Replan your journey</a>
72
- </dd>
73
- </dl>
74
- </div>
75
- </div>
76
- </li>
77
- </ul>
78
-
79
- <h2>Tube stations</h2>
80
- <ul id="stations">
81
- <li class="ltn-closed">
82
- <h3>Closed stations</h3>
83
- <ul>
84
- <li class="ltn-station" id="stop-10000xx">
85
- <h4 class="ltn-name">Bank</h4>
86
- <div class="message">
87
- <p>Closed due to excessive noise.</p>
88
- <dl class="linklist">
89
- <dd>
90
- Replan your journey
91
- <a href="journeyplanner">to</a>
92
- /
93
- <a href="http://journeyplanner">from</a>
94
- this station
95
- </dd>
96
- </dl>
97
- </div>
98
- </li>
99
-
100
- <li class="ltn-station" id="stop-10000xx">
101
- <h4 class="ltn-name">Holborn</h4>
102
- <div class="message">
103
- <p>Closed due to fire investigation.</p>
104
- <p>Go to Chancery Lane or Tottenham Court Road instead.</p>
105
- <dl class="linklist">
106
- <dd>
107
- Replan your journey
108
- <a href="journeyplanner">to</a>
109
- /
110
- <a href="http://journeyplanner">from</a>
111
- this station
112
- </dd>
113
- </dl>
114
- </div>
115
- </li>
116
- </ul>
117
- </li>
118
-
119
- <li>
120
- <h3>Station maintenance</h3>
121
- <p class="ltn-more-info">(lifts, escalators etc.)</p>
122
- <ul>
123
- <li class="ltn-station" id="stop-10000xx">
124
- <h4 class="ltn-name">Elephant &amp; Castle</h4>
125
- <div class="message">
126
- <p>Reduced lift service.</p>
127
- <dl class="linklist">
128
- <dd>
129
- Replan your journey
130
- <a href="journeyplanner">to</a>
131
- /
132
- <a href="http://journeyplanner">from</a>
133
- this station
134
- </dd>
135
- </dl>
136
- </div>
137
- </li>
138
- </ul>
139
- </li>
140
- </ul>
141
- </div>
142
- </div>
143
- </div>
144
- </body>
145
- </html>
@@ -1,140 +0,0 @@
1
- require "test/unit"
2
-
3
- require File.expand_path("../../lib/tube/status", __FILE__)
4
-
5
- class TestStatusParser < Test::Unit::TestCase
6
- def test_parse_updated
7
- document = Nokogiri::HTML("<h2>Service update at 18:26</h2>")
8
- element = document.at_css("h2")
9
- result = Tube::StatusParser.parse_updated(element)
10
-
11
- assert_equal(Time.parse("6:26pm"), result)
12
- end
13
-
14
- def test_parse_updated_with_anchor_in_element
15
- document = Nokogiri::HTML(%Q{<h2>Service update at 12:12 <a href="/later.html">View engineering works planned for later today</a></h2>})
16
- element = document.at_css("h2")
17
- result = Tube::StatusParser.parse_updated(element)
18
-
19
- assert_equal(Time.parse("12:12pm"), result)
20
- end
21
-
22
- def test_parse_line
23
- document = Nokogiri::HTML(%Q{<li class="ltn-line"><h3 class="central ltn-name">Central</h3><div class="status">Good service</div></li>})
24
- element = document.at_css("li")
25
- result = Tube::StatusParser.parse_line(element)
26
-
27
- assert_equal("Central", result[:name])
28
- assert_equal("central", result[:html_class])
29
- assert_equal("Good service", result[:status][:headline])
30
- end
31
-
32
- def test_parse_line_with_complex_name
33
- document = Nokogiri::HTML(%Q{<li class="ltn-line"><h3 class="waterlooandcity ltn-name">Waterloo &amp; City</h3><div class="status">Good service</div></li>})
34
- element = document.at_css("li")
35
- result = Tube::StatusParser.parse_line(element)
36
-
37
- assert_equal("Waterloo & City", result[:name])
38
- assert_equal("waterlooandcity", result[:html_class])
39
- end
40
-
41
- def test_parse_status
42
- document = Nokogiri::HTML(%Q{<div class="status">Good service</div>})
43
- element = document.at_css("div")
44
- result = Tube::StatusParser.parse_status(element)
45
-
46
- assert_equal("Good service", result[:headline])
47
- end
48
-
49
- def test_parse_status_with_problem
50
- document = Nokogiri::HTML(%Q{<div class="problem status">Part suspended</div>})
51
- element = document.at_css("div")
52
- result = Tube::StatusParser.parse_status(element)
53
-
54
- assert_equal(true, result[:problem])
55
- end
56
-
57
- def test_parse_status_with_header
58
- document = Nokogiri::HTML(%Q{<div class="status"><h4 class="ltn-title">Part suspended</h4></div>})
59
- element = document.at_css("div")
60
- result = Tube::StatusParser.parse_status(element)
61
-
62
- assert_equal("Part suspended", result[:headline])
63
- end
64
-
65
- def test_parse_status_with_message
66
- document = Nokogiri::HTML(%Q{<div class="problem status"><h4 class="ltn-title">Part closure</h4><div class="message"><p>engineering works, etc...</p></div></div>})
67
- element = document.at_css("div.status")
68
- result = Tube::StatusParser.parse_status(element)
69
-
70
- assert_equal("Part closure", result[:headline])
71
- assert_equal(true, result[:problem])
72
- assert_equal("engineering works, etc...", result[:message])
73
- end
74
-
75
- def test_parse_status_message
76
- document = Nokogiri::HTML(%Q{<div><p>engineering works, etc...</p></div>})
77
- elements = document.css("div p")
78
- result = Tube::StatusParser.parse_status_message(elements)
79
-
80
- assert_equal("engineering works, etc...", result)
81
- end
82
-
83
- def test_parse_status_message_with_multi_paragraph_message
84
- document = Nokogiri::HTML(%Q{<div><p>Rail replacement bus</p><p>Service A: details...</p></div>})
85
- elements = document.css("div p")
86
- result = Tube::StatusParser.parse_status_message(elements)
87
-
88
- assert_equal("Rail replacement bus\nService A: details...", result)
89
- end
90
-
91
- def test_parse_status_message_removes_anchor_from_message
92
- document = Nokogiri::HTML(%Q{<div><p>Closed Sunday.</p><p><a href="/projectsandschemes"><p>Click for further information.</p></a></p></div>})
93
- elements = document.css("div > p")
94
- result = Tube::StatusParser.parse_status_message(elements)
95
-
96
- assert_equal("Closed Sunday.", result)
97
- end
98
-
99
- def test_parse_station_group
100
- document = Nokogiri::HTML(%Q{<li class="ltn-closed"><h3>Closed stations</h3><ul>
101
- <li class="ltn-station" id="stop-1000013"><h4 class="ltn-name">Bank</h4><div class="message"><p>Closed due to excessive noise.</p></div></li>
102
- <li class="ltn-station" id="stop-10000xx"><h4 class="ltn-name">Holborn</h4><div class="message"><p>Closed due to fire investigation.</p></div></li></ul></li>})
103
- element = document.at_css("li.ltn-closed")
104
- result = Tube::StatusParser.parse_station_group(element)
105
-
106
- assert_equal("Closed stations", result[:name])
107
- assert_equal("Bank", result[:stations].first[:name])
108
- assert_equal("Holborn", result[:stations].last[:name])
109
- end
110
-
111
- def test_parse_station
112
- document = Nokogiri::HTML(%Q{<li class="ltn-station" id="stop-1000013"><h4 class="ltn-name">Bank</h4><div class="message"><p>Closed due to excessive noise.</p></div></li>})
113
- element = document.at_css("li")
114
- result = Tube::StatusParser.parse_station(element)
115
-
116
- assert_equal("Bank", result[:name])
117
- # This seriously happend once.
118
- assert_equal("Closed due to excessive noise.", result[:message])
119
- end
120
-
121
- def test_parse
122
- # the file used here is an approximation of the most important bits of the
123
- # Live travel news at http://www.tfl.gov.uk/tfl/livetravelnews/realtime/tube/default.html
124
- document = open("#{File.dirname( __FILE__ )}/dummy.html").read
125
- result = Tube::StatusParser.parse(document)
126
-
127
- assert(result)
128
- assert_equal(Time.parse("12:12pm"), result[:updated])
129
- assert_equal(3, result[:lines].length)
130
- assert_equal("Central", result[:lines].first[:name])
131
- assert_equal("Closed Sunday.", result[:lines].last[:status][:message])
132
- assert_equal(2, result[:station_groups].length)
133
- assert_equal(2, result[:station_groups].first[:stations].length)
134
- assert_equal(1, result[:station_groups].last[:stations].length)
135
- assert_equal("Closed stations", result[:station_groups].first[:name])
136
- assert_equal("Elephant & Castle", result[:station_groups].last[:stations].first[:name])
137
-
138
- assert_equal({:updated=>Time.parse("12:12pm"), :station_groups=>[{:stations=>[{:message=>"Closed due to excessive noise.", :name=>"Bank"}, {:message=>"Closed due to fire investigation.\nGo to Chancery Lane or Tottenham Court Road instead.", :name=>"Holborn"}], :name=>"Closed stations"}, {:stations=>[{:message=>"Reduced lift service.", :name=>"Elephant & Castle"}], :name=>"Station maintenance"}], :lines=>[{:status=>{:problem=>false, :message=>nil, :headline=>"Good service"}, :html_class=>"central", :name=>"Central"}, {:status=>{:problem=>true, :message=>"Rail replacement bus\nService A: details...", :headline=>"Part closure"}, :html_class=>"district", :name=>"District"}, {:status=>{:problem=>true, :message=>"Closed Sunday.", :headline=>"Planned closure"}, :html_class=>"waterlooandcity", :name=>"Waterloo & City"}]}, result)
139
- end
140
- end