informator 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,168 @@
1
+ # encoding: utf-8
2
+
3
+ require "timecop"
4
+
5
+ describe Informator::Publisher do
6
+
7
+ before { Timecop.freeze } # to allow time-dependent events being equal
8
+ after { Timecop.return }
9
+
10
+ let(:pub_class) { Informator::Foo = Class.new(described_class) }
11
+ let(:publisher) { pub_class.new attributes }
12
+ let(:attributes) { { foo: :FOO, bar: :BAR } }
13
+ let(:listener) { double callback => nil, freeze: nil }
14
+ let(:callback) { :call }
15
+ let(:name) { :foo }
16
+ let(:subscriber) { Informator::Subscriber.new listener, callback }
17
+ let(:event) { Informator::Event.new publisher, name, attributes }
18
+
19
+ describe ".new" do
20
+
21
+ subject { publisher }
22
+
23
+ it { is_expected.to be_frozen }
24
+
25
+ it "doesn't freeze attirbutes" do
26
+ expect { subject }.not_to change { attributes.frozen? }
27
+ end
28
+
29
+ end # describe .new
30
+
31
+ describe "#attributes" do
32
+
33
+ subject { publisher.attributes }
34
+
35
+ it { is_expected.to be_frozen }
36
+ it { is_expected.to eql attributes }
37
+
38
+ context "by default" do
39
+
40
+ let(:publisher) { pub_class.new }
41
+
42
+ it { is_expected.to eql({}) }
43
+
44
+ end # context
45
+
46
+ end # describe #attributes
47
+
48
+ describe "#==" do
49
+
50
+ subject { publisher == other }
51
+
52
+ context "with the same types and attributes" do
53
+
54
+ let(:other) { publisher.subscribe(listener, callback) }
55
+ it { is_expected.to eql true }
56
+
57
+ end # context
58
+
59
+ context "with different types" do
60
+
61
+ let(:other) { described_class.new(attributes) }
62
+ it { is_expected.to eql false }
63
+
64
+ end # context
65
+
66
+ context "with different attributes" do
67
+
68
+ let(:other) { pub_class.new }
69
+ it { is_expected.to eql false }
70
+
71
+ end # context
72
+
73
+ end # describe #==
74
+
75
+ describe "#eql?" do
76
+
77
+ subject { publisher == other }
78
+ let(:other) { publisher.subscribe(listener, callback) }
79
+
80
+ it "aliases #==" do
81
+ expect(subject).to eql true
82
+ end
83
+
84
+ end # describe #==
85
+
86
+ describe "#inspect" do
87
+
88
+ subject { publisher.inspect }
89
+ it { is_expected.to eql "#<Informator::Foo @attributes=#{attributes}>" }
90
+
91
+ end # describe #inspect
92
+
93
+ describe "#to_s" do
94
+
95
+ subject { publisher.to_s }
96
+ it { is_expected.to eql publisher.inspect }
97
+
98
+ end # describe #to_s
99
+
100
+ describe "#subscribers" do
101
+
102
+ subject { publisher.subscribers }
103
+
104
+ it { is_expected.to eql Set.new }
105
+ it { is_expected.to be_frozen }
106
+
107
+ end # describe #attributes
108
+
109
+ describe "#subscribe" do
110
+
111
+ subject { publisher.subscribe(listener, callback) }
112
+
113
+ it { is_expected.to be_kind_of described_class }
114
+
115
+ it "preserves attributes" do
116
+ expect(subject.attributes).to eql attributes
117
+ end
118
+
119
+ it "registers new subscriber" do
120
+ other = Informator::Subscriber.new listener, "other"
121
+
122
+ updated = subject.subscribe(listener, "other")
123
+ expect(updated.subscribers).to contain_exactly subscriber, other
124
+ end
125
+
126
+ it "skips registered subscriber" do
127
+ updated = subject.subscribe(listener, callback)
128
+ expect(updated.subscribers).to contain_exactly subscriber
129
+ end
130
+
131
+ end # describe #subscribe
132
+
133
+ describe "#publish" do
134
+
135
+ subject { publisher.subscribe(listener, callback).publish name, attributes }
136
+
137
+ it "sends event to subscribers" do
138
+ expect(listener).to receive(callback).with(event)
139
+ subject
140
+ end
141
+
142
+ it { is_expected.to eql event }
143
+
144
+ end # describe #publish
145
+
146
+ describe "#publish!" do
147
+
148
+ let(:caller) { publisher.subscribe(listener, callback) }
149
+ subject { caller.publish! name, attributes }
150
+
151
+ it "sends event to subscribers" do
152
+ expect(listener).to receive(callback).with(event)
153
+ subject rescue nil
154
+ end
155
+
156
+ it "throws an exception" do
157
+ expect { subject }.to raise_error(ArgumentError)
158
+ end
159
+
160
+ it "carries the event" do
161
+ expect(catch(:published) { subject }).to eql event
162
+ end
163
+
164
+ end # describe #publish!
165
+
166
+ after { Informator.send :remove_const, :Foo }
167
+
168
+ end # describe Informator::Publisher
@@ -2,84 +2,70 @@
2
2
 
