scorm_engine 0.1.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.
Files changed (147) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/Rakefile +13 -0
  4. data/lib/scorm_engine.rb +13 -0
  5. data/lib/scorm_engine/api/endpoints.rb +50 -0
  6. data/lib/scorm_engine/api/endpoints/about.rb +59 -0
  7. data/lib/scorm_engine/api/endpoints/courses.rb +136 -0
  8. data/lib/scorm_engine/api/endpoints/courses/configuration.rb +146 -0
  9. data/lib/scorm_engine/api/endpoints/courses/import.rb +83 -0
  10. data/lib/scorm_engine/api/endpoints/ping.rb +20 -0
  11. data/lib/scorm_engine/api/endpoints/registrations.rb +321 -0
  12. data/lib/scorm_engine/api/endpoints/registrations/configuration.rb +146 -0
  13. data/lib/scorm_engine/api/endpoints/registrations/launch_history.rb +47 -0
  14. data/lib/scorm_engine/client.rb +17 -0
  15. data/lib/scorm_engine/configuration.rb +43 -0
  16. data/lib/scorm_engine/faraday/connection.rb +35 -0
  17. data/lib/scorm_engine/faraday/request.rb +54 -0
  18. data/lib/scorm_engine/models.rb +9 -0
  19. data/lib/scorm_engine/models/course.rb +66 -0
  20. data/lib/scorm_engine/models/course_configuration.rb +37 -0
  21. data/lib/scorm_engine/models/course_import.rb +42 -0
  22. data/lib/scorm_engine/models/learner.rb +24 -0
  23. data/lib/scorm_engine/models/registration.rb +82 -0
  24. data/lib/scorm_engine/models/registration_activity_detail.rb +37 -0
  25. data/lib/scorm_engine/models/registration_configuration.rb +37 -0
  26. data/lib/scorm_engine/models/registration_launch_history.rb +92 -0
  27. data/lib/scorm_engine/models/registration_runtime_interaction.rb +52 -0
  28. data/lib/scorm_engine/response.rb +26 -0
  29. data/lib/scorm_engine/utils.rb +13 -0
  30. data/lib/scorm_engine/version.rb +3 -0
  31. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about/is_successful.yml +38 -0
  32. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about/knows_the_platform.yml +38 -0
  33. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about/knows_the_version.yml +38 -0
  34. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about_user_count/accepts_before_option.yml +38 -0
  35. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about_user_count/accepts_since_option.yml +38 -0
  36. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about_user_count/is_successful.yml +38 -0
  37. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about_user_count/tracks_combined_counts.yml +38 -0
  38. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about_user_count/tracks_per_tenantcounts.yml +38 -0
  39. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_delete_course/fails_when_id_is_invalid.yml +38 -0
  40. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_delete_course/works.yml +32 -0
  41. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_course_detail/is_successful.yml +41 -0
  42. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_course_detail/results/sucessfully_creates_the_Course_attributes.yml +41 -0
  43. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_course_preview/fails_when_id_is_invalid.yml +38 -0
  44. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_course_preview/is_successful.yml +38 -0
  45. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_course_preview/results/returns_a_URL_string.yml +38 -0
  46. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/_course_id_option/fetches_a_single_course_but_perhaps_multiple_versions.yml +39 -0
  47. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/_course_id_option/returns_404_when_ID_is_invalid.yml +38 -0
  48. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/_more_option_pagination_/returns_all_the_courses.yml +89 -0
  49. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/_more_option_pagination_/returns_the_more_key_in_the_raw_response.yml +48 -0
  50. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/_since_option/fails_when_passed_an_invalid_value.yml +37 -0
  51. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/_since_option/works.yml +43 -0
  52. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/is_successful.yml +43 -0
  53. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/results/is_an_enumerator_of_Course_models.yml +43 -0
  54. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/results/sucessfully_creates_the_Course_attributes.yml +43 -0
  55. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_get_course_configuration/fails_when_id_is_invalid.yml +38 -0
  56. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_get_course_configuration/is_successful.yml +38 -0
  57. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_get_course_configuration/results/makes_settings_available_as_key/value_pairs.yml +38 -0
  58. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_get_course_configuration_setting/fails_when_course_id_is_invalid.yml +38 -0
  59. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_get_course_configuration_setting/fails_when_setting_id_is_invalid.yml +36 -0
  60. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_get_course_configuration_setting/is_successful.yml +65 -0
  61. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_get_course_configuration_setting/results/returns_the_value_as_a_string.yml +65 -0
  62. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_post_course_configuration/fails_when_id_is_invalid.yml +38 -0
  63. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_post_course_configuration/fails_when_settings_are_invalid.yml +36 -0
  64. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_post_course_configuration/is_successful.yml +32 -0
  65. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_post_course_configuration/persists_the_settings.yml +131 -0
  66. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_put_course_configuration_setting/fails_when_course_id_is_invalid.yml +38 -0
  67. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_put_course_configuration_setting/fails_when_setting_id_is_invalid.yml +36 -0
  68. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_put_course_configuration_setting/is_successful.yml +65 -0
  69. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_put_course_configuration_setting/results/persists_the_changes.yml +98 -0
  70. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Import/_get_course_import/successful_imports/works.yml +147 -0
  71. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Import/_get_course_import/unsuccessful_imports/fails_to_import_given_an_invalid_url.yml +326 -0
  72. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Import/_post_course_import/successful_imports/works.yml +38 -0
  73. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Import/_post_course_import/unsuccessful_imports/fails_to_import_a_previously_existing_course.yml +36 -0
  74. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Ping/_get_ping/is_successful.yml +38 -0
  75. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Ping/_get_ping/reports_the_api_is_up.yml +38 -0
  76. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Ping/_get_ping/with_invalid_password/is_unsuccessful.yml +41 -0
  77. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Ping/_get_ping/with_invalid_password/returns_status_403.yml +41 -0
  78. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_delete_registration/is_failure_when_registration_does_not_exist.yml +38 -0
  79. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_delete_registration/is_successful_when_registration_exists.yml +32 -0
  80. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_exists/is_false_when_registration_does_not_exist.yml +38 -0
  81. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_exists/is_true_when_registration_exists.yml +36 -0
  82. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_instances/includes_results_we_expect.yml +39 -0
  83. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_instances/is_successful.yml +39 -0
  84. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_instances/returns_an_array_of_registrations.yml +39 -0
  85. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_launch_link/fails_when_id_is_invalid.yml +38 -0
  86. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_launch_link/is_successful.yml +38 -0
  87. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_launch_link/results/returns_a_URL_string.yml +38 -0
  88. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_progress/detail/does_not_return_activity_details_by_default.yml +39 -0
  89. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_progress/detail/returns_activity_details_if_requested.yml +41 -0
  90. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_progress/fails_when_registration_does_not_exist.yml +38 -0
  91. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_progress/returns_a_registration_when_it_exists.yml +39 -0
  92. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registrations/filtering_by_course_id/excludes_results.yml +38 -0
  93. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registrations/filtering_by_course_id/includes_results.yml +40 -0
  94. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registrations/filtering_by_learner_id/excludes_results.yml +38 -0
  95. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registrations/filtering_by_learner_id/includes_results.yml +39 -0
  96. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registrations/includes_results_we_expect.yml +40 -0
  97. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registrations/is_successful.yml +40 -0
  98. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registrations/returns_an_array_of_registrations.yml +40 -0
  99. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_post_registration/fails_if_course_id_is_invalid.yml +36 -0
  100. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_post_registration/fails_if_registration_id_already_exists.yml +36 -0
  101. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_post_registration/is_successful.yml +61 -0
  102. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_get_registration_configuration/fails_when_id_is_invalid.yml +38 -0
  103. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_get_registration_configuration/is_successful.yml +38 -0
  104. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_get_registration_configuration/results/makes_settings_available_as_key/value_pairs.yml +38 -0
  105. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_get_registration_configuration_setting/fails_when_registration_id_is_invalid.yml +38 -0
  106. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_get_registration_configuration_setting/fails_when_setting_id_is_invalid.yml +36 -0
  107. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_get_registration_configuration_setting/is_successful.yml +65 -0
  108. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_get_registration_configuration_setting/results/returns_the_value_as_a_string.yml +65 -0
  109. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_post_registration_configuration/fails_when_id_is_invalid.yml +38 -0
  110. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_post_registration_configuration/fails_when_settings_are_invalid.yml +36 -0
  111. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_post_registration_configuration/is_successful.yml +32 -0
  112. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_post_registration_configuration/persists_the_settings.yml +131 -0
  113. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_put_registration_configuration_setting/fails_when_registration_id_is_invalid.yml +38 -0
  114. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_put_registration_configuration_setting/fails_when_setting_id_is_invalid.yml +36 -0
  115. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_put_registration_configuration_setting/is_successful.yml +65 -0
  116. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_put_registration_configuration_setting/results/persists_the_changes.yml +98 -0
  117. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_LaunchHistory/_get_registration_launch_history/fails_when_registration_does_not_exist.yml +38 -0
  118. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_LaunchHistory/_get_registration_launch_history/is_successful.yml +54 -0
  119. data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_LaunchHistory/_get_registration_launch_history/returns_an_array_of_registration_launch_histories.yml +54 -0
  120. data/spec/fixtures/zip/Non-working SCORM.zip +0 -0
  121. data/spec/fixtures/zip/RuntimeBasicCalls_SCORM20043rdEdition.zip +0 -0
  122. data/spec/scorm_engine/api/endpoints/about_spec.rb +59 -0
  123. data/spec/scorm_engine/api/endpoints/courses/configuration_spec.rb +143 -0
  124. data/spec/scorm_engine/api/endpoints/courses/import_spec.rb +92 -0
  125. data/spec/scorm_engine/api/endpoints/courses_spec.rb +155 -0
  126. data/spec/scorm_engine/api/endpoints/ping_spec.rb +27 -0
  127. data/spec/scorm_engine/api/endpoints/registrations/configuration_spec.rb +154 -0
  128. data/spec/scorm_engine/api/endpoints/registrations/launch_history_spec.rb +46 -0
  129. data/spec/scorm_engine/api/endpoints/registrations_spec.rb +201 -0
  130. data/spec/scorm_engine/configuration_spec.rb +29 -0
  131. data/spec/scorm_engine/models/course_configuration_spec.rb +16 -0
  132. data/spec/scorm_engine/models/course_import_spec.rb +86 -0
  133. data/spec/scorm_engine/models/course_spec.rb +92 -0
  134. data/spec/scorm_engine/models/learner_spec.rb +27 -0
  135. data/spec/scorm_engine/models/registration_activity_detail_spec.rb +101 -0
  136. data/spec/scorm_engine/models/registration_launch_history_spec.rb +86 -0
  137. data/spec/scorm_engine/models/registration_runtime_interaction_spec.rb +91 -0
  138. data/spec/scorm_engine/models/registration_spec.rb +82 -0
  139. data/spec/scorm_engine/utils_spec.rb +15 -0
  140. data/spec/scorm_engine/version_spec.rb +5 -0
  141. data/spec/scorm_engine_spec.rb +2 -0
  142. data/spec/spec_helper.rb +47 -0
  143. data/spec/support/scorm_engine.rb +72 -0
  144. data/spec/support/scorm_engine_client.rb +6 -0
  145. data/spec/support/scorm_engine_configuration.rb +7 -0
  146. data/spec/support/vcr.rb +53 -0
  147. metadata +329 -0
