-
Notifications
You must be signed in to change notification settings - Fork 149
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
285 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
require 'wisper' | ||
|
||
module Wisper | ||
class Testing | ||
class << self | ||
attr_accessor :__test_mode | ||
|
||
def __set_test_mode(mode, &block) | ||
if block | ||
current_mode = self.__test_mode | ||
begin | ||
self.__test_mode = mode | ||
block.call | ||
ensure | ||
self.__test_mode = current_mode | ||
end | ||
else | ||
self.__test_mode = mode | ||
end | ||
end | ||
|
||
def disable!(&block) | ||
__set_test_mode(:disable, &block) | ||
end | ||
|
||
def fake!(&block) | ||
__set_test_mode(:fake, &block) | ||
end | ||
|
||
def enabled? | ||
self.__test_mode != :disable | ||
end | ||
|
||
def disabled? | ||
self.__test_mode == :disable | ||
end | ||
|
||
def fake? | ||
self.__test_mode == :fake | ||
end | ||
|
||
attr_accessor :__patch_state | ||
|
||
# Performs any patching necessary for Wisper::Testing to function. | ||
def patch! | ||
return if patched? | ||
Wisper::Publisher.wisper_testing_patch! | ||
self.__patch_state = :patched | ||
end | ||
|
||
# Restores Wisper and related objects to their original state before {#patch} was called. | ||
def unpatch! | ||
return unless patched? | ||
Wisper::Publisher.wisper_testing_unpatch! | ||
self.__patch_state = :unpatched | ||
end | ||
|
||
def patched? | ||
self.__patch_state == :patched | ||
end | ||
end | ||
end | ||
|
||
module Publisher | ||
# If testing is in "fake" mode, returns `true` as if broadcasting worked. If not in "fake" | ||
# mode, broadcasts the event using the original `broadcast` method. | ||
# This allows tests to determine whether an event was broadcast, and optionally skip the | ||
# delivery of the event. | ||
def broadcast_testing(event, *args) | ||
Publisher.record_testing_event(event, *args) | ||
if Wisper::Testing.fake? | ||
true | ||
else | ||
broadcast_real(event, *args) | ||
end | ||
end | ||
|
||
def self.wisper_testing_patch! | ||
alias_method :broadcast_real, :broadcast | ||
alias_method :broadcast, :broadcast_testing | ||
alias_method :publish, :broadcast_testing | ||
private :broadcast, :publish | ||
end | ||
|
||
def self.wisper_testing_unpatch! | ||
alias_method :broadcast, :broadcast_real | ||
alias_method :publish, :broadcast_real | ||
private :broadcast, :publish | ||
end | ||
|
||
# Allows tests to ask a Wisper publisher whether a listener has been subscribed to events | ||
# from it. | ||
def wisper_subscribed_locally?(listener) | ||
local_registrations.any? { |registration| registration.listener == listener } | ||
end | ||
|
||
class << self | ||
attr_reader :testing_event_recorder | ||
|
||
def record_testing_event(event, *args) | ||
testing_event_recorder.send(event, *args) if testing_event_recorder | ||
end | ||
|
||
# Allows tests to run a block that records all events sent during the block. | ||
# `event_recorder` will have the event sent to it as if it were a listener that | ||
# is subscribed to any of the events broadcast during this method's run. | ||
def with_testing_event_recorder(event_recorder) | ||
@testing_event_recorder = event_recorder | ||
begin | ||
yield | ||
ensure | ||
@testing_event_recorder = nil | ||
end | ||
end | ||
end | ||
end | ||
|
||
class << self | ||
# List of all registrations that exist in Wisper. | ||
def registrations | ||
GlobalListeners.registrations + TemporaryListeners.registrations | ||
end | ||
|
||
# Determines whether an object is registered as a listener within Wisper. | ||
def subscribed?(listener) | ||
registrations.any? { |reg| reg.listener == listener } | ||
end | ||
|
||
# Determines whether an object is registered as a listener for a specific publisher object. | ||
def subscribed_to_publisher?(listener, publisher_class) | ||
registrations.any? { |reg| | ||
reg.listener == listener && reg.allowed_classes.include?(publisher_class.to_s) | ||
} | ||
end | ||
end | ||
end | ||
|
||
unless ENV['SKIP_WISPER_TESTING_PATCH'] | ||
Wisper::Testing.patch! | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
ENV['SKIP_WISPER_TESTING_PATCH'] = 'true' | ||
require 'wisper/testing' | ||
|
||
describe 'Wisper::Testing' do | ||
let(:our_publisher_class) { publisher_class } | ||
let(:publisher) { our_publisher_class.new } | ||
let(:listener) { double('listener', event_name: true) } | ||
|
||
context 'after patching and unpatching' do | ||
before do | ||
Wisper::Testing.patch! | ||
Wisper::Testing.unpatch! | ||
Wisper::Testing.fake! | ||
end | ||
after do | ||
Wisper::Testing.disable! | ||
end | ||
it 'uses the original broadcast method' do | ||
publisher.subscribe(listener) | ||
publisher.send(:broadcast, 'event_name', :arg1, :arg2) | ||
expect(listener).to have_received(:event_name).with(:arg1, :arg2) | ||
end | ||
end | ||
|
||
context 'while Wisper is patched' do | ||
before do | ||
Wisper::Testing.patch! | ||
end | ||
after do | ||
Wisper::Testing.unpatch! | ||
end | ||
|
||
describe 'Wisper::Publisher.wisper_subscribed_locally?' do | ||
subject { publisher.wisper_subscribed_locally?(listener) } | ||
|
||
context 'when the listener is not registered' do | ||
it { is_expected.to be_falsey } | ||
end | ||
context 'when the listener is registered' do | ||
before do | ||
publisher.subscribe(listener) | ||
end | ||
it { is_expected.to be_truthy } | ||
end | ||
end | ||
|
||
describe 'Wisper.subscribed?' do | ||
subject { Wisper.subscribed?(listener) } | ||
|
||
context 'when the listener is not registered' do | ||
it { is_expected.to be_falsey } | ||
end | ||
context 'when the listener is registered' do | ||
before do | ||
Wisper.subscribe(listener) | ||
end | ||
it { is_expected.to be_truthy } | ||
end | ||
end | ||
|
||
describe 'Wisper.subscribed_to_publisher?' do | ||
subject { Wisper.subscribed_to_publisher?(listener, our_publisher_class) } | ||
|
||
context 'when the listener is not registered' do | ||
it { is_expected.to be_falsey } | ||
end | ||
context 'when the listener is registered' do | ||
before do | ||
our_publisher_class.subscribe(listener) | ||
end | ||
it { is_expected.to be_truthy } | ||
end | ||
end | ||
|
||
describe 'Wisper.with_testing_event_recorder' do | ||
let(:event_recorder) { double('event_recorder', event_name: true) } | ||
before do | ||
publisher.subscribe(listener) | ||
end | ||
subject { | ||
Wisper::Publisher.with_testing_event_recorder(event_recorder) do | ||
publisher.send(:broadcast, 'event_name', :arg1, :arg2) | ||
end | ||
} | ||
it 'records the event' do | ||
expect(event_recorder).to receive(:event_name).with(:arg1, :arg2) | ||
subject | ||
end | ||
context 'with Wisper::Testing.disabled! (the default)' do | ||
it 'publishes the event' do | ||
expect(listener).to receive(:event_name).with(:arg1, :arg2) | ||
subject | ||
end | ||
end | ||
context 'with Wisper::Testing.fake!' do | ||
before do | ||
Wisper::Testing.fake! | ||
end | ||
after do | ||
Wisper::Testing.disable! | ||
end | ||
it 'does not publish the event' do | ||
expect(listener).not_to receive(:event_name).with(:arg1, :arg2) | ||
subject | ||
end | ||
end | ||
end | ||
end | ||
end |