rtunesu 0.2.4 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. data/.gitignore +3 -0
  2. data/History.txt +0 -5
  3. data/README.txt +2 -2
  4. data/Rakefile +15 -2
  5. data/VERSION +1 -0
  6. data/lib/rtunesu/connection.rb +152 -54
  7. data/lib/rtunesu/document.rb +21 -26
  8. data/lib/rtunesu/entities/course.rb +4 -13
  9. data/lib/rtunesu/entities/division.rb +5 -12
  10. data/lib/rtunesu/entities/external_feed.rb +14 -0
  11. data/lib/rtunesu/entities/group.rb +5 -14
  12. data/lib/rtunesu/entities/permission.rb +1 -5
  13. data/lib/rtunesu/entities/section.rb +15 -11
  14. data/lib/rtunesu/entities/site.rb +6 -13
  15. data/lib/rtunesu/entities/template.rb +4 -0
  16. data/lib/rtunesu/entities/theme.rb +3 -15
  17. data/lib/rtunesu/entities/track.rb +12 -27
  18. data/lib/rtunesu/entity.rb +185 -74
  19. data/lib/rtunesu/log.rb +69 -0
  20. data/lib/rtunesu/subentities.rb +60 -0
  21. data/lib/rtunesu/user.rb +3 -1
  22. data/lib/rtunesu/version.rb +2 -2
  23. data/lib/rtunesu.rb +11 -6
  24. data/lib/show_tree.xml +7 -0
  25. data/spec/connection_spec.rb +6 -30
  26. data/spec/document_spec.rb +82 -8
  27. data/spec/entities/course_spec.rb +13 -40
  28. data/spec/entities/division_spec.rb +13 -3
  29. data/spec/entities/external_feed_spec.rb +21 -0
  30. data/spec/entities/group_spec.rb +14 -3
  31. data/spec/entities/permission_spec.rb +12 -3
  32. data/spec/entities/section_spec.rb +32 -3
  33. data/spec/entities/site_spec.rb +16 -3
  34. data/spec/entities/track_spec.rb +32 -3
  35. data/spec/entity_spec.rb +147 -86
  36. data/spec/fixtures/requests/create_course.xml +17 -0
  37. data/spec/fixtures/requests/create_division.xml +11 -0
  38. data/spec/fixtures/requests/create_group.xml +11 -0
  39. data/spec/fixtures/requests/create_section.xml +11 -0
  40. data/spec/fixtures/requests/delete_course.xml +8 -0
  41. data/spec/fixtures/requests/delete_group.xml +8 -0
  42. data/spec/fixtures/requests/delete_section.txt +8 -0
  43. data/spec/fixtures/requests/show_course.xml +8 -0
  44. data/spec/fixtures/requests/show_group.xml +8 -0
  45. data/spec/fixtures/requests/show_section.xml +8 -0
  46. data/spec/fixtures/requests/update_course.xml +10 -0
  47. data/spec/fixtures/requests/update_group.xml +9 -0
  48. data/spec/fixtures/requests/update_section.txt +10 -0
  49. data/spec/fixtures/responses/failure/create_course.xml +5 -0
  50. data/spec/fixtures/responses/failure/create_division.xml +5 -0
  51. data/spec/fixtures/responses/failure/create_group.xml +5 -0
  52. data/spec/fixtures/responses/failure/create_section.xml +5 -0
  53. data/spec/fixtures/responses/failure/delete_group.xml +5 -0
  54. data/spec/fixtures/responses/failure/show_course.xml +11 -0
  55. data/spec/fixtures/responses/failure/show_division.xml +11 -0
  56. data/spec/fixtures/responses/failure/show_group.xml +11 -0
  57. data/spec/fixtures/responses/failure/show_section.xml +11 -0
  58. data/spec/fixtures/responses/failure/show_site.xml +11 -0
  59. data/spec/fixtures/responses/failure/update_section.txt +5 -0
  60. data/spec/fixtures/responses/success/create_course.xml +5 -0
  61. data/spec/fixtures/responses/success/create_division.xml +5 -0
  62. data/spec/fixtures/responses/success/create_group.xml +5 -0
  63. data/spec/fixtures/responses/success/create_section.xml +5 -0
  64. data/spec/fixtures/responses/success/delete_course.xml +4 -0
  65. data/spec/fixtures/responses/success/delete_division.xml +4 -0
  66. data/spec/fixtures/responses/success/delete_group.xml +4 -0
  67. data/spec/fixtures/responses/success/delete_section.txt +4 -0
  68. data/spec/fixtures/responses/success/delete_section.xml +4 -0
  69. data/spec/fixtures/responses/success/show_course.xml +393 -0
  70. data/spec/fixtures/responses/success/show_division.xml +393 -0
  71. data/spec/fixtures/responses/success/show_group.xml +137 -0
  72. data/spec/fixtures/responses/success/show_section.xml +152 -0
  73. data/spec/fixtures/responses/success/show_site.xml +393 -0
  74. data/spec/fixtures/responses/success/update_course.xml +4 -0
  75. data/spec/fixtures/responses/success/update_division.xml +4 -0
  76. data/spec/fixtures/responses/success/update_group.xml +4 -0
  77. data/spec/fixtures/responses/success/update_section.txt +4 -0
  78. data/spec/fixtures/responses/success/update_section.xml +4 -0
  79. data/spec/fixtures/responses/success/update_site.xml +4 -0
  80. data/spec/spec_helper.rb +72 -7
  81. data/spec/token_generation_spec.rb +23 -0
  82. data/spec/user_spec.rb +3 -3
  83. metadata +81 -76
  84. data/Manifest.txt +0 -77
  85. data/config/hoe.rb +0 -76
  86. data/config/requirements.rb +0 -15
  87. data/lib/multipart.rb +0 -53
  88. data/spec/documents/add_spec.rb +0 -41
  89. data/spec/documents/delete_spec.rb +0 -30
  90. data/spec/documents/merge_spec.rb +0 -30
  91. data/spec/documents/show_tree_spec.rb +0 -16
  92. data/spec/fixtures/add_course.xml +0 -26
  93. data/spec/fixtures/add_division.xml +0 -26
  94. data/spec/fixtures/add_group.xml +0 -27
  95. data/spec/fixtures/add_permission.xml +0 -12
  96. data/spec/fixtures/add_section.xml +0 -34
  97. data/spec/fixtures/add_track.xml +0 -19
  98. data/spec/fixtures/delete_course.xml +0 -8
  99. data/spec/fixtures/delete_division.xml +0 -8
  100. data/spec/fixtures/delete_group.xml +0 -8
  101. data/spec/fixtures/delete_permission.xml +0 -9
  102. data/spec/fixtures/delete_section.xml +0 -8
  103. data/spec/fixtures/delete_track.xml +0 -7
  104. data/spec/fixtures/merge_course.xml +0 -38
  105. data/spec/fixtures/merge_division.xml +0 -47
  106. data/spec/fixtures/merge_group.xml +0 -29
  107. data/spec/fixtures/merge_permission.xml +0 -12
  108. data/spec/fixtures/merge_section.xml +0 -36
  109. data/spec/fixtures/merge_site.xml +0 -31
  110. data/spec/fixtures/merge_track.xml +0 -18
  111. data/spec/fixtures/requests/add_coures_request.xml +0 -0
  112. data/spec/fixtures/show_tree.xml +0 -273
  113. data/spec/fixtures/update_group.xml +0 -7
  114. data/tasks/deployment.rake +0 -34
  115. data/tasks/website.rake +0 -17
  116. data/website/index.html +0 -54
  117. data/website/index.txt +0 -7
  118. data/website/javascripts/rounded_corners_lite.inc.js +0 -285
  119. data/website/stylesheets/screen.css +0 -138
  120. data/website/template.html.erb +0 -48