@@ -0,0 +1,92 @@
1
+ RSpec.describe ScormEngine::Api::Endpoints::Courses::Import do
2
+ let(:subject) { scorm_engine_client }
3
+
4
+ before do
5
+ against_real_scorm_engine do
6
+ ensure_course_exists(client: subject, course_id: "testing-golf-explained")
7
+ end
8
+ end
9
+
10
+ describe "#post_course_import" do
11
+ context "raising ArgumentError" do
12
+ it "when :course is missing" do
13
+ expect { subject.post_course_import }.to raise_error(ArgumentError, /course_id missing/)
14
+ end
15
+
16
+ it "when :url is missing" do
17
+ expect { subject.post_course_import(course_id: "id123") }.to raise_error(ArgumentError, /url missing/)
18
+ end
19
+ end
20
+
21
+ describe "arguments posted to the api" do
22
+ it "works in the general case" do
23
+ expect(subject).to receive(:post).with("courses/importJobs", { course: "id123", mayCreateNewVersion: false }, { url: "http://path.to/scorm.zip", courseName: "id123" })
24
+ subject.post_course_import(course_id: "id123", url: "http://path.to/scorm.zip")
25
+ end
26
+
27
+ it "allows creating a new version" do
28
+ expect(subject).to receive(:post).with("courses/importJobs", { course: "id123", mayCreateNewVersion: true }, { url: "http://path.to/scorm.zip", courseName: "id123" })
29
+ subject.post_course_import(course_id: "id123", url: "http://path.to/scorm.zip", may_create_new_version: true)
30
+ end
31
+
32
+ it "allows overriding course name" do
33
+ expect(subject).to receive(:post).with("courses/importJobs", { course: "id123", mayCreateNewVersion: false }, { url: "http://path.to/scorm.zip", courseName: "the name" })
34
+ subject.post_course_import(course_id: "id123", url: "http://path.to/scorm.zip", name: "the name")
35
+ end
36
+ end
37
+
38
+ describe "successful imports" do
39
+ it "works" do
40
+ import = subject.post_course_import(course_id: "testing123", url: "https://github.com/phallstrom/scorm_engine/raw/master/spec/fixtures/zip/RuntimeBasicCalls_SCORM20043rdEdition.zip", may_create_new_version: true)
41
+
42
+ aggregate_failures do
43
+ expect(import.success?).to eq true
44
+ expect(import.result.running?).to eq true
45
+ expect(import.result.id).to match(/^[-a-f0-9]+$/)
46
+ end
47
+ end
48
+ end
49
+
50
+ describe "unsuccessful imports" do
51
+ it "fails to import a previously existing course" do
52
+ against_real_scorm_engine { ensure_course_exists(client: subject, course_id: "a-previously-existing-course", may_create_new_version: true) }
53
+ import = import_course(client: subject, course_id: "a-previously-existing-course", may_create_new_version: false)
54
+
55
+ aggregate_failures do
56
+ expect(import.success?).to eq false
57
+ expect(import.result).to be_falsey
58
+ expect(import.message).to match(/A course already exists with the specified id: .*\|a-previously-existing-course!/)
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ describe "#get_course_import" do
65
+ describe "successful imports" do
66
+ it "works" do
67
+ import = import_course(client: subject, course_id: "a-valid-course-url")
68
+ import_status = subject.get_course_import(id: import.result.id)
69
+
70
+ aggregate_failures do
71
+ expect(import_status.success?).to eq true
72
+ expect(import_status.result.complete?).to eq true
73
+ expect(import_status.result.course).to be_a ScormEngine::Models::Course
74
+ expect(import_status.result.course.id).to eq "a-valid-course-url"
75
+ end
76
+ end
77
+ end
78
+
79
+ describe "unsuccessful imports" do
80
+ it "fails to import given an invalid url" do
81
+ import = import_course(client: subject, course_id: "an-invalid-course-url", key: "non-existent-key")
82
+ import_status = subject.get_course_import(id: import.result.id)
83
+
84
+ aggregate_failures do
85
+ expect(import_status.success?).to eq true
86
+ expect(import_status.result.error?).to eq true
87
+ expect(import_status.result.course).to eq nil
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,155 @@
1
+ RSpec.describe ScormEngine::Api::Endpoints::Courses do
2
+ let(:subject) { scorm_engine_client }
3
+
4
+ before do
5
+ against_real_scorm_engine do
6
+ ensure_course_exists(client: subject, course_id: "testing-golf-explained")
7
+ end
8
+ end
9
+
10
+ describe "#get_courses" do
11
+ let(:courses) { subject.get_courses }
12
+
13
+ it "is successful" do
14
+ expect(courses.success?).to eq true
15
+ end
16
+
17
+ describe "results" do
18
+ it "is an enumerator of Course models" do
19
+ expect(courses.results).to be_a Enumerator
20
+ expect(courses.results.first).to be_a ScormEngine::Models::Course
21
+ end
22
+
23
+ it "sucessfully creates the Course attributes" do
24
+ aggregate_failures do
25
+ course = courses.results.detect { |c| c.id == "testing-golf-explained" }
26
+ expect(course.version).to be >= 0
27
+ expect(course.title).to eq "Golf Explained - Run-time Basic Calls"
28
+ expect(course.registration_count).to eq 0
29
+ expect(course.updated).to be_a Time
30
+ expect(course.description).to eq nil
31
+ end
32
+ end
33
+ end
34
+
35
+ describe ":course_id option" do
36
+ it "fetches a single course, but perhaps multiple versions" do
37
+ response = subject.get_courses(course_id: "testing-golf-explained")
38
+ expect(response.results.all? { |c| c.title == "Golf Explained - Run-time Basic Calls" }).to eq true
39
+ end
40
+
41
+ it "returns 404 when ID is invalid" do
42
+ response = subject.get_courses(course_id: "invalid-bogus")
43
+ expect(response.success?).to eq false
44
+ expect(response.status).to eq 404
45
+ expect(response.message).to match(/External Package ID 'invalid-bogus'/)
46
+ end
47
+ end
48
+
49
+ describe ":since option" do
50
+ it "works" do
51
+ courses = subject.get_courses(since: Time.parse("2000-01-1 00:00:00 UTC"))
52
+ aggregate_failures do
53
+ expect(courses.success?).to eq true
54
+ expect(courses.results.to_a.size).to be >= 0
55
+ end
56
+ end
57
+
58
+ it "fails when passed an invalid value" do
59
+ courses = subject.get_courses(since: "invalid")
60
+ aggregate_failures do
61
+ expect(courses.success?).to eq false
62
+ expect(courses.status).to eq 400
63
+ expect(courses.results.to_a).to eq []
64
+ expect(courses.message).to match(/'invalid' is either not a timestamp or seems to be not formatted according to ISO 8601/)
65
+ end
66
+ end
67
+ end
68
+
69
+ describe ":more option (pagination)" do
70
+ before do
71
+ against_real_scorm_engine do
72
+ 11.times do |idx|
73
+ ensure_course_exists(client: subject, course_id: "paginated-course-#{idx}")
74
+ end
75
+ end
76
+ end
77
+
78
+ it "returns the :more key in the raw response" do
79
+ expect(subject.get_courses.raw_response.body["more"]).to match(%r{https?://.*&more=.+})
80
+ end
81
+
82
+ it "returns all the courses" do
83
+ expect(subject.get_courses.results.to_a.size).to be >= 11 # there may be other ones beyond those we just added
84
+ end
85
+ end
86
+ end
87
+
88
+ describe "#delete_course" do
89
+ before do
90
+ against_real_scorm_engine do
91
+ ensure_course_exists(client: subject, course_id: "course-to-be-deleted")
92
+ end
93
+ end
94
+
95
+ it "works" do
96
+ response = subject.delete_course(course_id: "course-to-be-deleted")
97
+ expect(response.success?).to eq true
98
+ expect(response.status).to eq 204
99
+ end
100
+
101
+ it "raises ArgumentError when :course_id is missing" do
102
+ expect { subject.delete_course }.to raise_error(ArgumentError, /course_id missing/)
103
+ end
104
+
105
+ it "fails when id is invalid" do
106
+ response = subject.delete_course(course_id: "nonexistent-course")
107
+ expect(response.success?).to eq false
108
+ expect(response.status).to eq 404
109
+ expect(response.message).to match(/External Package ID 'nonexistent-course'/)
110
+ end
111
+ end
112
+
113
+ describe "#get_course_detail" do
114
+ let(:response) { subject.get_course_detail(course_id: "testing-golf-explained") }
115
+
116
+ it "is successful" do
117
+ expect(response.success?).to eq true
118
+ end
119
+
120
+ describe "results" do
121
+ it "sucessfully creates the Course attributes" do
122
+ aggregate_failures do
123
+ course = response.result
124
+ expect(course.version).to be >= 0
125
+ expect(course.title).to eq "Golf Explained - Run-time Basic Calls"
126
+ expect(course.registration_count).to be >= 0
127
+ expect(course.updated).to be_a Time
128
+ expect(course.description).to eq nil
129
+ end
130
+ end
131
+ end
132
+ end
133
+
134
+ describe "#get_course_preview" do
135
+ let(:response) { subject.get_course_preview(course_id: "testing-golf-explained", redirect_on_exit_url: "https://example.com") }
136
+
137
+ it "is successful" do
138
+ expect(response.success?).to eq true
139
+ end
140
+
141
+ describe "results" do
142
+ it "returns a URL string" do
143
+ url = response.result
144
+ expect(url).to match(%r{/defaultui/launch.jsp\?.*testing-golf-explained.*RedirectOnExitUrl=https%3A%2F%2Fexample.com})
145
+ end
146
+ end
147
+
148
+ it "fails when id is invalid" do
149
+ response = subject.get_course_preview(course_id: "nonexistent-course")
150
+ expect(response.success?).to eq false
151
+ expect(response.status).to eq 404
152
+ expect(response.message).to match(/External Package ID 'nonexistent-course'/)
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,27 @@
1
+ RSpec.describe ScormEngine::Api::Endpoints::Ping do
2
+ describe "#get_ping" do
3
+ let(:subject) { scorm_engine_client.get_ping }
4
+
5
+ it "is successful" do
6
+ expect(subject.success?).to eq true
7
+ end
8
+
9
+ it "reports the api is up" do
10
+ expect(subject.message).to match(/API is up/)
11
+ end
12
+
13
+ context "with invalid password" do
14
+ before do
15
+ ScormEngine.configuration.password = "invalid"
16
+ end
17
+
18
+ it "is unsuccessful" do
19
+ expect(subject.success?).to eq false
20
+ end
21
+
22
+ it "returns status 403" do
23
+ expect(subject.status).to eq 403
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,154 @@
1
+ RSpec.describe ScormEngine::Api::Endpoints::Registrations::Configuration do
2
+ let(:subject) { scorm_engine_client }
3
+
4
+ let(:registration_options) { {
5
+ course_id: "testing-golf-explained",
6
+ registration_id: "testing-golf-explained-registration-1",
7
+ learner: {
8
+ id: "testing-golf-explained-learner-1",
9
+ first_name: "Arnold",
10
+ last_name: "Palmer",
11
+ }
12
+ } }
13
+
14
+ before do
15
+ against_real_scorm_engine do
16
+ ensure_course_exists(client: subject, course_id: registration_options[:course_id])
17
+ ensure_registration_exists(registration_options.merge(client: subject))
18
+ end
19
+ end
20
+
21
+ describe "#get_registration_configuration" do
22
+ let(:response) { subject.get_registration_configuration(registration_id: registration_options[:registration_id]) }
23
+
24
+ it "is successful" do
25
+ expect(response.success?).to eq true
26
+ end
27
+
28
+ describe "results" do
29
+ it "makes settings available as key/value pairs" do
30
+ settings = response.result.settings
31
+ aggregate_failures do
32
+ # just a sampling
33
+ expect(settings.key?("PlayerStatusRollupModeValue")).to be_truthy
34
+ expect(settings.key?("PlayerLaunchType")).to be_truthy
35
+ end
36
+ end
37
+ end
38
+
39
+ it "fails when id is invalid" do
40
+ response = subject.get_registration_configuration(registration_id: "nonexistent-registration", settings: {})
41
+ expect(response.success?).to eq false
42
+ expect(response.status).to eq 404
43
+ expect(response.message).to match(/External Registration ID 'nonexistent-registration'/)
44
+ end
45
+ end
46
+
47
+ describe "#post_registration_configuration" do
48
+ let(:response) {
49
+ subject.post_registration_configuration(
50
+ registration_id: registration_options[:registration_id],
51
+ settings: { "PlayerCaptureHistoryDetailed" => "NO",
52
+ "PlayerStatusRollupModeThresholdScore" => 80 }
53
+ )
54
+ }
55
+
56
+ it "is successful" do
57
+ expect(response.success?).to eq true
58
+ end
59
+
60
+ it "persists the settings" do
61
+ response # trigger the api
62
+ configuration = subject.get_registration_configuration(registration_id: registration_options[:registration_id]).result
63
+ expect(configuration.settings["PlayerCaptureHistoryDetailed"]).to eq "NO"
64
+ expect(configuration.settings["PlayerStatusRollupModeThresholdScore"]).to eq "80"
65
+
66
+ subject.post_registration_configuration(
67
+ registration_id: registration_options[:registration_id],
68
+ settings: { "PlayerCaptureHistoryDetailed" => "YES",
69
+ "PlayerStatusRollupModeThresholdScore" => 42 }
70
+ )
71
+
72
+ configuration = subject.get_registration_configuration(registration_id: registration_options[:registration_id]).result
73
+ expect(configuration.settings["PlayerCaptureHistoryDetailed"]).to eq "YES"
74
+ expect(configuration.settings["PlayerStatusRollupModeThresholdScore"]).to eq "42"
75
+ end
76
+
77
+ it "fails when id is invalid" do
78
+ response = subject.post_registration_configuration(registration_id: "nonexistent-registration", settings: {})
79
+ expect(response.success?).to eq false
80
+ expect(response.status).to eq 404
81
+ expect(response.message).to match(/External Registration ID 'nonexistent-registration'/)
82
+ end
83
+
84
+ it "fails when settings are invalid" do
85
+ response = subject.post_registration_configuration(registration_id: registration_options[:registration_id], settings: { "NonExistentSettingTotesBogus" => "YES" })
86
+ expect(response.success?).to eq false
87
+ expect(response.status).to eq 400
88
+ expect(response.message).to match(/No configuration setting found with id.*NonExistentSettingTotesBogus/)
89
+ end
90
+ end
91
+
92
+ describe "#get_registration_configuration_setting" do
93
+ let(:response) {
94
+ subject.put_registration_configuration_setting(registration_id: registration_options[:registration_id], setting_id: "PlayerStatusRollupModeThresholdScore", value: 42)
95
+ subject.get_registration_configuration_setting(registration_id: registration_options[:registration_id], setting_id: "PlayerStatusRollupModeThresholdScore")
96
+ }
97
+
98
+ it "is successful" do
99
+ expect(response.success?).to eq true
100
+ end
101
+
102
+ describe "results" do
103
+ it "returns the value as a string" do
104
+ expect(response.result).to eq "42"
105
+ end
106
+ end
107
+
108
+ it "fails when registration_id is invalid" do
109
+ response = subject.get_registration_configuration_setting(registration_id: "nonexistent-registration", setting_id: "PlayerStatusRollupModeThresholdScore")
110
+ expect(response.success?).to eq false
111
+ expect(response.status).to eq 404
112
+ expect(response.message).to match(/External Registration ID 'nonexistent-registration'/)
113
+ end
114
+
115
+ it "fails when setting_id is invalid" do
116
+ response = subject.get_registration_configuration_setting(registration_id: registration_options[:registration_id], setting_id: "NonExistentSettingTotesBogus")
117
+ expect(response.success?).to eq false
118
+ expect(response.status).to eq 400
119
+ expect(response.message).to match(/No configuration setting found with id.*NonExistentSettingTotesBogus/)
120
+ end
121
+ end
122
+
123
+ describe "#put_registration_configuration_setting" do
124
+ let(:value) { subject.get_registration_configuration_setting(registration_id: registration_options[:registration_id], setting_id: "PlayerStatusRollupModeThresholdScore").result }
125
+ let(:new_value) { (value.to_i + 1).to_s }
126
+ let(:response) { subject.put_registration_configuration_setting(registration_id: registration_options[:registration_id], setting_id: "PlayerStatusRollupModeThresholdScore", value: new_value) }
127
+
128
+ it "is successful" do
129
+ expect(response.success?).to eq true
130
+ end
131
+
132
+ describe "results" do
133
+ it "persists the changes" do
134
+ response # trigger the api
135
+ new_response = subject.get_registration_configuration_setting(registration_id: registration_options[:registration_id], setting_id: "PlayerStatusRollupModeThresholdScore")
136
+ expect(new_response.result).to eq new_value
137
+ end
138
+ end
139
+
140
+ it "fails when registration_id is invalid" do
141
+ response = subject.put_registration_configuration_setting(registration_id: "nonexistent-registration", setting_id: "PlayerStatusRollupModeThresholdScore", value: "42")
142
+ expect(response.success?).to eq false
143
+ expect(response.status).to eq 404
144
+ expect(response.message).to match(/External Registration ID 'nonexistent-registration'/)
145
+ end
146
+
147
+ it "fails when setting_id is invalid" do
148
+ response = subject.get_registration_configuration_setting(registration_id: registration_options[:registration_id], setting_id: "NonExistentSettingTotesBogus", value: "42")
149
+ expect(response.success?).to eq false
150
+ expect(response.status).to eq 400
151
+ expect(response.message).to match(/No configuration setting found with id.*NonExistentSettingTotesBogus/)
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,46 @@
1
+ RSpec.describe ScormEngine::Api::Endpoints::Registrations::LaunchHistory do
2
+ let(:subject) { scorm_engine_client }
3
+
4
+ let(:registration_options) { {
5
+ course_id: "testing-golf-explained",
6
+ registration_id: "testing-golf-explained-registration-1",
7
+ learner: {
8
+ id: "testing-golf-explained-learner-1",
9
+ first_name: "Arnold",
10
+ last_name: "Palmer",
11
+ }
12
+ } }
13
+
14
+ before do
15
+ against_real_scorm_engine do
16
+ ensure_course_exists(client: subject, course_id: registration_options[:course_id])
17
+ ensure_registration_exists(registration_options.merge(client: subject))
18
+ # NOTE: For this to work you'll need to visit the launch URL at least once manually
19
+ # so that we have something to record in VCR for later.
20
+ #
21
+ # subject.get_registration_launch_link(
22
+ # registration_id: registration_options[:registration_id]
23
+ # ).result
24
+ end
25
+ end
26
+
27
+ describe "#get_registration_launch_history" do
28
+ let(:histories) { subject.get_registration_launch_history(registration_id: registration_options[:registration_id]) }
29
+
30
+ it "is successful" do
31
+ expect(histories.success?).to eq true
32
+ end
33
+
34
+ it "returns an array of registration launch histories" do
35
+ expect(histories.result.all? { |r| r.is_a?(ScormEngine::Models::RegistrationLaunchHistory) }).to eq true
36
+ end
37
+
38
+ it "fails when registration does not exist" do
39
+ response = subject.get_registration_launch_history(registration_id: "reg-does-not-exist")
40
+ aggregate_failures do
41
+ expect(response.success?).to eq false
42
+ expect(response.status).to eq 404
43
+ end
44
+ end
45
+ end
46
+ end