gnip-gnip 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data/README +144 -0
  2. data/Rakefile +221 -0
  3. data/TODO +72 -0
  4. data/bin/gnip +651 -0
  5. data/doc/api.html +1201 -0
  6. data/gemspec.rb +25 -0
  7. data/gnip-ruby.gemspec +26 -0
  8. data/lib/gnip.rb +71 -0
  9. data/lib/gnip/activity.rb +665 -0
  10. data/lib/gnip/api.rb +191 -0
  11. data/lib/gnip/arguments.rb +21 -0
  12. data/lib/gnip/blankslate.rb +5 -0
  13. data/lib/gnip/config.rb +144 -0
  14. data/lib/gnip/filter.rb +311 -0
  15. data/lib/gnip/list.rb +126 -0
  16. data/lib/gnip/options.rb +96 -0
  17. data/lib/gnip/orderedhash.rb +199 -0
  18. data/lib/gnip/publisher.rb +316 -0
  19. data/lib/gnip/resource.rb +301 -0
  20. data/lib/gnip/template.rb +44 -0
  21. data/lib/gnip/util.rb +120 -0
  22. data/sample/data/activity.yml +21 -0
  23. data/test/auth.rb +60 -0
  24. data/test/config.yml +2 -0
  25. data/test/data/activity.xml +14 -0
  26. data/test/data/activity_only_required.xml +4 -0
  27. data/test/data/activity_with_payload.xml +22 -0
  28. data/test/data/activity_with_place.xml +18 -0
  29. data/test/data/activity_with_place_wo_bounds.xml +36 -0
  30. data/test/data/activity_with_unbounded_media_urls.xml +44 -0
  31. data/test/data/activity_without_bounds.xml +24 -0
  32. data/test/helper.rb +115 -0
  33. data/test/integration/auth.rb +12 -0
  34. data/test/integration/publisher.rb +86 -0
  35. data/test/lib/shoulda.rb +9 -0
  36. data/test/lib/shoulda/action_controller.rb +28 -0
  37. data/test/lib/shoulda/action_controller/helpers.rb +47 -0
  38. data/test/lib/shoulda/action_controller/macros.rb +277 -0
  39. data/test/lib/shoulda/action_controller/matchers.rb +37 -0
  40. data/test/lib/shoulda/action_controller/matchers/assign_to_matcher.rb +109 -0
  41. data/test/lib/shoulda/action_controller/matchers/filter_param_matcher.rb +57 -0
  42. data/test/lib/shoulda/action_controller/matchers/render_with_layout_matcher.rb +81 -0
  43. data/test/lib/shoulda/action_controller/matchers/respond_with_content_type_matcher.rb +70 -0
  44. data/test/lib/shoulda/action_controller/matchers/respond_with_matcher.rb +77 -0
  45. data/test/lib/shoulda/action_controller/matchers/route_matcher.rb +93 -0
  46. data/test/lib/shoulda/action_controller/matchers/set_session_matcher.rb +83 -0
  47. data/test/lib/shoulda/action_controller/matchers/set_the_flash_matcher.rb +85 -0
  48. data/test/lib/shoulda/action_mailer.rb +10 -0
  49. data/test/lib/shoulda/action_mailer/assertions.rb +38 -0
  50. data/test/lib/shoulda/action_view.rb +10 -0
  51. data/test/lib/shoulda/action_view/macros.rb +56 -0
  52. data/test/lib/shoulda/active_record.rb +16 -0
  53. data/test/lib/shoulda/active_record/assertions.rb +69 -0
  54. data/test/lib/shoulda/active_record/helpers.rb +40 -0
  55. data/test/lib/shoulda/active_record/macros.rb +586 -0
  56. data/test/lib/shoulda/active_record/matchers.rb +42 -0
  57. data/test/lib/shoulda/active_record/matchers/allow_mass_assignment_of_matcher.rb +83 -0
  58. data/test/lib/shoulda/active_record/matchers/allow_value_matcher.rb +102 -0
  59. data/test/lib/shoulda/active_record/matchers/association_matcher.rb +226 -0
  60. data/test/lib/shoulda/active_record/matchers/ensure_inclusion_of_matcher.rb +87 -0
  61. data/test/lib/shoulda/active_record/matchers/ensure_length_of_matcher.rb +141 -0
  62. data/test/lib/shoulda/active_record/matchers/have_db_column_matcher.rb +169 -0
  63. data/test/lib/shoulda/active_record/matchers/have_index_matcher.rb +105 -0
  64. data/test/lib/shoulda/active_record/matchers/have_named_scope_matcher.rb +125 -0
  65. data/test/lib/shoulda/active_record/matchers/have_readonly_attribute_matcher.rb +59 -0
  66. data/test/lib/shoulda/active_record/matchers/validate_acceptance_of_matcher.rb +41 -0
  67. data/test/lib/shoulda/active_record/matchers/validate_numericality_of_matcher.rb +39 -0
  68. data/test/lib/shoulda/active_record/matchers/validate_presence_of_matcher.rb +60 -0
  69. data/test/lib/shoulda/active_record/matchers/validate_uniqueness_of_matcher.rb +148 -0
  70. data/test/lib/shoulda/active_record/matchers/validation_matcher.rb +56 -0
  71. data/test/lib/shoulda/assertions.rb +59 -0
  72. data/test/lib/shoulda/autoload_macros.rb +46 -0
  73. data/test/lib/shoulda/context.rb +304 -0
  74. data/test/lib/shoulda/helpers.rb +8 -0
  75. data/test/lib/shoulda/macros.rb +73 -0
  76. data/test/lib/shoulda/private_helpers.rb +20 -0
  77. data/test/lib/shoulda/proc_extensions.rb +14 -0
  78. data/test/lib/shoulda/rails.rb +13 -0
  79. data/test/lib/shoulda/rspec.rb +9 -0
  80. data/test/lib/shoulda/tasks.rb +3 -0
  81. data/test/lib/shoulda/tasks/list_tests.rake +29 -0
  82. data/test/lib/shoulda/tasks/yaml_to_shoulda.rake +28 -0
  83. data/test/lib/shoulda/test_unit.rb +19 -0
  84. data/test/lib/xmlsimple.rb +1021 -0
  85. data/test/loader.rb +25 -0
  86. data/test/unit/activity.rb +26 -0
  87. data/test/unit/util.rb +39 -0
  88. metadata +158 -0
