f1results 2.0 → 3.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 20e8936ca3cd5baf306ab90eb7ba9e6324c275f6
4
- data.tar.gz: 6c019079bb2e03f2e55cd45616f27c64236160ab
2
+ SHA256:
3
+ metadata.gz: aa2c935bee2392688a8b77b2c56668778bb6b84525c3fb6ea4331d5520675d59
4
+ data.tar.gz: 0a035e5ce0d87d87dad070597b860cdb33e2a32cb77f0c48e5b5f9bf4968f8b8
5
5
  SHA512:
6
- metadata.gz: 3512907a131f27c0d834016b79061e342dc3a93d30bd2288544ba2109dd1bd13c1e0455bbdc72063c19387ebb7974c7c01d2d13e53fe1a2d942064403c7604fc
7
- data.tar.gz: 81d89f42b758c3a673b0cedbe231150aef324bf22491a1da822b7aa0a4ac0cb8e7ae872734201f1b911b8a00e428bb5bc3117cf6c8328bf5ef9ea781c9d32883
6
+ metadata.gz: 7664c1698d0b058b1e7a2da0889e322869eac9fbc59c3589297690f843e5c4fcb38867b78448aa50aace0f9d73b32ec1415017f78f443d451497d98522c31235
7
+ data.tar.gz: d5deaedc384e08a0f02434cca1bd1e902c8b276b2bbf4d324ebc4b74ff44c1f51ab6709ea9e6df5ee3e5b1580052da5069b3eefd77ab4a6eea3f21683096a327
data/Rakefile CHANGED
@@ -1,10 +1,58 @@
1
- require 'bundler/setup'
2
- require 'rake'
3
- require 'rake/testtask'
1
+ require "bundler/setup"
2
+ require "rake"
3
+ require "rake/testtask"
4
+ require "./test/lib/fixtures"
5
+ require "open-uri"
6
+ require "fileutils"
7
+ require "tempfile"
4
8
 
5
9
  task default: :test
6
10
 
7
11
  Rake::TestTask.new do |t|
8
- t.libs << 'test/lib'
9
- t.pattern = 'test/*_test.rb'
12
+ t.libs << "test/lib"
13
+ t.pattern = "test/*_test.rb"
14
+ t.warning = false
10
15
  end
16
+
17
+ def fixture_downloads
18
+ Fixtures::STUBS.flat_map do |_name, mappings|
19
+ mappings.filter_map do |path, fixture|
20
+ next if fixture.is_a?(Integer)
21
+
22
+ {
23
+ url: URI.join(F1Results::BASE_URL, path).to_s,
24
+ destination: File.join(Fixtures::FIXTURES_DIR, fixture)
25
+ }
26
+ end
27
+ end
28
+ end
29
+
30
+ namespace :fixtures do
31
+ desc "List fixture URLs and destinations without downloading them"
32
+ task :list do
33
+ fixture_downloads.each do |download|
34
+ puts "#{download[:url]} => #{download[:destination]}"
35
+ end
36
+ end
37
+
38
+ desc "Download fixtures from formula1.com"
39
+ task :download do
40
+ WebMock.disable!
41
+ FileUtils.mkdir_p(Fixtures::FIXTURES_DIR)
42
+
43
+ fixture_downloads.each do |download|
44
+ puts "Downloading #{download[:url]} => #{download[:destination]}"
45
+
46
+ Tempfile.create(["f1results-fixture-", ".html"], Fixtures::FIXTURES_DIR) do |temporary|
47
+ URI.open(download[:url]) do |remote_file|
48
+ IO.copy_stream(remote_file, temporary)
49
+ end
50
+ temporary.close
51
+ FileUtils.mv(temporary.path, download[:destination])
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ desc "Download fixtures from formula1.com (alias for fixtures:download)"
58
+ task download_fixtures: "fixtures:download"
data/bin/f1results CHANGED
@@ -3,24 +3,24 @@
3
3
  require 'rubygems'
4
4
  require 'optparse'
5
5
  require 'terminal-table'
6
- require File.expand_path('../../lib/f1results.rb', __FILE__)
6
+ require_relative '../lib/f1results'
7
7
 
8
8
  year = Time.now.year
9
- country = ''
9
+ grand_prix = ''
10
10
  event_type = :race
11
11
  url = nil
12
12
 
13
13
  optparse = OptionParser.new do |opts|
14
- opts.on('-y', '--year=YEAR', Integer) { |val| year = val }
15
- opts.on('-c', '--country=COUNTRY', String) { |val| country = val.titleize }
16
- opts.on('-e', '--event=EVENT', String) { |val| event_type = val.downcase.to_sym }
17
- opts.on('-u', '--url=URL', String) { |val| url = val }
14
+ opts.on('-y', '--year=YEAR', Integer) { |val| year = val }
15
+ opts.on('-g', '--grandprix=GRANDPRIX', String) { |val| grand_prix = val.capitalize }
16
+ opts.on('-e', '--event=EVENT', String) { |val| event_type = val.downcase.to_sym }
17
+ opts.on('-u', '--url=URL', String) { |val| url = val }
18
18
  opts.parse!
