shard-spectator/src/spectator/dsl/structure_dsl.cr

204 lines
5.1 KiB
Crystal
Raw Normal View History

2018-09-15 17:21:23 +00:00
require "../example_group"
module Spectator
module DSL
module StructureDSL
macro describe(what, type = "Describe", &block)
context({{what}}, {{type}}) {{block}}
end
macro context(what, type = "Context", &block)
module {{type.id}}%context
include {{@type.id}}
2018-09-15 17:21:23 +00:00
::Spectator::Definitions::GROUPS[\{{@type.symbolize}}] =
ExampleGroup.new(
{{what.is_a?(StringLiteral) ? what : what.stringify}},
::Spectator::Definitions::GROUPS[{{@type.symbolize}}]
)
2018-09-15 17:21:23 +00:00
2018-09-20 01:29:33 +00:00
{% if what.is_a?(Path) || what.is_a?(Generic) %}
_described_class {{what}}
{% end %}
2018-09-15 17:21:23 +00:00
{{block.body}}
end
end
macro given(collection, &block)
module Given%given
include {{@type.id}}
def %collection
{{collection}}
end
def %first
%collection.first
end
@%wrapper : ValueWrapper
def {{block.args.empty? ? "value".id : block.args.first}}
@%wrapper.as(TypedValueWrapper(typeof(%first))).value
end
def initialize(locals : Hash(Symbol, ValueWrapper))
super
@%wrapper = locals[:%given]
end
_given_collection Collection%collection, %to_a do
2018-09-15 17:21:23 +00:00
{{collection}}
end
%to_a = Collection%collection.new.%to_a
2018-09-15 17:21:23 +00:00
::Spectator::Definitions::GROUPS[\{{@type.symbolize}}] =
GivenExampleGroup(typeof(%to_a.first)).new(
{{collection.stringify}},
%to_a,
:%given,
::Spectator::Definitions::GROUPS[{{@type.symbolize}}]
)
{{block.body}}
end
end
2018-09-15 17:21:23 +00:00
macro _given_collection(class_name, to_a_method_name, &block)
class {{class_name.id}}
include {{@type.id}}
def %collection
{{block.body}}
end
2018-09-15 17:21:23 +00:00
def %first
%collection.first
end
def {{to_a_method_name.id}}
Array(typeof(%first)).new.tap do |%array|
%collection.each do |%item|
%array << %item
end
end
end
2018-09-15 17:21:23 +00:00
end
end
macro subject(&block)
let(:subject) {{block}}
end
macro let(name, &block)
let!(%value) {{block}}
@%wrapper : ValueWrapper?
def {{name.id}}
if (wrapper = @%wrapper)
wrapper.unsafe_as(TypedValueWrapper(typeof(%value))).value
else
%value.tap do |value|
@%wrapper = TypedValueWrapper(typeof(%value)).new(value)
end
end
end
end
macro let!(name, &block)
def {{name.id}}
{{block.body}}
end
end
macro before_all(&block)
::Spectator::Definitions::GROUPS[{{@type.symbolize}}].before_all_hooks << -> {{block}}
2018-09-15 17:21:23 +00:00
end
macro before_each(&block)
::Spectator::Definitions::GROUPS[{{@type.symbolize}}].before_each_hooks << -> {{block}}
2018-09-15 17:21:23 +00:00
end
macro after_all(&block)
::Spectator::Definitions::GROUPS[{{@type.symbolize}}].after_all_hooks << -> {{block}}
2018-09-15 17:21:23 +00:00
end
macro after_each(&block)
::Spectator::Definitions::GROUPS[{{@type.symbolize}}].after_each_hooks << -> {{block}}
2018-09-15 17:21:23 +00:00
end
macro around_each(&block)
::Spectator::Definitions::GROUPS[{{@type.symbolize}}].around_each_hooks << Proc(Proc(Nil), Nil).new {{block}}
2018-09-15 17:21:23 +00:00
end
def include_examples
raise NotImplementedError.new("Spectator::DSL#include_examples")
end
macro it(description, &block)
2018-09-20 01:32:59 +00:00
class Wrapper%example
2018-09-15 17:21:23 +00:00
include ::Spectator::DSL::ExampleDSL
include {{@type.id}}
2018-09-15 17:21:23 +00:00
def initialize(locals : Hash(Symbol, ValueWrapper))
super
end
def %run
2018-09-15 17:21:23 +00:00
{{block.body}}
end
end
2018-09-20 01:32:59 +00:00
class Example%example < ::Spectator::RunnableExample
2018-09-15 17:21:23 +00:00
protected def run_instance
Wrapper%example.new(locals).%run
2018-09-15 17:21:23 +00:00
end
def description
{{description.is_a?(StringLiteral) ? description : description.stringify}}
2018-09-15 17:21:23 +00:00
end
def group
::Spectator::Definitions::GROUPS[{{@type.symbolize}}]
end
2018-09-15 17:21:23 +00:00
end
2018-09-20 01:32:59 +00:00
class Factory%example < ::Spectator::ExampleFactory
def build(locals = {} of Symbol => ValueWrapper)
Example%example.new(locals)
end
end
::Spectator::Definitions::GROUPS[\{{@type.symbolize}}].children << Factory%example.new
2018-09-15 17:21:23 +00:00
end
macro pending(description, &block)
end
2018-09-15 17:21:23 +00:00
def it_behaves_like
raise NotImplementedError.new("Spectator::DSL#it_behaves_like")
end
2018-09-15 17:21:23 +00:00
macro _described_class(what)
2018-09-20 01:29:33 +00:00
def described_class
{{what}}.tap do |thing|
raise "#{thing} must be a type name to use #described_class or #subject,\
but it is a #{typeof(thing)}" unless thing.is_a?(Class)
2018-09-15 17:21:23 +00:00
end
2018-09-20 01:29:33 +00:00
end
2018-09-15 17:21:23 +00:00
2018-09-20 01:29:33 +00:00
_implicit_subject
2018-09-15 17:21:23 +00:00
end
macro _implicit_subject
def subject
described_class.new
end
2018-09-15 17:21:23 +00:00
end
end
end
end