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.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/Rakefile +13 -0
- data/lib/scorm_engine.rb +13 -0
- data/lib/scorm_engine/api/endpoints.rb +50 -0
- data/lib/scorm_engine/api/endpoints/about.rb +59 -0
- data/lib/scorm_engine/api/endpoints/courses.rb +136 -0
- data/lib/scorm_engine/api/endpoints/courses/configuration.rb +146 -0
- data/lib/scorm_engine/api/endpoints/courses/import.rb +83 -0
- data/lib/scorm_engine/api/endpoints/ping.rb +20 -0
- data/lib/scorm_engine/api/endpoints/registrations.rb +321 -0
- data/lib/scorm_engine/api/endpoints/registrations/configuration.rb +146 -0
- data/lib/scorm_engine/api/endpoints/registrations/launch_history.rb +47 -0
- data/lib/scorm_engine/client.rb +17 -0
- data/lib/scorm_engine/configuration.rb +43 -0
- data/lib/scorm_engine/faraday/connection.rb +35 -0
- data/lib/scorm_engine/faraday/request.rb +54 -0
- data/lib/scorm_engine/models.rb +9 -0
- data/lib/scorm_engine/models/course.rb +66 -0
- data/lib/scorm_engine/models/course_configuration.rb +37 -0
- data/lib/scorm_engine/models/course_import.rb +42 -0
- data/lib/scorm_engine/models/learner.rb +24 -0
- data/lib/scorm_engine/models/registration.rb +82 -0
- data/lib/scorm_engine/models/registration_activity_detail.rb +37 -0
- data/lib/scorm_engine/models/registration_configuration.rb +37 -0
- data/lib/scorm_engine/models/registration_launch_history.rb +92 -0
- data/lib/scorm_engine/models/registration_runtime_interaction.rb +52 -0
- data/lib/scorm_engine/response.rb +26 -0
- data/lib/scorm_engine/utils.rb +13 -0
- data/lib/scorm_engine/version.rb +3 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about/is_successful.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about/knows_the_platform.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about/knows_the_version.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about_user_count/accepts_before_option.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about_user_count/accepts_since_option.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about_user_count/is_successful.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about_user_count/tracks_combined_counts.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_About/_get_about_user_count/tracks_per_tenantcounts.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_delete_course/fails_when_id_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_delete_course/works.yml +32 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_course_detail/is_successful.yml +41 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_course_detail/results/sucessfully_creates_the_Course_attributes.yml +41 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_course_preview/fails_when_id_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_course_preview/is_successful.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_course_preview/results/returns_a_URL_string.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/_course_id_option/fetches_a_single_course_but_perhaps_multiple_versions.yml +39 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/_course_id_option/returns_404_when_ID_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/_more_option_pagination_/returns_all_the_courses.yml +89 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/_more_option_pagination_/returns_the_more_key_in_the_raw_response.yml +48 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/_since_option/fails_when_passed_an_invalid_value.yml +37 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/_since_option/works.yml +43 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/is_successful.yml +43 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/results/is_an_enumerator_of_Course_models.yml +43 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses/_get_courses/results/sucessfully_creates_the_Course_attributes.yml +43 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_get_course_configuration/fails_when_id_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_get_course_configuration/is_successful.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_get_course_configuration/results/makes_settings_available_as_key/value_pairs.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_get_course_configuration_setting/fails_when_course_id_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_get_course_configuration_setting/fails_when_setting_id_is_invalid.yml +36 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_get_course_configuration_setting/is_successful.yml +65 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_get_course_configuration_setting/results/returns_the_value_as_a_string.yml +65 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_post_course_configuration/fails_when_id_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_post_course_configuration/fails_when_settings_are_invalid.yml +36 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_post_course_configuration/is_successful.yml +32 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_post_course_configuration/persists_the_settings.yml +131 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_put_course_configuration_setting/fails_when_course_id_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_put_course_configuration_setting/fails_when_setting_id_is_invalid.yml +36 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_put_course_configuration_setting/is_successful.yml +65 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Configuration/_put_course_configuration_setting/results/persists_the_changes.yml +98 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Import/_get_course_import/successful_imports/works.yml +147 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Import/_get_course_import/unsuccessful_imports/fails_to_import_given_an_invalid_url.yml +326 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Import/_post_course_import/successful_imports/works.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Courses_Import/_post_course_import/unsuccessful_imports/fails_to_import_a_previously_existing_course.yml +36 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Ping/_get_ping/is_successful.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Ping/_get_ping/reports_the_api_is_up.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Ping/_get_ping/with_invalid_password/is_unsuccessful.yml +41 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Ping/_get_ping/with_invalid_password/returns_status_403.yml +41 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_delete_registration/is_failure_when_registration_does_not_exist.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_delete_registration/is_successful_when_registration_exists.yml +32 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_exists/is_false_when_registration_does_not_exist.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_exists/is_true_when_registration_exists.yml +36 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_instances/includes_results_we_expect.yml +39 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_instances/is_successful.yml +39 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_instances/returns_an_array_of_registrations.yml +39 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_launch_link/fails_when_id_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_launch_link/is_successful.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_launch_link/results/returns_a_URL_string.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_progress/detail/does_not_return_activity_details_by_default.yml +39 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_progress/detail/returns_activity_details_if_requested.yml +41 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_progress/fails_when_registration_does_not_exist.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registration_progress/returns_a_registration_when_it_exists.yml +39 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registrations/filtering_by_course_id/excludes_results.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registrations/filtering_by_course_id/includes_results.yml +40 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registrations/filtering_by_learner_id/excludes_results.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registrations/filtering_by_learner_id/includes_results.yml +39 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registrations/includes_results_we_expect.yml +40 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registrations/is_successful.yml +40 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_get_registrations/returns_an_array_of_registrations.yml +40 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_post_registration/fails_if_course_id_is_invalid.yml +36 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_post_registration/fails_if_registration_id_already_exists.yml +36 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations/_post_registration/is_successful.yml +61 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_get_registration_configuration/fails_when_id_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_get_registration_configuration/is_successful.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_get_registration_configuration/results/makes_settings_available_as_key/value_pairs.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_get_registration_configuration_setting/fails_when_registration_id_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_get_registration_configuration_setting/fails_when_setting_id_is_invalid.yml +36 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_get_registration_configuration_setting/is_successful.yml +65 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_get_registration_configuration_setting/results/returns_the_value_as_a_string.yml +65 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_post_registration_configuration/fails_when_id_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_post_registration_configuration/fails_when_settings_are_invalid.yml +36 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_post_registration_configuration/is_successful.yml +32 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_post_registration_configuration/persists_the_settings.yml +131 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_put_registration_configuration_setting/fails_when_registration_id_is_invalid.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_put_registration_configuration_setting/fails_when_setting_id_is_invalid.yml +36 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_put_registration_configuration_setting/is_successful.yml +65 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_Configuration/_put_registration_configuration_setting/results/persists_the_changes.yml +98 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_LaunchHistory/_get_registration_launch_history/fails_when_registration_does_not_exist.yml +38 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_LaunchHistory/_get_registration_launch_history/is_successful.yml +54 -0
- data/spec/fixtures/vcr/ScormEngine_Api_Endpoints_Registrations_LaunchHistory/_get_registration_launch_history/returns_an_array_of_registration_launch_histories.yml +54 -0
- data/spec/fixtures/zip/Non-working SCORM.zip +0 -0
- data/spec/fixtures/zip/RuntimeBasicCalls_SCORM20043rdEdition.zip +0 -0
- data/spec/scorm_engine/api/endpoints/about_spec.rb +59 -0
- data/spec/scorm_engine/api/endpoints/courses/configuration_spec.rb +143 -0
- data/spec/scorm_engine/api/endpoints/courses/import_spec.rb +92 -0
- data/spec/scorm_engine/api/endpoints/courses_spec.rb +155 -0
- data/spec/scorm_engine/api/endpoints/ping_spec.rb +27 -0
- data/spec/scorm_engine/api/endpoints/registrations/configuration_spec.rb +154 -0
- data/spec/scorm_engine/api/endpoints/registrations/launch_history_spec.rb +46 -0
- data/spec/scorm_engine/api/endpoints/registrations_spec.rb +201 -0
- data/spec/scorm_engine/configuration_spec.rb +29 -0
- data/spec/scorm_engine/models/course_configuration_spec.rb +16 -0
- data/spec/scorm_engine/models/course_import_spec.rb +86 -0
- data/spec/scorm_engine/models/course_spec.rb +92 -0
- data/spec/scorm_engine/models/learner_spec.rb +27 -0
- data/spec/scorm_engine/models/registration_activity_detail_spec.rb +101 -0
- data/spec/scorm_engine/models/registration_launch_history_spec.rb +86 -0
- data/spec/scorm_engine/models/registration_runtime_interaction_spec.rb +91 -0
- data/spec/scorm_engine/models/registration_spec.rb +82 -0
- data/spec/scorm_engine/utils_spec.rb +15 -0
- data/spec/scorm_engine/version_spec.rb +5 -0
- data/spec/scorm_engine_spec.rb +2 -0
- data/spec/spec_helper.rb +47 -0
- data/spec/support/scorm_engine.rb +72 -0
- data/spec/support/scorm_engine_client.rb +6 -0
- data/spec/support/scorm_engine_configuration.rb +7 -0
- data/spec/support/vcr.rb +53 -0
- metadata +329 -0
@@ -0,0 +1,101 @@
|
|
1
|
+
RSpec.describe ScormEngine::Models::RegistrationActivityDetail do
|
2
|
+
describe ".new_from_api" do
|
3
|
+
let(:options) { {
|
4
|
+
"id" => "activity-123",
|
5
|
+
"runtime" => {
|
6
|
+
"runtimeInteractions" => [
|
7
|
+
{ "id" => "root-interaction-1" },
|
8
|
+
{ "id" => "root-interaction-2" },
|
9
|
+
],
|
10
|
+
},
|
11
|
+
"children" => [
|
12
|
+
{
|
13
|
+
"id" => "child-1",
|
14
|
+
"runtime" => {
|
15
|
+
"runtimeInteractions" => [
|
16
|
+
{ "id" => "child-1-interaction-1" },
|
17
|
+
{ "id" => "child-1-interaction-2" },
|
18
|
+
],
|
19
|
+
},
|
20
|
+
"children" => [
|
21
|
+
{
|
22
|
+
"id" => "grandchild-1",
|
23
|
+
"runtime" => { "runtimeInteractions" => [] },
|
24
|
+
},
|
25
|
+
],
|
26
|
+
},
|
27
|
+
{
|
28
|
+
"id" => "child-2",
|
29
|
+
"runtime" => {
|
30
|
+
"runtimeInteractions" => [
|
31
|
+
{ "id" => "child-2-interaction-1" },
|
32
|
+
],
|
33
|
+
},
|
34
|
+
"children" => [
|
35
|
+
{
|
36
|
+
"id" => "grandchild-2",
|
37
|
+
"runtime" => {
|
38
|
+
"runtimeInteractions" => [
|
39
|
+
{ "id" => "grandchild-1-interaction-1" },
|
40
|
+
{ "id" => "grandchild-1-interaction-2" },
|
41
|
+
],
|
42
|
+
},
|
43
|
+
},
|
44
|
+
{
|
45
|
+
"id" => "grandchild-3",
|
46
|
+
"runtime" => {},
|
47
|
+
},
|
48
|
+
],
|
49
|
+
},
|
50
|
+
],
|
51
|
+
} }
|
52
|
+
|
53
|
+
let(:activity) { described_class.new_from_api(options) }
|
54
|
+
|
55
|
+
describe ":id" do
|
56
|
+
it "is set properly" do
|
57
|
+
expect(activity.id).to eq "activity-123"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe ":children" do
|
62
|
+
it "is set properly" do
|
63
|
+
ids = activity.children.map(&:id)
|
64
|
+
expect(ids).to match_array %w[child-1 child-2]
|
65
|
+
end
|
66
|
+
|
67
|
+
it "is set properly for children" do
|
68
|
+
ids = activity.children.flat_map(&:children).map(&:id)
|
69
|
+
expect(ids).to match_array %w[grandchild-1 grandchild-2 grandchild-3]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe ":runtime_interactions" do
|
74
|
+
it "is set properly" do
|
75
|
+
ids = activity.runtime_interactions.map(&:id)
|
76
|
+
expect(ids).to match_array %w[root-interaction-1 root-interaction-2]
|
77
|
+
end
|
78
|
+
|
79
|
+
it "is set properly for children" do
|
80
|
+
ids = activity.children.detect { |c| c.id == "child-1" }.runtime_interactions.map(&:id)
|
81
|
+
expect(ids).to match_array %w[child-1-interaction-1 child-1-interaction-2]
|
82
|
+
end
|
83
|
+
|
84
|
+
it "is set properly for grandchildren" do
|
85
|
+
child = activity.children.detect { |c| c.id == "child-2" }
|
86
|
+
ids = child.children.detect { |c| c.id == "grandchild-2" }.runtime_interactions.map(&:id)
|
87
|
+
expect(ids).to match_array %w[grandchild-1-interaction-1 grandchild-1-interaction-2]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "#all_runtime_interactions" do
|
92
|
+
it "returns all interactions" do
|
93
|
+
expect(activity.all_runtime_interactions.map(&:id)).to match_array %w[
|
94
|
+
root-interaction-1 root-interaction-2
|
95
|
+
child-1-interaction-1 child-1-interaction-2 child-2-interaction-1
|
96
|
+
grandchild-1-interaction-1 grandchild-1-interaction-2
|
97
|
+
]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
RSpec.describe ScormEngine::Models::RegistrationLaunchHistory do
|
2
|
+
describe ".new_from_api" do
|
3
|
+
let(:launch_history) { described_class.new_from_api(
|
4
|
+
"id" => "registration-456",
|
5
|
+
"instanceId" => 1.0,
|
6
|
+
"launchTime" => "07/25/2018 20:02:02 PM",
|
7
|
+
"launchTimeUtc" => "07/25/2018 20:02:02 PM",
|
8
|
+
"exitTime" => "07/25/2018 20:02:14 PM",
|
9
|
+
"exitTimeUtc" => "07/25/2018 20:02:14 PM",
|
10
|
+
"completionStatus" => "Incomplete",
|
11
|
+
"successStatus" => "Failed",
|
12
|
+
"lastRuntimeUpdate" => "07/25/2018 20:02:14 PM",
|
13
|
+
"lastRuntimeUpdateUtc" => "2018-07-25T20:01:58.000Z", # intentionally tweaked from what is really returned
|
14
|
+
"score" => { "scaled" => 93.0 },
|
15
|
+
)}
|
16
|
+
|
17
|
+
describe ":id" do
|
18
|
+
it "is set properly" do
|
19
|
+
expect(launch_history.id).to eq "registration-456"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe ":score" do
|
24
|
+
it "is set properly" do
|
25
|
+
expect(launch_history.score).to eq 93.0
|
26
|
+
end
|
27
|
+
|
28
|
+
it "is left unset if not present" do
|
29
|
+
launch_history = described_class.new_from_api({})
|
30
|
+
expect(launch_history.score).to eq nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe ":total_seconds_tracked" do
|
35
|
+
it "is set properly when set in the root level with a trailing space" do
|
36
|
+
launch_history = described_class.new_from_api("totalSecondsTracked " => 123)
|
37
|
+
expect(launch_history.total_seconds_tracked).to eq 123
|
38
|
+
end
|
39
|
+
|
40
|
+
it "is set properly when set in the root level without a trailing space" do
|
41
|
+
launch_history = described_class.new_from_api("totalSecondsTracked" => 123)
|
42
|
+
expect(launch_history.total_seconds_tracked).to eq 123
|
43
|
+
end
|
44
|
+
|
45
|
+
it "is set properly when set in the score object with a trailing space" do
|
46
|
+
launch_history = described_class.new_from_api("score" => { "totalSecondsTracked " => 123 })
|
47
|
+
expect(launch_history.total_seconds_tracked).to eq 123
|
48
|
+
end
|
49
|
+
|
50
|
+
it "is set properly when set in the score object without a trailing space" do
|
51
|
+
launch_history = described_class.new_from_api("score" => { "totalSecondsTracked" => 123 })
|
52
|
+
expect(launch_history.total_seconds_tracked).to eq 123
|
53
|
+
end
|
54
|
+
|
55
|
+
it "is set to zero when it's negative" do
|
56
|
+
launch_history = described_class.new_from_api("totalSecondsTracked" => -9.223372036854776e+16)
|
57
|
+
expect(launch_history.total_seconds_tracked).to eq 0
|
58
|
+
end
|
59
|
+
|
60
|
+
it "is left unset if not present" do
|
61
|
+
launch_history = described_class.new_from_api({})
|
62
|
+
expect(launch_history.total_seconds_tracked).to eq nil
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe ":instance_id" do
|
67
|
+
it "is coerced to an integer" do
|
68
|
+
expect(launch_history.instance_id).to eq 1
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
%i[launch_time exit_time last_runtime_update].each do |attr|
|
73
|
+
describe ":#{attr}" do
|
74
|
+
it "is set properly in the UTC timezone" do
|
75
|
+
expect(launch_history.send(attr)).to be_a Time
|
76
|
+
expect(launch_history.send(attr).zone).to eq "UTC"
|
77
|
+
end
|
78
|
+
|
79
|
+
it "is left unset if not present" do
|
80
|
+
launch_history = described_class.new_from_api({})
|
81
|
+
expect(launch_history.send(attr)).to eq nil
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
RSpec.describe ScormEngine::Models::RegistrationRuntimeInteraction do
|
2
|
+
describe ".new_from_api" do
|
3
|
+
let(:options) { {
|
4
|
+
"id" => "interaction-123",
|
5
|
+
"description" => " foo \t bar \n baz ",
|
6
|
+
"timestampUtc" => "2018-05-24T00:01:02.00Z",
|
7
|
+
"correctResponses" => %w[one two],
|
8
|
+
"learnerResponse" => "one",
|
9
|
+
"result" => "correct",
|
10
|
+
"weighting" => "3",
|
11
|
+
"latency" => "0012:34:59"
|
12
|
+
} }
|
13
|
+
|
14
|
+
let(:interaction) { described_class.new_from_api(options) }
|
15
|
+
|
16
|
+
describe ":id" do
|
17
|
+
it "is set properly" do
|
18
|
+
expect(interaction.id).to eq "interaction-123"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe ":description" do
|
23
|
+
it "is set properly" do
|
24
|
+
expect(interaction.description).to eq "foo bar baz"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "is set to nil if blank" do
|
28
|
+
interaction = described_class.new_from_api(options.merge("description" => " "))
|
29
|
+
expect(interaction.description).to eq nil
|
30
|
+
end
|
31
|
+
|
32
|
+
it "is set to nil if literal value 'null'" do
|
33
|
+
interaction = described_class.new_from_api(options.merge("description" => "null"))
|
34
|
+
expect(interaction.description).to eq nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe ":timestamp" do
|
39
|
+
it "is set properly" do
|
40
|
+
expect(interaction.timestamp.iso8601).to eq "2018-05-24T00:01:02Z"
|
41
|
+
end
|
42
|
+
|
43
|
+
it "is set to nil if blank" do
|
44
|
+
interaction = described_class.new_from_api(options.merge("timestampUtc" => ""))
|
45
|
+
expect(interaction.timestamp).to eq nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe ":correct_responses" do
|
50
|
+
it "is set properly" do
|
51
|
+
expect(interaction.correct_responses).to eq %w[one two]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe ":learner_response" do
|
56
|
+
it "is set properly" do
|
57
|
+
expect(interaction.learner_response).to eq "one"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe ":result" do
|
62
|
+
it "is set properly" do
|
63
|
+
expect(interaction.result).to eq "correct"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe ":weighting" do
|
68
|
+
it "is set properly" do
|
69
|
+
expect(interaction.weighting).to eq "3"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe ":latency" do
|
74
|
+
it "is set properly" do
|
75
|
+
expect(interaction.latency).to eq "0012:34:59"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "#latency_in_seconds" do
|
80
|
+
it "parses valid values" do
|
81
|
+
interaction = described_class.new_from_api("latency" => "0012:34:59")
|
82
|
+
expect(interaction.latency_in_seconds).to eq 45_299
|
83
|
+
end
|
84
|
+
|
85
|
+
it "returns zero for invalid values" do
|
86
|
+
interaction = described_class.new_from_api("latency" => "wat")
|
87
|
+
expect(interaction.latency_in_seconds).to eq 0
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
RSpec.describe ScormEngine::Models::Registration do
|
2
|
+
describe ".new_from_api" do
|
3
|
+
let(:options) { {
|
4
|
+
"id" => "registration-456",
|
5
|
+
"score" => {
|
6
|
+
"scaled" => "3.14159",
|
7
|
+
"additionalProperties" => {},
|
8
|
+
},
|
9
|
+
"course" => {
|
10
|
+
"id" => "course-789",
|
11
|
+
"title" => "Golf 101",
|
12
|
+
},
|
13
|
+
"learner" => {
|
14
|
+
"id" => "learner-123",
|
15
|
+
"firstName" => "Bobby",
|
16
|
+
"lastName" => "Jones",
|
17
|
+
},
|
18
|
+
} }
|
19
|
+
|
20
|
+
let(:registration) { described_class.new_from_api(options) }
|
21
|
+
|
22
|
+
describe ":id" do
|
23
|
+
it "is set properly" do
|
24
|
+
expect(registration.id).to eq "registration-456"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe ":score" do
|
29
|
+
it "is set properly" do
|
30
|
+
expect(registration.score).to be_a Numeric
|
31
|
+
expect(registration.score.round(2)).to eq 3.14
|
32
|
+
end
|
33
|
+
|
34
|
+
it "is left unset if not present" do
|
35
|
+
registration = described_class.new_from_api({})
|
36
|
+
expect(registration.score).to eq nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe ":completed_date" do
|
41
|
+
it "is set properly when key is in root level" do
|
42
|
+
registration = described_class.new_from_api(options.merge("completedDate" => "2018-05-24T00:01:02.000Z"))
|
43
|
+
expect(registration.completed_date).to be_a Time
|
44
|
+
expect(registration.completed_date.iso8601).to eq "2018-05-24T00:01:02Z"
|
45
|
+
end
|
46
|
+
|
47
|
+
it "is set properly when key is in score object" do
|
48
|
+
registration = described_class.new_from_api(options.merge("score" => { "completedDate" => "2018-05-24T00:01:02.000Z" }))
|
49
|
+
expect(registration.completed_date).to be_a Time
|
50
|
+
expect(registration.completed_date.iso8601).to eq "2018-05-24T00:01:02Z"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "is left unset if not present" do
|
54
|
+
expect(registration.completed_date).to eq nil
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe ":course" do
|
59
|
+
it "is set properly" do
|
60
|
+
expect(registration.course).to be_a ScormEngine::Models::Course
|
61
|
+
expect(registration.course.id).to eq "course-789"
|
62
|
+
end
|
63
|
+
|
64
|
+
it "is left unset if not present" do
|
65
|
+
registration = described_class.new_from_api({})
|
66
|
+
expect(registration.course).to eq nil
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe ":learner" do
|
71
|
+
it "is set properly" do
|
72
|
+
expect(registration.learner).to be_a ScormEngine::Models::Learner
|
73
|
+
expect(registration.learner.id).to eq "learner-123"
|
74
|
+
end
|
75
|
+
|
76
|
+
it "is left unset if not present" do
|
77
|
+
registration = described_class.new_from_api({})
|
78
|
+
expect(registration.learner).to eq nil
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
RSpec.describe ScormEngine::Utils do
|
2
|
+
describe ".sanitized_text" do
|
3
|
+
it "removes unescaped HTML" do
|
4
|
+
expect(described_class.sanitized_text("<b class='world'>Hello</b>")).to eq "Hello"
|
5
|
+
end
|
6
|
+
|
7
|
+
it "strips and squeezes all white space" do
|
8
|
+
expect(described_class.sanitized_text(" a b\n\r\t c ")).to eq "a b c"
|
9
|
+
end
|
10
|
+
|
11
|
+
pending "encodes string to utf8"
|
12
|
+
pending "replaces invalid utf8"
|
13
|
+
pending "replaces undefined utf8"
|
14
|
+
end
|
15
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require "bundler/setup"
|
2
|
+
require "dotenv"
|
3
|
+
require "pry"
|
4
|
+
require "scorm_engine"
|
5
|
+
|
6
|
+
# Ensure we're picking up only the test scorm settings
|
7
|
+
Dotenv.load(".env.test")
|
8
|
+
|
9
|
+
RSpec.configure do |config|
|
10
|
+
# Enable flags like --only-failures and --next-failure
|
11
|
+
config.example_status_persistence_file_path = ".rspec_status"
|
12
|
+
|
13
|
+
# Disable RSpec exposing methods globally on `Module` and `main`
|
14
|
+
config.disable_monkey_patching!
|
15
|
+
|
16
|
+
# rspec-expectations config goes here. You can use an alternate
|
17
|
+
# assertion/expectation library such as wrong or the stdlib/minitest
|
18
|
+
# assertions if you prefer.
|
19
|
+
config.expect_with :rspec do |expectations|
|
20
|
+
# Enable only the newer, non-monkey-patching expect syntax.
|
21
|
+
# For more details, see:
|
22
|
+
# - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
|
23
|
+
expectations.syntax = :expect
|
24
|
+
end
|
25
|
+
|
26
|
+
# Run specs in random order to surface order dependencies. If you find an
|
27
|
+
# order dependency and want to debug it, you can fix the order by providing
|
28
|
+
# the seed, which is printed after each run.
|
29
|
+
# --seed 1234
|
30
|
+
config.order = :random
|
31
|
+
|
32
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
33
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
34
|
+
# test failures related to randomization by passing the same `--seed` value
|
35
|
+
# as the one that triggered the failure.
|
36
|
+
Kernel.srand config.seed
|
37
|
+
|
38
|
+
# Tag all groups and examples to use VCR
|
39
|
+
config.define_derived_metadata do |metadata|
|
40
|
+
metadata[:vcr] = true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Require every spec support file
|
45
|
+
Dir[File.join(File.dirname(__FILE__), "support", "**/*.rb")].each do |file|
|
46
|
+
require file
|
47
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module ScormEngineHelpers
|
2
|
+
#
|
3
|
+
# If a real scorm engine is available this method will disable VCR and
|
4
|
+
# execute the passed block. It is useful for when we need to ensure certain
|
5
|
+
# records are present in SCORM engine, but we do not want them recorded as
|
6
|
+
# the act of recording would break later expectations. That is if we record
|
7
|
+
# importing a course and play it back other tests that expect the actual
|
8
|
+
# record to exist in SCORM will fail.
|
9
|
+
#
|
10
|
+
def against_real_scorm_engine
|
11
|
+
return unless scorm_engine_is_available?
|
12
|
+
|
13
|
+
cassette = VCR.eject_cassette
|
14
|
+
VCR.turned_off do
|
15
|
+
yield
|
16
|
+
end
|
17
|
+
VCR.insert_cassette(cassette.name, cassette.instance_variable_get(:@options))
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# Check to see if a scorm engine is available. Probably true while developing
|
22
|
+
# locally, definitely not true in Travis.
|
23
|
+
#
|
24
|
+
def scorm_engine_is_available?
|
25
|
+
ENV["SCORM_ENGINE_IS_AVAILABLE"] == "true"
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# Ensure that the specified course exists in SCORM engine. Will import course
|
30
|
+
# if not present.
|
31
|
+
#
|
32
|
+
def ensure_course_exists(options = {})
|
33
|
+
response = options[:client].get_courses(course_id: options[:course_id])
|
34
|
+
return if response&.results&.first&.id == options[:course_id]
|
35
|
+
import_course(options)
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Attempt to import a course to SCORM engine.
|
40
|
+
#
|
41
|
+
def import_course(options = {})
|
42
|
+
options = { key: "RuntimeBasicCalls_SCORM20043rdEdition", may_create_new_version: true }.merge(options)
|
43
|
+
|
44
|
+
url = "https://github.com/phallstrom/scorm_engine/raw/master/spec/fixtures/zip/#{options[:key]}.zip"
|
45
|
+
|
46
|
+
import = options[:client].post_course_import(course_id: options[:course_id], url: url, may_create_new_version: options[:may_create_new_version])
|
47
|
+
|
48
|
+
if import.success?
|
49
|
+
loop do
|
50
|
+
import = options[:client].get_course_import(id: import.result.id)
|
51
|
+
break unless import.success? && import.result.running?
|
52
|
+
sleep 5
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
import
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# Ensure that the specified registration exists in SCORM engine. Course
|
61
|
+
# must exist first.
|
62
|
+
#
|
63
|
+
def ensure_registration_exists(options = {})
|
64
|
+
response = options[:client].get_registration_exists(registration_id: options[:registration_id])
|
65
|
+
return if response&.result
|
66
|
+
options[:client].post_registration(options)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
RSpec.configure do |c|
|
71
|
+
c.include ScormEngineHelpers
|
72
|
+
end
|