trecs 0.0.1.alpha
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/.bundle/config +1 -0
- data/.gitignore +4 -0
- data/.rspec +2 -0
- data/.spec +0 -0
- data/.travis.yml +4 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +38 -0
- data/LICENCE.txt +22 -0
- data/README.org +44 -0
- data/Rakefile +7 -0
- data/bin/trecs +33 -0
- data/bin/trecs_message +20 -0
- data/bin/trecs_terminal +25 -0
- data/doc/steps.org +18 -0
- data/lib/player.rb +75 -0
- data/lib/players/zip_file_player.rb +56 -0
- data/lib/recorder.rb +68 -0
- data/lib/recorders/message_recorder.rb +18 -0
- data/lib/recorders/ttyrec_recorder.rb +13 -0
- data/lib/recorders/zip_file_recorder.rb +41 -0
- data/lib/recording_strategies/incremental_recording_strategy.rb +25 -0
- data/lib/recording_strategies/ttyrec_recording_strategy.rb +30 -0
- data/lib/recording_strategy.rb +10 -0
- data/lib/screens/terminal_screen.rb +22 -0
- data/lib/timestamps.rb +22 -0
- data/lib/trecs/version.rb +3 -0
- data/sandbox/create_recording.rb +28 -0
- data/sandbox/lipsum_end +1 -0
- data/sandbox/lipsum_start +1 -0
- data/sandbox/record +50 -0
- data/sandbox/record_diff +26 -0
- data/sandbox/record_script_file +45 -0
- data/spec/player_spec.rb +196 -0
- data/spec/recorder_spec.rb +248 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/timestamps_spec.rb +44 -0
- data/spec/trecs_message_spec.rb +125 -0
- data/spec/trecs_spec.rb +110 -0
- data/spec/zip_file_recorder_spec.rb +58 -0
- data/trecs.gemspec +31 -0
- metadata +179 -0
data/sandbox/record
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative "./create_recording"
|
4
|
+
require "trollop"
|
5
|
+
|
6
|
+
def com(c)
|
7
|
+
IO.popen(c).read
|
8
|
+
end
|
9
|
+
|
10
|
+
def cowsay(msg="")
|
11
|
+
com "cowsay '#{msg}'"
|
12
|
+
end
|
13
|
+
|
14
|
+
def figlet(msg="")
|
15
|
+
com "figlet '#{msg}'"
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
def map_increments(s='')
|
20
|
+
0.upto(s.size-1).map do |i|
|
21
|
+
s[0..i]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
options = Trollop::options do
|
26
|
+
opt :file, "File name", short: 'f', type: String
|
27
|
+
opt :message, "Message", short: 'm', type: String
|
28
|
+
opt :step, "step", short: 's', type: String
|
29
|
+
opt :cow
|
30
|
+
opt :figlet
|
31
|
+
end
|
32
|
+
|
33
|
+
step = (options[:step] || 250).to_i
|
34
|
+
|
35
|
+
frames = map_increments(options[:message])
|
36
|
+
|
37
|
+
create_recording(file_name: options[:file]) do
|
38
|
+
frames.each_with_index do |frame, i|
|
39
|
+
frame = if options[:cow]
|
40
|
+
cowsay(frame)
|
41
|
+
elsif options[:figlet]
|
42
|
+
figlet(frame)
|
43
|
+
else
|
44
|
+
frame
|
45
|
+
end
|
46
|
+
create_frame time: i*step, content: frame
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
puts "Recorded to: #{options[:file]}"
|
data/sandbox/record_diff
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative "./create_recording"
|
4
|
+
require "trollop"
|
5
|
+
|
6
|
+
def run_cmd(cmd="")
|
7
|
+
IO.popen(cmd).read
|
8
|
+
end
|
9
|
+
|
10
|
+
options = Trollop::options do
|
11
|
+
opt :start, "Starting file", short: 's', type: String
|
12
|
+
opt :end, "End file", short: 'e', type: String
|
13
|
+
end
|
14
|
+
|
15
|
+
start_file = options[:start]
|
16
|
+
end_file = options[:end]
|
17
|
+
|
18
|
+
number_of_lines = 100
|
19
|
+
|
20
|
+
cmd = %W[diff #{start_file} #{end_file}]
|
21
|
+
|
22
|
+
diff = run_cmd(cmd).split("\n")
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
puts diff.inspect
|
@@ -0,0 +1,45 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative "./create_recording"
|
4
|
+
#require "trollop"
|
5
|
+
#
|
6
|
+
#options = Trollop::options do
|
7
|
+
# opt :file, "File name", short: 'f', type: String
|
8
|
+
# opt :inputfile, "Input File", short: 'i', type: String
|
9
|
+
# opt :timesfile, "Times File", short: 't', type: String
|
10
|
+
#end
|
11
|
+
|
12
|
+
|
13
|
+
Timing = Struct.new(:time, :chars)
|
14
|
+
|
15
|
+
timings = [].concat(File.open(ARGV[2]).each_line.map { |l|
|
16
|
+
ll = l.split(" ")
|
17
|
+
Timing.new(ll[0].to_f, ll[1].to_i)
|
18
|
+
}.sort_by{|t|t.time}
|
19
|
+
)
|
20
|
+
|
21
|
+
@start = 0
|
22
|
+
@end = 0
|
23
|
+
file = File.open(ARGV[1]) do |f|
|
24
|
+
timings.each do |time|
|
25
|
+
time.chars.times do
|
26
|
+
print f.getc
|
27
|
+
end
|
28
|
+
sleep (time.time)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
#[46, 33].each do |t|
|
33
|
+
# t.times do
|
34
|
+
# print file.gets
|
35
|
+
# end
|
36
|
+
#end
|
37
|
+
#frames = []
|
38
|
+
#
|
39
|
+
#create_recording(file_name: ARGV[0]) do
|
40
|
+
# frames.each_with_index do |frame, i|
|
41
|
+
# create_frame time: i*step, content: frame
|
42
|
+
# end
|
43
|
+
#end
|
44
|
+
|
45
|
+
puts "Recorded to: #{ARGV[0]}"
|
data/spec/player_spec.rb
ADDED
@@ -0,0 +1,196 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
require "player"
|
4
|
+
require "screens/terminal_screen"
|
5
|
+
|
6
|
+
module TRecs
|
7
|
+
class DummyPlayer < Player
|
8
|
+
def initialize(frames:, **options)
|
9
|
+
@frames = frames
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_timestamps
|
14
|
+
@frames.keys
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_frame(time)
|
18
|
+
@frames[time]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class DummyOutput
|
23
|
+
def initialize
|
24
|
+
@output = []
|
25
|
+
end
|
26
|
+
|
27
|
+
def puts(str=nil)
|
28
|
+
@output << str.to_s
|
29
|
+
end
|
30
|
+
|
31
|
+
def clear
|
32
|
+
@output << :clear_screen
|
33
|
+
end
|
34
|
+
|
35
|
+
def raw_output
|
36
|
+
@output
|
37
|
+
end
|
38
|
+
|
39
|
+
def output
|
40
|
+
@output.select { |f| f.is_a? String }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
describe Player do
|
46
|
+
define :have_frames do |expected|
|
47
|
+
match do |actual|
|
48
|
+
raw_expected = expected.map { |o| [:clear_screen, o] }.flatten
|
49
|
+
a = actual.raw_output == raw_expected
|
50
|
+
b = actual.output == expected
|
51
|
+
a && b
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def create_recording
|
56
|
+
frames = {}
|
57
|
+
yield frames
|
58
|
+
DummyPlayer.new(frames: frames, output: output)
|
59
|
+
end
|
60
|
+
|
61
|
+
let(:output) { DummyOutput.new }
|
62
|
+
|
63
|
+
it "reads a one frame screencast" do
|
64
|
+
player = create_recording do |frames|
|
65
|
+
frames[0] = "FIRST FRAME"
|
66
|
+
end
|
67
|
+
|
68
|
+
player.play
|
69
|
+
|
70
|
+
output.should have_frames ["FIRST FRAME"]
|
71
|
+
end
|
72
|
+
|
73
|
+
it "returns the frame at certain time" do
|
74
|
+
player = create_recording do |frames|
|
75
|
+
frames[0] = "FIRST FRAME",
|
76
|
+
frames[100] = "FRAME AT 100"
|
77
|
+
end
|
78
|
+
|
79
|
+
player.play_frame(100)
|
80
|
+
|
81
|
+
output.should have_frames ["FRAME AT 100"]
|
82
|
+
end
|
83
|
+
|
84
|
+
it "returns the previous frame if no frame at certain time" do
|
85
|
+
player = create_recording do |frames|
|
86
|
+
frames[0] = "FIRST FRAME"
|
87
|
+
frames[100] = "FRAME AT 100"
|
88
|
+
frames[200] = "FRAME AT 200"
|
89
|
+
end
|
90
|
+
|
91
|
+
player.play_frame(111)
|
92
|
+
|
93
|
+
output.output.should == ["FRAME AT 100"]
|
94
|
+
end
|
95
|
+
|
96
|
+
it "returns the last frame if asking for exceeding time" do
|
97
|
+
player = create_recording do |frames|
|
98
|
+
frames[0] = "FIRST FRAME"
|
99
|
+
frames[100] = "FRAME AT 100"
|
100
|
+
frames[200] = "FRAME AT 200"
|
101
|
+
end
|
102
|
+
|
103
|
+
player.play_frame(201)
|
104
|
+
|
105
|
+
output.should have_frames ["FRAME AT 200"]
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "multiple frame screencast" do
|
110
|
+
it "playing two frames" do
|
111
|
+
player = create_recording do |frames|
|
112
|
+
frames[0] = "FIRST FRAME"
|
113
|
+
frames[100] = "FRAME AT 100"
|
114
|
+
end
|
115
|
+
|
116
|
+
player.play
|
117
|
+
|
118
|
+
output.should have_frames [
|
119
|
+
"FIRST FRAME",
|
120
|
+
"FRAME AT 100"
|
121
|
+
]
|
122
|
+
end
|
123
|
+
|
124
|
+
it "playing all the frames" do
|
125
|
+
player = create_recording do |frames|
|
126
|
+
frames[0] = "FIRST FRAME"
|
127
|
+
frames[100] = "FRAME AT 100"
|
128
|
+
frames[200] = "FRAME AT 200"
|
129
|
+
end
|
130
|
+
|
131
|
+
player.play
|
132
|
+
|
133
|
+
output.should have_frames [
|
134
|
+
"FIRST FRAME",
|
135
|
+
"FRAME AT 100",
|
136
|
+
"FRAME AT 200"
|
137
|
+
]
|
138
|
+
end
|
139
|
+
|
140
|
+
it "playing a recording" do
|
141
|
+
player = create_recording do |frames|
|
142
|
+
frames[0] = "FIRST FRAME"
|
143
|
+
frames[100] = "FRAME AT 100"
|
144
|
+
frames[200] = "FRAME AT 200"
|
145
|
+
frames[301] = "FRAME AT 301"
|
146
|
+
frames[499] = "FRAME AT 499"
|
147
|
+
frames[599] = "FRAME AT 599"
|
148
|
+
end
|
149
|
+
|
150
|
+
player.play
|
151
|
+
|
152
|
+
output.should have_frames [
|
153
|
+
"FIRST FRAME",
|
154
|
+
"FRAME AT 100",
|
155
|
+
"FRAME AT 200",
|
156
|
+
"FRAME AT 200",
|
157
|
+
"FRAME AT 301",
|
158
|
+
"FRAME AT 499",
|
159
|
+
"FRAME AT 599",
|
160
|
+
]
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
context "Timestamps" do
|
165
|
+
it "returns all the frame timestamps" do
|
166
|
+
player = create_recording do |frames|
|
167
|
+
frames[0] = "FIRST FRAME"
|
168
|
+
frames[100] = "FRAME AT 100"
|
169
|
+
frames[200] = "FRAME AT 200"
|
170
|
+
end
|
171
|
+
|
172
|
+
player.timestamps.should == [0, 100, 200]
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
177
|
+
|
178
|
+
context "output" do
|
179
|
+
it "receives a Screen object to manage output" do
|
180
|
+
player = Player.new(output: :output)
|
181
|
+
|
182
|
+
player.output.should == :output
|
183
|
+
end
|
184
|
+
|
185
|
+
it "defaults to the Terminal Screen" do
|
186
|
+
player = Player.new
|
187
|
+
|
188
|
+
player.output.class.should == TerminalScreen
|
189
|
+
end
|
190
|
+
|
191
|
+
context "message ... puts ... print" do
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
@@ -0,0 +1,248 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
require "recorders/message_recorder"
|
4
|
+
|
5
|
+
module TRecs
|
6
|
+
describe Recorder do
|
7
|
+
class DummyRecorder < Recorder
|
8
|
+
attr_reader :result
|
9
|
+
|
10
|
+
def initialize(frames: nil, **options)
|
11
|
+
@frames = frames.is_a?(Hash) ? frames : Array(frames)
|
12
|
+
super(**options)
|
13
|
+
end
|
14
|
+
|
15
|
+
def perform_recording
|
16
|
+
if @frames.is_a?(Hash)
|
17
|
+
@frames.each do |time, content|
|
18
|
+
current_frame(time: time, content: content)
|
19
|
+
end
|
20
|
+
else
|
21
|
+
@frames.each do |content|
|
22
|
+
current_frame(content: content)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def create_frame
|
28
|
+
@result[current_time] = current_content
|
29
|
+
end
|
30
|
+
|
31
|
+
def setup
|
32
|
+
@result = {}
|
33
|
+
end
|
34
|
+
|
35
|
+
def render
|
36
|
+
# no-op
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "recording" do
|
41
|
+
context "with custom timestamps" do
|
42
|
+
it "records a one frame trecs" do
|
43
|
+
rec = DummyRecorder.new frames: {0 => "a"}
|
44
|
+
rec.record
|
45
|
+
|
46
|
+
rec.result.should == {0 => "a"}
|
47
|
+
end
|
48
|
+
|
49
|
+
it "records a two frames trecs" do
|
50
|
+
rec = DummyRecorder.new frames: {
|
51
|
+
0 => "a",
|
52
|
+
100 => "b"
|
53
|
+
}
|
54
|
+
rec.record
|
55
|
+
|
56
|
+
rec.result.should == {
|
57
|
+
0 => "a",
|
58
|
+
100 => "b"
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
it "records a three frames trecs" do
|
63
|
+
rec = DummyRecorder.new frames: {
|
64
|
+
0 => "a",
|
65
|
+
100 => "b",
|
66
|
+
150 => "c"
|
67
|
+
}
|
68
|
+
rec.record
|
69
|
+
|
70
|
+
rec.result.should == {
|
71
|
+
0 => "a",
|
72
|
+
100 => "b",
|
73
|
+
150 => "c"
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
it "calls start_recording" do
|
78
|
+
rec = DummyRecorder.new
|
79
|
+
rec.should_receive(:setup)
|
80
|
+
|
81
|
+
rec.record
|
82
|
+
end
|
83
|
+
|
84
|
+
it "calls finish_recording" do
|
85
|
+
rec = DummyRecorder.new
|
86
|
+
rec.should_receive(:render)
|
87
|
+
|
88
|
+
rec.record
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
context "with custom timestamps" do
|
94
|
+
it "records a one frame trecs" do
|
95
|
+
rec = DummyRecorder.new frames: ["a"]
|
96
|
+
rec.record
|
97
|
+
|
98
|
+
rec.result.should == {0 => "a"}
|
99
|
+
end
|
100
|
+
|
101
|
+
it "records a two frames trecs" do
|
102
|
+
rec = DummyRecorder.new frames: ["a", "b"]
|
103
|
+
rec.record
|
104
|
+
|
105
|
+
rec.result.should == {
|
106
|
+
0 => "a",
|
107
|
+
100 => "b"
|
108
|
+
}
|
109
|
+
end
|
110
|
+
|
111
|
+
it "records a three frames trecs" do
|
112
|
+
rec = DummyRecorder.new frames: ["a", "b", "c"]
|
113
|
+
rec.record
|
114
|
+
|
115
|
+
rec.result.should == {
|
116
|
+
0 => "a",
|
117
|
+
100 => "b",
|
118
|
+
200 => "c"
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
it "records a three frames trecs" do
|
123
|
+
rec = DummyRecorder.new frames: ["a", "b", "c"], step: 75
|
124
|
+
rec.record
|
125
|
+
|
126
|
+
rec.result.should == {
|
127
|
+
0 => "a",
|
128
|
+
75 => "b",
|
129
|
+
150 => "c"
|
130
|
+
}
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context "sanitizing the recording" do
|
135
|
+
it "records a three frames trecs" do
|
136
|
+
rec = DummyRecorder.new frames: {
|
137
|
+
0 => "a",
|
138
|
+
50 => "b",
|
139
|
+
100 => "b",
|
140
|
+
150 => "c",
|
141
|
+
}
|
142
|
+
rec.record
|
143
|
+
|
144
|
+
rec.result.should == {
|
145
|
+
0 => "a",
|
146
|
+
50 => "b",
|
147
|
+
150 => "c",
|
148
|
+
}
|
149
|
+
end
|
150
|
+
|
151
|
+
it "records a three frames trecs" do
|
152
|
+
rec = DummyRecorder.new frames: {
|
153
|
+
0 => "a",
|
154
|
+
50 => "a",
|
155
|
+
100 => "b",
|
156
|
+
150 => "c",
|
157
|
+
}
|
158
|
+
rec.record
|
159
|
+
|
160
|
+
rec.result.should == {
|
161
|
+
0 => "a",
|
162
|
+
100 => "b",
|
163
|
+
150 => "c",
|
164
|
+
}
|
165
|
+
end
|
166
|
+
|
167
|
+
it "records a three frames trecs" do
|
168
|
+
rec = DummyRecorder.new frames: {
|
169
|
+
0 => "a",
|
170
|
+
50 => "b",
|
171
|
+
100 => "c",
|
172
|
+
150 => "c",
|
173
|
+
}
|
174
|
+
rec.record
|
175
|
+
|
176
|
+
rec.result.should == {
|
177
|
+
0 => "a",
|
178
|
+
50 => "b",
|
179
|
+
100 => "c",
|
180
|
+
}
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
context "timestamps" do
|
188
|
+
it "starts with 0 as the current time" do
|
189
|
+
rec = Recorder.new
|
190
|
+
|
191
|
+
rec.current_time.should == nil
|
192
|
+
end
|
193
|
+
|
194
|
+
it "calculates the next timestamp" do
|
195
|
+
rec = Recorder.new(step: 100)
|
196
|
+
|
197
|
+
rec.next_timestamp.should == 0
|
198
|
+
rec.current_time.should == 0
|
199
|
+
end
|
200
|
+
|
201
|
+
it "calculates the second next timestamp" do
|
202
|
+
rec = Recorder.new(step: 100)
|
203
|
+
|
204
|
+
rec.next_timestamp
|
205
|
+
rec.next_timestamp.should == 100
|
206
|
+
rec.current_time.should == 100
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
describe "#current_time" do
|
211
|
+
it "sets the current time" do
|
212
|
+
rec = Recorder.new
|
213
|
+
|
214
|
+
rec.current_time(40)
|
215
|
+
|
216
|
+
rec.current_time.should == 40
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
describe "#current_content" do
|
221
|
+
it "sets the current time" do
|
222
|
+
rec = Recorder.new
|
223
|
+
|
224
|
+
rec.current_content("HELLO")
|
225
|
+
|
226
|
+
rec.current_content.should == "HELLO"
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
describe "#current_frame" do
|
231
|
+
it "sets the current time and content" do
|
232
|
+
rec = Recorder.new
|
233
|
+
|
234
|
+
rec.current_frame(time: 40, content: "HELLO")
|
235
|
+
|
236
|
+
rec.current_time.should == 40
|
237
|
+
rec.current_content.should == "HELLO"
|
238
|
+
end
|
239
|
+
|
240
|
+
it "sets the current time and content" do
|
241
|
+
rec = Recorder.new()
|
242
|
+
rec.should_receive(:create_frame)
|
243
|
+
|
244
|
+
rec.current_frame(time: 40, content: "HELLO")
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
RSpec.configure do |config|
|
8
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
9
|
+
config.run_all_when_everything_filtered = true
|
10
|
+
config.filter_run :focus
|
11
|
+
|
12
|
+
# Run specs in random order to surface order dependencies. If you find an
|
13
|
+
# order dependency and want to debug it, you can fix the order by providing
|
14
|
+
# the seed, which is printed after each run.
|
15
|
+
# --seed 1234
|
16
|
+
config.order = 'random'
|
17
|
+
end
|
18
|
+
|
19
|
+
$:.unshift(File.expand_path("../lib", __FILE__))
|
20
|
+
|
21
|
+
def create_dir(dir_path)
|
22
|
+
mkdir_p dir_path unless File.exist?(dir_path)
|
23
|
+
dir_path
|
24
|
+
end
|
25
|
+
|
26
|
+
def file_name(string=nil)
|
27
|
+
if string
|
28
|
+
@file_name = "#{project_dir}/#{string}.trecs"
|
29
|
+
else
|
30
|
+
@file_name
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "timestamps"
|
3
|
+
|
4
|
+
describe Timestamps do
|
5
|
+
context "invalid inputs" do
|
6
|
+
it "returns 0 with invalid imputs" do
|
7
|
+
ts = Timestamps.new([0, 10, 20, 30])
|
8
|
+
[-1, :a, "hola", Object.new].each do |input|
|
9
|
+
ts.time_at(input).should == 0
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context "empty collection" do
|
15
|
+
it "returns 0 at 0" do
|
16
|
+
ts = Timestamps.new([])
|
17
|
+
ts.time_at(0).should == 0
|
18
|
+
end
|
19
|
+
|
20
|
+
it "returns 0 at > 0" do
|
21
|
+
ts = Timestamps.new([])
|
22
|
+
ts.time_at(10).should == 0
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "with timestamps and valid imputs" do
|
27
|
+
let(:subject) { Timestamps.new([0, 10, 20]) }
|
28
|
+
|
29
|
+
it "returns the exact time" do
|
30
|
+
subject.time_at(0).should == 0
|
31
|
+
subject.time_at(10).should == 10
|
32
|
+
subject.time_at(20).should == 20
|
33
|
+
end
|
34
|
+
|
35
|
+
it "returns the previous valid time if no exact time in the collection" do
|
36
|
+
subject.time_at(5).should == 0
|
37
|
+
subject.time_at(15).should == 10
|
38
|
+
end
|
39
|
+
|
40
|
+
it "returns the last time when passing a time greater than the greater time" do
|
41
|
+
subject.time_at(25).should == 20
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|