@@ -1,16 +1,90 @@
1
1
  require File.dirname(__FILE__) + '/spec_helper.rb'
2
2
  include RTunesU
3
+ include Document
3
4
 
4
- describe Document do
5
- before(:all) do
6
- @xml = Document::Merge.new(Course.new).xml
5
+ [Course, Division, Section, Group].each do |klass|
6
+ [:Add, :Merge, :Delete].each do |action|
7
+ describe "Document building for #{klass} for #{action}" do
8
+ before(:each) do
9
+ @entity = klass.new
10
+ @entity.parent_handle = '1'
11
+ @document = Hpricot.XML(Document.const_get(action).new(@entity).xml)
12
+ end
13
+
14
+ it "should have a base element of ITunesUDocument" do
15
+ @document.at("ITunesUDocument").should_not be_nil
16
+ end
17
+
18
+ it "should have a Version element with the iTunesU Version as content" do
19
+ @document.at("ITunesUDocument/Version").should_not be_nil
20
+ end
21
+ end
7
22
  end
8
23
 
9
- it 'includes a base element of ITunesUDocument' do
10
- (Hpricot.XML(@xml) % 'ITunesUDocument').should_not be_nil
24
+ describe "Document::Add for #{klass}" do
25
+ before(:each) do
26
+ @entity = klass.new
27
+ @entity.parent_handle = '1'
28
+ @document = Hpricot.XML(Document::Add.new(@entity).xml)
29
+ end
30
+
31
+ it "should raise error without parent handle" do
32
+ @entity.parent_handle = nil
33
+ lambda { Hpricot.XML(Document::Add.new(@entity).xml) }.should raise_error(MissingParent)
34
+ end
35
+
36
+ it "should have a Add element" do
37
+ @document.at("ITunesUDocument/Add#{@entity.class_name}").should_not be_nil
38
+ end
39
+
40
+ it "should have a ParentHandle element" do
41
+ @document.at("ITunesUDocument/Add#{@entity.class_name}/ParentHandle").should_not be_nil
42
+ end
43
+
44
+ it "should have a ParentPath element" do
45
+ @document.at("ITunesUDocument/Add#{@entity.class_name}/ParentPath").should_not be_nil
46
+ end
47
+
48
+ it "should have an element for its Entity" do
49
+ @document.at("ITunesUDocument/Add#{@entity.class_name}/#{@entity.class_name}").should_not be_nil
50
+ end
11
51
  end