3
3
  describe Informator::Subscriber do
4
4
 
5
- let(:callback) { "foo" }
6
- let(:event) { double }
7
- let(:object) { double callback.to_sym => callback, freeze: nil }
8
-
9
- subject(:subscriber) { described_class.new object, callback }
5
+ let(:callback) { "foo" }
6
+ let(:event) { double }
7
+ let(:listener) { double callback => callback, freeze: nil }
8
+ let(:subscriber) { described_class.new listener, callback }
10
9
 
11
10
  describe ".new" do
12
11
 
12
+ subject { subscriber }
13
13
  it { is_expected.to be_frozen }
14
14
 
15
15
  end # describe .new
16
16
 
17
- describe "#object" do
17
+ describe "#listener" do
18
18
 
19
- subject { subscriber.object }
20
- it { is_expected.to eql object }
19
+ subject { subscriber.listener }
20
+ it { is_expected.to eql listener }
21
21
 
22
- end # describe #object
22
+ end # describe #listener
23
23
 
24
24
  describe "#callback" do
25
25
 
26
26
  subject { subscriber.callback }
27
27
  it { is_expected.to eql callback.to_sym }
28
28
 
29
- context "when callback isn't defined" do
30
-
31
- let(:subscriber) { described_class.new object }
32
- it { is_expected.to eql :receive }
33
-
34
- end # context
35
-
36
29
  end # describe #callback
37
30
 
38
- describe "#notify" do
39
-
40
- subject { subscriber.notify event }
41
-
42
- it "sends event to object via callback" do
43
- expect(object).to receive(callback).with(event)
44
- subject
45
- end
46
-
47
- it { is_expected.to eql event }
48
-
49
- end # describe #notify
50
-
51
31
  describe "#==" do
52
32
 
53
33
  subject { subscriber == other }
54
34
 
55
- context "to subscriber with the same object and callback" do
35
+ context "with the same listeners and callbacks" do
56
36
 
57
- let(:other) { subscriber.dup }
37
+ let(:other) { described_class.new listener, callback }
58
38
  it { is_expected.to eql true }
59
39
 
60
40
  end # context
61
41
 
62
- context "to event with another object" do
42
+ context "with different listeners" do
63
43
 
64
- let(:other) { double freeze: nil }
44
+ let(:other) { described_class.new double(freeze: nil), callback }
65
45
  it { is_expected.to eql false }
66
46
 
67
47
  end # context
68
48
 
69
- context "to event with other attributes" do
49
+ context "with different callbacks" do
70
50
 
71
- let(:other) { described_class.new object, :other }
51
+ let(:other) { described_class.new listener, "other" }
72
52
  it { is_expected.to eql false }
73
53
 
74
54
  end # context
75
55
 
76
- context "to non-subscriber" do
56
+ end # describe #==
77
57
 
78
- let(:other) { :foo }
79
- it { is_expected.to eql false }
58
+ describe "#notify" do
80
59
 
81
- end # context
60
+ subject { subscriber.notify event }
82
61
 
83
- end # describe #==
62
+ it "sends event to listener via callback" do
63
+ expect(listener).to receive(callback).with(event)
64
+ subject
65
+ end
66
+
67
+ it { is_expected.to eql event }
68
+
69
+ end # describe #notify
84
70
 
85
71
  end # describe Informator::Subscriber
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: informator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kozin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-12 00:00:00.000000000 Z
11
+ date: 2015-07-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: equalizer
14
+ name: i18n
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.0'
19
+ version: '0.7'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.0'
26
+ version: '0.7'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: ice_nine
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -38,6 +38,34 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0.11'
41
+ - !ruby/object:Gem::Dependency
42
+ name: inflecto
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: equalizer
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.0'
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: hexx-rspec
43
71
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +80,20 @@ dependencies:
52
80
  - - "~>"