19
19
  end
20
20
 
21
21
  begin
22
22
  event = if url.nil?
23
- F1Results.fetch(year, country, event_type)
23
+ F1Results.fetch(year, grand_prix, event_type)
24
24
  else
25
25
  F1Results.fetch_with_url(url)
26
26
  end
@@ -29,7 +29,7 @@ rescue RuntimeError => e
29
29
  exit
30
30
  end
31
31
 
32
- title = url.nil? ? "#{event.year} #{event.country} #{event.type_name}\n#{event.name}" : event.name
32
+ title = url.nil? ? "#{event.year} #{event.grand_prix} #{event.type_name}\n#{event.name}" : event.name
33
33
  table = Terminal::Table.new title: title, rows: event.to_a
34
34
 
35
35
  if event.practice?
@@ -58,5 +58,4 @@ elsif event.race?
58
58
  table.align_column 6, :right
59
59
  end
60
60
 
61
- puts event.results[0].inspect
62
61
  puts table
@@ -2,6 +2,10 @@ require 'mechanize'
2
2
 
3
3
  module F1Results
4
4
  class Agent < ::Mechanize
5
+ def initialize
6
+ super
7
+ self.verify_mode = OpenSSL::SSL::VERIFY_NONE
8
+ end
5
9
 
6
10
  def get_url(event)
7
11
  @event = event
@@ -11,13 +15,13 @@ module F1Results
11
15
  def get_results(new_event)
12
16
  @event = new_event
13
17
  event.url ||= url
14
- update_results
18
+ update_event
15
19
  return event
16
20
  end
17
21
 
18
22
  def get_results_with_url(new_url)
19
23
  event.url = new_url
20
- update_results
24
+ update_event
21
25
  return event
22
26
  end
23
27
 
@@ -28,64 +32,103 @@ module F1Results
28
32
  end
29
33
 
30
34
  def url
31
- base_path = "content/fom-website/en/results.html/#{event.year}/"
32
- year_url = URI.join F1Results::BASEURL, base_path, 'races.html'
35
+ base_uri = URI.join F1Results::BASE_URL, "en/results/#{event.year}/"
36
+ year_uri = URI.join base_uri, 'races'
33
37
  begin
34
- get(year_url)
38
+ get(year_uri)
35
39
  rescue Mechanize::ResponseCodeError, Net::HTTPNotFound
36
40
  raise "No results found for #{event.year}"
37
41
  end
38
42
 
39
- file_name = html_file_name
40
- key = meeting_key
43
+ grand_prix_nodes = page.parser.xpath("//table//tbody/tr/td[1]//a[contains(@href, '/races/')]").map do |a|
44
+ # Remove SVG icons from the links
45
+ a2 = a.dup
46
+ a2.search('.//svg').remove
47
+ a2
48
+ end
41
49
 
42
- uri = URI.join F1Results::BASEURL, base_path, "races/#{key}/#{file_name}"
43
- return uri.to_s
44
- end
50
+ grand_prix_node = grand_prix_nodes.find { |node| node.text.strip.downcase == event.grand_prix.downcase }
51
+ raise "No grand prix '#{event.grand_prix}' found for #{event.year}" if grand_prix_node.nil?
52
+
53
+ grand_prix_uri = URI.join base_uri, grand_prix_node.attr('href')
45
54
 
46
- def update_results
47
55
  begin
48
- get(event.url)
49
- new_event = Parser.new(page).parse
50
- event.results = new_event.results
51
- event.type ||= new_event.type
52
- event.country ||= new_event.country
53
- event.name ||= new_event.name
56
+ get(grand_prix_uri)
54
57
  rescue Mechanize::ResponseCodeError, Net::HTTPNotFound
55
- raise "No results found at #{url}"
58
+ raise "Error fetching #{grand_prix_uri}"
56
59
  end
57
- end
58
60
 
59
- def meeting_key
60
- country = event.country.parameterize
61
- options = page.parser.xpath('//select[@name="meetingKey"]/option')
62
- meeting_key_node = options.detect do |node|
63
- node.attr('value') =~ /^\d+\/#{country}/ || node.text.parameterize =~ /#{country}/
61
+ event_names = {
62
+ "race result" => :race_result_node,
63
+ "fastest laps" => :fastest_laps_node,
64
+ "pit stop summary" => :pit_stop_summary_node,
65
+ "starting grid" => :starting_grid_node,
66
+ "overall qualifying" => :overall_qualifying_node,
67
+ "qualifying" => :qualifying_node,
68
+ "practice 3" => :practice3_node,
69
+ "practice 2" => :practice2_node,
70
+ "practice 1" => :practice1_node,
71
+ "sprint" => :sprint_node,
72
+ "sprint grid" => :sprint_grid_node,
73
+ "sprint qualifying" => :sprint_qualifying_node
74
+ }
75
+
76
+ event_nodes = page.parser.xpath("//menu[@aria-labelledby='sidebar-dropdown']//li/a").map do |a|
77
+ # Remove SVG icons from the links
78
+ a2 = a.dup
79
+ a2.search('.//svg').remove
80
+ a2
64
81
  end