12
52
 
13
- it 'includes a version number' do
14
- (Hpricot.XML(@xml) % 'ITunesUDocument/Version').should_not be_nil
53
+ describe "Document::Merge for #{klass}" do
54
+ before(:each) do
55
+ @entity = klass.new
56
+ @document = Hpricot.XML(Document::Merge.new(@entity).xml)
57
+ end
58
+
59
+ it "should have a Merge element" do
60
+ @document.at("ITunesUDocument/Merge#{@entity.class_name}").should_not be_nil
61
+ end
62
+
63
+ it "should have a Handle element" do
64
+ @document.at("ITunesUDocument/Merge#{@entity.class_name}/#{@entity.class_name}Handle").should_not be_nil
65
+ end
66
+
67
+ it "should have an element for its Entity" do
68
+ @document.at("ITunesUDocument/Merge#{@entity.class_name}/#{@entity.class_name}").should_not be_nil
69
+ end
70
+ end
71
+
72
+ describe "Document::Delete for #{klass}" do
73
+ before(:each) do
74
+ @entity = klass.new
75
+ @document = Hpricot.XML(Document::Delete.new(@entity).xml)
76
+ end
77
+
78
+ it "should have a Delete element" do
79
+ @document.at("ITunesUDocument/Delete#{@entity.class_name}").should_not be_nil
80
+ end
81
+
82
+ it "should have a Handle element" do
83
+ @document.at("ITunesUDocument/Delete#{@entity.class_name}/#{@entity.class_name}Handle").should_not be_nil
84
+ end
85
+
86
+ it "should have a Path element" do
87
+ @document.at("ITunesUDocument/Delete#{@entity.class_name}/#{@entity.class_name}Path").should_not be_nil
88
+ end
15
89
  end
16
- end
90
+ end
@@ -1,47 +1,20 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+ require File.dirname(__FILE__) + '/../entity_spec.rb'
3
+ require File.dirname(__FILE__) + '/../document_spec.rb'
4
+
2
5
  include RTunesU
3
6
 
4
- describe Course do
5
- before do
6
- u = RTunesU::User.new(0, 'admin', 'Admin', 'admin@example.com')
7
- u.credentials = ['Administrator@urn:mace:example.edu']
8
- @connection = RTunesU::Connection.new(:user => u, :site => 'example.edu', :shared_secret => 'STRINGOFTHIRTYTWOLETTERSORDIGITS')
7
+ describe Course do
8
+ before(:each) do
9
+ @klass = Course
10
+ @entity = Course.new
11
+ @course = @entity
12
+ @attributes = {:name => 'Sample Course'}
9
13
  end
10
14
 
11
- describe 'finding' do
12
- it 'can find itself in iTunesU' do
13
- @connection.should_receive(:process).and_return(File.open(File.dirname(__FILE__) + '/../fixtures/responses/show_tree_course.xml'))
14
- @course = Course.find(1257981186, @connection)
15
- end
16
- end
15
+ it_should_behave_like "an Entity"
17
16
 
