canvas-workflow 0.5.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.
data/spec/file_spec.rb ADDED
@@ -0,0 +1,108 @@
1
+ require "spec_helper"
2
+
3
+ # [ ] test with incorrect authorization [error]
4
+ # [ ] with non-existing prefix [error]
5
+ # [X] with non-existing course [error]
6
+ # [X] for non-existing path [error]
7
+ # [X] for non-existing file [error]
8
+ # [ ] for ambiguous file [error]
9
+ # [X] for existing file in root folder [pass]
10
+ # [X] for existing file in nested folder [pass]
11
+
12
+ describe Canvas::Workflow::Tags::FileTag do
13
+ let(:doc) { doc_with_content(content) }
14
+ let(:prefix) { doc.site.config['canvas']['prefix'] }
15
+ let(:course) { doc.site.config['canvas']['course'] }
16
+ let(:content) { "{% file #{path}#{file} %}" }
17
+ let(:output) do
18
+ doc.content = content
19
+ doc.output = Jekyll::Renderer.new(doc.site, doc).run
20
+ end
21
+
22
+ before :each do
23
+ stub_request(:get, url1).to_return(:status => status1, :body => fixture(fixture1), :headers => { "Content-Type" => "application/json; charset=utf-8" })
24
+ stub_request(:get, url2).to_return(:status => status2, :body => fixture(fixture2), :headers => { "Content-Type" => "application/json; charset=utf-8" })
25
+ end
26
+ let(:url1) { "#{prefix}/api/v1/courses/#{course}/folders/by_path/#{path}" }
27
+ let(:url2) { "#{prefix}/api/v1/folders/#{folder}/files?search_term=#{file}" }
28
+
29
+ context "with existing file" do
30
+ let(:status1) { 200 }
31
+ let(:status2) { 200 }
32
+ let(:fixture2) { "file" }
33
+ let(:file) { "file.txt" }
34
+
35
+ context "in course folder" do
36
+ let(:fixture1) { "root" }
37
+ let(:path) { "" }
38
+ let(:folder) { 2937 } # from id of :path in folders.json
39
+
40
+ it "produces the correct url" do
41
+ expect(output).to eq("<p>http://www.canvas.instructure.com/files/569/download?download_frd=1&amp;verifier=c6HdZmxOZa0Fiin2cbvZeI8I5ry7yqD7RChQzb6P</p>\n")
42
+ end
43
+ end
44
+
45
+ context "in nested folder" do
46
+ let(:fixture1) { "nested" }
47
+ let(:path) { "nested/examples/" }
48
+ let(:folder) { 2939 } # from id of :path in folders.json
49
+
50
+ it "produces the correct url" do
51
+ expect(output).to eq("<p>http://www.canvas.instructure.com/files/569/download?download_frd=1&amp;verifier=c6HdZmxOZa0Fiin2cbvZeI8I5ry7yqD7RChQzb6P</p>\n")
52
+ end
53
+ end
54
+ end
55
+
56
+ context "with non-existing component" do
57
+ context "course does not exist" do
58
+ let(:output) do
59
+ doc.site.config['canvas']['course'] = course
60
+ doc.content = content
61
+ doc.output = Jekyll::Renderer.new(doc.site, doc).run
62
+ end
63
+
64
+ let(:course) { "0123456789" }
65
+ let(:status1) { 404 }
66
+ let(:fixture1) { "doesnotexist" }
67
+ let(:path) { "nested/examples/" }
68
+
69
+ let(:status2) { "unused" }
70
+ let(:fixture2) { "doesnotexist" }
71
+ let(:folder) { "unused" }
72
+ let(:file) { "unused" }
73
+
74
+ it "raises an error" do
75
+ expect(-> { output }).to raise_error(Footrest::HttpError::NotFound)
76
+ end
77
+ end
78
+
79
+ context "path does not exist" do
80
+ let(:status1) { 404 }
81
+ let(:fixture1) { "doesnotexist" }
82
+ let(:path) { "non-existent/path/" }
83
+
84
+ let(:status2) { "unused" }
85
+ let(:fixture2) { "doesnotexist" }
86
+ let(:folder) { "unused" }
87
+ let(:file) { "unused" }
88
+
89
+ it "raises an error" do
90
+ expect(-> { output }).to raise_error(Footrest::HttpError::NotFound)
91
+ end
92
+ end
93
+
94
+ context "file does not exist on path" do
95
+ let(:status1) { 200 }
96
+ let(:status2) { 404 }
97
+ let(:fixture1) { "nested" }
98
+ let(:fixture2) { "doesnotexist" }
99
+ let(:path) { "nested/examples/" }
100
+ let(:folder) { 2939 } # from id of :path in folders.json
101
+ let(:file) { "non-existent-file.txt" }
102
+
103
+ it "raises an error" do
104
+ expect(-> { output }).to raise_error(Footrest::HttpError::NotFound)
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,191 @@
1
+ [
2
+ {
3
+ // the ID of the assignment
4
+ "id": 4,
5
+ // the name of the assignment
6
+ "name": "some assignment",
7
+ // the assignment description, in an HTML fragment
8
+ "description": "<p>Do the following:</p>...",
9
+ // The time at which this assignment was originally created
10
+ "created_at": "2012-07-01T23:59:00-06:00",
11
+ // The time at which this assignment was last modified in any way
12
+ "updated_at": "2012-07-01T23:59:00-06:00",
13
+ // the due date for the assignment. returns null if not present. NOTE: If this
14
+ // assignment has assignment overrides, this field will be the due date as it
15
+ // applies to the user requesting information from the API.
16
+ "due_at": "2012-07-01T23:59:00-06:00",
17
+ // the lock date (assignment is locked after this date). returns null if not
18
+ // present. NOTE: If this assignment has assignment overrides, this field will be
19
+ // the lock date as it applies to the user requesting information from the API.
20
+ "lock_at": "2012-07-01T23:59:00-06:00",
21
+ // the unlock date (assignment is unlocked after this date) returns null if not
22
+ // present NOTE: If this assignment has assignment overrides, this field will be
23
+ // the unlock date as it applies to the user requesting information from the API.
24
+ "unlock_at": "2012-07-01T23:59:00-06:00",
25
+ // whether this assignment has overrides
26
+ "has_overrides": true,
27
+ // (Optional) all dates associated with the assignment, if applicable
28
+ "all_dates": null,
29
+ // the ID of the course the assignment belongs to
30
+ "course_id": 123,
31
+ // the URL to the assignment's web page
32
+ "html_url": "https://...",
33
+ // the URL to download all submissions as a zip
34
+ "submissions_download_url": "https://example.com/courses/:course_id/assignments/:id/submissions?zip=1",
35
+ // the ID of the assignment's group
36
+ "assignment_group_id": 2,
37
+ // Boolean flag indicating whether the assignment requires a due date based on the
38
+ // account level setting
39
+ "due_date_required": true,
40
+ // Allowed file extensions, which take effect if submission_types includes
41
+ // 'online_upload'.
42
+ "allowed_extensions": ["docx", "ppt"],
43
+ // An integer indicating the maximum length an assignment's name may be
44
+ "max_name_length": 15,
45
+ // Boolean flag indicating whether or not Turnitin has been enabled for the
46
+ // assignment. NOTE: This flag will not appear unless your account has the Turnitin
47
+ // plugin available
48
+ "turnitin_enabled": true,
49
+ // Boolean flag indicating whether or not VeriCite has been enabled for the
50
+ // assignment. NOTE: This flag will not appear unless your account has the VeriCite
51
+ // plugin available
52
+ "vericite_enabled": true,
53
+ // Settings to pass along to turnitin to control what kinds of matches should be
54
+ // considered. originality_report_visibility can be 'immediate', 'after_grading',
55
+ // 'after_due_date', or 'never' exclude_small_matches_type can be null, 'percent',
56
+ // 'words' exclude_small_matches_value: - if type is null, this will be null also -
57
+ // if type is 'percent', this will be a number between 0 and 100 representing match
58
+ // size to exclude as a percentage of the document size. - if type is 'words', this
59
+ // will be number > 0 representing how many words a match must contain for it to be
60
+ // considered NOTE: This flag will not appear unless your account has the Turnitin
61
+ // plugin available
62
+ "turnitin_settings": null,
63
+ // If this is a group assignment, boolean flag indicating whether or not students
64
+ // will be graded individually.
65
+ "grade_group_students_individually": false,
66
+ // (Optional) assignment's settings for external tools if submission_types include
67
+ // 'external_tool'. Only url and new_tab are included (new_tab defaults to false).
68
+ // Use the 'External Tools' API if you need more information about an external
69
+ // tool.
70
+ "external_tool_tag_attributes": null,
71
+ // Boolean indicating if peer reviews are required for this assignment
72
+ "peer_reviews": false,
73
+ // Boolean indicating peer reviews are assigned automatically. If false, the
74
+ // teacher is expected to manually assign peer reviews.
75
+ "automatic_peer_reviews": false,
76
+ // Integer representing the amount of reviews each user is assigned. NOTE: This key
77
+ // is NOT present unless you have automatic_peer_reviews set to true.
78
+ "peer_review_count": 0,
79
+ // String representing a date the reviews are due by. Must be a date that occurs
80
+ // after the default due date. If blank, or date is not after the assignment's due
81
+ // date, the assignment's due date will be used. NOTE: This key is NOT present
82
+ // unless you have automatic_peer_reviews set to true.
83
+ "peer_reviews_assign_at": "2012-07-01T23:59:00-06:00",
84
+ // Boolean representing whether or not members from within the same group on a
85
+ // group assignment can be assigned to peer review their own group's work
86
+ "intra_group_peer_reviews": false,
87
+ // The ID of the assignment’s group set, if this is a group assignment. For group
88
+ // discussions, set group_category_id on the discussion topic, not the linked
89
+ // assignment.
90
+ "group_category_id": 1,
91
+ // if the requesting user has grading rights, the number of submissions that need
92
+ // grading.
93
+ "needs_grading_count": 17,
94
+ // if the requesting user has grading rights and the
95
+ // 'needs_grading_count_by_section' flag is specified, the number of submissions
96
+ // that need grading split out by section. NOTE: This key is NOT present unless you
97
+ // pass the 'needs_grading_count_by_section' argument as true. ANOTHER NOTE: it's
98
+ // possible to be enrolled in multiple sections, and if a student is setup that way
99
+ // they will show an assignment that needs grading in multiple sections
100
+ // (effectively the count will be duplicated between sections)
101
+ "needs_grading_count_by_section": [{"section_id":"123456","needs_grading_count":5}, {"section_id":"654321","needs_grading_count":0}],
102
+ // the sorting order of the assignment in the group
103
+ "position": 1,
104
+ // (optional, present if Sync Grades to SIS feature is enabled)
105
+ "post_to_sis": true,
106
+ // (optional, Third Party unique identifier for Assignment)
107
+ "integration_id": "12341234",
108
+ // (optional, Third Party integration data for assignment)
109
+ "integration_data": "12341234",
110
+ // whether the assignment is muted
111
+ "muted": null,
112
+ // the maximum points possible for the assignment
113
+ "points_possible": 12,
114
+ // the types of submissions allowed for this assignment list containing one or more
115
+ // of the following: 'discussion_topic', 'online_quiz', 'on_paper', 'none',
116
+ // 'external_tool', 'online_text_entry', 'online_url', 'online_upload'
117
+ // 'media_recording'
118
+ "submission_types": ["online_text_entry"],
119
+ // If true, the assignment has been submitted to by at least one student
120
+ "has_submitted_submissions": true,
121
+ // The type of grading the assignment receives; one of 'pass_fail', 'percent',
122
+ // 'letter_grade', 'gpa_scale', 'points'
123
+ "grading_type": "points",
124
+ // The id of the grading standard being applied to this assignment. Valid if
125
+ // grading_type is 'letter_grade' or 'gpa_scale'.
126
+ "grading_standard_id": null,
127
+ // Whether the assignment is published
128
+ "published": true,
129
+ // Whether the assignment's 'published' state can be changed to false. Will be
130
+ // false if there are student submissions for the assignment.
131
+ "unpublishable": false,
132
+ // Whether the assignment is only visible to overrides.
133
+ "only_visible_to_overrides": false,
134
+ // Whether or not this is locked for the user.
135
+ "locked_for_user": false,
136
+ // (Optional) Information for the user about the lock. Present when locked_for_user
137
+ // is true.
138
+ "lock_info": null,
139
+ // (Optional) An explanation of why this is locked for the user. Present when
140
+ // locked_for_user is true.
141
+ "lock_explanation": "This assignment is locked until September 1 at 12:00am",
142
+ // (Optional) id of the associated quiz (applies only when submission_types is
143
+ // ['online_quiz'])
144
+ "quiz_id": 620,
145
+ // (Optional) whether anonymous submissions are accepted (applies only to quiz
146
+ // assignments)
147
+ "anonymous_submissions": false,
148
+ // (Optional) the DiscussionTopic associated with the assignment, if applicable
149
+ "discussion_topic": null,
150
+ // (Optional) Boolean indicating if assignment will be frozen when it is copied.
151
+ // NOTE: This field will only be present if the AssignmentFreezer plugin is
152
+ // available for your account.
153
+ "freeze_on_copy": false,
154
+ // (Optional) Boolean indicating if assignment is frozen for the calling user.
155
+ // NOTE: This field will only be present if the AssignmentFreezer plugin is
156
+ // available for your account.
157
+ "frozen": false,
158
+ // (Optional) Array of frozen attributes for the assignment. Only account
159
+ // administrators currently have permission to change an attribute in this list.
160
+ // Will be empty if no attributes are frozen for this assignment. Possible frozen
161
+ // attributes are: title, description, lock_at, points_possible, grading_type,
162
+ // submission_types, assignment_group_id, allowed_extensions, group_category_id,
163
+ // notify_of_update, peer_reviews NOTE: This field will only be present if the
164
+ // AssignmentFreezer plugin is available for your account.
165
+ "frozen_attributes": ["title"],
166
+ // (Optional) If 'submission' is included in the 'include' parameter, includes a
167
+ // Submission object that represents the current user's (user who is requesting
168
+ // information from the api) current submission for the assignment. See the
169
+ // Submissions API for an example response. If the user does not have a submission,
170
+ // this key will be absent.
171
+ "submission": null,
172
+ // (Optional) If true, the rubric is directly tied to grading the assignment.
173
+ // Otherwise, it is only advisory. Included if there is an associated rubric.
174
+ "use_rubric_for_grading": true,
175
+ // (Optional) An object describing the basic attributes of the rubric, including
176
+ // the point total. Included if there is an associated rubric.
177
+ "rubric_settings": {"points_possible":12},
178
+ // (Optional) A list of scoring criteria and ratings for each rubric criterion.
179
+ // Included if there is an associated rubric.
180
+ "rubric": null,
181
+ // (Optional) If 'assignment_visibility' is included in the 'include' parameter,
182
+ // includes an array of student IDs who can see this assignment.
183
+ "assignment_visibility": [137, 381, 572],
184
+ // (Optional) If 'overrides' is included in the 'include' parameter, includes an
185
+ // array of assignment override objects.
186
+ "overrides": null,
187
+ // (Optional) If true, the assignment will be omitted from the student's final
188
+ // grade
189
+ "omit_from_final_grade": true
190
+ }
191
+ ]
@@ -0,0 +1 @@
1
+ while(1);{"errors":[{"message":"The specified resource does not exist."}],"error_report_id":7039743803}
@@ -0,0 +1,28 @@
1
+ [
2
+ {
3
+ "size": 4,
4
+ "content-type": "text/plain",
5
+ "url": "http://www.canvas.instructure.com/files/569/download?download_frd=1&verifier=c6HdZmxOZa0Fiin2cbvZeI8I5ry7yqD7RChQzb6P",
6
+ "id": 569,
7
+ "display_name": "file.txt",
8
+ "created_at": "2012-07-06T14:58:50Z",
9
+ "updated_at": "2012-07-06T14:58:50Z",
10
+ "unlock_at": null,
11
+ "modified_at": "2012-07-06T14:58:50Z",
12
+ "locked": false,
13
+ "hidden": false,
14
+ "lock_at": null,
15
+ "locked_for_user": false,
16
+ "lock_info": null,
17
+ "lock_explanation": "This assignment is locked until September 1 at 12:00am",
18
+ "hidden_for_user": false,
19
+ "thumbnail_url": null,
20
+ // simplified content-type mapping
21
+ "mime_class": null,
22
+ // identifier for file in third-party transcoding service
23
+ "media_entry_id": null,
24
+ // optional: url to the document preview. This url is specific to the user
25
+ // making the api call. Only included in submission endpoints.
26
+ "preview_url": null
27
+ }
28
+ ]
@@ -0,0 +1,68 @@
1
+ [
2
+ {
3
+ "context_type": "Course",
4
+ "context_id": 1401,
5
+ "files_count": 1,
6
+ "position": 3,
7
+ "updated_at": "2012-07-06T14:58:50Z",
8
+ "folders_url": "https://www.canvas.instructure.com/api/v1/folders/2937/folders",
9
+ "files_url": "https://www.canvas.instructure.com/api/v1/folders/2937/files",
10
+ "full_name": "course files",
11
+ "lock_at": "2012-07-06T14:58:50Z",
12
+ "id": 2937,
13
+ "folders_count": 1,
14
+ "name": "course files",
15
+ "parent_folder_id": null,
16
+ "created_at": "2012-07-06T14:58:50Z",
17
+ "unlock_at": null,
18
+ "hidden": false,
19
+ "hidden_for_user": false,
20
+ "locked": true,
21
+ "locked_for_user": false,
22
+ "for_submissions": false
23
+ },
24
+ {
25
+ "context_type": "Course",
26
+ "context_id": 1401,
27
+ "files_count": 0,
28
+ "position": 3,
29
+ "updated_at": "2012-07-06T14:58:50Z",
30
+ "folders_url": "https://www.canvas.instructure.com/api/v1/folders/2938/folders",
31
+ "files_url": "https://www.canvas.instructure.com/api/v1/folders/2938/files",
32
+ "full_name": "course files/nested",
33
+ "lock_at": "2012-07-06T14:58:50Z",
34
+ "id": 2938,
35
+ "folders_count": 1,
36
+ "name": "nested",
37
+ "parent_folder_id": 2937,
38
+ "created_at": "2012-07-06T14:58:50Z",
39
+ "unlock_at": null,
40
+ "hidden": false,
41
+ "hidden_for_user": false,
42
+ "locked": true,
43
+ "locked_for_user": false,
44
+ "for_submissions": false
45
+ },
46
+ {
47
+ "context_type": "Course",
48
+ "context_id": 1401,
49
+ "files_count": 1,
50
+ "position": 3,
51
+ "updated_at": "2012-07-06T14:58:50Z",
52
+ "folders_url": "https://www.canvas.instructure.com/api/v1/folders/2939/folders",
53
+ "files_url": "https://www.canvas.instructure.com/api/v1/folders/2939/files",
54
+ "full_name": "course files/nested/examples",
55
+ "lock_at": "2012-07-06T14:58:50Z",
56
+ "id": 2939,
57
+ "folders_count": 0,
58
+ "name": "examples",
59
+ "parent_folder_id": 2938,
60
+ "created_at": "2012-07-06T14:58:50Z",
61
+ "unlock_at": null,
62
+ "hidden": false,
63
+ "hidden_for_user": false,
64
+ "locked": true,
65
+ "locked_for_user": false,
66
+ "for_submissions": false
67
+ }
68
+ ]
@@ -0,0 +1,24 @@
1
+ [
2
+ {
3
+ "context_type": "Course",
4
+ "context_id": 1401,
5
+ "files_count": 1,
6
+ "position": 3,
7
+ "updated_at": "2012-07-06T14:58:50Z",
8
+ "folders_url": "https://www.canvas.instructure.com/api/v1/folders/2937/folders",
9
+ "files_url": "https://www.canvas.instructure.com/api/v1/folders/2937/files",
10
+ "full_name": "course files",
11
+ "lock_at": "2012-07-06T14:58:50Z",
12
+ "id": 2937,
13
+ "folders_count": 1,
14
+ "name": "course files",
15
+ "parent_folder_id": null,
16
+ "created_at": "2012-07-06T14:58:50Z",
17
+ "unlock_at": null,
18
+ "hidden": false,
19
+ "hidden_for_user": false,
20
+ "locked": true,
21
+ "locked_for_user": false,
22
+ "for_submissions": false
23
+ }
24
+ ]
data/spec/gist_spec.rb ADDED
@@ -0,0 +1,29 @@
1
+ require "spec_helper"
2
+
3
+ describe Canvas::Workflow::Tags::GistTag do
4
+ let(:doc) { doc_with_content(content) }
5
+ let(:content) { "{% gist #{gist} %}" }
6
+ let(:output) do
7
+ doc.content = content
8
+ doc.output = Jekyll::Renderer.new(doc.site, doc).run
9
+ end
10
+ let(:html) { "<p><iframe style=\"width: 100%; height: 400px;\" title=\"GitHub gist\" src=\"https://www.edu-apps.org/tools/github/github_summary_gist.html\##{gist}\" width=\"100%\" height=\"400\" allowfullscreen=\"allowfullscreen\" webkitallowfullscreen=\"webkitallowfullscreen\" mozallowfullscreen=\"mozallowfullscreen\"></iframe></p>\n" }
11
+
12
+ context "valid gist" do
13
+ let(:gist) { "jiverson002/a409d902fcea90800c9ea6c02c71d97d" }
14
+
15
+ it "produces the correct html" do
16
+ expect(output).to eq(html)
17
+ end
18
+ end
19
+
20
+ context "invalid gist" do
21
+ context "no gist present" do
22
+ let(:gist) { "" }
23
+
24
+ it "raises an error" do
25
+ expect(-> { output }).to raise_error(ArgumentError, "Cannot have empty gist")
26
+ end
27
+ end
28
+ end
29
+ end