65
- raise "No country '#{event.country}' found for #{event.year}" if meeting_key_node.nil?
66
- return meeting_key_node.attr('value')
67
- end
68
82
 
69
- def html_file_name
70
- result_types = {}
71
- page.parser.xpath('//a[@data-name="resultType"]').each do |node|
72
- key = node.text.parameterize('_').to_sym
73
- value = node.attr('data-value')
74
- result_types[key] = value
83
+ # Create a hash to store the nodes
84
+ nodes = {}
85
+ event_names.each do |name, key|
86
+ nodes[key] = event_nodes.find { |node| node.text.strip.downcase == name }
75
87
  end
76
88
 
77
89
  # TODO: add support for Starting Grid, Warm Up, Pit Stop Summary, Fastest Laps
78
- file_name = case
90
+ node = case
79
91
  when event.race?
80
- 'race-result'
92
+ nodes[:race_result_node]
81
93
  when event.qualifying?
82
- result_types[:qualifying] || result_types[:overall_qualifying]
83
- when event.practice?
84
- event.type_name.parameterize
94
+ nodes[:qualifying_node] || nodes[:overall_qualifying_node]
95
+ when event.practice3?
96
+ nodes[:practice3_node]
97
+ when event.practice2?
98
+ nodes[:practice2_node]
99
+ when event.practice1?
100
+ nodes[:practice1_node]
85
101
  else
86
- raise "No results for event type '#{event.type}' at #{event.year} #{event.country}"
102
+ raise "Unsupported event type '#{event.type}'"
103
+ end
104
+
105
+ raise "No results for event type '#{event.type}' at #{event.year} #{event.grand_prix}" if node.nil?
106
+
107
+ uri = URI.join base_uri, node.attr('href')
108
+ return uri.to_s
109
+ end
110
+
111
+ def update_event
112
+ begin
113
+ get(event.url)
114
+ rescue Mechanize::ResponseCodeError, Net::HTTPNotFound
115
+ raise "No results found at '#{url}'"
116
+ end
117
+
118
+ new_event = Parser.new(page).parse
119
+ event.type ||= new_event.type
120
+ validate_event(new_event)
121
+
122
+ event.grand_prix ||= new_event.grand_prix
123
+ event.circuit ||= new_event.circuit
124
+ event.name ||= new_event.name
125
+ event.results = new_event.results
126
+ end
127
+
128
+ def validate_event(new_event)
129
+ if event.type != new_event.type
130
+ raise "Results at '#{url}' are returning from '#{new_event.type_name}', not the requested '#{event.type_name}'"
87
131
  end
88
- return file_name + '.html'
89
132
  end
90
133
 
91
134
  end
@@ -1,40 +1,42 @@
1
- require 'active_support/core_ext/string'
2
-
3
1
  module F1Results
4
2
  class Event
5
- attr_accessor :year, :country, :country_slug, :type, :name, :results, :url
6
-
7
- TYPE_ALIASES = {
8
- p1: :practice1,
9
- p2: :practice2,
10
- p3: :practice3,
11
- q: :qualifying,
12
- r: :race
13
- }
3
+ attr_accessor :year, :grand_prix, :circuit, :type, :name, :results, :url
14
4
 
15
5
  def initialize(args = {})
16
6
  @results = []
17
7
  args.each { |k,v| send("#{k}=", v) }
18
8
  end
19
9
 
20
- def type=(type)
21
- type = type.to_s.downcase.gsub(' ', '').to_sym
22
- @type = TYPE_ALIASES[type] || type
10
+ def grand_prix_slug
11
+ grand_prix.strip.downcase.gsub(/[:space:]+/, '-')
23
12
  end
24
13
 
25
- # Human readable type, e.g. "Practice 1", "Qualifying"
14
+ # Human readable type, e.g. "Practice 1", "Qualifying", "Starting Grid"
26
15
  def type_name
27
- @type.to_s.gsub(/\d/, ' \0').capitalize
28
- end
29
-
30
- def type_slug
31
- type_name.parameterize
16
+ @type.to_s
17
+ .gsub(/\d/, ' \0')
18
+ .gsub('_', ' ')
19
+ .split(' ')
20
+ .map(&:capitalize)
21
+ .join(' ')
32
22
  end
33
23
 
34
24
  def practice?
35
25
  /^practice(1|2|3)$/ =~ @type.to_s
36
26
  end
37
27
 
28
+ def practice1?
29
+ @type == :practice1
30
+ end
31
+
32
+ def practice2?
33
+ @type == :practice2
34
+ end
35
+
36
+ def practice3?
37
+ @type == :practice3
38
+ end
39
+
38
40
  def qualifying?
39
41
  @type == :qualifying
40
42
  end
@@ -8,7 +8,8 @@ module F1Results
8
8
  def parse
9
9
  @event.name = event_name
10
10
  @event.type = event_type
11
- @event.country = event_country
11
+ @event.grand_prix = event_grand_prix
12
+ @event.circuit = event_circuit
12
13
  @event.results = event_results
13
14
  # TODO: date
14
15
  return @event
@@ -17,49 +18,56 @@ module F1Results
17
18
  private
