rmuh 0.1.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 +7 -0
- data/.gitignore +33 -0
- data/.rspec +2 -0
- data/.travis.yml +8 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +19 -0
- data/Rakefile +15 -0
- data/lib/rmuh.rb +22 -0
- data/lib/rmuh/rpt/log/fetch.rb +56 -0
- data/lib/rmuh/rpt/log/parsers/base.rb +29 -0
- data/lib/rmuh/rpt/log/parsers/unitedoperationslog.rb +94 -0
- data/lib/rmuh/rpt/log/parsers/unitedoperationsrpt.rb +65 -0
- data/lib/rmuh/rpt/log/util/unitedoperations.rb +127 -0
- data/lib/rmuh/rpt/log/util/unitedoperationslog.rb +26 -0
- data/lib/rmuh/rpt/log/util/unitedoperationsrpt.rb +37 -0
- data/lib/rmuh/serverstats/base.rb +55 -0
- data/lib/rmuh/version.rb +10 -0
- data/rmuh.gemspec +33 -0
- data/spec/files/content-length.txt +1 -0
- data/spec/helpers/spec_helper.rb +13 -0
- data/spec/helpers/unitedoperations.rb +106 -0
- data/spec/rmuh_rpt_log_fetch_spec.rb +112 -0
- data/spec/rmuh_rpt_log_parsers_base_spec.rb +57 -0
- data/spec/rmuh_rpt_log_parsers_unitedoperationslog_spec.rb +390 -0
- data/spec/rmuh_rpt_log_parsers_unitedoperationsrpt_spec.rb +252 -0
- data/spec/rmuh_rpt_log_util_unitedoperations_spec.rb +473 -0
- data/spec/rmuh_rpt_log_util_unitedoperationslog_spec.rb +66 -0
- data/spec/rmuh_rpt_log_util_unitedoperationsrpt_spec.rb +122 -0
- data/spec/rmuh_rpt_spec.rb +45 -0
- data/spec/rmuh_serverstats_base_spec.rb +190 -0
- metadata +225 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
module RMuh
|
3
|
+
module RPT
|
4
|
+
module Log
|
5
|
+
module Util
|
6
|
+
# The utility module for the UnitedOperationsLog parser
|
7
|
+
# This provides the constants needed for Regex matches
|
8
|
+
# as well as the validate_chat function
|
9
|
+
#
|
10
|
+
module UnitedOperationsLog
|
11
|
+
ONE_DAY ||= 86_400
|
12
|
+
TIME ||= '^\s*?(?<hour>\d+?):(?<min>\d+?):(?<sec>\d+)\s' \
|
13
|
+
'BattlEye\sServer:\s'
|
14
|
+
GUID ||= Regexp.new(
|
15
|
+
"#{TIME}.*Verified\\sGUID\\s\\((?<player_beguid>.*?)\\).*#\\d+?" \
|
16
|
+
'\s(?<player>.+)$'
|
17
|
+
)
|
18
|
+
CHAT ||= Regexp.new(
|
19
|
+
"#{TIME}\\((?<channel>Group|Global|Side|Vehicle|Command|Unknown)" \
|
20
|
+
'\)\s+?(?<player>.+?):\s(?<message>.*)$'
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
module RMuh
|
3
|
+
module RPT
|
4
|
+
module Log
|
5
|
+
module Util
|
6
|
+
# The utility module for the UnitedOperationsRPT parser
|
7
|
+
# This provides the constants for Regexp matches
|
8
|
+
#
|
9
|
+
module UnitedOperationsRPT
|
10
|
+
DTR ||= '(?<year>\d+)/(?<month>\d+)/(?<day>\d+),\s+?(?<hour>\d+):' \
|
11
|
+
'(?<min>\d+):(?<sec>\d+)'
|
12
|
+
KILLED ||= Regexp.new(
|
13
|
+
"^#{DTR}\\s\"(?<server_time>[0-9.]+).*?:\\s(?<victim>.*?)\\s\\(" \
|
14
|
+
'(?<victim_team>.*?)\)\s.*?by\s(?<offender>.*?)\s\(' \
|
15
|
+
'(?<offender_team>.*?)\).*?position: \[(?<victim_position>.*?)\]' \
|
16
|
+
'.*?GRID (?<victim_grid>\d+)\).*?position: \[' \
|
17
|
+
'(?<offender_position>.*?)\].*?GRID (?<offender_grid>\d*)\).*?:' \
|
18
|
+
'\s(?<distance>[0-9e.+]+).*?(?:(?<nearby_players>None.|\[.*?\])")'
|
19
|
+
)
|
20
|
+
DIED ||= Regexp.new(
|
21
|
+
"^#{DTR}\\s\"(?<server_time>[0-9.]+).*?:\\s(?<victim>.*?) " \
|
22
|
+
'has died at \[(?<victim_position>.*?)\].*?GRID ' \
|
23
|
+
'(?<victim_grid>\d+)\).*?(?:(?<nearby_players>None.|\[.*?\])")'
|
24
|
+
)
|
25
|
+
WOUNDED ||= Regexp.new(
|
26
|
+
"^#{DTR}\\s\"(?<server_time>[0-9.]+).*?:\\s(?<victim>.*?)\\s" \
|
27
|
+
'\((?<victim_team>.*?)\)\s.*?by\s(?<offender>.*?)\s\(' \
|
28
|
+
'(?<offender_team>.*?)\).*?(?<damage>[0-9.]+)\sdamage'
|
29
|
+
)
|
30
|
+
ANNOUNCEMENT ||= Regexp.new(
|
31
|
+
"^#{DTR}\\s\"(?<head>[#]+?)\s(?<message>.*?)\s(?<tail>[#]+?)\""
|
32
|
+
)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
|
3
|
+
require 'gamespy_query'
|
4
|
+
|
5
|
+
module RMuh
|
6
|
+
# TODO: Documentation
|
7
|
+
#
|
8
|
+
module ServerStats
|
9
|
+
# TODO: Documentation
|
10
|
+
#
|
11
|
+
class Base
|
12
|
+
DEFAULT_PORT = 2_302
|
13
|
+
|
14
|
+
def initialize(opts = {})
|
15
|
+
fail ArgumentError, 'arg 1 must be a Hash' unless opts.is_a?(Hash)
|
16
|
+
self.class.validate_opts(opts)
|
17
|
+
opts_to_instance(opts)
|
18
|
+
@gsq = GamespyQuery::Socket.new("#{@host}:#{@port}")
|
19
|
+
end
|
20
|
+
|
21
|
+
def stats
|
22
|
+
remote_stats
|
23
|
+
end
|
24
|
+
|
25
|
+
def update_cache
|
26
|
+
@serverstats = sync if @cache
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def self.validate_opts(opts)
|
32
|
+
fail ArgumentError, ':host is required' unless opts.key?(:host)
|
33
|
+
opts[:port] ||= DEFAULT_PORT
|
34
|
+
opts[:cache] = true unless opts.key?(:cache)
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def opts_to_instance(opts)
|
39
|
+
opts.each { |k, v| instance_variable_set(:"@#{k}", v) }
|
40
|
+
end
|
41
|
+
|
42
|
+
def remote_stats
|
43
|
+
if @cache
|
44
|
+
@serverstats
|
45
|
+
else
|
46
|
+
sync
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def sync
|
51
|
+
@gsq.sync
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/rmuh/version.rb
ADDED
data/rmuh.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
require 'English'
|
3
|
+
|
4
|
+
$LOAD_PATH << File.expand_path('../lib', __FILE__)
|
5
|
+
|
6
|
+
require 'rmuh/version'
|
7
|
+
|
8
|
+
Gem::Specification.new do |g|
|
9
|
+
g.name = 'rmuh'
|
10
|
+
g.version = RMuh::VERSION
|
11
|
+
g.date = '2014-02-18'
|
12
|
+
g.description = 'ArmA 2 Ruby Library for RPT, Log, and GameSpy'
|
13
|
+
g.summary = 'ArmA 2 Ruby Library'
|
14
|
+
g.authors = ['Tim Heckman']
|
15
|
+
g.email = 't@heckman.io'
|
16
|
+
g.homepage = 'https://github.com/theckman/rmuh'
|
17
|
+
g.license = 'MIT'
|
18
|
+
|
19
|
+
g.test_files = %x{git ls-files spec/*}.split
|
20
|
+
g.files = %x{git ls-files}.split
|
21
|
+
|
22
|
+
g.add_development_dependency 'rake', '~>10.1.0'
|
23
|
+
g.add_development_dependency 'rspec', '~>2.14.1'
|
24
|
+
g.add_development_dependency 'rubocop', '~> 0.18.1'
|
25
|
+
g.add_development_dependency 'fuubar', '~> 1.3.2'
|
26
|
+
g.add_development_dependency 'simplecov', '~> 0.8.2'
|
27
|
+
g.add_development_dependency 'coveralls', '~> 0.7.0'
|
28
|
+
|
29
|
+
g.add_runtime_dependency 'awesome_print', '~> 1.2.0'
|
30
|
+
g.add_runtime_dependency 'tzinfo', '~> 1.1.0'
|
31
|
+
g.add_runtime_dependency 'httparty', '~> 0.12.0'
|
32
|
+
g.add_runtime_dependency 'gamespy_query', '~> 0.1.5'
|
33
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
RSpec, yo
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
require 'rspec'
|
3
|
+
require 'simplecov'
|
4
|
+
require 'coveralls'
|
5
|
+
|
6
|
+
def repo_root
|
7
|
+
File.expand_path('../../..', __FILE__)
|
8
|
+
end
|
9
|
+
|
10
|
+
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
|
11
|
+
SimpleCov.start do
|
12
|
+
add_filter '/spec/'
|
13
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'digest'
|
2
|
+
|
3
|
+
def spec_guid_reference_implementation(mock_line)
|
4
|
+
line = mock_line.dup
|
5
|
+
data = spec_add_data(line)
|
6
|
+
|
7
|
+
line[:event_guid] = Digest::SHA1.hexdigest data
|
8
|
+
line
|
9
|
+
end
|
10
|
+
|
11
|
+
def spec_add_data(line)
|
12
|
+
data = spec_minimum_data(line)
|
13
|
+
spec_add_data_one!(line, data)
|
14
|
+
spec_add_data_two!(line, data)
|
15
|
+
data
|
16
|
+
end
|
17
|
+
|
18
|
+
def spec_minimum_data(line)
|
19
|
+
if line[:iso8601].nil?
|
20
|
+
data = "#{line[:year]}#{line[:month]}#{line[:day]}" \
|
21
|
+
"#{line[:hour]}#{line[:min]}#{line[:sec]}" \
|
22
|
+
"#{line[:type].to_s}"
|
23
|
+
else
|
24
|
+
data = "#{line[:iso8601]}#{line[:type].to_s}"
|
25
|
+
end
|
26
|
+
data
|
27
|
+
end
|
28
|
+
|
29
|
+
def spec_add_data_one!(line, data)
|
30
|
+
data << line[:message] unless line[:message].nil?
|
31
|
+
data << line[:victim] unless line[:victim].nil?
|
32
|
+
data << line[:offender] unless line[:offender].nil?
|
33
|
+
data << line[:server_time].to_s unless line[:server_time].nil?
|
34
|
+
data << line[:damage].to_s unless line[:damage].nil?
|
35
|
+
data
|
36
|
+
end
|
37
|
+
|
38
|
+
def spec_add_data_two!(line, data)
|
39
|
+
data << line[:distance].to_s unless line[:distance].nil?
|
40
|
+
data << line[:player] unless line[:player].nil?
|
41
|
+
data << line[:player_beguid] unless line[:player_beguid].nil?
|
42
|
+
data << line[:channel] unless line[:channel].nil?
|
43
|
+
data
|
44
|
+
end
|
45
|
+
|
46
|
+
def spec_killed_line
|
47
|
+
{
|
48
|
+
type: :killed, year: 2014, month: 2, day: 16, hour: 0, min: 7, sec: 22,
|
49
|
+
server_time: 4517.73, victim: 'Althain', victim_team: 'WEST',
|
50
|
+
offender: 'Geth', offender_team: 'CIV', iso8601: '2014-02-16T00:07:22Z',
|
51
|
+
victim_position: '12789.4,12697.3,0.00152588', victim_grid: '1278912697',
|
52
|
+
offender_position: '12795.3,12704.7,0.00137329', distance: 9.5636,
|
53
|
+
offender_grid: '1279512704', nearby_players: ['Brig.Gold101st'],
|
54
|
+
dtg: '160007Z FEB 14'
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
def spec_died_line
|
59
|
+
{
|
60
|
+
type: :died, year: 2014, month: 2, day: 16, hour: 1, min: 30, sec: 53,
|
61
|
+
server_time: 4280.29, victim_position: '4194.01,1633.02,0.00143814',
|
62
|
+
dtg: '160130Z FEB 14', nearby_players: [
|
63
|
+
'Synxe', 'Naught', 'Kiesbye', 'Aphex', 'Jeff Kid', 'Adam1', 'Lord Yod',
|
64
|
+
'Small', 'Mixtrate', 'James', 'Nickster', 'Tankman', 'JamaicanJews',
|
65
|
+
'Besiden'],
|
66
|
+
iso8601: '2014-02-16T01:30:53Z', victim_grid: '0419401633'
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
def spec_wounded_line
|
71
|
+
{
|
72
|
+
type: :wounded, year: 2014, month: 2, day: 16, hour: 0, min: 7, sec: 21,
|
73
|
+
server_time: 4517.55, victim: 'Althain', victim_team: 'WEST',
|
74
|
+
offender: 'Geth', offender_team: 'CIV', damage: 0.0780736,
|
75
|
+
iso8601: '2014-02-16T00:07:21Z', dtg: '160007Z FEB 14'
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
def spec_announcement_line
|
80
|
+
{
|
81
|
+
type: :announcement, year: 2014, month: 2, day: 16, hour: 1, min: 47,
|
82
|
+
sec: 43, head: '#############################', dtg: '160147Z FEB 14',
|
83
|
+
message: 'Start CO30_Operation_Trident_v2C',
|
84
|
+
tail: '#############################',
|
85
|
+
iso8601: '2014-02-16T01:47:43Z'
|
86
|
+
}
|
87
|
+
end
|
88
|
+
|
89
|
+
def spec_chat_line
|
90
|
+
{
|
91
|
+
type: :chat, hour: 5, min: 43, sec: 29, channel: 'group', player: 'Chris',
|
92
|
+
message: 'Ew ban Mara', year: 2014, month: 2, day: 16,
|
93
|
+
iso8601: '2014-02-16T05:43:29Z', dtg: '160543Z FEB 14',
|
94
|
+
event_guid: '8365d6da7375fde963371004b52012af0ef03678'
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
def spec_beguid_line
|
99
|
+
{
|
100
|
+
type: :guid, hour: 5, min: 53, sec: 49,
|
101
|
+
player_beguid: 'fd5c7ecf1f986badce8b5ece3f4d853a', player: 'Brock Samson',
|
102
|
+
year: 2014, month: 2, day: 16, iso8601: '2014-02-16T05:53:49Z',
|
103
|
+
dtg: '160553Z FEB 14',
|
104
|
+
event_guid: '89aeda0db1f774936619cd3e3ce392e28c1a3871'
|
105
|
+
}
|
106
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
require 'rspec'
|
3
|
+
require 'stringio'
|
4
|
+
require 'helpers/spec_helper'
|
5
|
+
require File.join(repo_root, 'lib/rmuh/rpt/log/fetch')
|
6
|
+
|
7
|
+
describe RMuh::RPT::Log::Fetch do
|
8
|
+
let(:url) do
|
9
|
+
'https://raw2.github.com/theckman/rmuh/master/spec/files/content-length.' \
|
10
|
+
'txt'
|
11
|
+
end
|
12
|
+
let(:fetch) { RMuh::RPT::Log::Fetch.new(url) }
|
13
|
+
context '#new' do
|
14
|
+
it 'should return an instance of RMuh::RPT::Log::Fetch' do
|
15
|
+
fetch.should be_an_instance_of RMuh::RPT::Log::Fetch
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should have a @cfg object which is an instance of OpenStruct' do
|
19
|
+
fetch.cfg.should be_an_instance_of OpenStruct
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should set the "byte_start" config item if specified as arg:1' do
|
23
|
+
rlfetch = RMuh::RPT::Log::Fetch.new(url, 10)
|
24
|
+
rlfetch.cfg.byte_start.should eql 10
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should set the "byte_end" config item if specified as arg:3' do
|
28
|
+
rlfetch = RMuh::RPT::Log::Fetch.new(url, 10, 42)
|
29
|
+
rlfetch.cfg.byte_end.should eql 42
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context '#byte_start' do
|
34
|
+
it 'should allow setting the value to Integer' do
|
35
|
+
expect { fetch.byte_start = 10 }.not_to raise_error
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should raise an error if the value is nil' do
|
39
|
+
expect { fetch.byte_start = nil }.to raise_error ArgumentError
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should raise an error if arg:1 is a String' do
|
43
|
+
expect { fetch.byte_start = 'urmom' }.to raise_error ArgumentError
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should raise an error if arg:1 is a Float' do
|
47
|
+
expect { fetch.byte_start = 4.2 }.to raise_error ArgumentError
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should update the @cfg.byte_start value' do
|
51
|
+
fetch.byte_start = 10
|
52
|
+
fetch.cfg.byte_start.should eql 10
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context '#byte_end' do
|
57
|
+
it 'should allow setting the value to Integer' do
|
58
|
+
expect { fetch.byte_end = 10 }.not_to raise_error
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should allow setting the value is nil' do
|
62
|
+
expect { fetch.byte_end = nil }.not_to raise_error
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should raise an error if arg:1 is a String' do
|
66
|
+
expect { fetch.byte_end = 'urmom' }.to raise_error ArgumentError
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should raise an error if arg:1 is a Float' do
|
70
|
+
expect { fetch.byte_end = 4.2 }.to raise_error ArgumentError
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should update the @cfg.byte_end value' do
|
74
|
+
fetch.byte_end = 42
|
75
|
+
fetch.cfg.byte_end.should eql 42
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context '#size' do
|
80
|
+
it 'should return a Integer object' do
|
81
|
+
fetch.size.should be_an_instance_of Fixnum
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should return the size' do
|
85
|
+
fetch.size.should eql 10
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context '#log' do
|
90
|
+
it 'should return a StringIO object' do
|
91
|
+
fetch.log.should be_an_instance_of StringIO
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'should return the log' do
|
95
|
+
fetch.log.read.should eql "RSpec, yo\n"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context '#dos2unix' do
|
100
|
+
let(:dos) { "text\r\n" }
|
101
|
+
let(:dos_newline) { /\r\n$/ }
|
102
|
+
|
103
|
+
it 'should match the Regexp object' do
|
104
|
+
expect(dos_newline.match(dos)).not_to be nil
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'should strip out DOS new lines' do
|
108
|
+
match = /\r\n/.match(fetch.send(:dos2unix, dos))
|
109
|
+
match.should be nil
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
require 'rspec'
|
3
|
+
require 'stringio'
|
4
|
+
|
5
|
+
REPO_ROOT = File.expand_path('../..', __FILE__)
|
6
|
+
|
7
|
+
require File.join(REPO_ROOT, 'lib/rmuh/rpt/log/parsers/base')
|
8
|
+
|
9
|
+
describe RMuh::RPT::Log::Parsers::Base do
|
10
|
+
let(:text) { StringIO.new("This is a string.\nSo is this!") }
|
11
|
+
let(:base) { RMuh::RPT::Log::Parsers::Base.new }
|
12
|
+
|
13
|
+
context 'text' do
|
14
|
+
it 'should be a StringIO object' do
|
15
|
+
text.should be_an_instance_of StringIO
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context '#new' do
|
20
|
+
it 'should take no more than one arg' do
|
21
|
+
expect do
|
22
|
+
RMuh::RPT::Log::Parsers::Base.new(nil, nil)
|
23
|
+
end.to raise_error ArgumentError
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should return an instance of RMuh::RPT::Log::Parsers::Base' do
|
27
|
+
base.should be_an_instance_of RMuh::RPT::Log::Parsers::Base
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context '#parse' do
|
32
|
+
it 'should take at most 1 argument' do
|
33
|
+
expect { base.parse(text, text) }.to raise_error ArgumentError
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should take at least 1 argument' do
|
37
|
+
expect { base.parse }.to raise_error ArgumentError
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should only accept a StringIO object' do
|
41
|
+
expect { base.parse('urmom') }.to raise_error ArgumentError
|
42
|
+
expect { base.parse(42) }.to raise_error ArgumentError
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should return an Array' do
|
46
|
+
expect(base.parse(text)).to be_an_instance_of Array
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'the Array size should be 2' do
|
50
|
+
expect(base.parse(text).size).to be 2
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should be an Array of hashes' do
|
54
|
+
base.parse(text).each { |p| p.should be_an_instance_of Hash }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|