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 CHANGED
@@ -1 +1 @@
1
- 0.5.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
@@ -32,6 +32,9 @@ class MyUW
32
32
 
33
33
  # Grab the credits
34
34
  get_credits schedule_page
35
+
36
+ # Return the courses
37
+ @courses
35
38
  end
36
39
 
37
40
  def get_courses(schedule)
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.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-27}
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/schedule_test.rb",
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