lib/sus/it.rb



# frozen_string_literal: true

# Released under the MIT License.
# Copyright, 2021-2024, by Samuel Williams.

require_relative "context"

module Sus
	module It
		def self.build(parent, description = nil, unique: true, &block)
			base = Class.new(parent)
			base.extend(It)
			base.description = description
			base.identity = Identity.nested(parent.identity, base.description, unique: unique)
			base.set_temporary_name("#{self}[#{description}]")
			
			if block_given?
				base.define_method(:call, &block)
			end
			
			return base
		end
		
		def leaf?
			true
		end
		
		def print(output)
			self.superclass.print(output)
			
			output.write(" it ", :it, self.description, :reset, " ", :identity, self.identity.to_s, :reset)
		end
		
		def to_s
			"it #{description}"
		end
		
		def call(assertions)
			assertions.nested(self, identity: self.identity, isolated: true, measure: true) do |assertions|
				instance = self.new(assertions)
				
				instance.around do
					handle_skip(instance, assertions)
				end
			end
		end
		
		def handle_skip(instance, assertions)
			catch(:skip) do
				return instance.call
			end
		end
	end
	
	module Context
		def it(...)
			add It.build(self, ...)
		end
	end
	
	class Base
		# Skip the current test with a reason.
		# @parameter reason [String] The reason for skipping the test.
		def skip(reason)
			@__assertions__.skip(reason)
			throw :skip, reason
		end
		
		def skip_unless_method_defined(method, target)
			unless target.method_defined?(method)
				skip "Method #{method} is not defined in #{target}!"
			end
		end
		
		def skip_unless_constant_defined(constant, target = Object)
			unless target.const_defined?(constant)
				skip "Constant #{constant} is not defined in #{target}!"
			end
		end
		
		def skip_unless_minimum_ruby_version(version)
			unless RUBY_VERSION >= version
				skip "Ruby #{version} is required, but running #{RUBY_VERSION}!"
			end
		end
		
		def skip_if_maximum_ruby_version(version)
			if RUBY_VERSION >= version
				skip "Ruby #{version} is not supported, but running #{RUBY_VERSION}!"
			end
		end
		
		def skip_if_ruby_platform(pattern)
			if match = RUBY_PLATFORM.match(pattern)
				skip "Ruby platform #{match} is not supported!"
			end
		end
	end
end