powerapi 1.0.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.
@@ -0,0 +1,464 @@
1
+ {
2
+ "return": {
3
+ "@type": "ax290:ResultsVO",
4
+ "courseRequestRulesVO": {
5
+ "@nil": "true"
6
+ },
7
+ "studentDataVOs": {
8
+ "@type": "ax290:StudentDataVO",
9
+ "assignmentCategories": [
10
+ {
11
+ "@type": "ax290:AsmtCatVO",
12
+ "abbreviation": "S",
13
+ "description": "Testing assignments",
14
+ "id": 1,
15
+ "name": "Sample"
16
+ }
17
+ ],
18
+ "assignmentScores": [
19
+ {
20
+ "@type": "ax290:AssignmentScoreVO",
21
+ "assignmentId": 1,
22
+ "collected": false,
23
+ "comment": {
24
+ "@nil": "true"
25
+ },
26
+ "exempt": false,
27
+ "id": 1,
28
+ "late": false,
29
+ "letterGrade": 100,
30
+ "missing": false,
31
+ "percent": 100,
32
+ "score": 100,
33
+ "scoretype": 0
34
+ }
35
+ ],
36
+ "assignments": [
37
+ {
38
+ "@type": "ax290:AssignmentVO",
39
+ "abbreviation": "Assignment",
40
+ "assignmentid": 1,
41
+ "categoryId": 1,
42
+ "description": "Sample Description",
43
+ "dueDate": "2014-08-20T04:00:00.000Z",
44
+ "id": 1,
45
+ "includeinfinalgrades": 1,
46
+ "name": "Sample Assignment",
47
+ "pointspossible": 5,
48
+ "publishDaysBeforeDue": 0,
49
+ "publishState": 0,
50
+ "publishonspecificdate": {
51
+ "@nil": "true"
52
+ },
53
+ "publishscores": 1,
54
+ "sectionid": 1,
55
+ "type": 0,
56
+ "weight": 1
57
+ }
58
+ ],
59
+ "attendance": [
60
+ {
61
+ "@type": "ax290:AttendanceVO",
62
+ "adaValueCode": 0,
63
+ "adaValueTime": 0,
64
+ "admValue": 0,
65
+ "attCodeid": 504,
66
+ "attComment": {
67
+ "@nil": "true"
68
+ },
69
+ "attDate": "2014-08-19T04:00:00.000Z",
70
+ "attFlags": 0,
71
+ "attInterval": 0,
72
+ "attModeCode": "ATT_ModeMeeting",
73
+ "ccid": 1,
74
+ "id": 1,
75
+ "periodid": 1,
76
+ "schoolid": 1,
77
+ "studentid": 1,
78
+ "totalMinutes": 0,
79
+ "transactionType": {
80
+ "@nil": "true"
81
+ },
82
+ "yearid": 2015
83
+ }
84
+ ],
85
+ "attendanceCodes": [
86
+ {
87
+ "@type": "ax290:AttendanceCodeVO",
88
+ "attCode": {
89
+ "@nil": "true"
90
+ },
91
+ "codeType": 1,
92
+ "description": "Present",
93
+ "id": 509,
94
+ "schoolid": 1,
95
+ "sortorder": 1,
96
+ "yearid": 2015
97
+ },
98
+ {
99
+ "@type": "ax290:AttendanceCodeVO",
100
+ "attCode": "T",
101
+ "codeType": 1,
102
+ "description": "Tardy Unexcused",
103
+ "id": 508,
104
+ "schoolid": 1,
105
+ "sortorder": 2,
106
+ "yearid": 2015
107
+ },
108
+ {
109
+ "@type": "ax290:AttendanceCodeVO",
110
+ "attCode": "ET",
111
+ "codeType": 1,
112
+ "description": "Tardy Excused",
113
+ "id": 501,
114
+ "schoolid": 1,
115
+ "sortorder": 3,
116
+ "yearid": 2015
117
+ },
118
+ {
119
+ "@type": "ax290:AttendanceCodeVO",
120
+ "attCode": "UA",
121
+ "codeType": 2,
122
+ "description": "Absence Unexcused",
123
+ "id": 504,
124
+ "schoolid": 1,
125
+ "sortorder": 3,
126
+ "yearid": 2015
127
+ },
128
+ {
129
+ "@type": "ax290:AttendanceCodeVO",
130
+ "attCode": "EA",
131
+ "codeType": 2,
132
+ "description": "Absence Excused",
133
+ "id": 505,
134
+ "schoolid": 1,
135
+ "sortorder": 4,
136
+ "yearid": 2015
137
+ },
138
+ {
139
+ "@type": "ax290:AttendanceCodeVO",
140
+ "attCode": "SI",
141
+ "codeType": 2,
142
+ "description": "Sick",
143
+ "id": 503,
144
+ "schoolid": 1,
145
+ "sortorder": 5,
146
+ "yearid": 2015
147
+ },
148
+ {
149
+ "@type": "ax290:AttendanceCodeVO",
150
+ "attCode": "OSS",
151
+ "codeType": 2,
152
+ "description": "Out-of-School Suspension",
153
+ "id": 502,
154
+ "schoolid": 1,
155
+ "sortorder": 6,
156
+ "yearid": 2015
157
+ },
158
+ {
159
+ "@type": "ax290:AttendanceCodeVO",
160
+ "attCode": "ISS",
161
+ "codeType": 2,
162
+ "description": "In-School Suspension",
163
+ "id": 506,
164
+ "schoolid": 1,
165
+ "sortorder": 7,
166
+ "yearid": 2015
167
+ },
168
+ {
169
+ "@type": "ax290:AttendanceCodeVO",
170
+ "attCode": "SA",
171
+ "codeType": 1,
172
+ "description": "School-Related Absence",
173
+ "id": 507,
174
+ "schoolid": 1,
175
+ "sortorder": 8,
176
+ "yearid": 2015
177
+ }
178
+ ],
179
+ "citizenCodes": [
180
+ {
181
+ "@type": "ax290:CitizenCodeVO",
182
+ "codeName": "H",
183
+ "description": "Honorable",
184
+ "id": 29,
185
+ "sortOrder": 4
186
+ },
187
+ {
188
+ "@type": "ax290:CitizenCodeVO",
189
+ "codeName": "S",
190
+ "description": "Satisfactory",
191
+ "id": 30,
192
+ "sortOrder": 5
193
+ },
194
+ {
195
+ "@type": "ax290:CitizenCodeVO",
196
+ "codeName": "N",
197
+ "description": "Needs to improve",
198
+ "id": 31,
199
+ "sortOrder": 6
200
+ },
201
+ {
202
+ "@type": "ax290:CitizenCodeVO",
203
+ "codeName": "U",
204
+ "description": "Unsatisfactory",
205
+ "id": 32,
206
+ "sortOrder": 7
207
+ },
208
+ {
209
+ "@type": "ax290:CitizenCodeVO",
210
+ "codeName": "E",
211
+ "description": "Excellent",
212
+ "id": 301,
213
+ "sortOrder": 2
214
+ },
215
+ {
216
+ "@type": "ax290:CitizenCodeVO",
217
+ "codeName": "G",
218
+ "description": "Good",
219
+ "id": 302,
220
+ "sortOrder": 3
221
+ },
222
+ {
223
+ "@type": "ax290:CitizenCodeVO",
224
+ "codeName": "C",
225
+ "description": "Parental Conference Requested",
226
+ "id": 303,
227
+ "sortOrder": 1
228
+ }
229
+ ],
230
+ "feeBalance": {
231
+ "@nil": "true"
232
+ },
233
+ "finalGrades": [
234
+ {
235
+ "@type": "ax290:FinalGradeVO",
236
+ "commentValue": {
237
+ "@nil": "true"
238
+ },
239
+ "dateStored": {
240
+ "@nil": "true"
241
+ },
242
+ "grade": 100,
243
+ "id": 1,
244
+ "percent": 100,
245
+ "reportingTermId": 1,
246
+ "sectionid": 1,
247
+ "storeType": 2
248
+ }
249
+ ],
250
+ "notificationSettingsVO": {
251
+ "@nil": "true"
252
+ },
253
+ "periods": [
254
+ {
255
+ "@type": "ax290:PeriodVO",
256
+ "abbreviation": 1,
257
+ "id": 1,
258
+ "name": 1,
259
+ "periodNumber": 1,
260
+ "schoolid": 1,
261
+ "sortOrder": 1,
262
+ "yearid": 2015
263
+ }
264
+ ],
265
+ "reportingTerms": [
266
+ {
267
+ "@type": "ax290:ReportingTermVO",
268
+ "abbreviation": "Q1",
269
+ "endDate": "2014-10-17T04:00:00.000Z",
270
+ "id": 1,
271
+ "schoolid": 1,
272
+ "sendingGrades": true,
273
+ "startDate": "2014-08-18T04:00:00.000Z",
274
+ "suppressGrades": false,
275
+ "suppressPercents": false,
276
+ "termid": 2401,
277
+ "title": "Q1",
278
+ "yearid": 2015
279
+ }
280
+ ],
281
+ "schools": {
282
+ "@type": "ax290:SchoolVO",
283
+ "abbreviation": "SCS",
284
+ "address": "Sample High School\r\n123 Apple Seed Road,\r\nSample, SA 00000",
285
+ "disabledFeatures": {
286
+ "@type": "ax290:DisabledFeaturesVO",
287
+ "activities": true,
288
+ "assignments": false,
289
+ "attendance": false,
290
+ "citizenship": false,
291
+ "currentGpa": false,
292
+ "emailalerts": false,
293
+ "fees": false,
294
+ "finalGrades": false,
295
+ "meals": false,
296
+ "standards": false
297
+ },
298
+ "highGrade": 12,
299
+ "lowGrade": -3,
300
+ "mapMimeType": {
301
+ "@nil": "true"
302
+ },
303
+ "name": "Sample High School",
304
+ "schoolId": 1,
305
+ "schoolMapModifiedDate": {
306
+ "@nil": "true"
307
+ },
308
+ "schoolNumber": 1,
309
+ "schooladdress": "123 Apple Seed Road",
310
+ "schoolcity": "Sample",
311
+ "schoolcountry": {
312
+ "@nil": "true"
313
+ },
314
+ "schoolfax": "+00000000000",
315
+ "schoolphone": "+00000000000",
316
+ "schoolstate": {
317
+ "@nil": "true"
318
+ },
319
+ "schoolzip": 12345
320
+ },
321
+ "sections": [
322
+ {
323
+ "@type": "ax290:SectionVO",
324
+ "courseCode": 101,
325
+ "description": {
326
+ "@nil": "true"
327
+ },
328
+ "enrollments": {
329
+ "@type": "ax290:SectionEnrollmentVO",
330
+ "endDate": "2014-12-20T04:00:00.000Z",
331
+ "enrollStatus": 0,
332
+ "id": 1,
333
+ "startDate": "2014-08-18T04:00:00.000Z"
334
+ },
335
+ "expression": "1 (M-F)",
336
+ "id": 1,
337
+ "roomName": "HS101",
338
+ "schoolCourseTitle": "Sample Section",
339
+ "schoolNumber": 1,
340
+ "sectionNum": 1,
341
+ "startStopDates": [
342
+ {
343
+ "@type": "ax290:StartStopDateVO",
344
+ "sectionEnrollmentId": 1,
345
+ "start": "2014-08-21T12:47:00.000Z",
346
+ "stop": "2014-08-21T13:30:00.000Z"
347
+ }
348
+ ],
349
+ "teacherID": 1,
350
+ "termID": 2401
351
+ },
352
+ {
353
+ "@type": "ax290:SectionVO",
354
+ "courseCode": 102,
355
+ "description": {
356
+ "@nil": "true"
357
+ },
358
+ "enrollments": {
359
+ "@type": "ax290:SectionEnrollmentVO",
360
+ "endDate": "3000-12-20T04:00:00.000Z",
361
+ "enrollStatus": 0,
362
+ "id": 2,
363
+ "startDate": "3000-08-18T04:00:00.000Z"
364
+ },
365
+ "expression": "2 (M-F)",
366
+ "id": 2,
367
+ "roomName": "HS101",
368
+ "schoolCourseTitle": "Sample Future Section",
369
+ "schoolNumber": 1,
370
+ "sectionNum": 2,
371
+ "startStopDates": [
372
+ {
373
+ "@type": "ax290:StartStopDateVO",
374
+ "sectionEnrollmentId": 1,
375
+ "start": "3000-08-21T12:47:00.000Z",
376
+ "stop": "3000-08-21T13:30:00.000Z"
377
+ }
378
+ ],
379
+ "teacherID": 1,
380
+ "termID": 3000
381
+ },
382
+ {
383
+ "@type": "ax290:SectionVO",
384
+ "courseCode": 103,
385
+ "description": {
386
+ "@nil": "true"
387
+ },
388
+ "enrollments": {
389
+ "@type": "ax290:SectionEnrollmentVO",
390
+ "endDate": "2014-12-20T04:00:00.000Z",
391
+ "enrollStatus": 0,
392
+ "id": 3,
393
+ "startDate": "2014-08-18T04:00:00.000Z"
394
+ },
395
+ "expression": "3 (M-F)",
396
+ "id": 3,
397
+ "roomName": "HS101",
398
+ "schoolCourseTitle": "Sample Empty Section",
399
+ "schoolNumber": 1,
400
+ "sectionNum": 3,
401
+ "startStopDates": [
402
+ {
403
+ "@type": "ax290:StartStopDateVO",
404
+ "sectionEnrollmentId": 1,
405
+ "start": "2014-08-21T12:47:00.000Z",
406
+ "stop": "2014-08-21T13:30:00.000Z"
407
+ }
408
+ ],
409
+ "teacherID": 1,
410
+ "termID": 2401
411
+ }
412
+ ],
413
+ "student": {
414
+ "@type": "ax290:StudentVO",
415
+ "currentGPA": "4.0",
416
+ "currentMealBalance": 0,
417
+ "currentTerm": "S1",
418
+ "dcid": 1,
419
+ "dob": "1970-01-01T00:00:00.000Z",
420
+ "ethnicity": "US",
421
+ "firstName": "John",
422
+ "gender": "M",
423
+ "gradeLevel": 12,
424
+ "id": 1,
425
+ "lastName": "Doe",
426
+ "middleName": {
427
+ "@nil": "true"
428
+ },
429
+ "photoDate": {
430
+ "@nil": "true"
431
+ },
432
+ "startingMealBalance": 0
433
+ },
434
+ "studentDcid": 1,
435
+ "studentId": 1,
436
+ "teachers": [
437
+ {
438
+ "@type": "ax290:TeacherVO",
439
+ "email": "msue@example.edu",
440
+ "firstName": "Mary",
441
+ "id": 1,
442
+ "lastName": "Sue",
443
+ "schoolPhone": "+00000000000"
444
+ }
445
+ ],
446
+ "terms": [
447
+ {
448
+ "@type": "ax290:TermVO",
449
+ "abbrev": "S1",
450
+ "endDate": "2014-12-20T04:00:00.000Z",
451
+ "id": 2401,
452
+ "parentTermId": 0,
453
+ "schoolNumber": 1,
454
+ "startDate": "2014-08-18T04:00:00.000Z",
455
+ "title": "Semester 1"
456
+ }
457
+ ],
458
+ "yearId": 2015
459
+ },
460
+ "userSessionVO": {
461
+ "@nil": "true"
462
+ }
463
+ }
464
+ }
@@ -0,0 +1,150 @@
1
+ require "spec_helper"
2
+
3
+ describe PowerAPI::Parser do
4
+ before(:all) {
5
+ fixture = JSON.parse(File.read("spec/fixtures/transcript.json"))
6
+
7
+ @student_data = fixture["return"]["studentDataVOs"]
8
+
9
+ @assignment_categories = {
10
+ 1=>{
11
+ "@type"=>"ax290:AsmtCatVO",
12
+ "abbreviation"=>"S",
13
+ "description"=>"Testing assignments",
14
+ "id"=>1,
15
+ "name"=>"Sample"
16
+ }
17
+ }
18
+
19
+ @assignment_scores = {
20
+ 1=>{
21
+ "@type"=>"ax290:AssignmentScoreVO",
22
+ "assignmentId"=>1,
23
+ "collected"=>false,
24
+ "comment"=>{"@nil"=>"true"},
25
+ "exempt"=>false,
26
+ "id"=>1,
27
+ "late"=>false,
28
+ "letterGrade"=>100,
29
+ "missing"=>false,
30
+ "percent"=>100,
31
+ "score"=>100,
32
+ "scoretype"=>0
33
+ }
34
+ }
35
+
36
+ @final_grades = {1=>[{"@type"=>"ax290:FinalGradeVO", "commentValue"=>{"@nil"=>"true"}, "dateStored"=>{"@nil"=>"true"}, "grade"=>100, "id"=>1, "percent"=>100, "reportingTermId"=>1, "sectionid"=>1, "storeType"=>2}]}
37
+
38
+ @reporting_terms = {1=>"Q1"}
39
+
40
+ @teachers = {1=>{"@type"=>"ax290:TeacherVO", "email"=>"msue@example.edu", "firstName"=>"Mary", "id"=>1, "lastName"=>"Sue", "schoolPhone"=>"+00000000000"}}
41
+
42
+ }
43
+
44
+ describe "#assignments" do
45
+ before(:each) {
46
+ @assignments = PowerAPI::Parser.assignments(@student_data["assignments"], @assignment_categories, @assignment_scores)
47
+ }
48
+
49
+ it "has one assignment" do
50
+ expect(
51
+ @assignments.count
52
+ ).to be(1)
53
+ end
54
+
55
+ it "has Sample as the category at index 0" do
56
+ expect(
57
+ @assignments[1][0].category
58
+ ).to eq("Sample")
59
+ end
60
+
61
+ it "has Sample as the description at index 0" do
62
+ expect(
63
+ @assignments[1][0].description
64
+ ).to eq("Sample Description")
65
+ end
66
+
67
+ it "has Sample as the name at index 0" do
68
+ expect(
69
+ @assignments[1][0].name
70
+ ).to eq("Sample Assignment")
71
+ end
72
+
73
+ it "has Sample as the percent at index 0" do
74
+ expect(
75
+ @assignments[1][0].percent
76
+ ).to eq(100)
77
+ end
78
+
79
+ it "has Sample as the score at index 0" do
80
+ expect(
81
+ @assignments[1][0].score
82
+ ).to eq(100)
83
+ end
84
+ end
85
+
86
+ describe "#assignment_categories" do
87
+ it "properly parses the assignment categories" do
88
+ expect(
89
+ PowerAPI::Parser.assignment_categories(@student_data["assignmentCategories"])
90
+ ).to eq(@assignment_categories)
91
+ end
92
+ end
93
+
94
+ describe "#assignment_scores" do
95
+ it "properly parses the assignment scores" do
96
+ expect(
97
+ PowerAPI::Parser.assignment_scores(@student_data["assignmentScores"])
98
+ ).to eq(@assignment_scores)
99
+ end
100
+ end
101
+
102
+ describe "#final_grades" do
103
+ it "properly parses the final grades" do
104
+ expect(
105
+ PowerAPI::Parser.final_grades(@student_data["finalGrades"])
106
+ ).to eq(@final_grades)
107
+ end
108
+ end
109
+
110
+ describe "#reporting_terms" do
111
+ it "properly parses the reporting terms" do
112
+ expect(
113
+ PowerAPI::Parser.reporting_terms(@student_data["reportingTerms"])
114
+ ).to eq(@reporting_terms)
115
+ end
116
+ end
117
+
118
+ describe "#sections" do
119
+ before(:each) {
120
+ assignments = PowerAPI::Parser.assignments(@student_data["assignments"], @assignment_categories, @assignment_scores)
121
+ @sections = PowerAPI::Parser.sections(@student_data["sections"], assignments, @final_grades, @reporting_terms, @teachers)
122
+ }
123
+
124
+ it "contains two items" do
125
+ expect(
126
+ @sections.length
127
+ ).to eq(2)
128
+ end
129
+
130
+ it "contains a section at index 0" do
131
+ expect(
132
+ @sections[0]
133
+ ).to be_a(PowerAPI::Section)
134
+ end
135
+
136
+ it "contains a section at index 1" do
137
+ expect(
138
+ @sections[0]
139
+ ).to be_a(PowerAPI::Section)
140
+ end
141
+ end
142
+
143
+ describe "#teachers" do
144
+ it "properly parses the teachers" do
145
+ expect(
146
+ PowerAPI::Parser.teachers(@student_data["teachers"])
147
+ ).to eq(@teachers)
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,37 @@
1
+ require "spec_helper"
2
+
3
+ describe PowerAPI do
4
+ include Savon::SpecHelper
5
+
6
+ before(:all) {
7
+ savon.mock!
8
+ }
9
+
10
+ after(:all) {
11
+ savon.unmock!
12
+ }
13
+
14
+ describe "#authenticate" do
15
+ it "throws an error due to invalid credentials" do
16
+ fixture = File.read("spec/fixtures/authentication/failure.xml")
17
+ message = { username: "fail", password: "fail", userType: 2}
18
+
19
+ savon.expects(:login).with(message: message).returns(fixture)
20
+
21
+ expect {
22
+ PowerAPI.authenticate("http://powerschool.example", "fail", "fail")
23
+ }.to raise_error(PowerAPI::Exception)
24
+ end
25
+
26
+ it "returns a student object due to valid credentials" do
27
+ fixture = File.read("spec/fixtures/authentication/success.xml")
28
+ message = { username: "student", password: "123456", userType: 2}
29
+
30
+ savon.expects(:login).with(message: message).returns(fixture)
31
+
32
+ expect(
33
+ PowerAPI.authenticate("http://powerschool.example", "student", "123456", false)
34
+ ).to be_an_instance_of(PowerAPI::Student)
35
+ end
36
+ end
37
+ end