18
- describe ' after successful finding' do
19
- before(:all) do
20
- @connection.should_receive(:process).and_return(File.open(File.dirname(__FILE__) + '/../fixtures/responses/show_tree_course.xml'))
21
- @course = Course.find(1257981186, @connection)
22
- end
23
-
24
- it 'should access its attributes from the returned xml' do
25
- @course.Name.should eql('SI 539 001 W07')
26
- @course.Handle.should eql('1257981186')
27
- end
28
-
29
- it 'should find its parent element' do
30
- @course.parent.should be_an_instance_of(RTunesU::Section)
31
- end
32
-
33
- it 'should be able to find its groups (tabs)' do
34
- @course.Groups.should be_an_instance_of(Array)
35
- @course.Groups[0].should be_an_instance_of(RTunesU::Group)
36
- end
37
-
38
- it 'should be able to access it groups attributes' do
39
- @course.Groups[0].Handle.should eql('1257981189')
40
- end
41
-
42
- it 'should be able to access it groups tracks' do
43
- @course.Groups[0].Tracks.should be_an_instance_of(Array)
44
- @course.Groups[0].Tracks[0].should be_an_instance_of(RTunesU::Track)
45
- end
46
- end
17
+ it_should_be_composed_of :name, :instructor, :description, :identifier, :theme_handle, :short_name, :allow_subscription
18
+ it_should_be_composed_of_readonly :aggregate_file_size
19
+ it_should_have_many :permissions, :groups
47
20
  end
@@ -1,8 +1,18 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+ require File.dirname(__FILE__) + '/../entity_spec.rb'
2
3
  include RTunesU
3
4
 
4
5
  describe Division do
5
- it 'should find itself in iTunes U'
6
- it 'is valid'
7
- it 'converts itself to an xml document'
6
+ before(:each) do
7
+ @klass = Division
8
+ @entity = Division.new
9
+ @division = @entity
10
+ @attributes = {:name => 'Sample Division'}
11
+ end
12
+
13
+ it_should_behave_like "an Entity"
14
+
15
+ it_should_be_composed_of :name, :short_name, :identifier, :allow_subscription, :theme_handle, :description
16
+ it_should_be_composed_of_readonly :aggregate_file_size
17
+ it_should_have_many :permissions, :sections
8
18
  end
@@ -0,0 +1,21 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+ require File.dirname(__FILE__) + '/../entity_spec.rb'
3
+
4
+ include RTunesU
5
+
6
+ describe ExternalFeed do
7
+ before(:each) do
8
+ @klass = ExternalFeed
9
+ @entity = ExternalFeed.new
10
+ @external_feed = @entity
11
+ @attributes = {:owner_email => 'owner@exmaple.com'}
12
+ end
13
+
14
+ it_should_behave_like "an Entity with attribute assignment"
15
+ it_should_be_composed_of :polling_interval, :owner_email, :security_type, :signature_type, :basic_auth_username, :basic_auth_password
16
+
17
+ it "have a blank parent handle for polymorphism" do
18
+ @external_feed.parent_handle.should_not be_nil
19
+ @external_feed.parent_handle.should be_empty
20
+ end
21
+ end
@@ -1,8 +1,19 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+ require File.dirname(__FILE__) + '/../entity_spec.rb'
2
3
  include RTunesU
3
4
 
4
5
  describe Group do
5
- it 'should find itself in iTunes U'
6
- it 'is valid'
7
- it 'converts itself to an xml document'
6
+ before(:each) do
7
+ @klass = Group
8
+ @entity = Group.new
9
+ @group = @entity
10
+ @attributes = {:name => 'Sample Tab'}
11
+ end
12
+
13
+ it_should_behave_like "an Entity"
14
+
15
+ it_should_be_composed_of :name, :group_type, :short_name, :allow_subscription, :explicit
16
+ it_should_be_composed_of_readonly :aggregate_file_size
17
+ it_should_have_many :permissions, :tracks, :shared_objects
18
+ it_should_have_a :external_feed
8
19
  end
@@ -1,8 +1,17 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+ require File.dirname(__FILE__) + '/../entity_spec.rb'
3
+
2
4
  include RTunesU
3
5
 
4
6
  describe Permission do
5
- it 'should find itself in iTunes U'
6
- it 'is valid'
7
- it 'converts itself to an xml document'
7
+ before(:each) do
8
+ @klass = Permission
9
+ @entity = Permission.new
10
+ @permission = @entity
11
+ @attributes = {:credential => 'Administrator@urn:mace:itunesu.com:sites:example.edu'}
12
+ end
13
+
14
+ it_should_behave_like "an Entity with attribute assignment"
15
+ it_should_be_composed_of :credential, :access
16
+
8
17
  end
@@ -1,8 +1,37 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+ require File.dirname(__FILE__) + '/../entity_spec.rb'
3
+
2
4
  include RTunesU
3
5
 
4
6
  describe Section do
