carbonmu 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.
Files changed (89) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.rspec +2 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +14 -0
  7. data/Gemfile +3 -0
  8. data/Gemfile.lock +161 -0
  9. data/Guardfile +50 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +66 -0
  12. data/Rakefile +10 -0
  13. data/carbonmu.gemspec +64 -0
  14. data/config/i18n-tasks.yml +89 -0
  15. data/config/locales/en.yml +6 -0
  16. data/config/locales/nl.yml +6 -0
  17. data/console +9 -0
  18. data/doc/architecture.png +0 -0
  19. data/lib/carbonmu.rb +42 -0
  20. data/lib/commands/locale_command.rb +12 -0
  21. data/lib/commands/ping_command.rb +9 -0
  22. data/lib/commands/reboot_command.rb +9 -0
  23. data/lib/commands/say_command.rb +10 -0
  24. data/lib/commands/unknown_command.rb +7 -0
  25. data/lib/core/command.rb +26 -0
  26. data/lib/core/command_context.rb +12 -0
  27. data/lib/core/configuration.rb +22 -0
  28. data/lib/core/connection.rb +19 -0
  29. data/lib/core/internationalization.rb +16 -0
  30. data/lib/core/parser.rb +29 -0
  31. data/lib/core/server.rb +118 -0
  32. data/lib/core/server_supervision_group.rb +5 -0
  33. data/lib/core_ext/match_data.rb +7 -0
  34. data/lib/core_ext/string.rb +5 -0
  35. data/lib/edge_router/edge_connection.rb +39 -0
  36. data/lib/edge_router/edge_router.rb +104 -0
  37. data/lib/edge_router/edge_router_supervision_group.rb +5 -0
  38. data/lib/edge_router/telnet_connection.rb +35 -0
  39. data/lib/edge_router/telnet_receptor.rb +30 -0
  40. data/lib/errors.rb +4 -0
  41. data/lib/game_objects/container.rb +10 -0
  42. data/lib/game_objects/exit.rb +8 -0
  43. data/lib/game_objects/game_object.rb +13 -0
  44. data/lib/game_objects/movable.rb +12 -0
  45. data/lib/game_objects/player.rb +17 -0
  46. data/lib/game_objects/room.rb +16 -0
  47. data/lib/game_objects/thing.rb +7 -0
  48. data/lib/interactions/notify.rb +11 -0
  49. data/lib/interactions/reboot.rb +8 -0
  50. data/lib/ipc/carbon_ipc_socket.rb +21 -0
  51. data/lib/ipc/ipc_message.rb +54 -0
  52. data/lib/ipc/read_socket.rb +18 -0
  53. data/lib/ipc/write_socket.rb +12 -0
  54. data/lib/version.rb +7 -0
  55. data/mongoid.yml +12 -0
  56. data/spec/carbonmu_spec.rb +14 -0
  57. data/spec/i18n_spec.rb +18 -0
  58. data/spec/lib/commands/say_command_spec.rb +11 -0
  59. data/spec/lib/core/command_context_spec.rb +16 -0
  60. data/spec/lib/core/command_spec.rb +37 -0
  61. data/spec/lib/core/configuration_spec.rb +37 -0
  62. data/spec/lib/core/connection_spec.rb +46 -0
  63. data/spec/lib/core/internationalization_spec.rb +24 -0
  64. data/spec/lib/core/parser_spec.rb +30 -0
  65. data/spec/lib/core/server_spec.rb +35 -0
  66. data/spec/lib/edge_router/edge_connection_spec.rb +9 -0
  67. data/spec/lib/game_objects/container_spec.rb +9 -0
  68. data/spec/lib/game_objects/exit_spec.rb +7 -0
  69. data/spec/lib/game_objects/game_object_spec.rb +12 -0
  70. data/spec/lib/game_objects/movable_spec.rb +9 -0
  71. data/spec/lib/game_objects/player_spec.rb +24 -0
  72. data/spec/lib/game_objects/room_spec.rb +20 -0
  73. data/spec/lib/game_objects/thing_spec.rb +7 -0
  74. data/spec/lib/interactions/notify_spec.rb +26 -0
  75. data/spec/lib/interactions/reboot_spec.rb +9 -0
  76. data/spec/lib/ipc/carbon_ipc_socket_spec.rb +12 -0
  77. data/spec/lib/ipc/ipc_message_spec.rb +39 -0
  78. data/spec/lib/ipc/read_socket_spec.bak +51 -0
  79. data/spec/lib/ipc/write_socket_spec.bak +25 -0
  80. data/spec/spec_helper.rb +118 -0
  81. data/spec/support/helpers.rb +15 -0
  82. data/spec/support/matchers/be_boolean.rb +5 -0
  83. data/spec/support/shared_examples/carbon_ipc_socket.rb +3 -0
  84. data/spec/support/shared_examples/container.rb +3 -0
  85. data/spec/support/shared_examples/game_object.rb +6 -0
  86. data/spec/support/shared_examples/movable.rb +4 -0
  87. data/start +5 -0
  88. data/start-server-only +8 -0
  89. metadata +416 -0
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ describe Connection do
4
+ let(:id) { "foo" }
5
+ let(:connection) { Connection.new(id) }
6
+ let(:message) { "Watson, come here" }
7
+ let(:expected_sent_message) { "Watson, come here\n"}
8
+ let(:player) { double(Player) }
9
+
10
+ context ".id" do
11
+ it "has an ID" do
12
+ expect(connection.id).to eq(id)
13
+ end
14
+
15
+ it "won't let you set the ID" do
16
+ expect { connection.id = id }.to raise_exception(NameError)
17
+ end
18
+ end
19
+
20
+ context ".locale" do
21
+ it "has a locale" do
22
+ expect(connection.locale).to eq("en")
23
+ end
24
+
25
+ it "lets you set the locale" do
26
+ c = Connection.new(id)
27
+ c.locale = "nl"
28
+ expect(c.locale).to eq("nl")
29
+ end
30
+ end
31
+
32
+ context ".write_translated" do
33
+ it "sends .write to CarbonMU.server" do
34
+ expect(I18n).to receive(:t) { message }
35
+ server = stub_carbonmu_server
36
+ expect(server).to receive(:write_to_connection).with(id, expected_sent_message)
37
+ connection.write_translated(message)
38
+ end
39
+ end
40
+
41
+ context ".player" do
42
+ it "is nil for new connections" do
43
+ expect(connection.player).to eq(nil)
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,24 @@
1
+ require "spec_helper"
2
+
3
+ describe Internationalization do
4
+
5
+ context ".setup" do
6
+ include FakeFS::SpecHelpers
7
+
8
+ it "loads the right loadpath" do
9
+ FileUtils.mkdir_p("config/locales")
10
+ FileUtils.touch("config/locales/boo.yml")
11
+ CarbonMU::Internationalization.setup
12
+ expect(I18n.load_path).to eq(["/config/locales/boo.yml"])
13
+ end
14
+ end
15
+
16
+ context ".translate" do
17
+ it "calls I18n.t" do
18
+ str = "foo"
19
+ opts = {foo: "bar"}
20
+ expect(I18n).to receive(:t).with(str, [opts])
21
+ CarbonMU::Internationalization.translate(str, opts)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe Parser do
4
+ class ParseTestCommand < Command
5
+ syntax "testing_good_command"
6
+ end
7
+
8
+ let (:connection) { double(Connection).as_null_object }
9
+
10
+ context '.parse_and_execute' do
11
+ it "handles a bad command" do
12
+ expect_any_instance_of(UnknownCommand).to receive(:execute)
13
+
14
+ subject.parse_and_execute(connection, "DEFINITELY_NEVER_GOING_TO_BE_A_GOOD_COMMAND")
15
+ end
16
+
17
+ it "calls .execute on a good command" do
18
+ expect_any_instance_of(ParseTestCommand).to receive(:execute)
19
+ subject.parse_and_execute(connection, "testing_good_command")
20
+ end
21
+ end
22
+
23
+ context '.register_syntax' do
24
+ it "remembers a given syntax and class" do
25
+ class TestEmptyClass; end
26
+ Parser.register_syntax("foo", TestEmptyClass)
27
+ expect(Parser.syntaxes["foo"]).to eq(TestEmptyClass)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe Server do
4
+ context "minimal objects" do
5
+ it "should create the starter Room" do
6
+ r = Room.where(_special: :starting_room).first
7
+ expect(r.class).to eq(Room)
8
+ expect(r.name).to eq("Starting Room")
9
+ expect(r.description).to eq("This is the starting room for newly-created players. Feel free to rename and re-describe it.")
10
+ end
11
+
12
+ it "should create the lost & found Room" do
13
+ r = Room.where(_special: :lostandfound_room).first
14
+ expect(r.class).to eq(Room)
15
+ expect(r.name).to eq("Lost & Found Room")
16
+ expect(r.description).to eq("This is the room where objects and players go if the thing that was holding them gets destroyed.")
17
+ end
18
+
19
+ it "should create the superadmin player" do
20
+ p = Player.where(_special: :superadmin_player).first
21
+ expect(p.class).to eq(Player)
22
+ expect(p.name).to eq("Superadmin")
23
+ expect(p.description).to eq("Obviously the most powerful of his race, it could kill us all.")
24
+ end
25
+ end
26
+
27
+ context "connections" do
28
+ it "temporarily should set new connections to be the super-admin" do #TODO
29
+ s = Server.new(true)
30
+ s.add_connection(1)
31
+ c = s.connections.first
32
+ expect(c.player).to eq(Player.superadmin)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe EdgeConnection do
4
+ it "has a unique id" do
5
+ c1 = EdgeConnection.new
6
+ c2 = EdgeConnection.new
7
+ expect(c1.id).to_not eq(c2)
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ class MyContainer
4
+ include Container
5
+ end
6
+
7
+ describe MyContainer do
8
+ it_behaves_like "a Container"
9
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Exit do
4
+ it_behaves_like "a GameObject or descendant"
5
+ it_behaves_like "a Movable"
6
+ it { is_expected.to belong_to(:destination).of_type(Exit).as_inverse_of(:incoming_exits).with_index }
7
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe GameObject do
4
+ it_behaves_like "a GameObject or descendant"
5
+
6
+ context ".description" do
7
+ it "has a default description" do
8
+ g = GameObject.new
9
+ expect(g.description).to eq("You see nothing special.")
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ class MyMovable
4
+ include Movable
5
+ end
6
+
7
+ describe MyMovable do
8
+ it_behaves_like "a Movable"
9
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Player do
4
+ it_behaves_like "a GameObject or descendant"
5
+ it_behaves_like "a Movable"
6
+ it_behaves_like "a Container"
7
+
8
+ it "gets a location of the starter room if not otherwise specified" do
9
+ p = Player.create!(location: nil)
10
+ expect(p.location).to eq(Room.starting)
11
+ end
12
+
13
+ it "still can be given a location" do
14
+ r = Room.create!
15
+ p = Player.create!(location: r)
16
+ expect(p.location).to eq(r)
17
+ end
18
+
19
+ context ".superadmin" do
20
+ it "returns the actual superadmin player" do
21
+ expect(Player.superadmin._special).to eq(:superadmin_player)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe Room do
4
+ it_behaves_like "a GameObject or descendant"
5
+ it_behaves_like "a Container"
6
+
7
+ it { is_expected.to have_many(:incoming_exits).of_type(Exit).with_foreign_key(:destination) }
8
+
9
+ context ".starting" do
10
+ it "returns the actual starting room" do
11
+ expect(Room.starting._special).to eq(:starting_room)
12
+ end
13
+ end
14
+
15
+ context ".lostandfound" do
16
+ it "returns the actual lost & found room" do
17
+ expect(Room.lostandfound._special).to eq(:lostandfound_room)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Thing do
4
+ it_behaves_like "a GameObject or descendant"
5
+ it_behaves_like "a Movable"
6
+ it_behaves_like "a Container"
7
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Notify do
4
+ before(:each) do
5
+ @server = stub_carbonmu_server
6
+ allow(@server).to receive(:connections) { [connection1, connection2] }
7
+ end
8
+
9
+ let(:connection1) { double(Connection) }
10
+ let(:connection2) { double(Connection) }
11
+
12
+ context '.all' do
13
+ it "writes to all connections with the input specified" do
14
+ expect(connection1).to receive(:write_translated).with("foo", {})
15
+ expect(connection2).to receive(:write_translated).with("foo", {})
16
+ Notify.all("foo")
17
+ end
18
+ end
19
+
20
+ context '.one' do
21
+ it "writes to the connection specified with the input" do
22
+ expect(connection1).to receive(:write_translated).with("foo", {})
23
+ Notify.one(connection1, "foo")
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Reboot do
4
+ it "notifies all of reboot and signals server" do
5
+ expect(Notify).to receive(:all).with(/Rebooting, please wait/)
6
+ expect(Server).to receive(:trigger_reboot)
7
+ Reboot.reboot
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe CarbonIPCSocket do
4
+ it_behaves_like "a CarbonIPCSocket implementation"
5
+
6
+ it "closes a socket if one is defined" do
7
+ sock = CarbonIPCSocket.new
8
+ sock.zmq_socket = double("socket")
9
+ expect(sock.zmq_socket).to receive(:close)
10
+ sock.close
11
+ end
12
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe IPCMessage do
4
+ it "sets its operation properly" do
5
+ ipc = IPCMessage.new(:started)
6
+ expect(ipc.op).to eq(:started)
7
+ end
8
+
9
+ it "supports equality" do
10
+ ipc1 = IPCMessage.new(:write, connection_id: "123", output: "foo")
11
+ ipc2 = IPCMessage.new(:write, connection_id: "123", output: "foo")
12
+ expect(ipc1).to eq(ipc2)
13
+ end
14
+
15
+ it "accepts op parameters" do
16
+ ipc = IPCMessage.new(:write, connection_id: "123", output: "foo")
17
+ expect(ipc.params[:connection_id]).to eq("123")
18
+ expect(ipc.params[:output]).to eq("foo")
19
+ end
20
+
21
+ it "supports direct method access for op parameters" do
22
+ ipc = IPCMessage.new(:write, connection_id: "123", output: "foo")
23
+ expect(ipc.params[:connection_id]).to eq(ipc.connection_id)
24
+ end
25
+
26
+ it "enforces required op parameters" do
27
+ expect { IPCMessage.new(:write, connection_id: '123') }.to raise_error(ArgumentError,/output/)
28
+ end
29
+
30
+ it "raises if given an unknown op" do
31
+ expect { IPCMessage.new(:definitely_not_a_good_op) }.to raise_error(ArgumentError,/definitely_not_a_good_op/)
32
+ end
33
+
34
+ it "knows how to serialize and unserialize itself" do
35
+ original = IPCMessage.new(:write, connection_id: "123", output: "foo")
36
+ round_trip = IPCMessage.unserialize(original.serialize)
37
+ expect(round_trip).to eq(original)
38
+ end
39
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe ReadSocket do
4
+ it_behaves_like "a CarbonIPCSocket implementation"
5
+
6
+ it "raises on send(msg)" do
7
+ expect { ReadSocket.new.send('foo') }.to raise_error(NotImplementedError)
8
+ end
9
+
10
+ it "reads from the underlying socket" do
11
+ sock = ReadSocket.new
12
+ sock.zmq_socket = double("zmq")
13
+ sock.zmq_socket.should_receive(:read)
14
+ sock.read
15
+ end
16
+
17
+ it "attempts to BIND to tcp://127.0.0.1:<specified port>" do
18
+ port_number = rand(10000..20000)
19
+ zmqsocket = double("zmqsocket")
20
+ zmqsocket.stub(:connect).with(anything)
21
+ zmqsocket.should_receive(:bind).with("tcp://127.0.0.1:#{port_number}")
22
+ Celluloid::ZMQ::PullSocket.stub(:new) { zmqsocket }
23
+ ReadSocket.new(port_number)
24
+ end
25
+
26
+ it "knows its own port number" do
27
+ port_number = rand(10000..20000)
28
+ r = ReadSocket.new(port_number)
29
+ r.port_number.should eq(port_number)
30
+ end
31
+
32
+ context "ephemeral ports" do
33
+ it "supports binding to an ephemeral port" do
34
+ zmqsocket = double("zmqsocket")
35
+ zmqsocket.stub(:bind).with(anything)
36
+ zmqsocket.should_receive(:bind).with("tcp://127.0.0.1:*")
37
+ Celluloid::ZMQ::PullSocket.stub(:new) { zmqsocket }
38
+ ReadSocket.new
39
+ end
40
+
41
+ it "returns a valid port number when bound to an ephemeral port" do
42
+ ReadSocket.new.port_number.should be_between(1024,65535)
43
+ end
44
+
45
+ it "returns a different port number on successive instantiations" do
46
+ r1 = ReadSocket.new
47
+ r2 = ReadSocket.new
48
+ r1.port_number.should_not eq(r2.port_number)
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe WriteSocket do
4
+ it_behaves_like "a CarbonIPCSocket implementation"
5
+
6
+ it "raises on read" do
7
+ expect { WriteSocket.new.read }.to raise_error(NotImplementedError)
8
+ end
9
+
10
+ it "writes to the underlying socket" do
11
+ sock = WriteSocket.new
12
+ sock.zmq_socket = double("zmq")
13
+ expect(sock.zmq_socket).to receive(:send).with("foo")
14
+ sock.send("foo")
15
+ end
16
+
17
+ it "attempts to CONNECT to tcp://127.0.0.1:<specified port>" do
18
+ port_number = rand(10000..20000)
19
+ zmqsocket = double("zmqsocket")
20
+ allow(zmqsocket).to receive(:bind)
21
+ expect(zmqsocket).to receive(:connect).with("tcp://127.0.0.1:#{port_number}")
22
+ allow(Celluloid::ZMQ::PushSocket).to receive(:new) { zmqsocket }
23
+ WriteSocket.new(port_number)
24
+ end
25
+ end
@@ -0,0 +1,118 @@
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
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
4
+ # this file to always be loaded, without a need to explicitly require it in any
5
+ # files.
6
+ #
7
+ # Given that it is always loaded, you are encouraged to keep this file as
8
+ # light-weight as possible. Requiring heavyweight dependencies from this file
9
+ # will add to the boot time of your test suite on EVERY test run, even for an
10
+ # individual file that may not need all of that loaded. Instead, consider making
11
+ # a separate helper file that requires the additional dependencies and performs
12
+ # the additional setup, and require it from the spec files that actually need
13
+ # it.
14
+ #
15
+ # The `.rspec` file also contains a few flags that are not defaults but that
16
+ # users commonly want.
17
+
18
+ ENV['MONGOID_ENV'] = "testing"
19
+
20
+ require 'bundler'
21
+ require 'timecop'
22
+ require_relative '../lib/carbonmu.rb'
23
+ require 'pry'
24
+ require 'mongoid-rspec'
25
+ require 'database_cleaner'
26
+ require 'fakefs/spec_helpers'
27
+
28
+ Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
29
+
30
+ include CarbonMU
31
+ CarbonMU.configure do |c|
32
+ c.logger = Logger.new(nil)
33
+ end
34
+
35
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
36
+ RSpec.configure do |config|
37
+ config.filter_run_excluding :i18n => true
38
+ config.raise_errors_for_deprecations!
39
+ config.include Helpers
40
+ config.include Mongoid::Matchers
41
+
42
+ config.before(:suite) do
43
+ Server.initialize_database
44
+ DatabaseCleaner.strategy = :truncation
45
+ DatabaseCleaner.clean
46
+ end
47
+
48
+ config.around(:each) do |example|
49
+ DatabaseCleaner.cleaning do
50
+ Server.create_starter_objects
51
+ example.run
52
+ end
53
+ end
54
+
55
+
56
+ # rspec-expectations config goes here. You can use an alternate
57
+ # assertion/expectation library such as wrong or the stdlib/minitest
58
+ # assertions if you prefer.
59
+ config.expect_with :rspec do |expectations|
60
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
61
+ end
62
+
63
+ # rspec-mocks config goes here. You can use an alternate test double
64
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
65
+ config.mock_with :rspec do |mocks|
66
+ # Prevents you from mocking or stubbing a method that does not exist on
67
+ # a real object. This is generally recommended, and will default to
68
+ # `true` in RSpec 4.
69
+ mocks.verify_partial_doubles = true
70
+ end
71
+
72
+ # The settings below are suggested to provide a good initial experience
73
+ # with RSpec, but feel free to customize to your heart's content.
74
+ # These two settings work together to allow you to limit a spec run
75
+ # to individual examples or groups you care about by tagging them with
76
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
77
+ # get run.
78
+ config.filter_run :focus
79
+ config.run_all_when_everything_filtered = true
80
+
81
+ # Limits the available syntax to the non-monkey patched syntax that is
82
+ # recommended. For more details, see:
83
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
84
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
85
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
86
+ # config.disable_monkey_patching!
87
+
88
+ # This setting enables warnings. It's recommended, but in some cases may
89
+ # be too noisy due to issues in dependencies.
90
+ config.warnings = false
91
+
92
+ # Many RSpec users commonly either run the entire suite or an individual
93
+ # file, and it's useful to allow more verbose output when running an
94
+ # individual spec file.
95
+ if config.files_to_run.one?
96
+ # Use the documentation formatter for detailed output,
97
+ # unless a formatter has already been configured
98
+ # (e.g. via a command-line flag).
99
+ config.default_formatter = 'doc'
100
+ end
101
+
102
+ # Print the 10 slowest examples and example groups at the
103
+ # end of the spec run, to help surface which specs are running
104
+ # particularly slow.
105
+ # config.profile_examples = 10
106
+
107
+ # Run specs in random order to surface order dependencies. If you find an
108
+ # order dependency and want to debug it, you can fix the order by providing
109
+ # the seed, which is printed after each run.
110
+ # --seed 1234
111
+ config.order = :random
112
+
113
+ # Seed global randomization in this process using the `--seed` CLI option.
114
+ # Setting this allows you to use `--seed` to deterministically reproduce
115
+ # test failures related to randomization by passing the same `--seed` value
116
+ # as the one that triggered the failure.
117
+ Kernel.srand config.seed
118
+ end