informator 0.1.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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