5
- it 'should find itself in iTunes U'
6
- it 'is valid'
7
- it 'converts itself to an xml document'
7
+ before(:each) do
8
+ @klass = Section
9
+ @entity = Section.new
10
+ @section = @entity
11
+ @attributes = {:name => 'Sample Course'}
12
+ end
13
+
14
+ it_should_behave_like "an Entity"
15
+
16
+ it_should_be_composed_of :name
17
+ it_should_have_many :courses
18
+
19
+ describe "converted to XML" do
20
+ before(:each) do
21
+ @document = Hpricot.XML(@section.to_xml)
22
+ end
23
+ it "should have SectionPath element" do
24
+ @document.at('SectionPath').should_not == nil
25
+ end
26
+
27
+ it "should have MergeByHandle element" do
28
+ @document.at('MergeByHandle').should_not == nil
29
+ @document.at('MergeByHandle').innerHTML.should == "false"
30
+ end
31
+
32
+ it "should have Destructive element" do
33
+ @document.at('Destructive').should_not == nil
34
+ @document.at('Destructive').innerHTML.should == "false"
35
+ end
36
+ end
8
37
  end
@@ -1,8 +1,21 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+ require File.dirname(__FILE__) + '/../entity_spec.rb'
3
+
2
4
  include RTunesU
3
5
 
4
6
  describe Site do
5
- it 'should find itself in iTunes U'
6
- it 'is valid'
7
- it 'converts itself to an xml document'
7
+ before(:each) do
8
+ @klass = Site
9
+ @entity = Site.new
10
+ @site = @entity
11
+ @attributes = {:name => 'Example University'}
12
+ end
13
+
14
+ it_should_behave_like "a findable Entity"
15
+ it_should_behave_like "an updateable Entity"
16
+ it_should_behave_like "an Entity with attribute assignment"
17
+
18
+ it "should not allow deletion" do
19
+ lambda {@site.delete}.should raise_error
20
+ end
8
21
  end
@@ -1,8 +1,37 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+ require File.dirname(__FILE__) + '/../entity_spec.rb'
3
+
2
4
  include RTunesU
3
5
 
4
6
  describe Track do
5
- it 'should find itself in iTunes U'
6
- it 'is valid'
7
- it 'converts itself to an xml document'
7
+ before(:each) do
8
+ @klass = Track
9
+ @entity = Track.new
10
+ @track = @entity
11
+ @attributes = {:name => 'Sample Lecture'}
12
+ end
13
+
14
+ # it_should_behave_like "a creatable Entity"
15
+ # it_should_behave_like "an updateable Entity"
16
+ # it_should_behave_like "a deleteable Entity"
17
+ it_should_behave_like "an Entity with attribute assignment"
18
+
19
+ describe "finding" do
20
+ before(:each) do
21
+ mock_connect!
22
+ FakeWeb.register_uri(:get,
23
+ "https://deimos.apple.com/WebObjects/Core.woa/API/GetUploadURL/example.edu.2394598528?credentials=Administrator%40urn%3Amace%3Aitunesu.com%3Asites%3Aexample.edu&identity=%22Admin%22+%3Cadmin%40example.edu%3E+%28admin%29+%5B0%5D&time=1214619134&signature=121a6cf76c9c5ecda41450d87e3394b9d02c570a5f76b2bd16287f860f068302&type=XMLControlFile",
24
+ :body => mock_upload_url_for_handle(1))
25
+ FakeWeb.register_uri(:post, mock_upload_url_for_handle(1), :body => response_for(Course, 'show', true))
26
+ end
27
+
28
+ after(:each) do
29
+ FakeWeb.clean_registry
30
+ end
31
+
32
+ it "should have an handle" do
33
+ lambda { Track.find(2449134252, 2394598528) }.should_not raise_error
34
+ end
35
+
36
+ end
8
37
  end
data/spec/entity_spec.rb CHANGED
@@ -1,108 +1,169 @@
1
1
  require File.dirname(__FILE__) + '/spec_helper.rb'
2
2
  include RTunesU