18
19
 
19
20
  def event_name
20
- # TODO: make helper method for .gsub(/[[:space:]]+/, ' ').strip
21
- return @page.parser.xpath('//title').text
22
- .gsub(/[[:space:]]+/, ' ').strip
21
+ return @page.parser.at_xpath('//h1').text.gsub(/[[:space:]]+/, ' ').strip
23
22
  end
24
23
 
25
24
  def event_type
26
- if match = @event.name.match(/(?:.+) - (.+)/)
27
- result_title = match[1]
28
- .gsub(/(?<=RACE )RESULT/, '')
29
- .gsub(/OVERALL(?= QUALIFYING)/, '')
30
- .gsub(/(?<=PRACTICE)( )(?=[1|2|3])/, '')
31
- .parameterize('_')
32
- return result_title.to_sym
33
- else
34
- return nil
25
+ if m = @event.name.match(/(?:.+) - (.+)/)
26
+ result = m[1]
27
+ .gsub(/(?<=RACE )RESULT/i, '')
28
+ .gsub(/OVERALL(?= QUALIFYING)/i, '')
29
+ .gsub(/(?<=PRACTICE)( )(?=[1-3])/i, '')
30
+ .sub(/(?<=QUALIFYING)\s*\d+\z/i, '') # strip numbers for Qualifying
31
+ .strip
32
+ .downcase
33
+ result.to_sym
35
34
  end
36
35
  end
37
36
 
38
- def event_country
39
- node = @page.parser.at_xpath('//select[@name="meetingKey"]/option[@selected]')
40
- slug = node.attr('value').split('/')[-1]
41
- text = node.text
42
- return text
37
+ def event_grand_prix
38
+ node = @page.parser.at_xpath('(//dialog)[3]//a[.//title[text()="Active"]]')
39
+ node.xpath('.//svg').remove
40
+
41
+ return node.text.strip
42
+ end
43
+
44
+ def event_circuit
45
+ node = @page.parser.at_xpath('//h1/../../../../../div/following-sibling::div[1]//p[2]')
46
+ return node.text
43
47
  end
44
48
 
45
49
  def event_results
46
50
  results = []
47
- table = @page.parser.xpath('//tbody')
51
+ tbody = @page.parser.at_xpath('//tbody')
48
52
 
49
53
  # Remove driver abbreviation from driver cell
50
- table.xpath('//span[@class="uppercase hide-for-desktop"]').each(&:remove)
54
+ tbody.xpath('.//span[@class="md:hidden"]').each(&:remove)
51
55
 
52
- # Turn HTML table into an array of arrays
53
- data = table.xpath('//tr').map do |row|
56
+ # Turn HTML tbody into an array of arrays
57
+ data = tbody.xpath('.//tr').map do |row|
54
58
  row.xpath('./td|./th').map do |cell|
55
59
  cell = cell.text.gsub(/[[:space:]]+/, ' ').strip
56
- cell.blank? ? nil : cell
60
+ cell.empty? ? nil : cell
57
61
  end
58
62
  end
59
63
 
60
- # Shift top row of table and convert cell text into symbols
61
- header = data.shift.map do |cell|
62
- cell.to_s.parameterize('_').to_sym
64
+ header = @page.parser.xpath('//thead//th').map do |cell|
65
+ cell.text.to_s
66
+ .gsub(/\./, '') # Pos. -> Pos
67
+ .gsub(/[[:space:]]+/, '')
68
+ .gsub(/\/.*/, '') # Time/Retired -> Time
69
+ .downcase
70
+ .to_sym
63
71
  end
64
72
 
65
73
  # Set result class type
@@ -1,3 +1,3 @@
1
1
  module F1Results
2
- VERSION = '2.0'
2
+ VERSION = '3.0'
3
3
  end
data/lib/f1results.rb CHANGED
@@ -1,13 +1,13 @@
1
- require 'f1results/version'
2
- require 'f1results/agent'
3
- require 'f1results/parser'
4
- require 'f1results/event'
5
- require 'f1results/result'
1
+ require_relative './f1results/version'
2
+ require_relative './f1results/agent'
3
+ require_relative './f1results/parser'
4
+ require_relative './f1results/event'
5
+ require_relative './f1results/result'
6
6
 
7
7
  module F1Results
8
- BASEURL = 'http://www.formula1.com'
8
+ BASE_URL = 'https://www.formula1.com/'
9
9
 
10
- # Get results from formula1.com for a given year, country, and event type
10
+ # Get results from formula1.com for a given year, grand prix, and event type
11
11
  # (race or qualifying)
12
12
  #
13
13
  # F1Results.f1results(2010, 'australia', :qualifying)
@@ -15,8 +15,8 @@ module F1Results
15
15
  # Returns an `F1Results::Event` object which has a method `results`, which
16
16
  # returns multiple objects of type `F1Results::Result`
17
17
 
18
- def self.fetch(year, country, type = :race)
19
- event = Event.new(year: year, country: country, type: type)
18
+ def self.fetch(year, grand_prix, type = :race)
19
+ event = Event.new(year: year, grand_prix: grand_prix, type: type)
20
20
  event.get_results
