diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..b3687c2 --- /dev/null +++ b/Gemfile @@ -0,0 +1,2 @@ +gem sinatra +gem sinatra-cross_origin diff --git a/README.md b/README.md index c52a33e..25a17e4 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ -# Goals: +# Note +This is now directed at the `src` folder. The `game` folder is old code and is +kept for example stuff. + +# Goals: Make a multiplayer game that will run in the browser. This game should be a planet conquest type game where you can create a lobby and then players can @@ -43,11 +47,12 @@ I do eventually want to have AI players however for now I just want human players. Make sure that you help me to keep this easy as I am programming. Here are the resources that I am thinking of for now: - - Food - - Metal - - Fuel/energy - - Crystals - - Galaxy Credits (Universal money) + - Food (Local to planet) + - Energy (Local to planet) + - Metal (Global) + - Fuel (Global) + - Crystals (Global) + - Galaxy Credits (Global) How do we have resources travel be tween planets? I am not sure yet. Maybe have diff --git a/core/.rspec b/core/.rspec new file mode 100644 index 0000000..c99d2e7 --- /dev/null +++ b/core/.rspec @@ -0,0 +1 @@ +--require spec_helper diff --git a/core/Rakefile b/core/Rakefile new file mode 100644 index 0000000..04f0ae6 --- /dev/null +++ b/core/Rakefile @@ -0,0 +1,34 @@ +# Nathan Hinton 2 Oct 2025 +# Rake file + + +desc 'Run RSpec tests' +task :test do + begin + require 'rspec/core/rake_task' + RSpec::Core::RakeTask.new(:spec) + Rake::Task['spec'].invoke + rescue LoadError + puts 'Failed to load RSpec to run tests... Try installing rspec' + end +end + + +desc 'Run the server for clients to connect to' +task :serve do + raise NotImplementedError.new('Server task not yet implimented!') +end + + +namespace :doc do + desc 'Create the YARD documentation for the project' + task :yard do + res = sh 'yard doc *.rb' + sh 'yard stats *.rb --list-undoc' + end + + desc 'Create code coverage' + task :coverage do + Rake::Task[:test].invoke + end +end diff --git a/core/building.rb b/core/building.rb new file mode 100644 index 0000000..e3924bb --- /dev/null +++ b/core/building.rb @@ -0,0 +1,47 @@ +# Nathan Hinton 19 Dec 2025 + + +require './space_object' + + +# This class is for buildings that are built on a planet. Currently it +# inherrits the SpaceObject class however it should probably inherrit a class +# that is for planets. +class Building] List of planets captured by that player + def get_captured_planets(id) + player = check_id(id) + result = [] + @planets.each do |planet| + result.append(planet) if planet.owner == player + end + return result + end + + # Returns a string representation of the map + # Begin no coverage + # :nocov: + def to_s() + # Create char map: + game_map = [] + @height.times do + tmp = [] + @width.times do + tmp.append('') + end + game_map.append(tmp) + end + + # Add planets to the map: + @planets.each do |planet| + pos_x, pos_y, pos_z = planet.position + puts("x: #{pos_x}, y: #{pos_y}") + game_map[pos_y][pos_x] += 'p' + end + + require 'pp' + pp(game_map) + game_map.each do |row| + row.each do |col| + if col == '' + print(' ') + else + print(col) + end + end + print("\n") + end + end + # :nocov: + # End no coverage + +end + +# General game errors +class GameError 0, + 'energy' => 0, + 'people' => 10 + } + + end + + # Any clean up that the planet will need + def delete() + end + + # Build a building on the planet + # + # @param building [Building] The building to be built + def building_build(building) + @buildings.append(building) + end + + # Remove building from the planet + # + # @param building [Building] The building to be destroyed + def building_destroy(building) + index = @buildings.index(building) + if index == nil + raise PlanetError, 'Building not found to delete' + end + @buildings.delete_at(index) + end + + # Capture a planet for a player + # + # @param player [Player] The player who is capturing the planet + def capture(player) + @buildings = [] # Destroy all the buildings on the planet + @owner = player + end + + # Tick for the planet + def tick() + @buildings.each do |building| + building.tick + end + end +end + +# Generic error for plannets +class PlanetError < StandardError +end diff --git a/core/player.rb b/core/player.rb new file mode 100644 index 0000000..4545477 --- /dev/null +++ b/core/player.rb @@ -0,0 +1,43 @@ +# Nathan Hinton 19 Dec 2025 + + +require 'securerandom' + +# This defines the player class +class Player + attr_reader :name, :resources, :id + + attr_accessor :home_planet + + # initialize a player. + # + # @param name [String] The name of the player + def initialize(name: 'test player') + @name = name + @planets = [] + @fleets = [] + @tech = [] + @resources = { + 'metal' => 0, + 'crystals' => 0, + 'credits' => 0 + } + # This id will be used to validate the player in the game + @id = SecureRandom.hex() + @id_retrieved = false + + @home_planet = nil + end + + # Returns the player ID. This *should* only be called once. When called again + # it should print a warning to the log. + # + # @return [String] The ID of the player + def get_id + if @id_retrieved + # Print a warning message! + end + @id_retrieved = true + return @id + end +end diff --git a/core/readme.md b/core/readme.md new file mode 100644 index 0000000..c544ffb --- /dev/null +++ b/core/readme.md @@ -0,0 +1,6 @@ +# Core of game + +This will have the classes and a base loop however it will not do anything more +than just store stuff I think. + +For now only the x and y cords are used. diff --git a/core/server.rb b/core/server.rb new file mode 100644 index 0000000..5a2366c --- /dev/null +++ b/core/server.rb @@ -0,0 +1,55 @@ +# Nathan Hinton 19 Dec 2025 +# Runs the server for the game + +require 'sinatra' +require 'sinatra/cross_origin' +require 'json' + +require './game' + +configure do + enable :cross_origin +end + +# CORS headers for all routes +before do + headers 'Access-Control-Allow-Origin' => '*', # Allow all domains (you can change '*' to a specific domain for security) + 'Access-Control-Allow-Methods' => 'GET, POST, OPTIONS', # Allow only specific methods + 'Access-Control-Allow-Headers' => 'Content-Type, Authorization' +end + + +games = {} + + +# Get the server status +get '/status' do + return 'UP' +end + +# Creates a new game +# +# @param name [String] Required. The name of the game +# @param width [Integer] The width of the game space +# @param height [Integer] The height of the game space +# @param planets [Integer] The number of planets to have in the game +get '/create_game' do + puts "Creating game named #{params['name']}" + name = params['name'] + width = params['width'] || 10 + width = width.to_i + height = params['height'] || 10 + height = height.to_i + planets = params['planets'] || 20 + planets = planets.to_i + games.update({name => Game.new(width: width, height: height, planets: planets, name: name)}) + return 'OK' +end + + +# Gets games available +# +# @return [Array] list of game names +get '/list_games' do + return games.keys.to_json +end diff --git a/core/space_object.rb b/core/space_object.rb new file mode 100644 index 0000000..5f08ba8 --- /dev/null +++ b/core/space_object.rb @@ -0,0 +1,47 @@ +# Nathan Hinton 19 Dec 2025 + + +require 'yaml' + +# Base class for any object in space. This can be a planet, asteroid, ship etc. +class SpaceObject + attr_reader :position + + File.open('./config.yaml', 'r') do |fi| + @@config = YAML.safe_load(fi.read()) + end + + # Create the object + # + def initialize() + @position = [0, 0, 0] + end + + # Delete the object. This should be overwritten by the sub objects. For + # example when an asteroid is destroyed it might want to explode and damage + # anything nearby first before being removed from the game. This is the path + # that will be used for that. + def delete() + end + + # Move the object to a new position. Not everything should be movable so this + # can be disallowed by sub classes. + # + # @param position [Array] The position that the object should be + # moved to. + def move(position) + @position = position + end + + # This *should* be overridden by any object that wants to do anyting. For + # example a ship probaly would like to move when the game tick happens. + def tick() + end + + # Define a method to get the config + # + # @return [Hash] A hash containing the configuration + def get_config() + return @@config + end +end diff --git a/core/spec/building_spec.rb b/core/spec/building_spec.rb new file mode 100644 index 0000000..d88cbe0 --- /dev/null +++ b/core/spec/building_spec.rb @@ -0,0 +1,74 @@ +# Nathan Hinton 19 Dec 2025 + +# Defines tests for the buildings + + +require './building' +require './player' +require './planet' +require './space_object' + +RSpec.describe Building do + describe '#initialize' do + it 'Initializes to defaults' do + building = Building.new(Player.new(), Planet.new()) + expect(building.name).to eq 'default name' + expect(building.type).to eq 'Central Post' + end + + it 'initializes with custom values' do + building = Building.new(Player.new(), Planet.new(), name: 'nathan house', type: 'Solar Farm') + expect(building.name).to eq 'nathan house' + expect(building.type).to eq 'Solar Farm' + end + + it 'will raise error when invalid building type' do + expect{Building.new(Player.new(), Planet.new(), name: 'error', type: 'error')}.to raise_error BuildingError, "Invalid building type" + end + end + + describe '#tick' do + it 'Adds resources to the player' do + player = Player.new() + planet = Planet.new() + type = 'Central Post' + building = Building.new(player, planet, type: type) + config = SpaceObject.new().get_config + metal = config['buildings'][type]['produces']['metal'] + credits = config['buildings'][type]['produces']['credits'] + crystals = config['buildings'][type]['produces']['crystals'] + expect(player.resources).to eq({'metal' => 0, 'crystals' => 0, 'credits' => 0}) + expect{building.tick}.to_not raise_error + expect(player.resources).to eq({ + 'metal' => metal, + 'crystals' => crystals, + 'credits' => credits + }) + expect(planet.resources).to eq({ + 'food' => 0, + 'energy' => 0, + 'people' => 10 + }) + end + + it 'Adds resources to the planet' do + player = Player.new() + planet = Planet.new() + type = 'Nuclear Plant' + building = Building.new(player, planet, type: type) + config = SpaceObject.new().get_config + expect(player.resources).to eq({'metal' => 0, 'crystals' => 0, 'credits' => 0}) + expect{building.tick}.to_not raise_error + expect(player.resources).to eq({ + 'metal' => 0, + 'crystals' => 0, + 'credits' => 0 + }) + expect(planet.resources).to eq({ + 'food' => 0, + 'energy' => 1000, + 'people' => 10 + }) + end + end +end diff --git a/core/spec/examples.txt b/core/spec/examples.txt new file mode 100644 index 0000000..2878b6f --- /dev/null +++ b/core/spec/examples.txt @@ -0,0 +1,34 @@ +example_id | status | run_time | +---------------------------------- | ------ | --------------- | +./spec/building_spec.rb[1:1:1] | passed | 0.00024 seconds | +./spec/building_spec.rb[1:1:2] | passed | 0.00044 seconds | +./spec/building_spec.rb[1:1:3] | passed | 0.00059 seconds | +./spec/building_spec.rb[1:2:1] | passed | 0.00024 seconds | +./spec/building_spec.rb[1:2:2] | passed | 0.00208 seconds | +./spec/game_spec.rb[1:1:1] | passed | 0.00011 seconds | +./spec/game_spec.rb[1:1:2] | passed | 0.00011 seconds | +./spec/game_spec.rb[1:1:3] | passed | 0.00011 seconds | +./spec/game_spec.rb[1:1:4] | passed | 0.00014 seconds | +./spec/game_spec.rb[1:2:1] | passed | 0.00014 seconds | +./spec/game_spec.rb[1:2:2] | passed | 0.00016 seconds | +./spec/game_spec.rb[1:3:1] | passed | 0.00019 seconds | +./spec/game_spec.rb[1:3:2] | passed | 0.00026 seconds | +./spec/game_spec.rb[1:4:1] | passed | 0.00013 seconds | +./spec/game_spec.rb[1:4:2] | passed | 0.00016 seconds | +./spec/game_spec.rb[1:5:1] | passed | 0.00016 seconds | +./spec/planet_spec.rb[1:1:1] | passed | 0.00018 seconds | +./spec/planet_spec.rb[1:1:2] | passed | 0.00013 seconds | +./spec/planet_spec.rb[1:3:1] | passed | 0.00015 seconds | +./spec/planet_spec.rb[1:4:1] | passed | 0.00018 seconds | +./spec/planet_spec.rb[1:4:2] | passed | 0.00021 seconds | +./spec/planet_spec.rb[1:5:1] | passed | 0.00168 seconds | +./spec/planet_spec.rb[1:5:2] | passed | 0.00039 seconds | +./spec/planet_spec.rb[1:6:1] | passed | 0.00873 seconds | +./spec/player_spec.rb[1:1:1] | passed | 0.00035 seconds | +./spec/player_spec.rb[1:2:1] | passed | 0.00052 seconds | +./spec/player_spec.rb[1:2:2] | passed | 0.00044 seconds | +./spec/simple_game_spec.rb[1:1] | passed | 0.00956 seconds | +./spec/space_object_spec.rb[1:1:1] | passed | 0.00012 seconds | +./spec/space_object_spec.rb[1:3:1] | passed | 0.00023 seconds | +./spec/space_object_spec.rb[1:4:1] | passed | 0.00013 seconds | +./spec/space_object_spec.rb[1:6:1] | passed | 0.00012 seconds | diff --git a/core/spec/game_spec.rb b/core/spec/game_spec.rb new file mode 100644 index 0000000..c182da9 --- /dev/null +++ b/core/spec/game_spec.rb @@ -0,0 +1,87 @@ +# Nathan Hinton 19 Dec 2025 + + +require './game' +require './player' + +RSpec.describe Game do + describe '#initialize' do + it 'Creates an empty list of players' do + expect(Game.new().players).to eq [] + end + + it 'sets the width when passed in' do + expect(Game.new(width: 10).width).to eq 10 + end + + it 'sets the height when passed in' do + expect(Game.new(height: 11).height).to eq 11 + end + + it 'creates the specified number of planets' do + expect(Game.new(planets: 5).planets.length).to eq 5 + end + end + + + describe '#add_player' do + it 'adds a player to the game' do + game = Game.new(planets: 1) + player = Player.new() + game.add_player(player) + expect(game.players).to eq [player] + end + + it 'fails when there are no planets available for the player' do + game = Game.new(planets: 0) + player = Player.new() + expect{game.add_player(player)}.to raise_error GameError, "No available planets to add player to" + expect(game.players).to eq [] + end + end + + + describe '#remove_player' do + it 'removes a player from the game' do + game = Game.new(planets: 1) + player = Player.new() + game.add_player(player) + expect(game.players).to eq [player] + expect(game.remove_player(player)).to eq player + expect(game.players).to eq [] + end + + it 'returns an error when the player is not in the game' do + game = Game.new(planets: 1) + player = Player.new() + game.add_player(player) + player2 = Player.new() + expect{game.remove_player(player2)}.to raise_error GameError, 'Player not found to remove!' + end + end + + describe '#check_id' do + it 'returns true when the player id is valid for a player' do + game = Game.new(planets: 1) + player = Player.new() + game.add_player(player) + expect(game.check_id(player.get_id)).to eq player + end + + it 'returns false when the player id does not match a player' do + game = Game.new(planets: 1) + player = Player.new() + game.add_player(player) + expect{game.check_id('a')}.to raise_error GameError, 'Invalid player id!' + end + end + + describe '#get_captured_planets' do + it 'returns the captured planets of the player' do + game = Game.new(planets: 1) + player = Player.new() + game.add_player(player) + expect(game.get_captured_planets(player.get_id)).to eq game.instance_variable_get(:@planets) + end + end +end diff --git a/core/spec/planet_spec.rb b/core/spec/planet_spec.rb new file mode 100644 index 0000000..3a0afde --- /dev/null +++ b/core/spec/planet_spec.rb @@ -0,0 +1,95 @@ +# Nathan Hinton 19 Dec 2025 +# +# Defines tests for the planets + + +require './planet' +require './building' + +RSpec.describe Planet do + describe '#initialize' do + it 'Starts in a position' do + expect(Planet.new().instance_variable_get(:@position)).to eq [0, 0, 0] + end + + it 'Creates a buildings list' do + expect(Planet.new().instance_variable_get(:@buildings)).to eq [] + end + end + + + describe '#delete' do + end + + + describe '#building_build' do + it 'Adds a building to the planet building list' do + planet = Planet.new() + test_building = Building.new(Player.new(), planet) + expect{planet.building_build(test_building)}.to_not raise_error + expect(planet.instance_variable_get(:@buildings)).to eq [test_building] + end + end + + + describe '#building_destroy' do + it 'removes a building from the list' do + planet = Planet.new() + test_building = Building.new(Player.new(), planet) + planet.building_build(test_building) + expect(planet.instance_variable_get(:@buildings)).to eq [test_building] + expect(planet.building_destroy(test_building)).to eq test_building + expect(planet.instance_variable_get(:@buildings)).to eq [] + end + + it 'raises an error if the building can not be removed' do + planet = Planet.new() + test_building = Building.new(Player.new(), planet) + planet.building_build(test_building) + test_building2 = Building.new(Player.new(), planet) + expect{planet.building_destroy(test_building2)}.to raise_error PlanetError, 'Building not found to delete' + end + end + + + describe '#capture' do + it 'sets the planet owner' do + planet = Planet.new() + player = Player.new(name: 'test0') + expect(planet.capture(player)).to be player + expect(planet.instance_variable_get(:@owner)).to be player + end + + it 'removes all buildings from the planet' do + planet = Planet.new() + player = Player.new(name: 'test0') + planet.capture(player) + test_building = Building.new(player, planet) + planet.building_build(test_building) + + player1 = Player.new(name: 'test1') + expect(planet.instance_variable_get(:@buildings)).to eq [test_building] + expect(planet.capture(player1)).to be player1 + expect(planet.instance_variable_get(:@owner)).to be player1 + expect(planet.instance_variable_get(:@buildings)).to eq [] + end + end + + + describe '#tick' do + it 'Sends the tick event to all buildings on the planet' do + planet = Planet.new() + test_building1 = Building.new(Player.new(), planet) + test_building2 = Building.new(Player.new(), planet) + test_building3 = Building.new(Player.new(), planet) + planet.building_build(test_building1) + planet.building_build(test_building2) + planet.building_build(test_building3) + + expect(test_building1).to receive(:tick) + expect(test_building2).to receive(:tick) + expect(test_building3).to receive(:tick) + expect(planet.tick).to eq planet.instance_variable_get(:@buildings) + end + end +end diff --git a/core/spec/player_spec.rb b/core/spec/player_spec.rb new file mode 100644 index 0000000..fdc8310 --- /dev/null +++ b/core/spec/player_spec.rb @@ -0,0 +1,51 @@ +# Nathan Hinton 19 Dec 2025 +# Test file for the player class. + + +require 'securerandom' + +require './player' + +RSpec.describe Player do + # Set the testing id + let(:id) { 'cfeab1a60864fd529cb9ce993e9c3af4' } + + before(:each) do + # Make sure that we get the same ID every time. + allow(SecureRandom).to receive(:hex).and_return(id) + end + + describe '#initialize' do + it 'initializes with name' do + expect(Player.new(name: 'Nathan').name).to eq 'Nathan' + end + end + + describe '#get_id' do + it 'returns the id' do + player = Player.new() + expect(player.instance_variable_get(:@id_retrieved)).to be false + expect(player.get_id).to eq id + expect(player.instance_variable_get(:@id_retrieved)).to be true + end + + it 'prints a warning when the id is gotten more than once' do + player = Player.new() + player.get_id + expect(player.instance_variable_get(:@id_retrieved)).to be true + expect(player.get_id).to eq id + expect(player.instance_variable_get(:@id_retrieved)).to be true + end + end + + describe '#planets' do + end + + + describe '#fleets', pending: 'Ships not yet implimented' do + end + + + describe '#tech', pending: 'Tech not yet implimented' do + end +end diff --git a/core/spec/simple_game_spec.rb b/core/spec/simple_game_spec.rb new file mode 100644 index 0000000..c53361a --- /dev/null +++ b/core/spec/simple_game_spec.rb @@ -0,0 +1,23 @@ +# Nathan Hinton 19 Dec 2025 + + +require './player' +require './game' + + +# This tests a simple game. +RSpec.describe 'Simple game', :sim => true do + it 'Initalize a new game and add a player' do + # Setup the player + player = Player.new() + id = player.get_id + expect(player.resources).to eq({'metal' => 0, 'crystals' => 0, 'galaxy credits' => 0}) + + # Setup the start planet + game = Game.new(width: 5, height: 5, planets: 5) + expect(game.planets.length).to eq 5 + game.add_player(player) + expect(game.get_captured_planets(id).length).to eq 1 + puts(game) + end +end diff --git a/core/spec/space_object_spec.rb b/core/spec/space_object_spec.rb new file mode 100644 index 0000000..f2b82f2 --- /dev/null +++ b/core/spec/space_object_spec.rb @@ -0,0 +1,47 @@ +# Nathan Hinton 19 Dec 2025 +# +# Defines tests for the space object class + + +require './space_object' + +RSpec.describe SpaceObject do + describe '#initialize' do + it 'works with no args' do + expect(SpaceObject.new().instance_variable_get(:@position)).to eq [0, 0, 0] + end + end + + + describe '#delete' do + end + + + describe '#move' do + let(:so) { SpaceObject.new() } + it 'changes the objects position and returns the new position' do + expect(so.instance_variable_get(:@position)).to eq [0, 0, 0] + expect(so.move([2, 3, 4])).to eq [2, 3, 4] + expect(so.instance_variable_get(:@position)).to eq [2, 3, 4] + end + end + + + describe '#position' do + let(:so) { SpaceObject.new() } + it 'returns the current position' do + so.move([1, 2, 3]) + expect(so.position).to eq [1, 2, 3] + end + end + + + describe '#tick' do + end + + describe '#get_config' do + it 'returns the correct keys' do + expect(SpaceObject.new().get_config.keys).to eq ['planets', 'buildings'] + end + end +end diff --git a/core/spec/spec_helper.rb b/core/spec/spec_helper.rb new file mode 100644 index 0000000..47ee133 --- /dev/null +++ b/core/spec/spec_helper.rb @@ -0,0 +1,109 @@ +require 'simplecov' + +SimpleCov.configure do + coverage_dir 'coverage' + + # Start SimpleCov + SimpleCov.start +end + + +# This file was generated by the `rspec --init` command. Conventionally, all +# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. +# The generated `.rspec` file contains `--require spec_helper` which will cause +# this file to always be loaded, without a need to explicitly require it in any +# files. +# +# Given that it is always loaded, you are encouraged to keep this file as +# light-weight as possible. Requiring heavyweight dependencies from this file +# will add to the boot time of your test suite on EVERY test run, even for an +# individual file that may not need all of that loaded. Instead, consider making +# a separate helper file that requires the additional dependencies and performs +# the additional setup, and require it from the spec files that actually need +# it. +# +# See https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration +RSpec.configure do |config| + # rspec-expectations config goes here. You can use an alternate + # assertion/expectation library such as wrong or the stdlib/minitest + # assertions if you prefer. + config.expect_with :rspec do |expectations| + # This option will default to `true` in RSpec 4. It makes the `description` + # and `failure_message` of custom matchers include text for helper methods + # defined using `chain`, e.g.: + # be_bigger_than(2).and_smaller_than(4).description + # # => "be bigger than 2 and smaller than 4" + # ...rather than: + # # => "be bigger than 2" + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + # rspec-mocks config goes here. You can use an alternate test double + # library (such as bogus or mocha) by changing the `mock_with` option here. + config.mock_with :rspec do |mocks| + # Prevents you from mocking or stubbing a method that does not exist on + # a real object. This is generally recommended, and will default to + # `true` in RSpec 4. + mocks.verify_partial_doubles = true + end + + # This option will default to `:apply_to_host_groups` in RSpec 4 (and will + # have no way to turn it off -- the option exists only for backwards + # compatibility in RSpec 3). It causes shared context metadata to be + # inherited by the metadata hash of host groups and examples, rather than + # triggering implicit auto-inclusion in groups with matching metadata. + config.shared_context_metadata_behavior = :apply_to_host_groups + + # The settings below are suggested to provide a good initial experience + # with RSpec, but feel free to customize to your heart's content. + # This allows you to limit a spec run to individual examples or groups + # you care about by tagging them with `:focus` metadata. When nothing + # is tagged with `:focus`, all examples get run. RSpec also provides + # aliases for `it`, `describe`, and `context` that include `:focus` + # metadata: `fit`, `fdescribe` and `fcontext`, respectively. + config.filter_run_when_matching :focus + + # Allows RSpec to persist some state between runs in order to support + # the `--only-failures` and `--next-failure` CLI options. We recommend + # you configure your source control system to ignore this file. + config.example_status_persistence_file_path = "spec/examples.txt" + + # Limits the available syntax to the non-monkey patched syntax that is + # recommended. For more details, see: + # https://rspec.info/features/3-12/rspec-core/configuration/zero-monkey-patching-mode/ + config.disable_monkey_patching! + + # This setting enables warnings. It's recommended, but in some cases may + # be too noisy due to issues in dependencies. + config.warnings = true + + # Many RSpec users commonly either run the entire suite or an individual + # file, and it's useful to allow more verbose output when running an + # individual spec file. + if config.files_to_run.one? + # Use the documentation formatter for detailed output, + # unless a formatter has already been configured + # (e.g. via a command-line flag). + config.default_formatter = "doc" + end + + # Print the 10 slowest examples and example groups at the + # end of the spec run, to help surface which specs are running + # particularly slow. + config.profile_examples = 10 + + # Run specs in random order to surface order dependencies. If you find an + # order dependency and want to debug it, you can fix the order by providing + # the seed, which is printed after each run. + # --seed 1234 + config.order = :random + + # Seed global randomization in this process using the `--seed` CLI option. + # Setting this allows you to use `--seed` to deterministically reproduce + # test failures related to randomization by passing the same `--seed` value + # as the one that triggered the failure. + Kernel.srand config.seed + + # Exclude by default the simulate tests. + config.filter_run_excluding :sim => true +end