3
-
4
- # describe Entity do
5
- # it 'finds itself in iTunes U'
6
- # it 'rasies an error if it cannot be found in iTunes U'
7
- #
8
- # it "saves to iTunes U"
9
- # it "appepts to saves if valid"
10
- # it "it won't attempt to save (and rasies an error) if it's missing require attributes"
11
- #
12
- # it "creates if it didn't previously exist"
13
- # it "updates if it previously existed"
14
- #
15
- # it "rasies an error if saving failed"
16
- #
17
- # it "deletes"
18
- # it "raises an error if delting failed"
19
- #
20
- # it "converts to an xml string"
21
- # it "creats from a ITunesU Response"
22
- # end
23
- describe Entity, 'attribute assignment' do
24
- before do
25
- @entity = Entity.new
26
- end
27
-
28
- it 'assigns singular attributes to the edits hash as a string' do
29
- @entity.Name = 'Eng211'
30
- @entity.edits['Name'].should eql('Eng211')
31
- @entity.Name.should eql('Eng211')
32
- end
33
-
34
- it 'returns a default empty array for plural attributes' do
35
- @entity.Groups.should eql([])
36
- @entity.edits['Groups'].should eql([])
3
+ shared_examples_for "an updateable Entity" do
4
+ describe "updating" do
5
+ before(:each) do
6
+ mock_connect!
7
+ @entity = @klass.new(@attributes)
8
+ @entity.instance_variable_set("@handle", '1')
9
+ @entity.parent_handle = '1'
10
+ end
11
+
12
+ it "should clear its edits" do
13
+ FakeWeb.register_uri(:post,
14
+ "https://deimos.apple.com/WebObjects/Core.woa/API/ProcessWebServicesDocument/example.edu?credentials=Administrator%40urn%3Amace%3Aitunesu.com%3Asites%3Aexample.edu&identity=%22Admin%22+%3Cadmin%40example.edu%3E+%28admin%29+%5B0%5D&time=1214619134&signature=121a6cf76c9c5ecda41450d87e3394b9d02c570a5f76b2bd16287f860f068302",
15
+ :body => response_for(@klass, 'update', true)
16
+ )
17
+ @entity.name = 'some name'
18
+ @entity.edits.should_not be_empty
19
+ @entity.save
20
+ @entity.edits.should be_empty
21
+ end
22
+
37
23
  end
38
24
 
39
- it 'assigns plural attribute to the edits hash an array' do
40
- @entity.Groups = [Group.new(:name => 'does not matter')]
41
- @entity.Groups.size.should be(1)
42
- @entity.edits['Groups'].size.should be(1)
43
- end
44
25
 
45
- it 'adds plural attributes with <<' do
46
- @entity.Groups = [Group.new(:name => 'does not matter')]
47
- @entity.Groups.size.should be(1)
48
- @entity.Groups << Group.new(:name => 'another group')
49
- @entity.edits['Groups'].size.should be(2)
26
+ end
27
+
28
+ shared_examples_for "a deleteable Entity" do
29
+ describe "deleting" do
30
+ before(:each) do
31
+ mock_connect!
32
+ @entity = @klass.new(@attributes)
33
+ @entity.instance_variable_set("@handle", '1')
34
+ @entity.parent_handle = '1'
35
+ end
36
+
37
+ it "should no longer have a handle" do
38
+ FakeWeb.register_uri(:post,
39
+ "https://deimos.apple.com/WebObjects/Core.woa/API/ProcessWebServicesDocument/example.edu?credentials=Administrator%40urn%3Amace%3Aitunesu.com%3Asites%3Aexample.edu&identity=%22Admin%22+%3Cadmin%40example.edu%3E+%28admin%29+%5B0%5D&time=1214619134&signature=121a6cf76c9c5ecda41450d87e3394b9d02c570a5f76b2bd16287f860f068302",
40
+ :body => response_for(@klass, 'delete', true)
41
+ )
42
+ @entity.delete
43
+ @entity.handle.should == nil
44
+ end
50
45
  end
51
46
  end
52
47
 
53
- describe Entity, 'converting to XML' do
54
- describe 'with nested elements' do
55
- before do
56
- @entity = Entity.new(:Name => 'Example')
57
- @entity.Groups = [Group.new(:Name => 'example group 1'), Group.new(:Name => 'example group 2', :Description => 'Blah, blah, blah')]
58
- @xml = @entity.to_xml
48
+ shared_examples_for "a findable Entity" do
49
+ describe "finding" do
50
+ before(:each) do
51
+ mock_connect!
59
52
  end
60
53
 
61
- it 'should contain nested XML edits' do
62
- (Hpricot.XML(@xml) / 'Entity/Group').size.should be(2)
54
+ after(:each) do
55
+ FakeWeb.clean_registry
63
56
  end
64
57
 