21
21
  return event
22
22
  end
data/test/agent_test.rb CHANGED
@@ -1,82 +1,83 @@
1
1
  require 'test_helper'
2
2
 
3
- class AgentTest < MiniTest::Test
3
+ class AgentTest < Minitest::Test
4
4
  include Fixtures
5
5
 
6
6
  def setup
7
+ stub_all
7
8
  @agent = F1Results::Agent.new
8
9
  end
9
10
 
10
11
  def test_get_url_2016_australia_practice1
11
- event = F1Results::Event.new(year: 2016, country: 'Australia', type: :practice1)
12
- url = 'http://www.formula1.com/content/fom-website/en/results.html/2016/races/938/australia/practice-1.html'
12
+ event = F1Results::Event.new(year: 2016, grand_prix: 'Australia', type: :practice1)
13
+ url = 'https://www.formula1.com/en/results/2016/races/938/australia/practice/1'
13
14
  assert_equal url, @agent.get_url(event)
14
15
  end
15
16
 
16
17
  def test_get_url_2016_australia_qualifying
17
- event = F1Results::Event.new(year: 2016, country: 'Australia', type: :qualifying)
18
- url = 'http://www.formula1.com/content/fom-website/en/results.html/2016/races/938/australia/qualifying.html'
18
+ event = F1Results::Event.new(year: 2016, grand_prix: 'Australia', type: :qualifying)
19
+ url = 'https://www.formula1.com/en/results/2016/races/938/australia/qualifying'
19
20
  assert_equal url, @agent.get_url(event)
20
21
  end
21
22
 
22
23
  def test_get_url_2016_australia_race
23
- event = F1Results::Event.new(year: 2016, country: 'Australia', type: :race)
24
- url = 'http://www.formula1.com/content/fom-website/en/results.html/2016/races/938/australia/race-result.html'
24
+ event = F1Results::Event.new(year: 2016, grand_prix: 'Australia', type: :race)
25
+ url = 'https://www.formula1.com/en/results/2016/races/938/australia/race-result'
25
26
  assert_equal url, @agent.get_url(event)
26
27
  end
27
28
 
28
29
  def test_get_url_1984_brazil_qualifying
29
- event = F1Results::Event.new(year: 1984, country: 'Brazil', type: :qualifying)
30
- url = 'http://www.formula1.com/content/fom-website/en/results.html/1984/races/466/brazil/qualifying-0.html'
30
+ event = F1Results::Event.new(year: 1984, grand_prix: 'Brazil', type: :qualifying)
31
+ url = 'https://www.formula1.com/en/results/1984/races/466/brazil/qualifying/0'
31
32
  assert_equal url, @agent.get_url(event)
32
33
  end
33
34
 
34
35
  def test_get_url_1984_brazil_race
35
- event = F1Results::Event.new(year: 1984, country: 'Brazil', type: :race)
36
- url = 'http://www.formula1.com/content/fom-website/en/results.html/1984/races/466/brazil/race-result.html'
36
+ event = F1Results::Event.new(year: 1984, grand_prix: 'Brazil', type: :race)
37
+ url = 'https://www.formula1.com/en/results/1984/races/466/brazil/race-result'
37
38
  assert_equal url, @agent.get_url(event)
38
39
  end
39
40
 
40
41
  def test_get_url_1950_indianapolis_500_qualifying
41
- event = F1Results::Event.new(year: 1950, country: 'United States', type: :qualifying)
42
- url = 'http://www.formula1.com/content/fom-website/en/results.html/1950/races/96/indianapolis-500/qualifying-0.html'
42
+ event = F1Results::Event.new(year: 1950, grand_prix: 'Indianapolis', type: :qualifying)
43
+ url = 'https://www.formula1.com/en/results/1950/races/96/indianapolis/qualifying/0'
43
44
  assert_equal url, @agent.get_url(event)
44
45
  end
45
46
 
46
47
  def test_get_url_1950_indianapolis_500_race
47
- event = F1Results::Event.new(year: 1950, country: 'United States', type: :race)
48
- url = 'http://www.formula1.com/content/fom-website/en/results.html/1950/races/96/indianapolis-500/race-result.html'
48
+ event = F1Results::Event.new(year: 1950, grand_prix: 'Indianapolis', type: :race)
49
+ url = 'https://www.formula1.com/en/results/1950/races/96/indianapolis/race-result'
49
50
  assert_equal url, @agent.get_url(event)
50
51
  end
51
52
 
52
53
  def test_get_results_1950_indianapolis_500_race
53
- event = F1Results::Event.new(year: 1950, country: 'United States', type: :race)
54
+ event = F1Results::Event.new(year: 1950, grand_prix: 'Indianapolis', type: :race)
54
55
  event = @agent.get_results(event)
55
56
  assert_equal 36, event.results.length
56
57
  end
57
58
 
58
59
  def test_api
59
- event = F1Results.fetch(1950, 'United States', :race)
60
+ event = F1Results.fetch(1950, 'Indianapolis', :race)
60
61
  assert_equal 36, event.results.length
61
62
  end