@@ -0,0 +1,21 @@
1
+ ---
2
+ at: 2009-01-01
3
+ action: post
4
+ sources:
5
+ - one
6
+ - two
7
+ actors:
8
+ -
9
+ content: jane
10
+ uid: 1234
11
+ - john
12
+ places:
13
+ -
14
+ elev : 5000
15
+ point : [40, 102]
16
+ payload:
17
+ body: foobar
18
+ raw: @sample/data/activity.yml
19
+ media_urls:
20
+ content: http://media.fukung.net/images/2662/westley_willis.jpg
21
+ height: 42
@@ -0,0 +1,60 @@
1
+ # ensure gnip auth info is configured for integration tests
2
+ #
3
+ require 'yaml'
4
+
5
+ $config =
6
+ begin
7
+ YAML.load(IO.read(File.expand_path('~/.gnip.yml')))
8
+ rescue
9
+ begin
10
+ YAML.load(IO.read('test/gnip.yml'))
11
+ rescue
12
+ {}
13
+ end
14
+ end
15
+
16
+ $username = $config['username']||ENV['GNIP_USERNAME']||ENV['gnip_username']||ENV['USERNAME']||ENV['username']
17
+ $password = $config['password']||ENV['GNIP_PASSWORD']||ENV['gnip_password']||ENV['PASSWORD']||ENV['password']
18
+
19
+ unless $username and $password
20
+ div = '=' * 79
21
+
22
+ message = <<-message
23
+ #{ div }
24
+
25
+ you need to have a gnip account and set both your username and password
26
+ in the environment to run integration tests. you can get a gnip account
27
+ at
28
+
29
+ http://gnip.com/
30
+
31
+ there are 3 ways to setup your username and password for the tests
32
+
33
+ 1. via the environment variable:
34
+
35
+ export GNIP_USERNAME=your.username@domain.org
36
+ export GNIP_PASSWORD=your-password
37
+
38
+
39
+ 2. pass them in as rake variables:
40
+
41
+ rake username=me@domain.org password=secret
42
+ rake test:unit username=me@domain.org password=secret
43
+ rake test:integration USERNAME=me@domain.org PASSWORD=secret
44
+
45
+
46
+ 3. edit either ~/gnip.yml or ./test/gnip.yml to look similar to this
47
+
48
+ username : your.username@domain.org
49
+ password : your_password
50
+
51
+ #{ div }
52
+ message
53
+
54
+ indent = message[ %r/^([\s]+)[^\s]/ ].to_s
55
+ message.gsub!(%r/^#{ indent }/, '')
56
+ abort message
57
+ end
58
+
59
+ ENV['GNIP_USERNAME'] = $username
60
+ ENV['GNIP_PASSWORD'] = $password
@@ -0,0 +1,2 @@
1
+ username : username
2
+ password : password
@@ -0,0 +1,14 @@
1
+ <activity>
2
+ <regardingURL>http://blogger.com/users/posts/mary</regardingURL>
3
+ <activityID>yk994589klsl</activityID>
4
+ <actor metaURL="http://www.gnipcentral.com/users/joe" uid="1222">
5
+ Joe</actor>
6
+ <tag metaURL="http://gnipcentral.com/tags/horses">horses</tag>
7
+ <URL>http://www.gnipcentral.com</URL>
8
+ <action>post</action>
9
+ <destinationURL>http://somewhere.com/someplace</destinationURL>
10
+ <to metaURL="http://gnipcentral.com/users/mary">Mary</to>
11
+ <at>2008-07-02T11:16:16.000Z</at>
12
+ <keyword>ping</keyword>
13
+ <source>web</source>
14
+ </activity>
@@ -0,0 +1,4 @@
1
+ <activity>
2
+ <action>post</action>
3
+ <at>2008-07-02T11:16:16.000Z</at>
4
+ </activity>
@@ -0,0 +1,22 @@
1
+ <activity>
2
+ <place>
3
+ <point>45.256 -71.92</point>
4
+ </place>
5
+ <regardingURL metaURL="http://blogger.com/users/mary">
6
+ http://blogger.com/users/posts/mary</regardingURL>
7
+ <payload>
8
+ <body>woot</body>
9
+ <raw>H4sIAPGGyEkAAytIrMzJT0wBABVqLEIHAAAA</raw>
10
+ </payload>
11
+ <actor metaURL="http://www.gnipcentral.com/users/joe" uid="1222">
12
+ Joe</actor>
13
+ <tag metaURL="http://gnipcentral.com/tags/horses">horses</tag>
14
+ <URL>http://www.gnipcentral.com</URL>
15
+ <action>post</action>
16
+ <destinationURL metaURL="http://somewhere.com/someplace">
17
+ http://somewhere.com</destinationURL>
18
+ <to metaURL="http://gnipcentral.com/users/mary">Mary</to>
19
+ <at>2008-07-02T11:16:16.000Z</at>
20
+ <keyword>ping</keyword>
21
+ <source>web</source>
22
+ </activity>
@@ -0,0 +1,18 @@
1
+ <activity>
2
+ <place>
3
+ <point>45.256 -71.92</point>
4
+ </place>
5
+ <regardingURL metaURL="http://blogger.com/users/mary">
6
+ http://blogger.com/users/posts/mary</regardingURL>
7
+ <actor metaURL="http://www.gnipcentral.com/users/joe" uid="1222">
8
+ Joe</actor>
9
+ <tag metaURL="http://gnipcentral.com/tags/horses">horses</tag>
10
+ <URL>http://www.gnipcentral.com</URL>
11
+ <action>post</action>
12
+ <destinationURL metaURL="http://somewhere.com/someplace">
13
+ http://somewhere.com</destinationURL>
14
+ <to metaURL="http://gnipcentral.com/users/mary">Mary</to>
15
+ <at>2008-07-02T11:16:16.000Z</at>
16
+ <keyword>ping</keyword>
17
+ <source>web</source>
18
+ </activity>
@@ -0,0 +1,36 @@
1
+ <activity>
2
+ <place>
3
+ <point>45.256 -71.92</point>
4
+ </place>
5
+ <place>
6
+ <featurename>Boulder</featurename>
7
+ <featuretypetag>City</featuretypetag>
8
+ <floor>3</floor>
9
+ <point>22.778 -54.998</point>
10
+ <elev>5280</elev>
11
+ </place>
12
+ <place>
13
+ <point>77.900 -23.998</point>
14
+ </place>
15
+ <regardingURL metaURL="http://blogger.com/users/mary">
16
+ http://blogger.com/users/posts/mary</regardingURL>
17
+ <regardingURL>http://blogger.com/users/posts/james</regardingURL>
18
+ <actor metaURL="http://www.gnipcentral.com/users/joe" uid="1222">
19
+ Joe</actor>
20
+ <actor metaURL="http://www.gnipcentral.com/users/bob">Bob</actor>
21
+ <actor uid="1444">Susan</actor>
22
+ <tag metaURL="http://gnipcentral.com/tags/horses">horses</tag>
23
+ <tag>cows</tag>
24
+ <URL>http://www.gnipcentral.com</URL>
25
+ <action>post</action>
26
+ <destinationURL>http://somewhere.com</destinationURL>
27
+ <destinationURL>http://somewhere.com/someplace</destinationURL>
28
+ <destinationURL>http://flickr.com</destinationURL>
29
+ <to metaURL="http://gnipcentral.com/users/mary">Mary</to>
30
+ <to>James</to>
31
+ <at>2008-07-02T11:16:16.000Z</at>
32
+ <keyword>ping</keyword>
33
+ <keyword>pong</keyword>
34
+ <source>web</source>
35
+ <source>sms</source>
36
+ </activity>
@@ -0,0 +1,44 @@
1
+ <activity>
2
+ <place>
3
+ <point>45.256 -71.92</point>
4
+ </place>
5
+ <place>
6
+ <featurename>Boulder</featurename>
7
+ <featuretypetag>City</featuretypetag>
8
+ <floor>3</floor>
9
+ <point>22.778 -54.998</point>
10
+ <elev>5280</elev>
11
+ </place>
12
+ <place>
13
+ <point>77.900 -23.998</point>
14
+ </place>
15
+ <regardingURL metaURL="http://blogger.com/users/mary">
16
+ http://blogger.com/users/posts/mary</regardingURL>
17
+ <regardingURL>http://blogger.com/users/posts/james</regardingURL>
18
+ <payload>
19
+ <mediaURL mimeType="image/png" type="image">
20
+ http://www.flickr.com/tour</mediaURL>
21
+ <mediaURL mimeType="video/quicktime" type="movie">
22
+ http://www.gnipcentral.com/login</mediaURL>
23
+ <body>title</body>
24
+ <raw>H4sIAJuPyEkAAytIrMzJT0wBABVqLEIHAAAA</raw>
25
+ </payload>
26
+ <actor metaURL="http://www.gnipcentral.com/users/joe" uid="1222">
27
+ Joe</actor>
28
+ <actor metaURL="http://www.gnipcentral.com/users/bob">Bob</actor>
29
+ <actor uid="1444">Susan</actor>
30
+ <tag metaURL="http://gnipcentral.com/tags/horses">horses</tag>
31
+ <tag>cows</tag>
32
+ <URL>http://www.gnipcentral.com</URL>
33
+ <action>post</action>
34
+ <destinationURL>http://somewhere.com</destinationURL>
35
+ <destinationURL>http://somewhere.com/someplace</destinationURL>
36
+ <destinationURL>http://flickr.com</destinationURL>
37
+ <to metaURL="http://gnipcentral.com/users/mary">Mary</to>
38
+ <to>James</to>
39
+ <at>2008-07-02T11:16:16.000Z</at>
40
+ <keyword>ping</keyword>
41
+ <keyword>pong</keyword>
42
+ <source>web</source>
43
+ <source>sms</source>
44
+ </activity>
@@ -0,0 +1,24 @@
1
+ <activity>
2
+ <regardingURL metaURL="http://blogger.com/users/mary">
3
+ http://blogger.com/users/posts/mary</regardingURL>
4
+ <regardingURL>http://blogger.com/users/posts/james</regardingURL>
5
+ <actor metaURL="http://www.gnipcentral.com/users/joe" uid="1222">
6
+ Joe</actor>
7
+ <actor metaURL="http://www.gnipcentral.com/users/bob">Bob</actor>
8
+ <actor uid="1444">Susan</actor>
9
+ <tag metaURL="http://gnipcentral.com/tags/horses">horses</tag>
10
+ <tag>cows</tag>
11
+ <URL>http://www.gnipcentral.com</URL>
12
+ <action>post</action>
13
+ <destinationURL>http://somewhere.com</destinationURL>
14
+ <destinationURL metaURL='http://foo.com'>
15
+ http://somewhere.com/someplace</destinationURL>
16
+ <destinationURL>http://flickr.com</destinationURL>
17
+ <to metaURL="http://gnipcentral.com/users/mary">Mary</to>
18
+ <to>James</to>
19
+ <at>2008-07-02T11:16:16.000Z</at>
20
+ <keyword>ping</keyword>
21
+ <keyword>pong</keyword>
22
+ <source>web</source>
23
+ <source>sms</source>
24
+ </activity>
@@ -0,0 +1,115 @@
1
+ module Gnip
2
+ module Test
3
+ module Helper
4
+ def xml_in s
5
+ @eq_all_but_zero ||= Object.new.instance_eval do
6
+ def ==(other)
7
+ Integer(other) == 0 ? false : true
8
+ end
9
+ self
10
+ end
11
+
12
+ s = "#{ s }"
13
+
14
+ # munge some hard to compare stuff!
15
+ #
16
+ s.gsub! %r|\<raw\>.*?\</raw\>|mo, '<raw></raw>'
17
+
18
+ s.gsub!(%r|\<point\>(.*?)\</point\>|mo) do
19
+ content = Activity::Place::Point.for($1).to_s
20
+ "<point>#{ content }</point>"
21
+ end
22
+
23
+ s = XmlSimple.xml_in(s, 'normalisespace' => @eq_all_but_zero)
24
+ end
25
+ def xml_out o
26
+ XmlSimple.xml_out(o)
27
+ end
28
+ def xml_normalized s
29
+ xml_out(xml_in(s))
30
+ end
31
+ def xml_obj s
32
+ xml_in(xml_out(xml_in(s)))
33
+ end
34
+ def xml_cmp!(a, b)
35
+ a = xml_in(a)
36
+ b = xml_in(b)
37
+
38
+ #return a==b
39
+ a_keys = a.keys.sort
40
+ b_keys = b.keys.sort
41
+ unless a_keys==b_keys
42
+ STDERR.puts a_keys.inspect
43
+ STDERR.puts ' !='
44
+ STDERR.puts b_keys.inspect
45
+ abort
46
+ end
47
+ keys = a_keys.dup
48
+ a_values = keys.map{|k| a[k]}
49
+ b_values = keys.map{|k| b[k]}
50
+ a_values.zip(b_values).each do |a_val, b_val|
51
+ unless a_val==b_val
52
+ STDERR.puts a_val.inspect
53
+ STDERR.puts ' !='
54
+ STDERR.puts b_val.inspect
55
+ abort
56
+ end
57
+ end
58
+ true
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+
65
+ module Kernel
66
+ private
67
+ def Test(*args, &block)
68
+ Class.new(::Test::Unit::TestCase) do
69
+ include Gnip::Test::Helper
70
+ args.push 'default' if args.empty?
71
+ context(*args, &block)
72
+ end
73
+ end
74
+ end
75
+
76
+
77
+ __END__
78
+
79
+
80
+ module Gnip
81
+ module Test
82
+ Helper = lambda do
83
+ @@should = 0
84
+
85
+ def Test.should description, &block
86
+ desc = description.to_s.scan(%r/\w+/).join('__')
87
+ define_method("test_#{ '%03.3d' % (@@should+=1) }_#{ desc }", &block)
88
+ end
89
+
90
+ def xml_cmp(a, b)
91
+ eq_all_but_zero = Object.new.instance_eval do
92
+ def ==(other)
93
+ Integer(other) == 0 ? false : true
94
+ end
95
+ self
96
+ end
97
+ a = XmlSimple.xml_in(a.to_s, 'normalisespace' => eq_all_but_zero)
98
+ b = XmlSimple.xml_in(b.to_s, 'normalisespace' => eq_all_but_zero)
99
+ a == b
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ module Kernel
106
+ private
107
+ def Test(*args, &block)
108
+ Class.new(::Test::Unit::TestCase) do
109
+ module_eval &::Gnip::Test::Helper
110
+ module_eval &block
111
+ end
112
+ end
113
+ end
114
+
115
+ __END__
@@ -0,0 +1,12 @@
1
+ Class.new(Test::Unit::TestCase) do
2
+ context 'with username and password configured' do
3
+ setup do
4
+ assert( Gnip.username = ENV['GNIP_USERNAME'] )
5
+ assert( Gnip.password = ENV['GNIP_PASSWORD'] )
6
+ end
7
+
8
+ should 'be able to do an authenticated ping' do
9
+ assert_nothing_raised{ assert Gnip.ping }
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,86 @@
1
+ Class.new(Test::Unit::TestCase) do
2
+ context 'with username and password configured' do
3
+ setup do
4
+ assert( Gnip.username = ENV['GNIP_USERNAME'] )
5
+ assert( Gnip.password = ENV['GNIP_PASSWORD'] )
6
+ end
7
+
8
+ should 'be able to retreive a list of /gnip publishers' do
9
+ list = nil
10
+ assert_nothing_raised{ assert list=Gnip.publisher.list }
11
+ assert list
12
+ assert !list.empty?, 'not empty list'
13
+ list.each do |object|
14
+ assert object.respond_to?(:name), 'responds_to?(:name)'
15
+ assert object.respond_to?(:rules), 'responds_to?(:rules)'
16
+ end
17
+ end
18
+
19
+ should 'be able to get the notifications for publishers' do
20
+ list = nil
21
+ assert_nothing_raised{ assert list=Gnip.publisher.list }
22
+ assert list
23
+ list.each do |publisher|
24
+ notifications = nil
25
+ assert_nothing_raised{ assert notifications=publisher.notifications }
26
+ assert notifications
27
+ end
28
+ end
29
+
30
+ should 'be able to retreive a list of /my publishers' do
31
+ list = nil
32
+ assert_nothing_raised{ assert list=Gnip.publisher.list(:scope => 'my') }
33
+ assert list
34
+ end
35
+
36
+ should 'be able to retreive a given publisher by name in the /gnip scope' do
37
+ publisher = nil
38
+ name = 'gnip-sample'
39
+ assert_nothing_raised{ publisher = Gnip.publisher.for(name) }
40
+ assert publisher
41
+ assert name, publisher.name
42
+ end
43
+
44
+ should 'be able to retreive a given publisher with their rules boy!' do
45
+ publisher = nil
46
+ name = 'gnip-sample'
47
+ assert_nothing_raised{ publisher = Gnip.publisher.for(name) }
48
+ assert publisher
49
+ assert name, publisher.name
50
+ rules = []
51
+ assert_nothing_raised{ rules = publisher.rules }
52
+ assert !rules.empty?
53
+ assert Gnip.publisher.rule.list.include?(rules.first)
54
+ assert Gnip.publisher.rule.list.include?(rules.last)
55
+ end
56
+
57
+ context 'creating and destroying publishers' do
58
+ setup do
59
+ @hostname = Socket.gethostname rescue `hostname`.strip
60
+ @hostname = Array.new(4).map{ rand(256) }.join('.') if @hostname.strip.empty?
61
+ @hostname = @hostname.to_s.gsub %r/[^a-zA-Z0-9]/, '-'
62
+ @name = "gnip-ruby-integration-test-#{ @hostname }"
63
+ @rules = Gnip.publisher.rule.list
64
+ end
65
+
66
+ should 'be able to create and delete a publisher in the /my scope' do
67
+ publisher = Gnip.publisher.exists?(@name, :scope => :my)
68
+ if publisher
69
+ assert_nothing_raised{ Gnip.publisher.delete(@name, :scope => :my) }
70
+ assert !Gnip.publisher.exists?(@name, :scope => :my)
71
+ end
72
+
73
+ publisher = nil
74
+ assert_nothing_raised{ publisher = Gnip.publisher.create(@name, :scope => :my, :rules => @rules) }
75
+ assert publisher
76
+ assert_equal publisher.name, @name
77
+ assert_equal publisher.scope.to_s, 'my'
78
+
79
+ deleted = nil
80
+ assert_nothing_raised{ deleted = publisher.delete }
81
+ assert deleted
82
+ assert deleted.name, publisher.name
83
+ end
84
+ end
85
+ end
86
+ end