65
- it 'has nested elements that propely converted their singular attributes' do
66
- (Hpricot.XML(@xml) / 'Entity/Group')[0].at('Name').innerHTML.should eql('example group 1')
58
+ describe "with existing handle" do
59
+ it "should load external data into object" do
60
+ FakeWeb.register_uri(:get,
61
+ "https://deimos.apple.com/WebObjects/Core.woa/API/GetUploadURL/example.edu.1?credentials=Administrator%40urn%3Amace%3Aitunesu.com%3Asites%3Aexample.edu&identity=%22Admin%22+%3Cadmin%40example.edu%3E+%28admin%29+%5B0%5D&time=1214619134&signature=121a6cf76c9c5ecda41450d87e3394b9d02c570a5f76b2bd16287f860f068302&type=XMLControlFile",
62
+ :body => mock_upload_url_for_handle(1))
63
+ FakeWeb.register_uri(:post, mock_upload_url_for_handle(1), :body => response_for(@klass, 'show', true))
64
+ @entity = @klass.find(1)
65
+ end
67
66
  end
68
67
 
68
+ describe "with non-existant handle" do
69
+ it "should raise EntityNotFound" do
70
+ FakeWeb.register_uri(:get,
71
+ "https://deimos.apple.com/WebObjects/Core.woa/API/GetUploadURL/example.edu.1?credentials=Administrator%40urn%3Amace%3Aitunesu.com%3Asites%3Aexample.edu&identity=%22Admin%22+%3Cadmin%40example.edu%3E+%28admin%29+%5B0%5D&time=1214619134&signature=121a6cf76c9c5ecda41450d87e3394b9d02c570a5f76b2bd16287f860f068302&type=XMLControlFile",
72
+ :body => response_for(@klass, 'show', false),
73
+ :status => [404, "Not Found"]
74
+ )
75
+ lambda { @entity = @klass.find(1) }.should raise_error(EntityNotFound)
76
+ end
77
+ end
69
78
  end
70
79
  end
71
80
 
72
- describe Entity, 'loading from XML' do
73
- before do
74
- @source = File.read(File.dirname(__FILE__) + '/fixtures/responses/generic_entity_response.xml')
75
- @entity = Entity.new(:handle => 789)
76
- end
77
-
78
- it 'access attributes from XML source or from the edits hash' do
79
- @entity.load_from_xml(@source)
80
- @entity.Name.should eql('Example Entity Inside of A Section')
81
- @entity.Name = 'new test name'
82
- @entity.Name.should eql('new test name')
81
+ shared_examples_for "a creatable Entity" do
82
+ describe "creating" do
83
+ before(:each) do
84
+ mock_connect!
85
+ @entity = @klass.new(@attributes)
86
+ @entity.parent_handle = '1'
87
+ @entity.handle.should == nil
88
+ end
89
+
90
+ after(:each) do
91
+ FakeWeb.clean_registry
92
+ end
93
+
94
+ it "should not have a handle until saved" do
95
+ @entity.handle.should == nil
96
+ end
97
+
98
+ it "should obtain a handle from iTunes U when saved" do
99
+ FakeWeb.register_uri(:post,
100
+ "https://deimos.apple.com/WebObjects/Core.woa/API/ProcessWebServicesDocument/example.edu?credentials=Administrator%40urn%3Amace%3Aitunesu.com%3Asites%3Aexample.edu&identity=%22Admin%22+%3Cadmin%40example.edu%3E+%28admin%29+%5B0%5D&time=1214619134&signature=121a6cf76c9c5ecda41450d87e3394b9d02c570a5f76b2bd16287f860f068302",
101
+ :body => response_for(@klass, 'create', true)
102
+ )
103
+ @entity.save
104
+ @entity.handle.should_not == nil
105
+ end
106
+
107
+ it "should raise InvalidRecord if it cannot be saved" do
108
+ FakeWeb.register_uri(:post,
109
+ "https://deimos.apple.com/WebObjects/Core.woa/API/ProcessWebServicesDocument/example.edu?credentials=Administrator%40urn%3Amace%3Aitunesu.com%3Asites%3Aexample.edu&identity=%22Admin%22+%3Cadmin%40example.edu%3E+%28admin%29+%5B0%5D&time=1214619134&signature=121a6cf76c9c5ecda41450d87e3394b9d02c570a5f76b2bd16287f860f068302",
110
+ :body => response_for(@klass, 'create', false)
111
+ )
112
+ lambda { @entity.save }.should raise_error(CannotSave)
113
+ end
114
+
115
+ it "should clear its edits" do
116
+ FakeWeb.register_uri(:post,
117
+ "https://deimos.apple.com/WebObjects/Core.woa/API/ProcessWebServicesDocument/example.edu?credentials=Administrator%40urn%3Amace%3Aitunesu.com%3Asites%3Aexample.edu&identity=%22Admin%22+%3Cadmin%40example.edu%3E+%28admin%29+%5B0%5D&time=1214619134&signature=121a6cf76c9c5ecda41450d87e3394b9d02c570a5f76b2bd16287f860f068302",
118
+ :body => response_for(@klass, 'create', true)
119
+ )
120
+ @entity.name = 'some name'
121
+ @entity.edits.should_not be_empty
122
+ @entity.save
123
+ @entity.edits.should be_empty
124
+ end
83
125
  end