53
81
  - !ruby/object:Gem::Version
54
82
  version: '0.5'
83
+ - !ruby/object:Gem::Dependency
84
+ name: timecop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.7'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.7'
55
97
  description:
56
98
  email: andrew.kozin@gmail.com
57
99
  executables: []
@@ -87,14 +129,19 @@ files:
87
129
  - informator.gemspec
88
130
  - lib/informator.rb
89
131
  - lib/informator/event.rb
90
- - lib/informator/reporter.rb
132
+ - lib/informator/publisher.rb
133
+ - lib/informator/rspec.rb
91
134
  - lib/informator/subscriber.rb
92
135
  - lib/informator/version.rb
136
+ - lib/rspec/shared.rb
137
+ - spec/integration/en.yml
138
+ - spec/integration/fr.yml
139
+ - spec/integration/i18n.rb
140
+ - spec/integration/rspec_spec.rb
93
141
  - spec/spec_helper.rb
94
142
  - spec/unit/informator/event_spec.rb
95
- - spec/unit/informator/reporter_spec.rb
143
+ - spec/unit/informator/publisher_spec.rb
96
144
  - spec/unit/informator/subscriber_spec.rb
97
- - spec/unit/informator_spec.rb
98
145
  homepage: https://github.com/nepalez/informator
99
146
  licenses:
100
147
  - MIT
@@ -107,7 +154,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
107
154
  requirements:
108
155
  - - "~>"
109
156
  - !ruby/object:Gem::Version
110
- version: '2.1'
157
+ version: 1.9.3
111
158
  required_rubygems_version: !ruby/object:Gem::Requirement
112
159
  requirements:
113
160
  - - ">="
@@ -121,8 +168,9 @@ specification_version: 4
121
168
  summary: Implementation of publish/subscribe design pattern
122
169
  test_files:
123
170
  - spec/spec_helper.rb
124
- - spec/unit/informator_spec.rb
171
+ - spec/integration/i18n.rb
172
+ - spec/integration/rspec_spec.rb
125
173
  - spec/unit/informator/event_spec.rb
126
- - spec/unit/informator/reporter_spec.rb
174
+ - spec/unit/informator/publisher_spec.rb
127
175
  - spec/unit/informator/subscriber_spec.rb
128
176
  has_rdoc:
@@ -1,67 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Informator
4
-
5
- # Builds, collects and publishes events to selected subscribers
6
- #
7
- # @example
8
- # reporter = Reporter.new
9
- # reporter.events # => []
10
- #
11
- # reporter.remember :success
12
- # reporter.events # => [#<Event @type=:success @attributes={} @messages=[]>]
13
- #
14
- # # this will call subscriber.notify for any event
15
- # reporter.notify subscriber
16
- # reporter.events # => []
17
- #
18
- # @api private
19
- #
20
- class Reporter
21
-
22
- # @private
23
- def initialize
24
- @events = []
25
- freeze # freezes the instance, but left events mutable!
26
- end
27
-
28
- # @!attribute [r] events
29
- # @return [Array<Informator::Event>]
30
- # the list of registered events that havent'b been published yet
31
- attr_reader :events
32
-
33
- # @!method remember(type, messages, attributes)
34
- # Registers the event to be published to subscribers
35
- #
36
- # @param (see Informator::Event.new)
37
- #
38
- # @return [self] itself
39
- #
40
- def remember(*args)
41
- events << Event.new(*args)
42
-
43
- self
44
- end
45
-
46
- # Notifies subscribers on events registered since the last notification
47
- #
48
- # Mutates [#events] by excluding all events having been published.
49
- #
50
- # @param [Informator::Subscriber, Array<Informator::Subscriber>] subscribers
51
- # the list of subscribers to be notified
52
- #
53
- # @return [Array<Informator::Event>] the list of published events
54
- def notify(*subscribers)
55
- events.dup.each { publish subscribers.flatten }
56
- end
57
-
58
- private
59
-
60
- def publish(subscribers)
61
- event = events.shift
62
- subscribers.each { |subscriber| subscriber.notify(event) }
63
- end
64
-
65
- end # class Reporter
66
-
67
- end # module Informator