mitchellh-rubyuw 0.5.0 → 0.6.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/VERSION +1 -1
- data/lib/myuw/registration.rb +98 -0
- data/lib/myuw/schedule.rb +3 -0
- data/lib/myuw.rb +3 -0
- data/rubyuw.gemspec +14 -3
- data/test/live/registration_test.rb +46 -0
- data/test/mocked/fixture_pages/registration.html +699 -0
- data/test/mocked/fixture_pages/registration_error.html +699 -0
- data/test/mocked/fixture_pages/registration_error_no_rows.html +627 -0
- data/test/mocked/fixture_pages/registration_no_form.html +700 -0
- data/test/mocked/fixture_pages/registration_success.html +718 -0
- data/test/mocked/fixture_pages/registration_unknown.html +721 -0
- data/test/mocked/myuw_test.rb +5 -0
- data/test/mocked/registration_test.rb +105 -0
- metadata +13 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.6.0
|
@@ -0,0 +1,98 @@
|
|
1
|
+
class MyUW
|
2
|
+
# = Synopsis
|
3
|
+
# The Registration class can automate the registration
|
4
|
+
# process for a user. It does NOT support initial
|
5
|
+
# setup of the registration process such as verifying
|
6
|
+
# addresses and such (and doesnt plan to, that is
|
7
|
+
# an important step that should be done manually)
|
8
|
+
class Registration
|
9
|
+
attr_accessor :myuw
|
10
|
+
attr_reader :errors
|
11
|
+
|
12
|
+
def initialize(myuw=nil)
|
13
|
+
@myuw ||= myuw
|
14
|
+
@errors = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
# Registers for one or more courses. The courses
|
18
|
+
# parameter should be an Array of strings (the
|
19
|
+
# SLNs)
|
20
|
+
def register(courses)
|
21
|
+
raise NotLoggedInError.new("User must be logged in to register for classes.") unless @myuw.logged_in?
|
22
|
+
|
23
|
+
# Get registration page
|
24
|
+
register_page = @myuw.browser.get("https://sdb.admin.washington.edu/students/uwnetid/register.asp")
|
25
|
+
register_form = register_page.form_with(:name => 'regform')
|
26
|
+
raise InvalidPageError.new(register_page, "Could not verify registration page") if register_form.nil?
|
27
|
+
|
28
|
+
# Fill in the form
|
29
|
+
fill_registration_form(register_form, courses)
|
30
|
+
|
31
|
+
# Submit it and analyze result
|
32
|
+
get_registration_result(register_form.submit())
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_registration_result(result_page)
|
36
|
+
return true if result_page.body =~ /ALT="OK">Schedule updated\./i
|
37
|
+
raise InvalidPageError.new(result_page, "Unknown registration result.") unless result_page.body =~ /ALT="ERROR">Schedule not updated\./i
|
38
|
+
|
39
|
+
# Otherwise, get the errors out of the result page
|
40
|
+
extract_registration_errors(result_page)
|
41
|
+
false
|
42
|
+
end
|
43
|
+
|
44
|
+
def extract_registration_errors(result_page)
|
45
|
+
# //input[@type='hidden' and @name='action4']/following-sibling::input[@type='hidden']/following-sibling::td
|
46
|
+
registration_form = result_page.form_with(:name => 'regform')
|
47
|
+
start_index = get_add_section_index(registration_form)
|
48
|
+
current_index = start_index.to_i
|
49
|
+
|
50
|
+
@errors = {}
|
51
|
+
|
52
|
+
loop do
|
53
|
+
# Get current SLN, and if its empty, then return out
|
54
|
+
current_sln = registration_form["sln#{current_index}"]
|
55
|
+
return if current_sln.nil? || current_sln.empty?
|
56
|
+
|
57
|
+
error_cell = result_page.search("//input[@name='action#{current_index}']/parent::tr//td[5]")
|
58
|
+
raise InvalidPageError.new(result_page, "Couldn't extract errors (couldn't get data cells)") if error_cell.empty?
|
59
|
+
|
60
|
+
error_text = error_cell[0].inner_text.strip.gsub("\302\240", '')
|
61
|
+
@errors[current_sln] = error_text
|
62
|
+
|
63
|
+
current_index += 1
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def fill_registration_form(register_form, courses)
|
68
|
+
# Determine where to begin adding SLNs (what fields)
|
69
|
+
start_index = get_add_section_index(register_form)
|
70
|
+
|
71
|
+
current_index = start_index.to_i
|
72
|
+
courses.each do |course|
|
73
|
+
register_form["sln#{current_index}"] = course.to_s
|
74
|
+
current_index += 1
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# The registration page is one giant form.
|
79
|
+
# We need to figure out which index fields
|
80
|
+
# to begin filling in with SLN data. This
|
81
|
+
# method returns the index.
|
82
|
+
def get_add_section_index(register_form)
|
83
|
+
# First way is to add maxadds and maxdrops and
|
84
|
+
# determine the offset.
|
85
|
+
maxdrops = register_form["maxdrops"].to_i
|
86
|
+
index_by_hiddens = maxdrops + 1
|
87
|
+
|
88
|
+
# Verify by inspecting actions
|
89
|
+
1.upto(11) do |i|
|
90
|
+
# Find the version action with an "A" (meaning add)
|
91
|
+
if register_form["action#{i}"].to_s == "A"
|
92
|
+
raise InvalidPageError.new(nil, "Couldn't determine add offset.") unless i == index_by_hiddens
|
93
|
+
return i.to_s
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/lib/myuw/schedule.rb
CHANGED
data/lib/myuw.rb
CHANGED
@@ -7,6 +7,7 @@ require 'myuw/errors'
|
|
7
7
|
require 'myuw/session'
|
8
8
|
require 'myuw/sln'
|
9
9
|
require 'myuw/schedule'
|
10
|
+
require 'myuw/registration'
|
10
11
|
|
11
12
|
class MyUW
|
12
13
|
extend Forwardable
|
@@ -14,6 +15,7 @@ class MyUW
|
|
14
15
|
attr_accessor :browser
|
15
16
|
attr_accessor :session
|
16
17
|
attr_accessor :schedule
|
18
|
+
attr_accessor :registration
|
17
19
|
|
18
20
|
def initialize
|
19
21
|
# Initialize the browser instance and mascarade
|
@@ -32,6 +34,7 @@ class MyUW
|
|
32
34
|
# Initialize other members
|
33
35
|
@session = Session.new(self)
|
34
36
|
@schedule = Schedule.new(self)
|
37
|
+
@registration = Registration.new(self)
|
35
38
|
end
|
36
39
|
|
37
40
|
# Forward the session methods
|
data/rubyuw.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{rubyuw}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.6.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Mitchell Hashimoto"]
|
9
|
-
s.date = %q{2009-06-
|
9
|
+
s.date = %q{2009-06-28}
|
10
10
|
s.description = %q{TODO}
|
11
11
|
s.email = %q{mitchell.hashimoto@gmail.com}
|
12
12
|
s.extra_rdoc_files = [
|
@@ -19,10 +19,12 @@ Gem::Specification.new do |s|
|
|
19
19
|
"VERSION",
|
20
20
|
"lib/myuw.rb",
|
21
21
|
"lib/myuw/errors.rb",
|
22
|
+
"lib/myuw/registration.rb",
|
22
23
|
"lib/myuw/schedule.rb",
|
23
24
|
"lib/myuw/session.rb",
|
24
25
|
"lib/myuw/sln.rb",
|
25
26
|
"rubyuw.gemspec",
|
27
|
+
"test/live/registration_test.rb",
|
26
28
|
"test/live/schedule_test.rb",
|
27
29
|
"test/live/session_test.rb",
|
28
30
|
"test/live/sln_test.rb",
|
@@ -33,6 +35,12 @@ Gem::Specification.new do |s|
|
|
33
35
|
"test/mocked/fixture_pages/no_form_login.html",
|
34
36
|
"test/mocked/fixture_pages/no_login_button.html",
|
35
37
|
"test/mocked/fixture_pages/not_logged_in_relay.html",
|
38
|
+
"test/mocked/fixture_pages/registration.html",
|
39
|
+
"test/mocked/fixture_pages/registration_error.html",
|
40
|
+
"test/mocked/fixture_pages/registration_error_no_rows.html",
|
41
|
+
"test/mocked/fixture_pages/registration_no_form.html",
|
42
|
+
"test/mocked/fixture_pages/registration_success.html",
|
43
|
+
"test/mocked/fixture_pages/registration_unknown.html",
|
36
44
|
"test/mocked/fixture_pages/schedule.html",
|
37
45
|
"test/mocked/fixture_pages/schedule_diff_credit_row.html",
|
38
46
|
"test/mocked/fixture_pages/schedule_empty.html",
|
@@ -41,6 +49,7 @@ Gem::Specification.new do |s|
|
|
41
49
|
"test/mocked/fixture_pages/sln_status.html",
|
42
50
|
"test/mocked/fixture_pages/welcome.html",
|
43
51
|
"test/mocked/myuw_test.rb",
|
52
|
+
"test/mocked/registration_test.rb",
|
44
53
|
"test/mocked/schedule_test.rb",
|
45
54
|
"test/mocked/session_test.rb",
|
46
55
|
"test/mocked/sln_test.rb",
|
@@ -54,11 +63,13 @@ Gem::Specification.new do |s|
|
|
54
63
|
s.rubygems_version = %q{1.3.1}
|
55
64
|
s.summary = %q{Library which provides a ruby interface to the University of Washington student portal.}
|
56
65
|
s.test_files = [
|
57
|
-
"test/live/
|
66
|
+
"test/live/registration_test.rb",
|
67
|
+
"test/live/schedule_test.rb",
|
58
68
|
"test/live/session_test.rb",
|
59
69
|
"test/live/sln_test.rb",
|
60
70
|
"test/live/test_helper.rb",
|
61
71
|
"test/mocked/myuw_test.rb",
|
72
|
+
"test/mocked/registration_test.rb",
|
62
73
|
"test/mocked/schedule_test.rb",
|
63
74
|
"test/mocked/session_test.rb",
|
64
75
|
"test/mocked/sln_test.rb",
|
@@ -0,0 +1,46 @@
|
|
1
|
+
if $0 != __FILE__
|
2
|
+
puts <<-WORDS
|
3
|
+
Note: Registration tests can only be run by directly
|
4
|
+
invoking the registration_test.rb file in the
|
5
|
+
test/live directory.
|
6
|
+
WORDS
|
7
|
+
end
|
8
|
+
|
9
|
+
if $0 == __FILE__
|
10
|
+
# Only run tests in this file if we're executing it
|
11
|
+
# on its own
|
12
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
13
|
+
|
14
|
+
class LiveRegistrationTest < Test::Unit::TestCase
|
15
|
+
context "registering for a course" do
|
16
|
+
setup do
|
17
|
+
@myuw = MyUW.new
|
18
|
+
@session = @myuw.session
|
19
|
+
@session.email = MYUW_ID
|
20
|
+
@session.password = MYUW_PASSWORD
|
21
|
+
assert @session.login
|
22
|
+
|
23
|
+
@schedule = @myuw.schedule
|
24
|
+
@registration = @myuw.registration
|
25
|
+
|
26
|
+
@good_course = "17697"
|
27
|
+
@bad_courses = ["17778", "17779"]
|
28
|
+
end
|
29
|
+
|
30
|
+
should "successfully register for a course" do
|
31
|
+
assert !@schedule.schedule.empty?
|
32
|
+
@schedule.schedule.each { |course| assert_not_equal @good_course, course[:sln] }
|
33
|
+
|
34
|
+
assert @registration.register([@good_course])
|
35
|
+
|
36
|
+
@schedule.schedule(true)
|
37
|
+
assert !@schedule.schedule.select { |course| course[:sln].to_i == @good_course.to_i }.empty?
|
38
|
+
end
|
39
|
+
|
40
|
+
should "successfully read erroneous registration for multiple courses" do
|
41
|
+
assert !@registration.register(@bad_courses)
|
42
|
+
assert !@registration.errors["17779"].empty?
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|