84
-
85
- it 'can reset its edits' do
86
- @entity.load_from_xml(@source)
87
- @entity.Name.should eql('Example Entity Inside of A Section')
88
- @entity.Name = 'new test name'
89
- @entity.Name.should eql('new test name')
90
- @entity.reload
91
- @entity.Name.should eql('Example Entity Inside of A Section')
126
+ end
127
+
128
+ shared_examples_for "an Entity with attribute assignment" do
129
+ it "should initialize with optional starting attributes" do
130
+ @entity = @klass.new(@attributes)
131
+ @attributes.each do |attr,value|
132
+ @entity.send(attr).should == value
133
+ end
92
134
  end
93
135
 
94
- it 'should find its appropriate node in the XML based on node name and <Handle> element' do
95
- @entity.load_from_xml(@source)
96
- @entity.source_xml.name.should eql('Entity')
97
- end
136
+ describe "accessing handle" do
137
+ describe "when handle instance variable is set" do
138
+ it "should return the handle" do
139
+ @entity.instance_variable_set("@handle", "1")
140
+ @entity.handle.should == "1"
141
+ end
142
+ end
98
143
 
99
- it 'should raise an EntityNotFound error if the specific entity cannot be found' do
100
- @entity.handle = 1
101
- lambda { @entity.load_from_xml(@source) }.should raise_error(EntityNotFound)
102
- end
103
-
104
- it 'should still be able to access its parent XML node' do
105
- @entity.load_from_xml(@source)
106
- @entity.source_xml.parent.name.should eql('Section')
144
+ describe "when handle instance variable is not set" do
145
+ it "should access the handle from source xml if availabe" do
146
+ @entity.source_xml = Hpricot.XML(<<-XML
147
+ <#{@klass.name.demodulize}>
148
+ <Handle>1</Handle>
149
+ </#{@klass.name.demodulize}>
150
+ XML
151
+ )
152
+ @entity.handle.should == "1"
153
+ end
154
+
155
+ it "should retrun nil if source xml doesn't contain handle" do
156
+ @entity.handle.should be_nil
157
+ end
158
+ end
107
159
  end
108
- end
160
+ end
161
+
162
+
163
+ shared_examples_for "an Entity" do
164
+ it_should_behave_like "a creatable Entity"
165
+ it_should_behave_like "a findable Entity"
166
+ it_should_behave_like "an updateable Entity"
167
+ it_should_behave_like "a deleteable Entity"
168
+ it_should_behave_like "an Entity with attribute assignment"
169
+ end
@@ -0,0 +1,17 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ITunesUDocument>
3
+ <Version>1.1.1</Version>
4
+ <AddCourse>
5
+ <ParentHandle>123456789</ParentHandle>
6
+ <ParentPath></ParentPath>
7
+ <TemplateHandle>987654321</TemplateHandle>
8
+ <Course>
9
+ <Name>Introduction to the Humanities</Name>
10
+ <ShortName>HUM 211</ShortName>
11
+ <Identifier>identifier value</Identifier>
12
+ <Instructor>Dr. Jesse Sielaff</Instructor>
13
+ <Description>Lorem ipsum dolor sit amet</Description>
14
+ <AllowSubscription>true</AllowSubscription>
15
+ </Course>
16
+ </AddCourse>
17
+ </ITunesUDocument>
@@ -0,0 +1,11 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ITunesUDocument>
3
+ <Version>1.1.3</Version>
4
+ <AddDivision>
5
+ <ParentHandle>720939</ParentHandle>
6
+ <ParentPath></ParentPath>
7
+ <Division>
8
+ <Name>Example Division</Name>
9
+ </Division>
10
+ </AddDivision>
11
+ </ITunesUDocument>
@@ -0,0 +1,11 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ITunesUDocument>
3
+ <Version>1.1.3</Version>
4
+ <AddGroup>
5
+ <ParentHandle>2514401752</ParentHandle>
6
+ <ParentPath></ParentPath>
7
+ <Group>
8
+ <Name>Tab 1</Name>
9
+ </Group>
10
+ </AddGroup>
11
+ </ITunesUDocument>