tube 0.2.5 → 0.3.0pre

Sign up to get free protection for your applications and to get access to all the features.
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