tekeya 0.0.1

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.
Files changed (92) hide show
  1. data/.document +0 -0
  2. data/.gitignore +23 -0
  3. data/.rspec +3 -0
  4. data/.yardopts +1 -0
  5. data/Gemfile +39 -0
  6. data/Guardfile +40 -0
  7. data/LICENSE +22 -0
  8. data/README.md +37 -0
  9. data/Rakefile +13 -0
  10. data/TODO.todo +8 -0
  11. data/app/active_record/tekeya/activity.rb +7 -0
  12. data/app/active_record/tekeya/attachment.rb +5 -0
  13. data/app/active_record/tekeya/notification.rb +5 -0
  14. data/app/mongoid/tekeya/activity.rb +9 -0
  15. data/app/mongoid/tekeya/attachment.rb +6 -0
  16. data/app/mongoid/tekeya/notification.rb +10 -0
  17. data/db/migrate/00_create_activities.rb +11 -0
  18. data/db/migrate/01_create_attachments.rb +13 -0
  19. data/db/migrate/02_create_notifications.rb +14 -0
  20. data/lib/tasks/resque_tasks.rake +3 -0
  21. data/lib/tekeya.rb +81 -0
  22. data/lib/tekeya/configuration.rb +48 -0
  23. data/lib/tekeya/entity.rb +432 -0
  24. data/lib/tekeya/entity/group.rb +22 -0
  25. data/lib/tekeya/errors/tekeya_error.rb +11 -0
  26. data/lib/tekeya/errors/tekeya_fatal.rb +11 -0
  27. data/lib/tekeya/errors/tekeya_non_entity.rb +6 -0
  28. data/lib/tekeya/errors/tekeya_non_group.rb +6 -0
  29. data/lib/tekeya/errors/tekeya_relation_already_exists.rb +6 -0
  30. data/lib/tekeya/errors/tekeya_relation_non_existent.rb +6 -0
  31. data/lib/tekeya/feed/activity.rb +101 -0
  32. data/lib/tekeya/feed/activity/feed_item.rb +58 -0
  33. data/lib/tekeya/feed/activity/resque.rb +56 -0
  34. data/lib/tekeya/feed/activity/resque/activity_fanout.rb +61 -0
  35. data/lib/tekeya/feed/activity/resque/delete_activity.rb +43 -0
  36. data/lib/tekeya/feed/activity/resque/feed_copy.rb +34 -0
  37. data/lib/tekeya/feed/activity/resque/untrack_feed.rb +34 -0
  38. data/lib/tekeya/feed/attachable.rb +15 -0
  39. data/lib/tekeya/feed/attachment.rb +19 -0
  40. data/lib/tekeya/feed/notification.rb +93 -0
  41. data/lib/tekeya/railtie.rb +18 -0
  42. data/lib/tekeya/version.rb +3 -0
  43. data/spec/fabricators/attachment_fabricator.rb +3 -0
  44. data/spec/fabricators/group_fabricator.rb +4 -0
  45. data/spec/fabricators/status_fabricator.rb +3 -0
  46. data/spec/fabricators/user_fabricator.rb +3 -0
  47. data/spec/orm/active_record.rb +14 -0
  48. data/spec/orm/mongoid.rb +6 -0
  49. data/spec/rails_app/Rakefile +7 -0
  50. data/spec/rails_app/app/active_record/group.rb +3 -0
  51. data/spec/rails_app/app/active_record/status.rb +3 -0
  52. data/spec/rails_app/app/active_record/user.rb +3 -0
  53. data/spec/rails_app/app/controllers/application_controller.rb +3 -0
  54. data/spec/rails_app/app/helpers/application_helper.rb +2 -0
  55. data/spec/rails_app/app/mongoid/group.rb +6 -0
  56. data/spec/rails_app/app/mongoid/status.rb +6 -0
  57. data/spec/rails_app/app/mongoid/user.rb +7 -0
  58. data/spec/rails_app/app/views/layouts/application.html.erb +14 -0
  59. data/spec/rails_app/config.ru +4 -0
  60. data/spec/rails_app/config/application.rb +35 -0
  61. data/spec/rails_app/config/boot.rb +8 -0
  62. data/spec/rails_app/config/database.yml +21 -0
  63. data/spec/rails_app/config/environment.rb +5 -0
  64. data/spec/rails_app/config/environments/development.rb +18 -0
  65. data/spec/rails_app/config/environments/production.rb +33 -0
  66. data/spec/rails_app/config/environments/test.rb +33 -0
  67. data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  68. data/spec/rails_app/config/initializers/configure_mongoid.rb +6 -0
  69. data/spec/rails_app/config/initializers/inflections.rb +15 -0
  70. data/spec/rails_app/config/initializers/resque.rb +1 -0
  71. data/spec/rails_app/config/initializers/secret_token.rb +7 -0
  72. data/spec/rails_app/config/locales/en.yml +5 -0
  73. data/spec/rails_app/config/routes.rb +58 -0
  74. data/spec/rails_app/db/migrate/100_create_users.rb +9 -0
  75. data/spec/rails_app/db/migrate/101_create_groups.rb +11 -0
  76. data/spec/rails_app/db/migrate/102_create_statuses.rb +9 -0
  77. data/spec/rails_app/db/seeds.rb +7 -0
  78. data/spec/rails_app/public/404.html +26 -0
  79. data/spec/rails_app/public/422.html +26 -0
  80. data/spec/rails_app/public/500.html +25 -0
  81. data/spec/rails_app/public/favicon.ico +0 -0
  82. data/spec/rails_app/public/index.html +241 -0
  83. data/spec/rails_app/public/robots.txt +5 -0
  84. data/spec/rails_app/script/rails +6 -0
  85. data/spec/spec_helper.rb +78 -0
  86. data/spec/tekeya/activity_spec.rb +170 -0
  87. data/spec/tekeya/entity_spec.rb +158 -0
  88. data/spec/tekeya/notification_spec.rb +49 -0
  89. data/spec/tekeya_helper.rb +7 -0
  90. data/spec/tekeya_spec.rb +51 -0
  91. data/tekeya.gemspec +22 -0
  92. metadata +231 -0
