diff --git a/Manifest.txt b/Manifest.txt index e17c8df5..c1fd0745 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -32,7 +32,6 @@ lib/aruba/cucumber/parameter_types.rb lib/aruba/cucumber/testing_frameworks.rb lib/aruba/errors.rb lib/aruba/event_bus.rb -lib/aruba/event_bus/name_resolver.rb lib/aruba/events.rb lib/aruba/file_size.rb lib/aruba/generators/script_file.rb diff --git a/lib/aruba/errors.rb b/lib/aruba/errors.rb index 04d05900..5c79b01c 100644 --- a/lib/aruba/errors.rb +++ b/lib/aruba/errors.rb @@ -30,10 +30,4 @@ class CommandNotFoundError < ArgumentError; end # Raised if command was already started, otherwise aruba forgets about the # previous pid and you've got hidden commands run class CommandAlreadyStartedError < Error; end - - # Raised if an event name cannot be resolved - class EventNameResolveError < StandardError; end - - # Raised if given object is not an event - class NoEventError < StandardError; end end diff --git a/lib/aruba/event_bus.rb b/lib/aruba/event_bus.rb index b6ed34b5..069aa657 100644 --- a/lib/aruba/event_bus.rb +++ b/lib/aruba/event_bus.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true -require "aruba/event_bus/name_resolver" -require "aruba/errors" +require "cucumber/core/event_bus" module Aruba # Event bus @@ -9,55 +8,15 @@ module Aruba # Implements and in-process pub-sub events broadcaster allowing multiple observers # to subscribe to different events that fire as your tests are executed. # - class EventBus - # Create EventBus - # - # @param [#transform] resolver - # A resolver which transforms Symbol, String, Class into an event Class. - def initialize(resolver) - @resolver = resolver - @handlers = Hash.new { |h, k| h[k] = [] } - end - - # Register for an event - # - # @param [String, Symbol, Class, Array] event_ids - # If Array, register multiple events witht the same handler. If String, - # Symbol, Class register handler for given event. - # - # @param [#call] handler_object - # The handler object, needs to have method `#call`. Either - # `handler_object` or `block` can be defined. The handler object gets the - # event passed to `#call`. - # - # @yield - # Handler block which gets the event passed as parameter. - def register(event_ids, handler_object = nil, &handler_proc) - handler = handler_proc || handler_object - - if handler.nil? || !handler.respond_to?(:call) - raise ArgumentError, "Please pass either an object#call or a handler block" + class EventBus < Cucumber::Core::EventBus + def register(ids, handler_object = nil, &handler_proc) + Array(ids).each do |event_id| + on(event_id, handler_object, &handler_proc) end - - Array(event_ids).flatten.each do |id| - @handlers[ - @resolver.transform(id).to_s - ] << handler - end - - nil end - # Broadcast an event - # - # @param [Object] event - # An object of registered event class. This object is passed to the event - # handler. - # def notify(event) - raise NoEventError, "Please pass an event object, not a class" if event.is_a?(Class) - - @handlers[event.class.to_s].each { |handler| handler.call(event) } + broadcast(event) end end end diff --git a/lib/aruba/event_bus/name_resolver.rb b/lib/aruba/event_bus/name_resolver.rb deleted file mode 100644 index 5c696605..00000000 --- a/lib/aruba/event_bus/name_resolver.rb +++ /dev/null @@ -1,160 +0,0 @@ -# frozen_string_literal: true - -require "aruba/errors" - -# Event notification library -module Aruba - # EventBus - class EventBus - # Resolve name to Event name - class NameResolver - # @private - # Helpers for Resolvers - module ResolveHelpers - def camel_case(underscored_name) - underscored_name.to_s.split("_").map { |word| word.upcase[0] + word[1..] }.join - end - - # Thanks ActiveSupport - # (Only needed to support Ruby 1.9.3 and JRuby) - def constantize(camel_cased_word) - names = camel_cased_word.split("::") - - # Trigger a built-in NameError exception including the ill-formed - # constant in the message. - Object.const_get(camel_cased_word) if names.empty? - - # Remove the first blank element in case of '::ClassName' notation. - names.shift if names.size > 1 && names.first.empty? - - names.inject(Object) do |constant, name| - if constant == Object - constant.const_get(name) - else - candidate = constant.const_get(name) - - next candidate if constant.const_defined?(name, false) - - next candidate unless Object.const_defined?(name) - - # Go down the ancestors to check if it is owned directly. The check - # stops when we reach Object or the end of ancestors tree. - constant = constant.ancestors.inject do |const, ancestor| - break const if ancestor == Object - break ancestor if ancestor.const_defined?(name, false) - - const - end - - # owner is in Object, so raise - constant.const_get(name, false) - end - end - end - end - - # @private - # Convert a class in to an event class - class ClassResolver - class << self - def match?(event_id) - event_id.is_a? Class - end - - # Which types are supported - def supports - [Class] - end - end - - def transform(_, event_id) - event_id - end - end - - # @private - # Convert a string in to an event class - class StringResolver - include ResolveHelpers - - class << self - def match?(event_id) - event_id.is_a? String - end - - # Which types are supported - def supports - [String] - end - end - - def transform(_, event_id) - constantize(event_id) - end - end - - # @private - # Convert a symbol in to an event class - class SymbolResolver - include ResolveHelpers - - class << self - def match?(event_id) - event_id.is_a? Symbol - end - - # Which types are supported - def supports - [Symbol] - end - end - - def transform(default_namespace, event_id) - constantize("#{default_namespace}::#{camel_case(event_id)}") - end - end - - # @private - # Default failing resolver - # - # This comes into play if the user passes an invalid event type - class FailingResolver - class << self - def match?(event_id) - raise ArgumentError, - %(Input type "#{event_id.class}" of event_id "#{event_id}" is invalid) - end - - def supports - [] - end - end - end - - protected - - attr_reader :resolvers, :default_namespace - - public - - def initialize(default_namespace) - @default_namespace = default_namespace - - @resolvers = [] - @resolvers << ClassResolver - @resolvers << StringResolver - @resolvers << SymbolResolver - @resolvers << FailingResolver - end - - def transform(event_id) - resolvers.find { |r| r.match? event_id }.new.transform(default_namespace, event_id) - rescue StandardError => e - types = @resolvers.map(&:supports).flatten.join(", ") - message = "Transforming \"#{event_id}\" into an event class failed." \ - " Supported types are: #{types}. #{e.message}." - raise EventNameResolveError, message, cause: e - end - end - end -end diff --git a/lib/aruba/events.rb b/lib/aruba/events.rb index 90364487..6ee270fe 100644 --- a/lib/aruba/events.rb +++ b/lib/aruba/events.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "cucumber/core/event" + # Aruba module Aruba # Events @@ -10,13 +12,7 @@ module Events # inherited by normal events # # @private - class BasicEvent - attr_reader :entity - - def initialize(entity) - @entity = entity - end - end + class BasicEvent < Cucumber::Core::Event.new(:entity); end # Command was stopped class CommandStopped < BasicEvent; end @@ -38,5 +34,15 @@ class ChangedWorkingDirectory < BasicEvent; end # The configuration was changed class ChangedConfiguration < BasicEvent; end + + def self.registry + [CommandStarted, + CommandStopped, + AddedEnvironmentVariable, + ChangedEnvironmentVariable, + DeletedEnvironmentVariable, + ChangedWorkingDirectory, + ChangedConfiguration].to_h { |klass| [klass.event_id, klass] } + end end end diff --git a/lib/aruba/runtime.rb b/lib/aruba/runtime.rb index d975a93e..df0c396a 100644 --- a/lib/aruba/runtime.rb +++ b/lib/aruba/runtime.rb @@ -42,7 +42,7 @@ class Runtime attr_accessor :config, :environment, :logger, :command_monitor, :announcer, :event_bus def initialize(opts = {}) - @event_bus = EventBus.new(EventBus::NameResolver.new(Aruba::Events)) + @event_bus = EventBus.new(Aruba::Events.registry) @announcer = opts.fetch(:announcer, Aruba.platform.announcer.new) @config = opts.fetch(:config, ConfigWrapper.new(Aruba.config.make_copy, @event_bus)) diff --git a/spec/aruba/event_bus/name_resolver_spec.rb b/spec/aruba/event_bus/name_resolver_spec.rb deleted file mode 100644 index 6fedf651..00000000 --- a/spec/aruba/event_bus/name_resolver_spec.rb +++ /dev/null @@ -1,71 +0,0 @@ -# frozen_string_literal: true - -require "spec_helper" - -describe Aruba::EventBus::NameResolver do - let(:resolver) { described_class.new(default_name_space) } - - let(:default_name_space) { "Events" } - let(:resolved_name) { resolver.transform(original_name) } - - before do - stub_const("Events::MyEvent", Class.new) - end - - describe "#transform" do - context "when name is string" do - context "when simple" do - let(:original_name) { "Events::MyEvent" } - - it { expect(resolved_name).to eq Events::MyEvent } - end - - context "when prefixed" do - let(:original_name) { "::Events::MyEvent" } - - it { expect(resolved_name).to eq Events::MyEvent } - end - end - - context "when name is class" do - let(:original_name) { Events::MyEvent } - - it { expect(resolved_name).to eq Events::MyEvent } - end - - context "when name is symbol" do - let(:original_name) { :my_event } - - it { expect(resolved_name).to eq Events::MyEvent } - end - - context "when namespace ..." do - before do - stub_const("MyLib::Events::MyEvent", Class.new) - end - - context "when is string" do - let(:default_name_space) { "MyLib::Events" } - let(:original_name) { :my_event } - - it { expect(resolved_name).to eq MyLib::Events::MyEvent } - end - - context "when is module" do - let(:default_name_space) { MyLib::Events } - let(:original_name) { :my_event } - - it { expect(resolved_name).to eq MyLib::Events::MyEvent } - end - end - - context "when invalid" do - let(:original_name) { 1 } - - it { - expect { resolved_name } - .to raise_error Aruba::EventNameResolveError, /Transforming "1"/ - } - end - end -end diff --git a/spec/aruba/event_bus_spec.rb b/spec/aruba/event_bus_spec.rb index 799c5bfc..f5372fb3 100644 --- a/spec/aruba/event_bus_spec.rb +++ b/spec/aruba/event_bus_spec.rb @@ -3,9 +3,12 @@ require "spec_helper" describe Aruba::EventBus do - let(:bus) { described_class.new(name_resolver) } + let(:bus) { described_class.new(registry) } - let(:name_resolver) { Aruba::EventBus::NameResolver.new("Events") } + let(:registry) do + { test_event: Events::TestEvent, + another_test_event: Events::AnotherTestEvent } + end let(:event_klass) { Events::TestEvent } let(:event_instance) { event_klass.new } @@ -16,14 +19,13 @@ before do stub_const("Events::TestEvent", Class.new) stub_const("Events::AnotherTestEvent", Class.new) - stub_const("Events::MalformedTestEvent", Module.new) stub_const("MyHandler", Class.new { def call(*); end }) stub_const("MyMalformedHandler", Class.new) end describe "#notify" do before do - bus.register(event_klass) do |event| + bus.register(:test_event) do |event| @received_payload = event end end @@ -44,7 +46,7 @@ context "when event is not an event instance" do it "raises an error" do - expect { bus.notify event_klass }.to raise_error Aruba::NoEventError + expect { bus.notify event_klass }.to raise_error ArgumentError end end end @@ -54,10 +56,10 @@ let(:received_events) { [] } before do - bus.register(Events::TestEvent) do |event| + bus.register(:test_event) do |event| received_events << event end - bus.register(Events::TestEvent) do |event| + bus.register(:test_event) do |event| received_events << event end end @@ -69,20 +71,6 @@ end end - context "when event id is a string" do - let(:received_payload) { [] } - - before do - bus.register("Events::TestEvent") do |event| - received_payload << event - end - - bus.notify event_instance - end - - it { expect(received_payload).to include event_instance } - end - context "when event id is a symbol" do let(:received_payload) { [] } @@ -101,7 +89,7 @@ let(:received_payload) { [] } before do - bus.register [event_klass, another_event_klass] do |event| + bus.register [:test_event, :another_test_event] do |event| received_payload << event end end @@ -115,19 +103,12 @@ context "when valid custom handler" do before do - bus.register(event_klass, MyHandler.new) + bus.register(:test_event, MyHandler.new) end it { expect { bus.notify event_instance }.not_to raise_error } end - context "when malformed custom handler" do - it "raises an ArgumentError" do - expect { bus.register(event_klass, MyMalformedHandler.new) } - .to raise_error ArgumentError - end - end - context "when no handler is given" do it "raises an ArgumentError" do expect { bus.register(event_klass) }.to raise_error ArgumentError