62
63
 
63
64
  def test_event_with_bad_year
64
- assert_raise_with_message RuntimeError, 'No results found for 1900' do
65
- event = F1Results::Event.new(year: 1900, country: 'Australia', type: :race)
65
+ assert_raise_with_message RuntimeError, "No grand prix 'Australia' found for 1900" do
66
+ event = F1Results::Event.new(year: 1900, grand_prix: 'Australia', type: :race)
66
67
  @agent.get_url(event)
67
68
  end
68
69
  end
69
70
 
70
- def test_event_with_bad_grand_prix
71
- assert_raise_with_message RuntimeError, "No country 'New Zealand' found for 2016" do
72
- event = F1Results::Event.new(year: 2016, country: 'New Zealand', type: :race)
71
+ def test_event_with_bad_country
72
+ assert_raise_with_message RuntimeError, "No grand prix 'New Zealand' found for 2016" do
73
+ event = F1Results::Event.new(year: 2016, grand_prix: 'New Zealand', type: :race)
73
74
  @agent.get_url(event)
74
75
  end
75
76
  end
76
77
 
77
78
  def test_event_with_bad_event_name
78
- assert_raise_with_message RuntimeError, "No results for event type 'practice4' at 2016 Australia" do
79
- event = F1Results::Event.new(year: 2016, country: 'Australia', type: :practice4)
79
+ assert_raise_with_message RuntimeError, "Unsupported event type 'practice4'" do
80
+ event = F1Results::Event.new(year: 2016, grand_prix: 'Australia', type: :practice4)
80
81
  @agent.get_url(event)
81
82
  end
82
83
  end
data/test/event_test.rb CHANGED
@@ -1,37 +1,31 @@
1
1
  require 'test_helper'
2
2
 
3
- class EventTest < MiniTest::Test
4
- include Fixtures
5
-
3
+ class EventTest < Minitest::Test
6
4
  def setup
7
5
  @event = F1Results::Event.new
8
6
  end
9
7
 
10
- def test_type
11
- @event.type = :qualifying
12
- assert_equal 'qualifying', @event.type_slug
13
- @event.type = :practice3
14
- assert_equal 'practice-3', @event.type_slug
15
- @event.type = :p3
16
- assert_equal :practice3, @event.type
17
- end
18
-
19
8
  def test_type_name
9
+ @event.type = :practice1
10
+ assert_equal 'Practice 1', @event.type_name
20
11
  @event.type = :practice3
21
12
  assert_equal 'Practice 3', @event.type_name
22
13
  @event.type = :qualifying
23
14
  assert_equal 'Qualifying', @event.type_name
24
15
  @event.type = :race
25
16
  assert_equal 'Race', @event.type_name
26
- end
27
-
28
- def test_type_setter_with_humanized_input
29
- @event.type = 'Practice 3'
30
- assert_equal :practice3, @event.type
31
- @event.type = 'Qualifying'
32
- assert_equal :qualifying, @event.type
33
- @event.type = 'Race'
34
- assert_equal :race, @event.type
17
+ @event.type = :starting_grid
18
+ assert_equal 'Starting Grid', @event.type_name
19
+ @event.type = :warm_up
20
+ assert_equal 'Warm Up', @event.type_name
21
+ @event.type = :pit_stop_summary
22
+ assert_equal 'Pit Stop Summary', @event.type_name
23
+ @event.type = :fastest_laps
24
+ assert_equal 'Fastest Laps', @event.type_name
25
+ @event.type = :sprint
26
+ assert_equal 'Sprint', @event.type_name
27
+ @event.type = :sprint_grid
28
+ assert_equal 'Sprint Grid', @event.type_name
35
29
  end
36
30
 
37
31
  def test_type_boolean_methods
data/test/parser_test.rb CHANGED
@@ -1,12 +1,13 @@
1
1
  require 'test_helper'
2
2
 
3
- class ParserTest < MiniTest::Test
3
+ class ParserTest < Minitest::Test
4
4
  include Fixtures
5
5
 
6
6
  def test_2016_australia_practice1
7
- event = events(:'2016_australia_practice_1')
7
+ event = events(:event_2016_australia_practice_1)
8
8
  assert_equal '2016 FORMULA 1 ROLEX AUSTRALIAN GRAND PRIX - PRACTICE 1', event.name
9
- assert_equal 'Australia', event.country
9
+ assert_equal 'Australia', event.grand_prix
10
+ assert_equal 'Albert Park Grand Prix Circuit, Melbourne', event.circuit
10
11
  assert_equal :practice1, event.type
11
12
  assert_equal 22, event.results.length
12
13
  assert_equal 'Lewis Hamilton', event.winning.driver
@@ -14,19 +15,22 @@ class ParserTest < MiniTest::Test
14
15
  end
15
16
 
16
17
  def test_2016_australia_qualifying
17
- event = events(:'2016_australia_qualifying')
18
+ event = events(:event_2016_australia_qualifying)
18
19
  assert_equal '2016 FORMULA 1 ROLEX AUSTRALIAN GRAND PRIX - QUALIFYING', event.name
