warpaint 0.0.1
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.
- data/.gitignore +4 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/README.md +60 -0
- data/Rakefile +1 -0
- data/bin/warpaint +41 -0
- data/lib/warpaint.rb +18 -0
- data/lib/warpaint/cli.rb +32 -0
- data/lib/warpaint/gpx.rb +17 -0
- data/lib/warpaint/network_collection.rb +14 -0
- data/lib/warpaint/netxml.rb +24 -0
- data/lib/warpaint/ordered_collection.rb +15 -0
- data/lib/warpaint/parser.rb +8 -0
- data/lib/warpaint/point_collection.rb +14 -0
- data/lib/warpaint/renderer.rb +28 -0
- data/lib/warpaint/version.rb +3 -0
- data/spec/data/2011-11-23 21-06-20.gpx +1 -0
- data/spec/data/Kismet-20111124-01-56-22-1.netxml +530 -0
- data/spec/warpaint_cli_spec.rb +64 -0
- data/spec/warpaint_gpx_spec.rb +15 -0
- data/spec/warpaint_network_collection_spec.rb +21 -0
- data/spec/warpaint_netxml_spec.rb +14 -0
- data/spec/warpaint_ordered_collection_spec.rb +16 -0
- data/spec/warpaint_parser_spec.rb +15 -0
- data/spec/warpaint_point_collection_spec.rb +21 -0
- data/spec/warpaint_renderer_spec.rb +26 -0
- data/warpaint.gemspec +31 -0
- metadata +178 -0
@@ -0,0 +1,64 @@
|
|
1
|
+
require "warpaint/cli"
|
2
|
+
|
3
|
+
describe Warpaint::CLI do
|
4
|
+
before (:each) do
|
5
|
+
@args = ARGV.dup
|
6
|
+
end
|
7
|
+
|
8
|
+
# used to silence warnings when we redefine ARGV
|
9
|
+
module Kernel
|
10
|
+
def silence_warnings
|
11
|
+
original_verbosity = $VERBOSE
|
12
|
+
$VERBOSE = nil
|
13
|
+
result = yield
|
14
|
+
$VERBOSE = original_verbosity
|
15
|
+
return result
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should optionally write to an output file (with '-o path')" do
|
20
|
+
Kernel.silence_warnings do
|
21
|
+
ARGV = [ '-o', 'output.kml' ]
|
22
|
+
end
|
23
|
+
|
24
|
+
cli = Warpaint::CLI.new
|
25
|
+
cli.parse_options
|
26
|
+
cli.config[:output_file].should == 'output.kml'
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should optionally display usage info (with '-h or --help')" do
|
30
|
+
Kernel.silence_warnings do
|
31
|
+
ARGV = [ '-h' ]
|
32
|
+
end
|
33
|
+
|
34
|
+
cli = Warpaint::CLI.new
|
35
|
+
|
36
|
+
stdout = $stdout
|
37
|
+
trapped_output = StringIO.new
|
38
|
+
$stdout = trapped_output
|
39
|
+
|
40
|
+
lambda { cli.parse_options }.should raise_error SystemExit
|
41
|
+
trapped_output.string.should match /-o, --out OUTPUT\s+The output file \(\.KML\) to write/
|
42
|
+
trapped_output.string.should match /-h, --help\s+Show this message/
|
43
|
+
trapped_output.string.should match /-n NETXML_TIME_ADJUSTMENT,\s+Adjust the timestamps in NetXML file by seconds \(can be negative\)/
|
44
|
+
trapped_output.string.should match /-g, --gtime GPX_TIME_ADJUSTMENT\s+Adjust the timestamps in GPX file by seconds \(can be negative\)/
|
45
|
+
|
46
|
+
$stdout = stdout
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should optionally allow specification of time adjustment for network entries" do
|
50
|
+
Kernel.silence_warnings do
|
51
|
+
ARGV = [ '--ntime', '3600' ]
|
52
|
+
end
|
53
|
+
|
54
|
+
cli = Warpaint::CLI.new
|
55
|
+
cli.parse_options
|
56
|
+
cli.config[:adjust_netxml_time].should == "3600"
|
57
|
+
end
|
58
|
+
|
59
|
+
after(:each) do
|
60
|
+
Kernel.silence_warnings do
|
61
|
+
ARGV = @args
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "warpaint/gpx"
|
2
|
+
|
3
|
+
describe Warpaint::GPX do
|
4
|
+
it "should parse a GPS eXchange Format (.GPX) file into a given data stucture" do
|
5
|
+
parser = Warpaint::GPX.new('spec/data/2011-11-23 21-06-20.gpx')
|
6
|
+
struct = double()
|
7
|
+
|
8
|
+
struct.should_receive(:add_track_point).with(:time => Time.parse("2011-11-23T20:54:29Z"), :lat =>"38.97123336791992", :lon => "-92.31622314453125")
|
9
|
+
struct.should_receive(:add_track_point).with(:time => Time.parse("2011-11-23T20:54:30Z"), :lat =>"38.971229553222656", :lon => "-92.31639099121094")
|
10
|
+
struct.should_receive(:add_track_point).with(:time => Time.parse("2011-11-23T20:54:31Z"), :lat =>"38.971229553222656", :lon => "-92.31654357910156")
|
11
|
+
struct.stub!(:add_track_point)
|
12
|
+
|
13
|
+
parser.parse_into(struct)
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "warpaint/network_collection"
|
2
|
+
|
3
|
+
describe Warpaint::NetworkCollection do
|
4
|
+
it "should maintain sort order of networks by time (earliest first)" do
|
5
|
+
nc = Warpaint::NetworkCollection.new
|
6
|
+
|
7
|
+
nc.add_wireless_network(:last_time => Time.parse("Thu Nov 24 02:58:59 2011"), :essid => "HackShack", :encryption => "None")
|
8
|
+
nc.add_wireless_network(:last_time => Time.parse("Thu Nov 24 02:50:00 2011"), :essid => "Thunderdome", :encryption => "None")
|
9
|
+
nc.add_wireless_network(:last_time => Time.parse("Thu Nov 24 02:07:45 2011"), :essid => "NewHackCity", :encryption => "None")
|
10
|
+
|
11
|
+
nc.first.should == [Time.parse("Thu Nov 24 02:07:45 2011"), { :essid => "NewHackCity", :encryption => "None" }]
|
12
|
+
nc.last.should == [Time.parse("Thu Nov 24 02:58:59 2011"), { :essid => "HackShack", :encryption => "None" }]
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should optionally allow time adjustment in constructor" do
|
16
|
+
nc = Warpaint::NetworkCollection.new(3600)
|
17
|
+
time = Time.now
|
18
|
+
nc.add_wireless_network(:last_time => time, :essid => "HackShack", :encryption => "None")
|
19
|
+
nc.first.should == [time+3600, { :essid => "HackShack", :encryption => "None" }]
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "warpaint/netxml"
|
2
|
+
|
3
|
+
describe Warpaint::NetXML do
|
4
|
+
it "should parse a Kismet log (.NetXML) file into a given data stucture" do
|
5
|
+
parser = Warpaint::NetXML.new('spec/data/Kismet-20111124-01-56-22-1.netxml')
|
6
|
+
struct = double()
|
7
|
+
|
8
|
+
struct.should_receive(:add_wireless_network).with(:last_time => Time.parse("Thu Nov 24 02:58:59 2011"), :essid => "HackShack", :encryption => "None")
|
9
|
+
struct.should_receive(:add_wireless_network).with(:last_time => Time.parse("Thu Nov 24 02:50:00 2011"), :essid => "Thunderdome", :encryption => "None")
|
10
|
+
struct.should_receive(:add_wireless_network).with(:last_time => Time.parse("Thu Nov 24 02:07:45 2011"), :essid => "NewHackCity", :encryption => "None")
|
11
|
+
|
12
|
+
parser.parse_into(struct)
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "warpaint/ordered_collection"
|
2
|
+
require "time"
|
3
|
+
|
4
|
+
describe Warpaint::OrderedCollection do
|
5
|
+
it "should return the key-value pair closest to the given key" do
|
6
|
+
oc = Warpaint::OrderedCollection.new
|
7
|
+
|
8
|
+
oc[Time.parse("2011-11-23T20:30:00Z")] = :first
|
9
|
+
oc[Time.parse("2011-11-23T20:45:00Z")] = :second
|
10
|
+
oc[Time.parse("2011-11-23T21:00:00Z")] = :last
|
11
|
+
|
12
|
+
oc.closest_to(Time.parse("2011-11-23T20:00:00Z")).should == [Time.parse("2011-11-23T20:30:00Z"), :first]
|
13
|
+
oc.closest_to(Time.parse("2011-11-23T20:37:29Z")).should == [Time.parse("2011-11-23T20:30:00Z"), :first]
|
14
|
+
oc.closest_to(Time.parse("2011-11-23T20:37:31Z")).should == [Time.parse("2011-11-23T20:45:00Z"), :second]
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "warpaint/parser"
|
2
|
+
|
3
|
+
describe Warpaint::Parser do
|
4
|
+
DUMMY_INPUT_FILE = "dummy_input.netxml"
|
5
|
+
|
6
|
+
it "should take a path for an input file in its constructor" do
|
7
|
+
input_file = File.open(DUMMY_INPUT_FILE, "w+") { |f| f.write "test" }
|
8
|
+
lambda { Warpaint::Parser.new(DUMMY_INPUT_FILE) }.should_not raise_error
|
9
|
+
File.delete DUMMY_INPUT_FILE
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should raise an error if no valid file is given" do
|
13
|
+
lambda { Warpaint::Parser.new(DUMMY_INPUT_FILE) }.should raise_error "File not found: dummy_input.netxml"
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "warpaint/point_collection"
|
2
|
+
|
3
|
+
describe Warpaint::PointCollection do
|
4
|
+
it "should maintain sort order of track points by time (earliest first)" do
|
5
|
+
pc = Warpaint::PointCollection.new
|
6
|
+
|
7
|
+
pc.add_track_point(:time => Time.parse("2011-11-23T20:54:29Z"), :lat =>"38.97123336791992", :lon => "-92.31622314453125")
|
8
|
+
pc.add_track_point(:time => Time.parse("2011-11-23T20:54:31Z"), :lat =>"38.971229553222656", :lon => "-92.31654357910156")
|
9
|
+
pc.add_track_point(:time => Time.parse("2011-11-23T20:54:30Z"), :lat =>"38.971229553222656", :lon => "-92.31639099121094")
|
10
|
+
|
11
|
+
pc.first.should == [Time.parse("2011-11-23T20:54:29Z"), { :lat =>"38.97123336791992", :lon => "-92.31622314453125" }]
|
12
|
+
pc.last.should == [Time.parse("2011-11-23T20:54:31Z"), { :lat =>"38.971229553222656", :lon => "-92.31654357910156" }]
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should optionally allow time adjustment in constructor" do
|
16
|
+
pc = Warpaint::PointCollection.new(3600)
|
17
|
+
time = Time.now
|
18
|
+
pc.add_track_point(:time => time, :lat =>"38.97123336791992", :lon => "-92.31622314453125")
|
19
|
+
pc.first.should == [time+3600, { :lat =>"38.97123336791992", :lon => "-92.31622314453125" }]
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "warpaint/renderer"
|
2
|
+
|
3
|
+
describe Warpaint::Renderer do
|
4
|
+
it "should integrate a collection of networks with a collection of track points and render a KML Placemark for each" do
|
5
|
+
t1 = Time.parse("Thu Nov 24 02:58:59 2011")
|
6
|
+
t2 = Time.parse("Thu Nov 24 02:50:00 2011")
|
7
|
+
t3 = Time.parse("Thu Nov 24 02:07:45 2011")
|
8
|
+
|
9
|
+
networks = double()
|
10
|
+
networks.should_receive(:each).once.and_yield(t1, { :essid => "HackShack", :encryption => "None" }).
|
11
|
+
and_yield(t2, { :essid => "Thunderdome", :encryption => "None" }).
|
12
|
+
and_yield(t3, { :essid => "NewHackCity", :encryption => "None" })
|
13
|
+
|
14
|
+
track_points = double()
|
15
|
+
track_points.should_receive(:closest_to).with(t1).and_return([Time.parse("2011-11-23T20:54:29Z"), { :lat =>"38.97123336791992", :lon => "-92.31622314453125" }])
|
16
|
+
track_points.should_receive(:closest_to).with(t2).and_return([Time.parse("2011-11-23T20:54:31Z"), { :lat =>"38.971229553222656", :lon => "-92.31654357910156" }])
|
17
|
+
track_points.should_receive(:closest_to).with(t3).and_return([Time.parse("2011-11-23T20:54:30Z"), { :lat =>"38.971229553222656", :lon => "-92.31639099121094" }])
|
18
|
+
|
19
|
+
|
20
|
+
renderer = Warpaint::Renderer.new(networks, track_points)
|
21
|
+
buf = StringIO.new
|
22
|
+
renderer.render_to(buf)
|
23
|
+
|
24
|
+
# buf.string.should match //
|
25
|
+
end
|
26
|
+
end
|
data/warpaint.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "warpaint/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "warpaint"
|
7
|
+
s.version = Warpaint::VERSION
|
8
|
+
s.authors = ["Robert Boyd"]
|
9
|
+
s.email = ["robert.boyd@me.com"]
|
10
|
+
s.homepage = "http://github.com/rboyd"
|
11
|
+
s.summary = "Kismet + phone GPS = wardrive maps"
|
12
|
+
s.description = "Warpaint is a library and command-line utility for integrating GPS Exchange Format (GPX) files with Kismet logs (NetXML) to produce Google Earth (KML) output."
|
13
|
+
|
14
|
+
s.rubyforge_project = "warpaint"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
s.add_development_dependency "rspec"
|
23
|
+
s.add_development_dependency "rake"
|
24
|
+
|
25
|
+
s.add_runtime_dependency "nokogiri"
|
26
|
+
s.add_runtime_dependency "builder"
|
27
|
+
s.add_runtime_dependency "schleyfox-ruby_kml"
|
28
|
+
s.add_runtime_dependency "kamel"
|
29
|
+
s.add_runtime_dependency "mixlib-cli"
|
30
|
+
s.add_runtime_dependency "rbtree"
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: warpaint
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Robert Boyd
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-11-28 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &70313677944520 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70313677944520
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rake
|
27
|
+
requirement: &70313677943760 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70313677943760
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: nokogiri
|
38
|
+
requirement: &70313677922960 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70313677922960
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: builder
|
49
|
+
requirement: &70313677922240 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70313677922240
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: schleyfox-ruby_kml
|
60
|
+
requirement: &70313677921520 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70313677921520
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: kamel
|
71
|
+
requirement: &70313677920800 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *70313677920800
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: mixlib-cli
|
82
|
+
requirement: &70313677919540 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :runtime
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *70313677919540
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: rbtree
|
93
|
+
requirement: &70313677917780 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
type: :runtime
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *70313677917780
|
102
|
+
description: Warpaint is a library and command-line utility for integrating GPS Exchange
|
103
|
+
Format (GPX) files with Kismet logs (NetXML) to produce Google Earth (KML) output.
|
104
|
+
email:
|
105
|
+
- robert.boyd@me.com
|
106
|
+
executables:
|
107
|
+
- warpaint
|
108
|
+
extensions: []
|
109
|
+
extra_rdoc_files: []
|
110
|
+
files:
|
111
|
+
- .gitignore
|
112
|
+
- .rspec
|
113
|
+
- Gemfile
|
114
|
+
- README.md
|
115
|
+
- Rakefile
|
116
|
+
- bin/warpaint
|
117
|
+
- lib/warpaint.rb
|
118
|
+
- lib/warpaint/cli.rb
|
119
|
+
- lib/warpaint/gpx.rb
|
120
|
+
- lib/warpaint/network_collection.rb
|
121
|
+
- lib/warpaint/netxml.rb
|
122
|
+
- lib/warpaint/ordered_collection.rb
|
123
|
+
- lib/warpaint/parser.rb
|
124
|
+
- lib/warpaint/point_collection.rb
|
125
|
+
- lib/warpaint/renderer.rb
|
126
|
+
- lib/warpaint/version.rb
|
127
|
+
- spec/data/2011-11-23 21-06-20.gpx
|
128
|
+
- spec/data/Kismet-20111124-01-56-22-1.netxml
|
129
|
+
- spec/warpaint_cli_spec.rb
|
130
|
+
- spec/warpaint_gpx_spec.rb
|
131
|
+
- spec/warpaint_network_collection_spec.rb
|
132
|
+
- spec/warpaint_netxml_spec.rb
|
133
|
+
- spec/warpaint_ordered_collection_spec.rb
|
134
|
+
- spec/warpaint_parser_spec.rb
|
135
|
+
- spec/warpaint_point_collection_spec.rb
|
136
|
+
- spec/warpaint_renderer_spec.rb
|
137
|
+
- warpaint.gemspec
|
138
|
+
homepage: http://github.com/rboyd
|
139
|
+
licenses: []
|
140
|
+
post_install_message:
|
141
|
+
rdoc_options: []
|
142
|
+
require_paths:
|
143
|
+
- lib
|
144
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ! '>='
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
segments:
|
151
|
+
- 0
|
152
|
+
hash: -3677766930814124799
|
153
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
154
|
+
none: false
|
155
|
+
requirements:
|
156
|
+
- - ! '>='
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
159
|
+
segments:
|
160
|
+
- 0
|
161
|
+
hash: -3677766930814124799
|
162
|
+
requirements: []
|
163
|
+
rubyforge_project: warpaint
|
164
|
+
rubygems_version: 1.8.10
|
165
|
+
signing_key:
|
166
|
+
specification_version: 3
|
167
|
+
summary: Kismet + phone GPS = wardrive maps
|
168
|
+
test_files:
|
169
|
+
- spec/data/2011-11-23 21-06-20.gpx
|
170
|
+
- spec/data/Kismet-20111124-01-56-22-1.netxml
|
171
|
+
- spec/warpaint_cli_spec.rb
|
172
|
+
- spec/warpaint_gpx_spec.rb
|
173
|
+
- spec/warpaint_network_collection_spec.rb
|
174
|
+
- spec/warpaint_netxml_spec.rb
|
175
|
+
- spec/warpaint_ordered_collection_spec.rb
|
176
|
+
- spec/warpaint_parser_spec.rb
|
177
|
+
- spec/warpaint_point_collection_spec.rb
|
178
|
+
- spec/warpaint_renderer_spec.rb
|