canvas-workflow 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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