19
- assert_equal 'Australia', event.country
20
+ assert_equal 'Australia', event.grand_prix
21
+ assert_equal 'Albert Park Grand Prix Circuit, Melbourne', event.circuit
20
22
  assert_equal :qualifying, event.type
21
23
  assert_equal 22, event.results.length
24
+
22
25
  assert_equal 'Lewis Hamilton', event.winning.driver
23
26
  assert_equal 'Pascal Wehrlein', event.losing.driver
24
27
  end
25
28
 
26
29
  def test_2016_australia_race
27
- event = events(:'2016_australia_race_result')
30
+ event = events(:event_2016_australia_race_result)
28
31
  assert_equal '2016 FORMULA 1 ROLEX AUSTRALIAN GRAND PRIX - RACE RESULT', event.name
29
- assert_equal 'Australia', event.country
32
+ assert_equal 'Australia', event.grand_prix
33
+ assert_equal 'Albert Park Grand Prix Circuit, Melbourne', event.circuit
30
34
  assert_equal :race, event.type
31
35
  assert_equal 22, event.results.length
32
36
  assert_equal 'Nico Rosberg', event.winning.driver
@@ -34,9 +38,10 @@ class ParserTest < MiniTest::Test
34
38
  end
35
39
 
36
40
  def test_1984_brazil_qualifying
37
- event = events(:'1984_brazil_qualifying_0')
38
- assert_equal 'Brazilian Grand Prix 1984 - OVERALL QUALIFYING', event.name
39
- assert_equal 'Brazil', event.country
41
+ event = events(:event_1984_brazil_qualifying_0)
42
+ assert_equal 'BRAZILIAN GRAND PRIX 1984 - OVERALL QUALIFYING', event.name
43
+ assert_equal 'Brazil', event.grand_prix
44
+ assert_equal 'Autódromo Internacional do Rio de Janeiro, Brazil', event.circuit
40
45
  assert_equal :qualifying, event.type
41
46
  assert_equal 24, event.results.length
42
47
  assert_equal 'Elio de Angelis', event.winning.driver
@@ -44,9 +49,10 @@ class ParserTest < MiniTest::Test
44
49
  end
45
50
 
46
51
  def test_1984_brazil_race
47
- event = events(:'1984_brazil_race_result')
48
- assert_equal 'Brazilian Grand Prix 1984 - RACE RESULT', event.name
49
- assert_equal 'Brazil', event.country
52
+ event = events(:event_1984_brazil_race_result)
53
+ assert_equal 'BRAZILIAN GRAND PRIX 1984 - RACE RESULT', event.name
54
+ assert_equal 'Brazil', event.grand_prix
55
+ assert_equal 'Autódromo Internacional do Rio de Janeiro, Brazil', event.circuit
50
56
  assert_equal :race, event.type
51
57
  assert_equal 24, event.results.length
52
58
  assert_equal 'Alain Prost', event.winning.driver
@@ -54,9 +60,10 @@ class ParserTest < MiniTest::Test
54
60
  end
55
61
 
56
62
  def test_1950_indianapolis_500_qualifying
57
- event = events(:'1950_indianapolis_500_qualifying_0')
58
- assert_equal '1950 Indianapolis 500 - QUALIFYING', event.name
59
- assert_equal 'United States', event.country
63
+ event = events(:event_1950_indianapolis_qualifying_0)
64
+ assert_equal '1950 INDIANAPOLIS 500 - QUALIFYING', event.name
65
+ assert_equal 'Indianapolis', event.grand_prix
66
+ assert_equal 'Indianapolis Motor Speedway, United States', event.circuit
60
67
  assert_equal :qualifying, event.type
61
68
  assert_equal 1, event.results.length
62
69
  assert_equal 'Walt Faulkner', event.winning.driver
@@ -64,13 +71,27 @@ class ParserTest < MiniTest::Test
64
71
  end
65
72
 
66
73
  def test_1950_indianapolis_500_race
67
- event = events(:'1950_indianapolis_500_race_result')
68
- assert_equal '1950 Indianapolis 500 - RACE RESULT', event.name
69
- assert_equal 'United States', event.country
74
+ event = events(:event_1950_indianapolis_race_result)
75
+ assert_equal '1950 INDIANAPOLIS 500 - RACE RESULT', event.name
76
+ assert_equal 'Indianapolis', event.grand_prix
77
+ assert_equal 'Indianapolis Motor Speedway, United States', event.circuit
70
78
  assert_equal :race, event.type
71
79
  # Note: 3 ties, so 36 finishers, 33 positions in this race
72
80
  assert_equal 36, event.results.length
73
81
  assert_equal 'Johnnie Parsons', event.winning.driver
74
82
  assert_equal 'Duke Dinsmore', event.losing.driver
75
83
  end
