peruse 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.ruby-version +1 -0
- data/AUTHORS +2 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +63 -0
- data/LICENSE +20 -0
- data/README.md +118 -0
- data/Rakefile +5 -0
- data/bin/peruse +75 -0
- data/examples/simple.json +25 -0
- data/examples/simple.rb +10 -0
- data/lib/peruse.rb +53 -0
- data/lib/peruse/helper.rb +90 -0
- data/lib/peruse/parser.rb +181 -0
- data/lib/peruse/result_set.rb +16 -0
- data/lib/peruse/transformer.rb +103 -0
- data/lib/peruse/utils.rb +25 -0
- data/lib/peruse/version.rb +3 -0
- data/peruse.gemspec +23 -0
- data/spec/basic_spec.rb +39 -0
- data/spec/binstub_spec.rb +33 -0
- data/spec/boolean_spec.rb +112 -0
- data/spec/chained_search_spec.rb +40 -0
- data/spec/field_value_spec.rb +52 -0
- data/spec/indices_spec.rb +41 -0
- data/spec/last_spec.rb +77 -0
- data/spec/limit_spec.rb +11 -0
- data/spec/nested_search_spec.rb +82 -0
- data/spec/regexp_spec.rb +48 -0
- data/spec/shared/dummy_client.rb +14 -0
- data/spec/shared/peruse_stubs.rb +5 -0
- data/spec/shared/time_stubs.rb +12 -0
- data/spec/spec_helper.rb +28 -0
- data/spec/window_spec.rb +54 -0
- metadata +221 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'shared/time_stubs'
|
3
|
+
require 'shared/peruse_stubs'
|
4
|
+
|
5
|
+
describe 'chained searches' do
|
6
|
+
include_context "time stubs"
|
7
|
+
include_context "peruse stubs"
|
8
|
+
|
9
|
+
it 'should parse last 24h & foo_type=bar & baz="fez" & host=27.224.123.110' do
|
10
|
+
result = Peruse.search 'last 24h & foo_type=bar & baz="fez" & host=27.224.123.110'
|
11
|
+
expected = Peruse::Helper.filter_builder({
|
12
|
+
and: [
|
13
|
+
Peruse::Helper.range_builder(
|
14
|
+
(@time - 24.hours).utc.to_datetime.iso8601(3),
|
15
|
+
@time.utc.to_datetime.iso8601(3)
|
16
|
+
),
|
17
|
+
Peruse::Helper.query_builder('foo_type:bar'),
|
18
|
+
Peruse::Helper.query_builder('baz:"fez"'),
|
19
|
+
Peruse::Helper.query_builder('host:27.224.123.110')
|
20
|
+
]
|
21
|
+
})
|
22
|
+
expect(result).to eq(expected)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should parse last 24h & (foo_type=bar AND baz="fez" AND host=27.224.123.110)' do
|
26
|
+
result = Peruse.search 'last 24h & (foo_type=bar AND baz="fez" AND host=27.224.123.110)'
|
27
|
+
expected = Peruse::Helper.filter_builder({
|
28
|
+
and: [
|
29
|
+
Peruse::Helper.range_builder(
|
30
|
+
(@time - 24.hours).utc.to_datetime.iso8601(3),
|
31
|
+
@time.utc.to_datetime.iso8601(3)
|
32
|
+
),
|
33
|
+
Peruse::Helper.query_builder('foo_type:bar'),
|
34
|
+
Peruse::Helper.query_builder('baz:"fez"'),
|
35
|
+
Peruse::Helper.query_builder('host:27.224.123.110')
|
36
|
+
]
|
37
|
+
})
|
38
|
+
expect(result).to eq(expected)
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'field / value searches' do
|
4
|
+
|
5
|
+
it 'should parse _foo.@bar=baz' do
|
6
|
+
result = Peruse.search '_foo.@bar=baz'
|
7
|
+
expected = Peruse::Helper.filter_builder(
|
8
|
+
Peruse::Helper.query_builder('_foo.@bar:baz')
|
9
|
+
)
|
10
|
+
expect(result).to eq(expected)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should parse _foo.@bar=(baz)' do
|
14
|
+
result = Peruse.search '_foo.@bar=(baz)'
|
15
|
+
expected = Peruse::Helper.filter_builder(
|
16
|
+
Peruse::Helper.query_builder('_foo.@bar:(baz)')
|
17
|
+
)
|
18
|
+
expect(result).to eq(expected)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should parse _foo.@fields.@bar="bar baz"' do
|
22
|
+
result = Peruse.search '_foo.@fields.@bar="bar baz"'
|
23
|
+
expected = Peruse::Helper.filter_builder(
|
24
|
+
Peruse::Helper.query_builder('_foo.@fields.@bar:"bar baz"')
|
25
|
+
)
|
26
|
+
expect(result).to eq(expected)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should parse _foo-barcr@5Y_+f!3*(name=bar' do
|
30
|
+
result = Peruse.search '_foo-barcr@5Y_+f!3*(name=bar'
|
31
|
+
expected = Peruse::Helper.filter_builder(
|
32
|
+
Peruse::Helper.query_builder('_foo-barcr@5Y_+f!3*(name:bar')
|
33
|
+
)
|
34
|
+
expect(result).to eq(expected)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should parse foo=bar-baz' do
|
38
|
+
result = Peruse.search 'foo=bar-baz'
|
39
|
+
expected = Peruse::Helper.filter_builder(
|
40
|
+
Peruse::Helper.query_builder('foo:bar-baz')
|
41
|
+
)
|
42
|
+
expect(result).to eq(expected)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should parse !src_ip=0.0.0.0' do
|
46
|
+
result = Peruse.search '!src_ip=0.0.0.0'
|
47
|
+
expected = Peruse::Helper.filter_builder(
|
48
|
+
Peruse::Helper.query_builder('!src_ip:0.0.0.0')
|
49
|
+
)
|
50
|
+
expect(result).to eq(expected)
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'the indices command' do
|
4
|
+
it 'should parse indices foo,bar,baz' do
|
5
|
+
result = Peruse.search 'indices foo,bar,baz'
|
6
|
+
expected = Peruse::Helper.filter_builder(
|
7
|
+
Peruse::Helper.indices_builder(%w(foo bar baz))
|
8
|
+
)
|
9
|
+
expect(result).to eq(expected)
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should parse indices foo , bar , baz' do
|
13
|
+
result = Peruse.search 'indices foo , bar , baz'
|
14
|
+
expected = Peruse::Helper.filter_builder(
|
15
|
+
Peruse::Helper.indices_builder(%w(foo bar baz))
|
16
|
+
)
|
17
|
+
expect(result).to eq(expected)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should parse indices foo , bar , baz & key = value' do
|
21
|
+
result = Peruse.search 'indices foo , bar , baz & key = value'
|
22
|
+
expected = Peruse::Helper.filter_builder(
|
23
|
+
and: [
|
24
|
+
Peruse::Helper.indices_builder(%w(foo bar baz)),
|
25
|
+
Peruse::Helper.query_builder('key:value')
|
26
|
+
]
|
27
|
+
)
|
28
|
+
expect(result).to eq(expected)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should parse key = value & indices foo , bar , baz' do
|
32
|
+
result = Peruse.search 'key = value & indices foo , bar , baz'
|
33
|
+
expected = Peruse::Helper.filter_builder(
|
34
|
+
and: [
|
35
|
+
Peruse::Helper.query_builder('key:value'),
|
36
|
+
Peruse::Helper.indices_builder(%w(foo bar baz))
|
37
|
+
]
|
38
|
+
)
|
39
|
+
expect(result).to eq(expected)
|
40
|
+
end
|
41
|
+
end
|
data/spec/last_spec.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'shared/time_stubs'
|
3
|
+
require 'shared/peruse_stubs'
|
4
|
+
|
5
|
+
describe 'the last command' do
|
6
|
+
include_context "time stubs"
|
7
|
+
include_context "peruse stubs"
|
8
|
+
|
9
|
+
it 'should parse last 24h' do
|
10
|
+
result = Peruse.search 'last 24h'
|
11
|
+
expected = Peruse::Helper.filter_builder(
|
12
|
+
Peruse::Helper.range_builder(
|
13
|
+
(@time - 24.hours).utc.to_datetime.iso8601(3),
|
14
|
+
@time.utc.to_datetime.iso8601(3)
|
15
|
+
)
|
16
|
+
)
|
17
|
+
expect(result).to eq(expected)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should parse last 24d' do
|
21
|
+
result = Peruse.search 'last 24d'
|
22
|
+
expected = Peruse::Helper.filter_builder(
|
23
|
+
Peruse::Helper.range_builder(
|
24
|
+
(@time - 24.days).utc.to_datetime.iso8601(3),
|
25
|
+
@time.utc.to_datetime.iso8601(3)
|
26
|
+
)
|
27
|
+
)
|
28
|
+
expect(result).to eq(expected)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should parse last 24w' do
|
32
|
+
result = Peruse.search 'last 24w'
|
33
|
+
expected = Peruse::Helper.filter_builder(
|
34
|
+
Peruse::Helper.range_builder(
|
35
|
+
(@time - 24.weeks).utc.to_datetime.iso8601(3),
|
36
|
+
@time.utc.to_datetime.iso8601(3)
|
37
|
+
)
|
38
|
+
)
|
39
|
+
expect(result).to eq(expected)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should parse last 24s' do
|
43
|
+
result = Peruse.search 'last 24s'
|
44
|
+
expected = Peruse::Helper.filter_builder(
|
45
|
+
Peruse::Helper.range_builder(
|
46
|
+
(@time - 24.seconds).utc.to_datetime.iso8601(3),
|
47
|
+
@time.utc.to_datetime.iso8601(3)
|
48
|
+
)
|
49
|
+
)
|
50
|
+
expect(result).to eq(expected)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should parse last 24m' do
|
54
|
+
result = Peruse.search 'last 24m'
|
55
|
+
expected = Peruse::Helper.filter_builder(
|
56
|
+
Peruse::Helper.range_builder(
|
57
|
+
(@time - 24.minutes).utc.to_datetime.iso8601(3),
|
58
|
+
@time.utc.to_datetime.iso8601(3)
|
59
|
+
)
|
60
|
+
)
|
61
|
+
expect(result).to eq(expected)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should parse last 1h & @fields.foo.@field=bar' do
|
65
|
+
result = Peruse.search 'last 1h & @fields.foo.@field=bar'
|
66
|
+
expected = Peruse::Helper.filter_builder(
|
67
|
+
and: [
|
68
|
+
Peruse::Helper.range_builder(
|
69
|
+
(@time - 1.hour).utc.to_datetime.iso8601(3),
|
70
|
+
@time.utc.to_datetime.iso8601(3)
|
71
|
+
),
|
72
|
+
Peruse::Helper.query_builder('@fields.foo.@field:bar')
|
73
|
+
]
|
74
|
+
)
|
75
|
+
expect(result).to eq(expected)
|
76
|
+
end
|
77
|
+
end
|
data/spec/limit_spec.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'shared/time_stubs'
|
3
|
+
require 'shared/peruse_stubs'
|
4
|
+
|
5
|
+
describe 'nested searches' do
|
6
|
+
include_context "time stubs"
|
7
|
+
include_context "peruse stubs"
|
8
|
+
|
9
|
+
before :each do
|
10
|
+
fake_results = {
|
11
|
+
foo: 'bar',
|
12
|
+
baz: 5,
|
13
|
+
arr: [ 0, 1, 2, 3 ],
|
14
|
+
:timestamp => @time.utc.to_datetime.iso8601(3)
|
15
|
+
}.to_json
|
16
|
+
allow_any_instance_of(Peruse::ResultSet).to receive(:eval).and_return(fake_results)
|
17
|
+
end
|
18
|
+
|
19
|
+
skip 'should transform' do
|
20
|
+
results = @transformer.apply @parser.parse('foo=`bar=baz|baz,fass,fdsd`')
|
21
|
+
expect(results.query).to eq({query:{filtered:{query:{query_string:{
|
22
|
+
query: 'foo:(5)'
|
23
|
+
}}}}})
|
24
|
+
end
|
25
|
+
|
26
|
+
skip 'should parse a nested basic search' do
|
27
|
+
@parsed = @parser.parse 'tshark.len = ` 226 | tshark.frame.time_epoch,tshark.ip.src`'
|
28
|
+
expect(@parsed[:field].to_s).to eq 'tshark.len'
|
29
|
+
expect(@parsed[:op].to_s).to eq '='
|
30
|
+
expect(@parsed[:value][:initial_query][:match].to_s).to eq '226'
|
31
|
+
expect(@parsed[:value][:extractors].to_s).to eq 'tshark.frame.time_epoch,tshark.ip.src'
|
32
|
+
end
|
33
|
+
|
34
|
+
skip 'should parse a nested regexp' do
|
35
|
+
@parsed = @parser.parse 'tshark.len = ` cif.malicious_ips=/foo/ | tshark.frame.time_epoch,tshark.ip.src`'
|
36
|
+
expect(@parsed[:field].to_s).to eq 'tshark.len'
|
37
|
+
expect(@parsed[:op].to_s).to eq '='
|
38
|
+
expect(@parsed[:value][:initial_query][:field].to_s).to eq 'cif.malicious_ips'
|
39
|
+
expect(@parsed[:value][:initial_query][:op].to_s).to eq '='
|
40
|
+
expect(@parsed[:value][:initial_query][:value].to_s).to eq '/foo/'
|
41
|
+
expect(@parsed[:value][:extractors].to_s).to eq 'tshark.frame.time_epoch,tshark.ip.src'
|
42
|
+
end
|
43
|
+
|
44
|
+
skip 'should parse a nested basic boolean' do
|
45
|
+
@parsed = @parser.parse 'tshark.len = `(foo OR bar) | tshark.frame.time_epoch,tshark.ip.src`'
|
46
|
+
expect(@parsed[:field].to_s).to eq 'tshark.len'
|
47
|
+
expect(@parsed[:op].to_s).to eq '='
|
48
|
+
expect(@parsed[:value][:initial_query][:match].to_s).to eq '(foo OR bar) '
|
49
|
+
expect(@parsed[:value][:extractors].to_s).to eq 'tshark.frame.time_epoch,tshark.ip.src'
|
50
|
+
end
|
51
|
+
|
52
|
+
skip 'should parse a nested field / value boolean' do
|
53
|
+
@parsed = @parser.parse 'tshark.len = `baz=(foo OR bar AND (bar OR fez)) | tshark.frame.time_epoch,tshark.ip.src`'
|
54
|
+
expect(@parsed[:field].to_s).to eq 'tshark.len'
|
55
|
+
expect(@parsed[:op].to_s).to eq '='
|
56
|
+
expect(@parsed[:value][:initial_query][:field].to_s).to eq 'baz'
|
57
|
+
expect(@parsed[:value][:initial_query][:op].to_s).to eq '='
|
58
|
+
expect(@parsed[:value][:initial_query][:value].to_s).to eq '(foo OR bar AND (bar OR fez)) '
|
59
|
+
expect(@parsed[:value][:extractors].to_s).to eq 'tshark.frame.time_epoch,tshark.ip.src'
|
60
|
+
end
|
61
|
+
|
62
|
+
skip 'should parse a nested last standalone timerange' do
|
63
|
+
@parsed = @parser.parse 'tshark.len = `last 24h | tshark.frame.time_epoch,tshark.ip.src`'
|
64
|
+
expect(@parsed[:field].to_s).to eq 'tshark.len'
|
65
|
+
expect(@parsed[:op].to_s).to eq '='
|
66
|
+
expect(@parsed[:value][:initial_query][:timerange][:quantity].to_s).to eq '24'
|
67
|
+
expect(@parsed[:value][:initial_query][:timerange][:quantifier].to_s).to eq 'h'
|
68
|
+
expect(@parsed[:value][:extractors].to_s).to eq 'tshark.frame.time_epoch,tshark.ip.src'
|
69
|
+
end
|
70
|
+
|
71
|
+
skip 'should parse a nested last timerange and field / value pair' do
|
72
|
+
@parsed = @parser.parse 'tshark.len = `last 24h foo=bar | tshark.frame.time_epoch,tshark.ip.src`'
|
73
|
+
expect(@parsed[:field].to_s).to eq 'tshark.len'
|
74
|
+
expect(@parsed[:op].to_s).to eq '='
|
75
|
+
expect(@parsed[:value][:initial_query][:timerange][:quantity].to_s).to eq '24'
|
76
|
+
expect(@parsed[:value][:initial_query][:timerange][:quantifier].to_s).to eq 'h'
|
77
|
+
expect(@parsed[:value][:initial_query][:search][:field].to_s).to eq 'foo'
|
78
|
+
expect(@parsed[:value][:initial_query][:search][:op].to_s).to eq '='
|
79
|
+
expect(@parsed[:value][:initial_query][:search][:value].to_s).to eq 'bar'
|
80
|
+
expect(@parsed[:value][:extractors].to_s).to eq 'tshark.frame.time_epoch,tshark.ip.src'
|
81
|
+
end
|
82
|
+
end
|
data/spec/regexp_spec.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'regexp searches' do
|
4
|
+
|
5
|
+
it 'should parse foo=/blah foo/' do
|
6
|
+
result = Peruse.search 'foo=/blah foo/'
|
7
|
+
expected = Peruse::Helper.filter_builder(
|
8
|
+
Peruse::Helper.regexp_builder(
|
9
|
+
'foo',
|
10
|
+
'blah foo'
|
11
|
+
)
|
12
|
+
)
|
13
|
+
expect(result).to eq(expected)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should parse foo=/blah\/ foo/' do
|
17
|
+
result = Peruse.search 'foo=/blah\/ foo/'
|
18
|
+
expected = Peruse::Helper.filter_builder(
|
19
|
+
Peruse::Helper.regexp_builder(
|
20
|
+
'foo',
|
21
|
+
'blah\/ foo'
|
22
|
+
)
|
23
|
+
)
|
24
|
+
expect(result).to eq(expected)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should parse foo=/blah\. foo/' do
|
28
|
+
result = Peruse.search 'foo=/blah\. foo/'
|
29
|
+
expected = Peruse::Helper.filter_builder(
|
30
|
+
Peruse::Helper.regexp_builder(
|
31
|
+
'foo',
|
32
|
+
'blah\. foo'
|
33
|
+
)
|
34
|
+
)
|
35
|
+
expect(result).to eq(expected)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'should parse http.headers=/.*User\-Agent\: Microsoft\-WebDAV.*/' do
|
39
|
+
result = Peruse.search 'http.headers=/.*User\-Agent\: Microsoft\-WebDAV.*/'
|
40
|
+
expected = Peruse::Helper.filter_builder(
|
41
|
+
Peruse::Helper.regexp_builder(
|
42
|
+
'http.headers',
|
43
|
+
'.*User\-Agent\: Microsoft\-WebDAV.*'
|
44
|
+
)
|
45
|
+
)
|
46
|
+
expect(result).to eq(expected)
|
47
|
+
end
|
48
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'peruse'
|
3
|
+
require 'parslet/rig/rspec'
|
4
|
+
require 'shared/dummy_client'
|
5
|
+
|
6
|
+
# Print ascii_tree when exception occurs
|
7
|
+
module Peruse
|
8
|
+
class ParserWrapper < Parser
|
9
|
+
def parse(query)
|
10
|
+
begin
|
11
|
+
super(query)
|
12
|
+
rescue Parslet::ParseFailed => failure
|
13
|
+
puts failure.cause.ascii_tree
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
RSpec.configure do |config|
|
20
|
+
config.before :all do
|
21
|
+
|
22
|
+
# configure test instance of Peruse to use wrapper parser
|
23
|
+
Peruse.configure do |c|
|
24
|
+
c.parser = Peruse::ParserWrapper.new
|
25
|
+
c.transformer = Peruse::Transformer.new
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/spec/window_spec.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'shared/time_stubs'
|
3
|
+
require 'shared/peruse_stubs'
|
4
|
+
require 'chronic'
|
5
|
+
|
6
|
+
describe 'the window command' do
|
7
|
+
include_context 'time stubs'
|
8
|
+
include_context 'peruse stubs'
|
9
|
+
|
10
|
+
it 'should parse window 3/11/13 to 3/12/13' do
|
11
|
+
result = Peruse.search 'window 3/11/13 to 3/12/13'
|
12
|
+
expected = Peruse::Helper.filter_builder(
|
13
|
+
Peruse::Helper.range_builder(
|
14
|
+
Peruse::Helper.timestamp_format(Chronic.parse('3/11/13')),
|
15
|
+
Peruse::Helper.timestamp_format(Chronic.parse('3/12/13'))
|
16
|
+
)
|
17
|
+
)
|
18
|
+
expect(result).to eq(expected)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should parse window "last monday" to "last thursday"' do
|
22
|
+
result = Peruse.search 'window "last monday" to "last thursday"'
|
23
|
+
expected = Peruse::Helper.filter_builder(
|
24
|
+
Peruse::Helper.range_builder(
|
25
|
+
Peruse::Helper.timestamp_format(Chronic.parse('last monday')),
|
26
|
+
Peruse::Helper.timestamp_format(Chronic.parse('last thursday'))
|
27
|
+
)
|
28
|
+
)
|
29
|
+
expect(result).to eq(expected)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should parse window -60m to -30m' do
|
33
|
+
result = Peruse.search 'window -60m to -30m'
|
34
|
+
expected = Peruse::Helper.filter_builder(
|
35
|
+
Peruse::Helper.range_builder(
|
36
|
+
Peruse::Helper.timestamp_format(@time - 60.minutes),
|
37
|
+
Peruse::Helper.timestamp_format(@time - 30.minutes)
|
38
|
+
)
|
39
|
+
)
|
40
|
+
expect(result).to eq(expected)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should parse NOT window -60m to -30m' do
|
44
|
+
result = Peruse.search 'NOT window -60m to -30m'
|
45
|
+
expected = Peruse::Helper.filter_builder(
|
46
|
+
not:
|
47
|
+
Peruse::Helper.range_builder(
|
48
|
+
Peruse::Helper.timestamp_format(@time - 60.minutes),
|
49
|
+
Peruse::Helper.timestamp_format(@time - 30.minutes)
|
50
|
+
)
|
51
|
+
)
|
52
|
+
expect(result).to eq(expected)
|
53
|
+
end
|
54
|
+
end
|