pokeplot 0.2.0beta

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,158 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
7
+ <title>Document</title>
8
+ <style>
9
+ * {
10
+ margin: 0;
11
+ padding: 0;
12
+ }
13
+ h1, h2 {
14
+ width: 100%;
15
+ text-align: center;
16
+ margin: auto;
17
+ }
18
+ </style>
19
+ </head>
20
+ <body>
21
+ <h1>Pokeplot Visualizations</h1>
22
+ <h2>Pokemon Frequency</h2>
23
+ <hr / />
24
+ <div id="frequency_pie" style="height: 50vh; width: 98vw;"></div>
25
+ <div id="least_frequent" style="height: 45vh; width: 48vw;display: inline-block;"></div>
26
+ <div id="most_frequent" style="height: 45vh; width: 48vw; display: inline-block;"></div>
27
+ <!-- <br />
28
+ <span id="num_unique">Number of unique pokemon found: <b>0</b></span> -->
29
+ <h2>Spawn Points</h2>
30
+ <hr />
31
+ <div id="spawn_frequency" style="height: 50vh; width: 98vw;"></div>
32
+ <script src="canvasjs.min.js"></script>
33
+ <script>
34
+ var pokemon = {};
35
+ var spawns = {};
36
+ function socket() {
37
+ websocket = new WebSocket("ws://" + document.location.hostname + ":9090");
38
+
39
+ websocket.onmessage = function(evt) {
40
+ data = JSON.parse(evt.data);
41
+ if (data.type == "count") {
42
+ data = data.data;
43
+ for (var mon in data) {
44
+ pokemon.hasOwnProperty(mon) ? (pokemon[mon] += data[mon]) : (pokemon[mon] = data[mon]);
45
+ }
46
+ }else if (data.type == "pokemon") {
47
+ data = data.data;
48
+ pokemon.hasOwnProperty(data.pokemon) ? (pokemon[data.pokemon] += 1) : (pokemon[data.pokemon] = 1);
49
+ spawns.hasOwnProperty(data.spawn_point_id) ? (spawns[data.spawn_point_id] += 1) : (spawns[data.spawn_point_id] = 1);
50
+ }else if (data.type == "spawn_points") {
51
+ data = data.data;
52
+ for (var spawn in data) {
53
+ spawns.hasOwnProperty(spawn) ? (spawns[spawn] += data[spawn]) : (spawns[spawn] = data[spawn]);
54
+ }
55
+ }
56
+ updateCharts();
57
+ };
58
+ websocket.onclose = function(evt) {
59
+ alert("Connection to server lost");
60
+ }
61
+ }
62
+ socket();
63
+
64
+ function freqPie(content, total) {
65
+ var chart = new CanvasJS.Chart("frequency_pie",
66
+ {
67
+ theme: "theme2",
68
+ exportFileName: "pokemon_freq_pie",
69
+ exportEnabled: true,
70
+ title:{
71
+ text: "Pokemon Frequency (Total: " + total + ")"
72
+ },
73
+ data: [
74
+ {
75
+ type: "pie",
76
+ toolTipContent: "{label}: {y} - #percent %",
77
+ indexLabel: "{label}: #percent%",
78
+ indexLabelFontSize: 15,
79
+ indexLabelFontColor: "darkslategray",
80
+ indexLabelPlacement: "outside",
81
+ indexLabelFormatter: function(e) { if (e.percent >= 1) { return e.dataPoint.label + ": " + e.percent.toFixed(2) + "%"} },
82
+ dataPoints: content
83
+ }
84
+ ]
85
+ });
86
+ chart.render();
87
+ }
88
+ function freqBar(contentSlice, title, total, id) {
89
+ var chart = new CanvasJS.Chart(id,
90
+ {
91
+ theme: 'theme2',
92
+ exportFileName: "pokemon_most_freq",
93
+ exportEnabled: true,
94
+ title: {text: title},
95
+ axisY: {title: "Number of encounters"},
96
+ axisX: {labelFontSize: 10, interval: 1},
97
+ data: [
98
+ {
99
+ type: "bar",
100
+ dataPoints: contentSlice
101
+ }
102
+ ]
103
+ });
104
+ chart.render();
105
+ }
106
+ function spawnFreq(content, total) {
107
+ var chart = new CanvasJS.Chart("spawn_frequency",
108
+ {
109
+ theme: 'theme2',
110
+ exportFileName: "spawn_frequency",
111
+ exportEnabled: true,
112
+ title: {text: "Spawn Point Frequency (Total: " + total + ")"},
113
+ axisY: {title: "Number of encounters"},
114
+ axisX: {labelFormatter: function (e) { return "" }, title: "Spawn Point Id (Hover)"},
115
+ data: [
116
+ {
117
+ type: "bar",
118
+ dataPoints: content
119
+ }
120
+ ]
121
+ });
122
+ chart.render();
123
+ }
124
+
125
+ function unique(n) {
126
+ document.getElementById('num_unique').innerHTML = "Number of unique pokemon found: <b>" + n + "</b>";
127
+ }
128
+
129
+ function updateCharts() {
130
+ dataPokemon1 = [];
131
+ dataSpawns1 = [];
132
+ totalEncounters = 0;
133
+ totalSpawns = 0;
134
+
135
+ for (var mon in pokemon) {
136
+ totalEncounters += pokemon[mon]
137
+ dataPokemon1.push({label: mon, y: pokemon[mon]});
138
+ }
139
+ dataPokemon1.sort(function(a,b) { return b.y - a.y });
140
+
141
+ for (var spawn in spawns) {
142
+ totalSpawns += 1
143
+ dataSpawns1.push({label: spawn, y: spawns[spawn]});
144
+ }
145
+ dataSpawns1 = dataSpawns1.slice(0, 31)
146
+ dataSpawns1.sort(function(a,b) { return b.y - a.y });
147
+
148
+ freqPie(dataPokemon1, totalEncounters);
149
+ freqBar(dataPokemon1.slice(-20), "Least Frequent Pokemon", totalEncounters, "least_frequent");
150
+ freqBar(dataPokemon1.slice(0, 21), "Most Frequent Pokemon", totalEncounters, "most_frequent");
151
+ //unique(Object.keys(pokemon).length);
152
+ spawnFreq(dataSpawns1.slice(0, 31), totalSpawns);
153
+ }
154
+
155
+
156
+ </script>
157
+ </body>
158
+ </html>
@@ -0,0 +1,26 @@
1
+ require 'sinatra/base'
2
+ require 'puma'
3
+
4
+ module Pokeplot
5
+ class Web < Sinatra::Base
6
+ include Database
7
+
8
+ set :bind, '0.0.0.0'
9
+ set :port, 5001
10
+ set :server, :puma
11
+ set :traps, false
12
+ set :static, true
13
+ set :public_folder, __dir__ + "/web"
14
+
15
+ def self.config(host = '0.0.0.0', port = 5001)
16
+ @@db = Database.mongo
17
+ set :bind, host
18
+ set :port, port
19
+ end
20
+
21
+ get '/' do
22
+ send_file File.join(settings.public_folder, 'index.html')
23
+ end
24
+
25
+ end
26
+ end
data/lib/pokeplot.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'pokeplot/version'
2
+ require 'pokeplot/database'
3
+ require 'pokeplot/api'
4
+ require 'pokeplot/miner'
5
+ require 'pokeplot/socket'
6
+ require 'pokeplot/web'
7
+ require 'pokeplot/pushbullet'
data/spec/api_spec.rb ADDED
@@ -0,0 +1,148 @@
1
+ require 'pokeplot/api'
2
+ require 'pokeplot/helpers/cell_ids'
3
+ require 'poke-api/errors'
4
+
5
+ describe Pokeplot::API do
6
+
7
+ subject(:api) {
8
+
9
+ api = double()
10
+
11
+ allow(api).to receive_messages(:lat => 40.7829, :lng => 73.9654)
12
+ allow(api).to receive_messages([
13
+ :activate_signature,
14
+ :lat=,
15
+ :lng=,
16
+ :login,
17
+ :get_player,
18
+ :get_hatched_eggs,
19
+ :get_inventory,
20
+ :check_awarded_badges,
21
+ :download_settings,
22
+ :get_map_objects,
23
+ :call
24
+ ])
25
+
26
+ expect(Poke::API::Logging).to receive(:log_level=)
27
+ expect(Poke::API::Client).to receive(:new).and_return(api).at_least(:once)
28
+
29
+ described_class.new(40.7829, 73.9654, '', false)
30
+ }
31
+
32
+ describe ".new" do
33
+ it "should create an instance of Pokeplot::API" do
34
+ expect(api).to be_a(Pokeplot::API)
35
+ end
36
+ end
37
+
38
+ describe "#login" do
39
+ context "successful" do
40
+ it "should login" do
41
+ client = api.instance_variable_get(:@api)
42
+ expect(client).to receive(:login).with(instance_of(String), instance_of(String), /(google|ptc)/)
43
+ expect(api).to receive(:loop).and_yield
44
+ api.login('', '', 'ptc')
45
+ end
46
+ end
47
+
48
+ context "error" do
49
+ error = StandardError.new
50
+ error.set_backtrace("test error")
51
+ error.exception
52
+ error = Poke::API::Errors::UnknownProtoFault.new(error)
53
+
54
+ it "should sleep for 5 seconds" do
55
+ client = api.instance_variable_get(:@api)
56
+ expect(client).to receive(:login).with(instance_of(String), instance_of(String), /(google|ptc)/).and_raise(error)
57
+ expect(api).to receive(:loop).and_yield
58
+ expect(api).to receive(:sleep).with(5)
59
+ api.login('','','ptc')
60
+ end
61
+ end
62
+ end
63
+
64
+ describe "#set_location" do
65
+ it "should set lat/lng" do
66
+ client = api.instance_variable_get(:@api)
67
+ expect(client).to receive(:lat=)
68
+ expect(client).to receive(:lng=)
69
+ api.set_location(40.7829, 73.9654)
70
+ end
71
+ end
72
+
73
+ describe "#lat=" do
74
+ it "should set lat" do
75
+ client = api.instance_variable_get(:@api)
76
+ expect(client).to receive(:lat=)
77
+ api.lat = 40.7829
78
+ end
79
+ end
80
+
81
+ describe "#lng=" do
82
+ it "should set lng" do
83
+ client = api.instance_variable_get(:@api)
84
+ expect(client).to receive(:lng=)
85
+ api.lng = 73.9654
86
+ end
87
+ end
88
+
89
+ describe "#map_heartbeat" do
90
+
91
+ before(:example) do |example|
92
+ data = [
93
+ {:status_code => 1},
94
+ {:status_code => 2},
95
+ {:status_code => 102},
96
+ {:status_code => 000}
97
+ ]
98
+
99
+ client = api.instance_variable_get(:@api)
100
+ expect(client).to receive_messages([:get_player, :get_hatched_eggs, :get_inventory, :check_awarded_badges, :download_settings, :get_map_objects])
101
+ expect(api).to receive(:loop).and_yield
102
+
103
+ call = double()
104
+ if example.metadata[:data].is_a?(Integer)
105
+ allow(call).to receive(:response).and_return(data[example.metadata[:data]])
106
+ else
107
+ error = StandardError.new
108
+ error.set_backtrace("test error")
109
+ error.exception
110
+ error = Poke::API::Errors::UnknownProtoFault.new(error)
111
+ allow(call).to receive(:response).and_raise(error)
112
+ end
113
+ expect(client).to receive(:call).and_return(call)
114
+ end
115
+
116
+
117
+ context "response succesful" do
118
+ it "should respond with a status code of 1", :data => 0 do
119
+ expect(api.map_heartbeat).to eq({:status_code => 1})
120
+ end
121
+ end
122
+
123
+ context "response error" do
124
+ it "could fail and rety", :data => 1 do
125
+ expect(api).to receive(:basic_request)
126
+ api.map_heartbeat
127
+ end
128
+
129
+ it "could re-login and retry", :data => 2 do
130
+ expect(api).to receive(:login)
131
+ api.map_heartbeat
132
+ end
133
+
134
+ it "could sleep and retry", :data => 3 do
135
+ expect(api).to receive(:sleep)
136
+ api.map_heartbeat
137
+ end
138
+ end
139
+
140
+ context "proto error" do
141
+ it "should re-login and retry" do
142
+ expect(api).to receive(:login)
143
+ api.map_heartbeat
144
+ end
145
+ end
146
+ end
147
+
148
+ end
@@ -0,0 +1,33 @@
1
+ require 'pokeplot/database'
2
+
3
+ describe Pokeplot::Database do
4
+
5
+ describe '.mongo' do
6
+ it "should create a new mongo client" do
7
+ expect(Mongo::Client).to receive(:new)
8
+ described_class.mongo
9
+ end
10
+ end
11
+
12
+ describe '.mongo_host=' do
13
+ it "should set mongo_host class variable" do
14
+ expect(
15
+ described_class.class_eval('@@mongo_host')
16
+ ).to eq('127.0.0.1:27017')
17
+
18
+ described_class.mongo_host = '127.0.0.1:30300'
19
+
20
+ expect(
21
+ described_class.class_eval('@@mongo_host')
22
+ ).to eq('127.0.0.1:30300')
23
+ end
24
+ end
25
+
26
+ describe '.mongo_monitor' do
27
+ it "Should subscribe a class to mongo global monitor" do
28
+ expect(Mongo::Monitoring::Global).to receive(:subscribe).with(Mongo::Monitoring::COMMAND, anything)
29
+ described_class.mongo_monitor(described_class)
30
+ end
31
+ end
32
+
33
+ end
@@ -0,0 +1,110 @@
1
+ require 'pokeplot/miner'
2
+ require 'pokeplot/database'
3
+ require 'pokeplot/helpers/math'
4
+
5
+ describe Pokeplot::Miner do
6
+
7
+ subject(:miner) {
8
+ db = double()
9
+ allow(db).to receive(:find).and_return(db)
10
+ allow(db).to receive(:insert_one)
11
+ allow(db).to receive(:count).and_return(0,0,1,1) #test unique and non unique
12
+ allow(db).to receive(:[]).and_return(db)
13
+
14
+ accounts = [{'username' => '', 'password' => '', 'provider' => 'ptc'}]
15
+
16
+ expect(Pokeplot::Database).to receive(:mongo).at_least(:once).and_return(db)
17
+ m = described_class.new(accounts, 74.3, 43.2, 1, 0, true, true, false, '', false, false)
18
+
19
+ return m
20
+ }
21
+
22
+ describe ".new" do
23
+ it "should create an instance of Pokeplot::Miner" do
24
+ expect(miner).to be_a(Pokeplot::Miner)
25
+ end
26
+ end
27
+
28
+ describe "#start" do
29
+
30
+ data2 = {:GET_MAP_OBJECTS => {:status => :SUCCESS, :map_cells => [{:s2_cell_id => 10, :current_timestamp_ms => 400, :forts => [{:id => 1, :enabled => false, :latitude => 0, :longitude => 0, :type => :GYM}], :wild_pokemons => [{:time_till_hidden_ms => 0, :encounter_id => 1, :latitude => 3, :longitude => 4, :spawn_point_id => 5, :pokemon_data => {:pokemon_id => :PIDGEY}}]}]}}
31
+ data1 = {:GET_MAP_OBJECTS => {:status => :SUCCESS, :map_cells => [{:forts => [], :wild_pokemons => [{:time_till_hidden_ms => -1, :pokemon_data => {:pokemon_id => :WEEDLE}}]}]}}
32
+
33
+ context "single thread" do
34
+ it "should create a miner thread" do
35
+ #To test normal and negative
36
+
37
+ api = double()
38
+ allow(api).to receive(:set_location).and_return(api)
39
+ allow(api).to receive(:map_heartbeat).and_return(data1, data2)
40
+ allow(api).to receive(:login).with(instance_of(String), instance_of(String), /(google|ptc)/)
41
+
42
+ expect(Thread).to receive(:new).and_yield
43
+ expect(miner).to receive(:loop).and_yield
44
+ expect(Pokeplot::API).to receive(:new).and_return(api)
45
+ miner.start
46
+ miner.stop
47
+ end
48
+ end
49
+
50
+ context "multiple threads" do
51
+ it "should create more than 1 thread" do
52
+ miner
53
+ api = double()
54
+ allow(api).to receive(:set_location).and_return(api)
55
+ allow(api).to receive(:map_heartbeat).and_return(data1, data2)
56
+ allow(api).to receive(:login).with(instance_of(String), instance_of(String), /(google|ptc)/).at_least(:once)
57
+
58
+ accounts = [{'username' => '', 'password' => '', 'provider' => 'ptc'}]
59
+ m = described_class.new(accounts, 74.3, 43.2, 1, 0, true, true, true, '', false, false)
60
+
61
+ expect(Thread).to receive(:new).at_least(:twice).and_yield
62
+ allow(m).to receive(:loop).and_yield
63
+ expect(Pokeplot::API).to receive(:new).and_return(api)
64
+
65
+ m.start
66
+ m.stop
67
+ end
68
+ end
69
+ end
70
+
71
+ describe "#stop" do
72
+ it "should delete the miner thread" do
73
+ miner.start
74
+ expect(miner.miner).not_to be(nil)
75
+ miner.stop
76
+ expect(miner.miner).to be(nil)
77
+ end
78
+ end
79
+
80
+ describe "#get_all_coords" do
81
+ it "should create an array of coords" do
82
+ expect(miner.send('get_all_coords')).to all(have_key(:lat) & have_key(:lng))
83
+ end
84
+ end
85
+
86
+ describe "#parse_map_objects" do
87
+ context "successful status" do
88
+ let(:data) { {:GET_MAP_OBJECTS => {:status => :SUCCESS, :map_cells => [{:s2_cell_id => 10, :current_timestamp_ms => 400, :forts => [{:id => 1, :enabled => false, :latitude => 0, :longitude => 0, :type => :GYM}], :wild_pokemons => [{:time_till_hidden_ms => 0, :encounter_id => 1, :latitude => 3, :longitude => 4, :spawn_point_id => 5, :pokemon_data => {:pokemon_id => :PIDGEY}}]}]}} }
89
+ it "should save encounters and forts" do
90
+
91
+ expect(miner.db).to receive(:find).with(instance_of(Hash)).twice
92
+ expect(miner.db).to receive(:insert_one).with(instance_of(Hash)).twice
93
+ expect(miner.db).to receive(:count).twice
94
+ expect(miner.db).to receive(:[]).with(instance_of(Symbol)).exactly(4).times
95
+
96
+ miner.send('parse_map_objects', data)
97
+ end
98
+ end
99
+
100
+ context "unsuccessful status" do
101
+ let(:data) { {:GET_MAP_OBJECTS => {:status => :ERROR}} }
102
+ it "should log an error" do
103
+ expect(
104
+ miner.send('parse_map_objects', data)
105
+ ).to eq(nil)
106
+ end
107
+ end
108
+ end
109
+
110
+ end
@@ -0,0 +1,31 @@
1
+ require 'pokeplot/pushbullet'
2
+
3
+ describe Pokeplot::Pushbullet do
4
+
5
+ describe ".new" do
6
+ it "should create a washbullet client" do
7
+ expect(Washbullet::Client).to receive(:new).with(instance_of(String))
8
+ described_class.new('apikey')
9
+ end
10
+ end
11
+
12
+ describe "#started" do
13
+ it "should sent a notification for pokemon" do
14
+ device = double()
15
+ allow(device).to receive_messages(:body => device, :[] => "identifier")
16
+ client = double()
17
+ allow(client).to receive(:devices).and_return([device])
18
+ expect(client).to receive(:push_note).with(instance_of(Hash))
19
+
20
+ mongo = double()
21
+ allow(mongo).to receive(:command).and_return({'insert' => 'encounters', 'documents' => [{:pokemon => "SEEL", :current_timestamp_ms => 400, :latitude => 0, :longitude => 0, :time_till_hidden_ms => 10}]})
22
+
23
+ expect(Washbullet::Client).to receive(:new).with(instance_of(String))
24
+
25
+ push = described_class.new("apikey", ['SEEL'])
26
+ push.instance_variable_set(:@client, client)
27
+ push.started(mongo)
28
+ end
29
+ end
30
+
31
+ end
@@ -0,0 +1,45 @@
1
+ require 'pokeplot/socket'
2
+ require 'pokeplot/database'
3
+ require 'eventmachine'
4
+
5
+ describe Pokeplot::Socket do
6
+
7
+ describe ".new" do
8
+ data = [{:pokemon => 1, :spawn_point_id => 1}, {:pokemon => 2, :spawn_point_id => 2}, {:pokemon => 1, :spawn_point_id => 1}]
9
+
10
+ it "should start a websocket" do
11
+ ws = double()
12
+ allow(ws).to receive(:onopen).and_yield(ws)
13
+ allow(ws).to receive(:onclose).and_yield
14
+ allow(ws).to receive(:onmessage)
15
+ allow(ws).to receive(:send)
16
+
17
+ db = double()
18
+ allow(db).to receive(:[]).and_return(db)
19
+ allow(db).to receive(:find).and_return(data)
20
+
21
+ expect(Thread).to receive(:new).and_yield
22
+ expect(Pokeplot::Database).to receive(:mongo).and_return(db)
23
+ expect(EventMachine).to receive(:run).and_yield
24
+ expect(EM::WebSocket).to receive(:run).and_yield(ws)
25
+ described_class.new
26
+ end
27
+ end
28
+
29
+ describe "#started" do
30
+ data = {'insert' => 'encounters', 'documents' => ["pokemon data"]}
31
+
32
+ it "should send data to the clients" do
33
+ client = double()
34
+ allow(client).to receive(:send)
35
+
36
+ event = double(:command => data)
37
+
38
+ expect(Thread).to receive(:new).and_return(nil)
39
+ socket = described_class.new
40
+ socket.instance_variable_set(:@clients, [client])
41
+ socket.started(event)
42
+ end
43
+ end
44
+
45
+ end
@@ -0,0 +1,115 @@
1
+ require "codeclimate-test-reporter"
2
+ CodeClimate::TestReporter.start
3
+
4
+ require 'rack/test'
5
+ ENV['RACK_ENV'] = 'test'
6
+
7
+ module RSpecMixin
8
+ include Rack::Test::Methods
9
+ def app() described_class end
10
+ end
11
+
12
+ # This file was generated by the `rspec --init` command. Conventionally, all
13
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
14
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
15
+ # this file to always be loaded, without a need to explicitly require it in any
16
+ # files.
17
+ #
18
+ # Given that it is always loaded, you are encouraged to keep this file as
19
+ # light-weight as possible. Requiring heavyweight dependencies from this file
20
+ # will add to the boot time of your test suite on EVERY test run, even for an
21
+ # individual file that may not need all of that loaded. Instead, consider making
22
+ # a separate helper file that requires the additional dependencies and performs
23
+ # the additional setup, and require it from the spec files that actually need
24
+ # it.
25
+ #
26
+ # The `.rspec` file also contains a few flags that are not defaults but that
27
+ # users commonly want.
28
+ #
29
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
30
+ RSpec.configure do |config|
31
+ config.include RSpecMixin
32
+ # rspec-expectations config goes here. You can use an alternate
33
+ # assertion/expectation library such as wrong or the stdlib/minitest
34
+ # assertions if you prefer.
35
+ config.expect_with :rspec do |expectations|
36
+ # This option will default to `true` in RSpec 4. It makes the `description`
37
+ # and `failure_message` of custom matchers include text for helper methods
38
+ # defined using `chain`, e.g.:
39
+ # be_bigger_than(2).and_smaller_than(4).description
40
+ # # => "be bigger than 2 and smaller than 4"
41
+ # ...rather than:
42
+ # # => "be bigger than 2"
43
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
44
+ end
45
+
46
+ # rspec-mocks config goes here. You can use an alternate test double
47
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
48
+ config.mock_with :rspec do |mocks|
49
+ # Prevents you from mocking or stubbing a method that does not exist on
50
+ # a real object. This is generally recommended, and will default to
51
+ # `true` in RSpec 4.
52
+ mocks.verify_partial_doubles = true
53
+ end
54
+
55
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
56
+ # have no way to turn it off -- the option exists only for backwards
57
+ # compatibility in RSpec 3). It causes shared context metadata to be
58
+ # inherited by the metadata hash of host groups and examples, rather than
59
+ # triggering implicit auto-inclusion in groups with matching metadata.
60
+ config.shared_context_metadata_behavior = :apply_to_host_groups
61
+
62
+ # The settings below are suggested to provide a good initial experience
63
+ # with RSpec, but feel free to customize to your heart's content.
64
+ =begin
65
+ # This allows you to limit a spec run to individual examples or groups
66
+ # you care about by tagging them with `:focus` metadata. When nothing
67
+ # is tagged with `:focus`, all examples get run. RSpec also provides
68
+ # aliases for `it`, `describe`, and `context` that include `:focus`
69
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
70
+ config.filter_run_when_matching :focus
71
+
72
+ # Allows RSpec to persist some state between runs in order to support
73
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
74
+ # you configure your source control system to ignore this file.
75
+ config.example_status_persistence_file_path = "spec/examples.txt"
76
+
77
+ # Limits the available syntax to the non-monkey patched syntax that is
78
+ # recommended. For more details, see:
79
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
80
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
81
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
82
+ config.disable_monkey_patching!
83
+
84
+ # This setting enables warnings. It's recommended, but in some cases may
85
+ # be too noisy due to issues in dependencies.
86
+ config.warnings = true
87
+
88
+ # Many RSpec users commonly either run the entire suite or an individual
89
+ # file, and it's useful to allow more verbose output when running an
90
+ # individual spec file.
91
+ if config.files_to_run.one?
92
+ # Use the documentation formatter for detailed output,
93
+ # unless a formatter has already been configured
94
+ # (e.g. via a command-line flag).
95
+ config.default_formatter = 'doc'
96
+ end
97
+
98
+ # Print the 10 slowest examples and example groups at the
99
+ # end of the spec run, to help surface which specs are running
100
+ # particularly slow.
101
+ config.profile_examples = 10
102
+
103
+ # Run specs in random order to surface order dependencies. If you find an
104
+ # order dependency and want to debug it, you can fix the order by providing
105
+ # the seed, which is printed after each run.
106
+ # --seed 1234
107
+ config.order = :random
108
+
109
+ # Seed global randomization in this process using the `--seed` CLI option.
110
+ # Setting this allows you to use `--seed` to deterministically reproduce
111
+ # test failures related to randomization by passing the same `--seed` value
112
+ # as the one that triggered the failure.
113
+ Kernel.srand config.seed
114
+ =end
115
+ end