84
+
85
+ def test_2024_belgium_race
86
+ event = events(:event_2024_belgium_race_result)
87
+ assert_equal 'FORMULA 1 ROLEX BELGIAN GRAND PRIX 2024 - RACE RESULT', event.name
88
+ assert_equal 'Belgium', event.grand_prix
89
+ assert_equal 'Circuit de Spa-Francorchamps, Spa-Francorchamps', event.circuit
90
+ assert event.race?
91
+ assert_equal 20, event.results.length
92
+ # Note: George Russell won but was DQ'd, but still shows as first result
93
+ assert_equal 'George Russell', event.winning.driver
94
+ assert_equal 'DQ', event.results[0].position_name
95
+ assert_equal 'Zhou Guanyu', event.losing.driver
96
+ end
76
97
  end
data/test/result_test.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
 
3
- class ResultTest < MiniTest::Test
3
+ class ResultTest < Minitest::Test
4
4
  def test_time
5
5
  result = F1Results::RaceResult.new
6
6
  result.time_or_retired = '1:25:11.288'
@@ -64,8 +64,8 @@ class ResultTest < MiniTest::Test
64
64
  def test_parse_qualifying_with_blank_values
65
65
  result = F1Results::QualifyingResult.new(position: '16', driver: 'Marcus Ericsson', team: 'Sauber', q1: '1:31.376', q2: nil, q3: nil, laps: 10)
66
66
  assert_equal '1:31.376', result.q1
67
- assert_equal nil, result.q2
68
- assert_equal nil, result.q3
67
+ assert_nil result.q2
68
+ assert_nil result.q3
69
69
  assert_equal 10, result.laps
70
70
  end
71
71
 
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: f1results
3
3
  version: !ruby/object:Gem::Version
4
- version: '2.0'
4
+ version: '3.0'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Darren Jeacocke
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2016-07-23 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: mechanize
@@ -16,84 +15,70 @@ dependencies:
16
15
  requirements:
17
16
  - - "~>"
18
17
  - !ruby/object:Gem::Version
19
- version: '2.7'
18
+ version: '2.14'
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - "~>"
25
24
  - !ruby/object:Gem::Version
26
- version: '2.7'
25
+ version: '2.14'
27
26
  - !ruby/object:Gem::Dependency
28
27
  name: terminal-table
29
28
  requirement: !ruby/object:Gem::Requirement
30
29
  requirements:
31
30
  - - "~>"
32
31
  - !ruby/object:Gem::Version
33
- version: '1.4'
32
+ version: '4.0'
34
33
  type: :runtime
35
34
  prerelease: false
36
35
  version_requirements: !ruby/object:Gem::Requirement
37
36
  requirements:
38
37
  - - "~>"
39
38
  - !ruby/object:Gem::Version
40
- version: '1.4'
41
- - !ruby/object:Gem::Dependency
42
- name: activesupport
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '4'
48
- type: :runtime
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '4'
39
+ version: '4.0'
55
40
  - !ruby/object:Gem::Dependency
56
41
  name: rake
57
42
  requirement: !ruby/object:Gem::Requirement
58
43
  requirements:
59
44
  - - "~>"
60
45
  - !ruby/object:Gem::Version
61
- version: '10.1'
46
+ version: '13.3'
62
47
  type: :development
63
48
  prerelease: false
64
49
  version_requirements: !ruby/object:Gem::Requirement
65
50
  requirements:
66
51
  - - "~>"
67
52
  - !ruby/object:Gem::Version
68
- version: '10.1'
53
+ version: '13.3'
69
54
  - !ruby/object:Gem::Dependency
70
55
  name: minitest
71
56
  requirement: !ruby/object:Gem::Requirement
72
57
  requirements:
73
58
  - - "~>"
74
59
  - !ruby/object:Gem::Version
75
- version: '5.3'
60
+ version: '5.25'
76
61
  type: :development
77
62
  prerelease: false
78
63
  version_requirements: !ruby/object:Gem::Requirement
79
64
  requirements:
80
65
  - - "~>"
81
66
  - !ruby/object:Gem::Version
82
- version: '5.3'
67
+ version: '5.25'
83
68
  - !ruby/object:Gem::Dependency
84
69
  name: webmock
85
70
  requirement: !ruby/object:Gem::Requirement
86
71
  requirements:
87
72
  - - "~>"
88
73
  - !ruby/object:Gem::Version
89
- version: '1.17'
74
+ version: 3.25.1
90
75
  type: :development
91
76
  prerelease: false
92
77
  version_requirements: !ruby/object:Gem::Requirement
93
78
  requirements:
94
79
  - - "~>"
95
80
  - !ruby/object:Gem::Version
96
- version: '1.17'
81
+ version: 3.25.1
97
82
  description: Get F1 results from formula1.com
98
83
  email: dazonic@me.com
99
84
  executables:
@@ -119,7 +104,6 @@ homepage: https://github.com/daz/f1results
119
104
  licenses:
120
105
  - MIT
121
106
  metadata: {}
122
- post_install_message:
123
107
  rdoc_options: []
124
108
  require_paths:
125
109
  - lib
@@ -134,9 +118,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
134
118
  - !ruby/object:Gem::Version
135
119
  version: '0'
136
120
  requirements: []
137
- rubyforge_project:
138
- rubygems_version: 2.4.5
139
- signing_key:
121
+ rubygems_version: 3.6.7
140
122
  specification_version: 4
141
123
  summary: F1 Results
142
124
  test_files: []