@@ -0,0 +1,5 @@
1
+ # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
2
+ #
3
+ # To ban all spiders from the entire site uncomment the next two lines:
4
+ # User-Agent: *
5
+ # Disallow: /
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
5
+ require File.expand_path('../../config/boot', __FILE__)
6
+ require 'rails/commands'
@@ -0,0 +1,78 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter '/spec/'
4
+ end
5
+
6
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
8
+
9
+ ENV["RAILS_ENV"] = "test"
10
+ TEKEYA_ORM = (ENV["TEKEYA_ORM"] || :active_record).to_sym
11
+
12
+ require 'rspec'
13
+ require 'tekeya'
14
+ require 'bundler'
15
+
16
+ Bundler.require :default, :development, :test
17
+
18
+ require 'database_cleaner'
19
+ require "#{File.dirname(__FILE__)}/tekeya_helper"
20
+ require "#{File.dirname(__FILE__)}/../lib/tekeya"
21
+ require "#{File.dirname(__FILE__)}/rails_app/config/environment"
22
+ require "#{File.dirname(__FILE__)}/orm/#{TEKEYA_ORM}"
23
+
24
+ # Requires supporting files with custom matchers and macros, etc,
25
+ # in ./support/ and its subdirectories.
26
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
27
+
28
+ RSpec.configure do |config|
29
+ Fabrication.configure do |config|
30
+ config.fabricator_path = 'fabricators'
31
+ config.path_prefix = File.dirname(__FILE__)
32
+ end
33
+
34
+ config.before(:each) do
35
+ DatabaseCleaner.clean
36
+ end
37
+
38
+ config.after(:each) do
39
+ Tekeya.relations.truncate
40
+ Tekeya.redis.flushall
41
+ end
42
+
43
+ config.before(:all) do
44
+ %w(tmp tmp/pids tmp/cache).each do |path|
45
+ FileUtils.mkdir_p "#{Dir.pwd}/#{path}"
46
+ end
47
+ end
48
+
49
+ REDIS_PID = File.join(File.dirname(__FILE__), '..', 'tmp','pids','redis-test.pid')
50
+ REDIS_CACHE_PATH = File.join(File.dirname(__FILE__), '..', 'tmp','cache')
51
+
52
+ config.before(:suite) do
53
+ redis_options = {
54
+ "daemonize" => 'yes',
55
+ "pidfile" => REDIS_PID,
56
+ "port" => 9736,
57
+ "timeout" => 300,
58
+ "save 900" => 1,
59
+ "save 300" => 1,
60
+ "save 60" => 10000,
61
+ "dbfilename" => "dump.rdb",
62
+ "dir" => REDIS_CACHE_PATH,
63
+ "loglevel" => "debug",
64
+ "logfile" => "stdout",
65
+ "databases" => 16
66
+ }.map { |k, v| "#{k} #{v}" }.join('\n')
67
+ `echo '#{redis_options}' | redis-server -`
68
+ end
69
+
70
+ config.after(:suite) do
71
+ %x{
72
+ cat #{REDIS_PID} | xargs kill -QUIT
73
+ rm -f #{REDIS_CACHE_PATH}dump.rdb
74
+ }
75
+
76
+ FileUtils.rm_r "#{File.dirname(__FILE__)}/rails_app/db/test.sqlite3" rescue nil
77
+ end
78
+ end
@@ -0,0 +1,170 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Tekeya" do
4
+ describe "Activity" do
5
+ before :each do
6
+ @user = Fabricate(:user)
7
+ @user2 = Fabricate(:user)
8
+ @user3 = Fabricate(:user)
9
+
10
+ @user2.track(@user)
11
+ @user3.track(@user)
12
+
13
+ # Normal Activities (1 & 2 should be grouped)
14
+ @act1 = @user.activities.liked Fabricate(:status), Fabricate(:status)
15
+ @act2 = @user.activities.liked Fabricate(:status)
16
+ @act3 = @user.activities.shared Fabricate(:status)
17
+
18
+ # Created after the grouping interval
19
+ @act4 = @user.activities.new activity_type: :liked, attachments: [Fabricate.build(:attachment)]
20
+ @act4.stub(:current_time_from_proper_timezone => @act1.created_at + 20.minutes)
21
+ @act4.save!
22
+
23
+ # Manually not grouped
24
+ @act5 = @user.activities.liked Fabricate(:status), group: false
25
+ end
26
+
27
+ it "should return the same aggregate key" do
28
+ @act1.activity_key.should == @act2.activity_key
29
+ end
30
+
31
+ it "should return different aggregate keys" do
32
+ @act1.activity_key.should_not == @act3.activity_key
33
+ end
34
+
35
+ it "should create an aggregate in redis" do
36
+ @act1.cached_in_redis?.should == true
37
+ @act2.cached_in_redis?.should == true
38
+ @act3.cached_in_redis?.should == true
39
+ @act4.cached_in_redis?.should == true
40
+ @act5.cached_in_redis?.should == true
41
+ end
42
+
43
+ it "should add the activity to the owner's profile feed and group activities of the same type within 15 min" do
44
+ id_array = @user.profile_feed.map(&:activity_id)
45
+ id_array.include?(@act1.id.to_s).should == true
46
+ id_array.include?(@act3.id.to_s).should == true
47
+ id_array.include?(@act4.id.to_s).should == true
48
+ id_array.include?(@act5.id.to_s).should == true
49
+ end
50
+
51
+ it "should not save the activity in the DB if its grouped with another" do
52
+ @act2.persisted?.should_not == true
53
+ end
54
+
55
+ it "should save the activity's attachments in the parent activity if its grouped" do
56
+ @act1.reload
57
+ (@act1.attachments & @act2.attachments).should == @act2.attachments
58
+ end
59
+
60
+ it "should fanout activities to the entity's trackers" do
61
+ id_array = (@user2.feed.map(&:activity_id) + @user3.feed.map(&:activity_id)).uniq
62
+ id_array.include?(@act1.id.to_s).should == true
63
+ id_array.include?(@act3.id.to_s).should == true
64
+ id_array.include?(@act4.id.to_s).should == true
65
+ id_array.include?(@act5.id.to_s).should == true
66
+ end
67
+
68
+ describe "invalid profile feed cache" do
69
+ it "should return profile activities from the DB when the profile cache is empty" do
70
+ ::Tekeya.redis.del(@user.profile_feed_key)
71
+ ::Tekeya.redis.del(@act1.activity_key)
72
+ ::Tekeya.redis.del(@act3.activity_key)
73
+ ::Tekeya.redis.del(@act4.activity_key)
74
+ ::Tekeya.redis.del(@act5.activity_key)
75
+
76
+ @act1.cached_in_redis?.should == false
77
+ @act3.cached_in_redis?.should == false
78
+ @act4.cached_in_redis?.should == false
79
+ @act5.cached_in_redis?.should == false
80
+
81
+ id_array = @user.profile_feed.map(&:activity_id)
82
+ id_array.include?(@act1.id.to_s).should == true
83
+ id_array.include?(@act3.id.to_s).should == true
84
+ id_array.include?(@act4.id.to_s).should == true
85
+ id_array.include?(@act5.id.to_s).should == true
86
+ end
87
+ end
88
+
89
+ describe "invalid feed cache" do
90
+ it "should return feed activities from the DB when the feed cache is empty" do
91
+ ::Tekeya.redis.del(@user2.feed_key)
92
+ ::Tekeya.redis.del(@user3.feed_key)
93
+
94
+ ::Tekeya.redis.zcard(@user2.feed_key).should == 0
95
+ ::Tekeya.redis.zcard(@user3.feed_key).should == 0
96
+
97
+ @user2.feed.count == 4
98
+ @user3.feed.count == 4
99
+ end
100
+ end
101
+
102
+ describe "activity deletion" do
103
+ before :each do
104
+ @act1.destroy
105
+ @act3.destroy
106
+ @act4.destroy
107
+ @act5.destroy
108
+ end
109
+
110
+ it "should remove the activity from the cache when its deleted from the db" do
111
+ @act1.cached_in_redis?.should_not == true
112
+ @act3.cached_in_redis?.should_not == true
113
+ @act4.cached_in_redis?.should_not == true
114
+ @act5.cached_in_redis?.should_not == true
115
+ end
116
+
117
+ it "should remove the activity from the profile cache when its deleted from the db" do
118
+ id_array = @user.profile_feed.map(&:activity_id)
119
+ id_array.include?(@act1.id.to_s).should_not == true
120
+ id_array.include?(@act3.id.to_s).should_not == true
121
+ id_array.include?(@act4.id.to_s).should_not == true
122
+ id_array.include?(@act5.id.to_s).should_not == true
123
+ end
124
+
125
+ it "should remove the activity from the trackers' feed when its deleted from the db" do
126
+ id_array = (@user2.feed.map(&:activity_id) + @user3.feed.map(&:activity_id)).uniq
127
+ id_array.include?(@act1.id.to_s).should_not == true
128
+ id_array.include?(@act3.id.to_s).should_not == true
129
+ id_array.include?(@act4.id.to_s).should_not == true
130
+ id_array.include?(@act5.id.to_s).should_not == true
131
+ end
132
+ end
133
+
134
+ describe "untracking" do
135
+ before :each do
136
+ @user2.untrack(@user)
137
+ end
138
+
139
+ it "should remove the feed of the untracked entity from the tracker's cache" do
140
+ id_array = @user2.feed.map(&:activity_id)
141
+ id_array.include?(@act1.id.to_s).should_not == true
142
+ id_array.include?(@act3.id.to_s).should_not == true
143
+ id_array.include?(@act4.id.to_s).should_not == true
144
+ id_array.include?(@act5.id.to_s).should_not == true
145
+
146
+ id_array = @user3.feed.map(&:activity_id)
147
+ id_array.include?(@act1.id.to_s).should == true
148
+ id_array.include?(@act3.id.to_s).should == true
149
+ id_array.include?(@act4.id.to_s).should == true
150
+ id_array.include?(@act5.id.to_s).should == true
151
+ end
152
+ end
153
+
154
+ describe "tracking" do
155
+ before :each do
156
+ @user4 = Fabricate(:user)
157
+
158
+ @user4.track(@user)
159
+ end
160
+
161
+ it "should copy the feed of the tracked entity into the tracker's feed" do
162
+ id_array = @user4.feed.map(&:activity_id)
163
+ id_array.include?(@act1.id.to_s).should == true
164
+ id_array.include?(@act3.id.to_s).should == true
165
+ id_array.include?(@act4.id.to_s).should == true
166
+ id_array.include?(@act5.id.to_s).should == true
167
+ end
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,158 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Tekeya" do
4
+ describe "Entity" do
5
+ before :each do
6
+ @user = Fabricate(:user)
7
+ @user2 = Fabricate(:user)
8
+ @group = Fabricate(:group)
9
+ end
10
+
11
+ it "should inherit all the relations and feed methods" do
12
+ # Public methods
13
+ User.method_defined?(:track).should == true
14
+ User.method_defined?(:tracking).should == true
15
+ User.method_defined?(:"tracks?").should == true
16
+ User.method_defined?(:untrack).should == true
17
+ User.method_defined?(:block).should == true
18
+ User.method_defined?(:blocked).should == true
19
+ User.method_defined?(:"blocks?").should == true
20
+ User.method_defined?(:unblock).should == true
21
+ User.method_defined?(:join).should == true
22
+ User.method_defined?(:groups).should == true
23
+ User.method_defined?(:"member_of?").should == true
24
+ User.method_defined?(:leave).should == true
25
+ User.method_defined?(:profile_feed).should == true
26
+ User.method_defined?(:feed).should == true
27
+ User.method_defined?(:profile_feed_key).should == true
28
+ User.method_defined?(:feed_key).should == true
29
+ # Private methods
30
+ User.private_method_defined?(:add_tekeya_relation).should == true
31
+ User.private_method_defined?(:delete_tekeya_relation).should == true
32
+ User.private_method_defined?(:tekeya_relations_of).should == true
33
+ User.private_method_defined?(:"tekeya_relation_exists?").should == true
34
+ end
35
+
36
+ describe "errors" do
37
+ it "should raise a non entity error when tracking or blocking a non entity" do
38
+ expect { @user.track(nil) }.to raise_error(Tekeya::Errors::TekeyaNonEntity)
39
+ expect { @user.block(nil) }.to raise_error(Tekeya::Errors::TekeyaNonEntity)
40
+ end
41
+
42
+ it "should raise a non group error if a non group is given when joining a non group" do
43
+ expect { @user.join(nil) }.to raise_error(Tekeya::Errors::TekeyaNonGroup)
44
+ end
45
+
46
+ it "should raise a relation already exists error when tracking, blocking or joining an already tracked, blocked or joined entity/group" do
47
+ @user.track(@user2)
48
+ expect { @user.track(@user2) }.to raise_error(Tekeya::Errors::TekeyaRelationAlreadyExists)
49
+ @user.block(@user2)
50
+ expect { @user.block(@user2) }.to raise_error(Tekeya::Errors::TekeyaRelationAlreadyExists)
51
+ @user.join(@group)
52
+ expect { @user.join(@group) }.to raise_error(Tekeya::Errors::TekeyaRelationAlreadyExists)
53
+ end
54
+
55
+ it "should raise a relation non existent error when untracking, unblocking or leaving an untracked, unblocked or unjoined entity/group" do
56
+ expect { @user.untrack(@user2) }.to raise_error(Tekeya::Errors::TekeyaRelationNonExistent)
57
+ expect { @user.unblock(@user2) }.to raise_error(Tekeya::Errors::TekeyaRelationNonExistent)
58
+ expect { @user.leave(@group) }.to raise_error(Tekeya::Errors::TekeyaRelationNonExistent)
59
+ end
60
+ end
61
+
62
+ describe "relations" do
63
+ it "should track another entity" do
64
+ @user.track(@user2).should == true
65
+ @user.tracks?(@user2).should == true
66
+ end
67
+
68
+ it "should untrack a tracked entity" do
69
+ @user.track(@user2)
70
+ @user.untrack(@user2).should == true
71
+ @user.tracks?(@user2).should_not == true
72
+ end
73
+
74
+ it "should block another entity/group" do
75
+ @user.block(@user2).should == true
76
+ @user.blocks?(@user2).should == true
77
+ @user.block(@group).should == true
78
+ @user.blocks?(@group).should == true
79
+ end
80
+
81
+ it "should unblock a blocked entity/group" do
82
+ @user.block(@user2)
83
+ @user.unblock(@user2).should == true
84
+ @user.blocks?(@user2).should_not == true
85
+
86
+ @user.block(@group)
87
+ @user.unblock(@group).should == true
88
+ @user.blocks?(@group).should_not == true
89
+ end
90
+
91
+ it "should join a group" do
92
+ @user.join(@group).should == true
93
+ @user.member_of?(@group).should == true
94
+ end
95
+
96
+ it "should leave a group" do
97
+ @user.join(@group)
98
+ @user.leave(@group).should == true
99
+ @user.member_of?(@group).should_not == true
100
+ end
101
+
102
+ describe "retrieval" do
103
+ before :each do
104
+ @user3 = Fabricate(:user)
105
+ @user.track(@user2)
106
+ @user.block(@user3)
107
+ @user.join(@group)
108
+ @user2.join(@group)
109
+ @user3.join(@group)
110
+ end
111
+
112
+ it "should return tracked entities" do
113
+ @user.tracking.include?(@user2).should == true
114
+ end
115
+
116
+ it "should return trackers" do
117
+ @user2.trackers.include?(@user).should == true
118
+ end
119
+
120
+ it "should return blocked entities" do
121
+ @user.blocked.include?(@user3).should == true
122
+ end
123
+
124
+ it "should return joined groups" do
125
+ @user.groups.include?(@group).should == true
126
+ end
127
+
128
+ it "should return group members" do
129
+ @group.members.should == [@user, @user2, @user3]
130
+ end
131
+ end
132
+
133
+ describe "blocking entities" do
134
+ it "should remove the tracking relation if it exists" do
135
+ @user.track(@user2)
136
+ @user2.track(@user)
137
+ @user.block(@user2)
138
+
139
+ @user.tracks?(@user2).should_not == true
140
+ @user2.tracks?(@user).should_not == true
141
+ end
142
+ end
143
+
144
+ describe "groups" do
145
+ it "should track the group automatically when an entity joins" do
146
+ @user.join(@group)
147
+ @user.tracks?(@group).should == true
148
+ end
149
+
150
+ it "should untrack the group automatically when an entity leaves" do
151
+ @user.join(@group)
152
+ @user.leave(@group)
153
+ @user.tracks?(@group).should_not == true
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,49 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Tekeya" do
4
+ describe "Notification" do
5
+ before :each do
6
+ @user = Fabricate(:user)
7
+ @user1 = Fabricate(:user)
8
+ end
9
+
10
+ describe "DSL" do
11
+ before :each do
12
+ @user1.track @user
13
+ @user.notifications.poked_by @user1
14
+
15
+ @user2 = Fabricate(:user)
16
+ @user3 = Fabricate(:user)
17
+ @user4 = Fabricate(:user)
18
+
19
+ @status = Fabricate(:status)
20
+ end
21
+
22
+ it "should notify the entity with the proper notification data" do
23
+ tracked_notification = @user.notifications.first
24
+
25
+ tracked_notification.notification_type.should == "tracked_by"
26
+ tracked_notification.subject.should == @user
27
+ tracked_notification.actors.map(&:attachable_id).include?(@user1.id).should == true
28
+
29
+ poked_notification = @user.notifications.last
30
+
31
+ poked_notification.notification_type.should == "poked_by"
32
+ poked_notification.subject.should == @user
33
+ poked_notification.actors.map(&:attachable_id).include?(@user1.id).should == true
34
+ end
35
+
36
+ it "should notify multiple entities" do
37
+ Tekeya::Notification.notify! [@user2, @user3, @user4], :posted, @status, @user
38
+
39
+ ((@user2.notifications == @user3.notifications) == (@user4.notifications == 1)).should == true
40
+ end
41
+
42
+ it "should return unread notifications correctly" do
43
+ @user.notifications.first.read!
44
+ @user.notifications.unread.count.should == 1
45
+ end
46
+ end
47
+
48
+ end
49
+ end