steps.py 6.4 KB
Newer Older
1
from lettuce import world, step
2
from .factories import *
3 4 5
from lettuce.django import django_url
from django.contrib.auth.models import User
from student.models import CourseEnrollment
6
from urllib import quote_plus
7
from nose.tools import assert_equals
8 9 10 11
from bs4 import BeautifulSoup
import time
import re
import os.path
12 13 14 15

from logging import getLogger
logger = getLogger(__name__)

Calen Pennington committed
16

17 18 19 20
@step(u'I wait (?:for )?"(\d+)" seconds?$')
def wait(step, seconds):
    time.sleep(float(seconds))

Calen Pennington committed
21

22 23 24 25 26
@step('I reload the page$')
def reload_the_page(step):
    world.browser.reload()


27 28 29 30 31
@step('I (?:visit|access|open) the homepage$')
def i_visit_the_homepage(step):
    world.browser.visit(django_url('/'))
    assert world.browser.is_element_present_by_css('header.global', 10)

Calen Pennington committed
32

33 34 35 36 37
@step(u'I (?:visit|access|open) the dashboard$')
def i_visit_the_dashboard(step):
    world.browser.visit(django_url('/dashboard'))
    assert world.browser.is_element_present_by_css('section.container.dashboard', 5)

Calen Pennington committed
38

39 40 41 42 43
@step('I should be on the dashboard page$')
def i_should_be_on_the_dashboard(step):
    assert world.browser.is_element_present_by_css('section.container.dashboard', 5)
    assert world.browser.title == 'Dashboard'

Calen Pennington committed
44

45 46 47 48 49
@step(u'I (?:visit|access|open) the courses page$')
def i_am_on_the_courses_page(step):
    world.browser.visit(django_url('/courses'))
    assert world.browser.is_element_present_by_css('section.courses')

Calen Pennington committed
50

51 52 53 54 55
@step(u'I press the "([^"]*)" button$')
def and_i_press_the_button(step, value):
    button_css = 'input[value="%s"]' % value
    world.browser.find_by_css(button_css).first.click()

Calen Pennington committed
56

57 58 59 60
@step(u'I click the link with the text "([^"]*)"$')
def click_the_link_with_the_text_group1(step, linktext):
    world.browser.find_link_by_text(linktext).first.click()

Calen Pennington committed
61

62 63 64 65
@step('I should see that the path is "([^"]*)"$')
def i_should_see_that_the_path_is(step, path):
    assert world.browser.url == django_url(path)

Calen Pennington committed
66

67 68 69 70
@step(u'the page title should be "([^"]*)"$')
def the_page_title_should_be(step, title):
    assert_equals(world.browser.title, title)

Calen Pennington committed
71

72 73 74 75 76
@step(u'the page title should contain "([^"]*)"$')
def the_page_title_should_contain(step, title):
    assert(title in world.browser.title)


77 78 79
@step('I am a logged in user$')
def i_am_logged_in_user(step):
    create_user('robot')
Calen Pennington committed
80 81
    log_in('robot@edx.org', 'test')

82 83 84 85 86

@step('I am not logged in$')
def i_am_not_logged_in(step):
    world.browser.cookies.delete()

Calen Pennington committed
87

88 89
@step('I am staff for course "([^"]*)"$')
def i_am_staff_for_course_by_id(step, course_id):
90
    register_by_course_id(course_id, True)
91

Calen Pennington committed
92

93 94
@step('I log in$')
def i_log_in(step):
Calen Pennington committed
95 96
    log_in('robot@edx.org', 'test')

97 98 99 100 101 102

@step(u'I am an edX user$')
def i_am_an_edx_user(step):
    create_user('robot')

#### helper functions
Calen Pennington committed
103

Will Daly committed
104

105 106 107 108 109
@world.absorb
def scroll_to_bottom():
    # Maximize the browser
    world.browser.execute_script("window.scrollTo(0, screen.height);")

Calen Pennington committed
110

111
@world.absorb
112
def create_user(uname):
113 114 115 116 117

    # If the user already exists, don't try to create it again
    if len(User.objects.filter(username=uname)) > 0:
        return

118 119 120 121 122 123 124 125 126 127
    portal_user = UserFactory.build(username=uname, email=uname + '@edx.org')
    portal_user.set_password('test')
    portal_user.save()

    registration = RegistrationFactory(user=portal_user)
    registration.register(portal_user)
    registration.activate()

    user_profile = UserProfileFactory(user=portal_user)

Calen Pennington committed
128

129
@world.absorb
Calen Pennington committed
130
def log_in(email, password):
131 132
    world.browser.cookies.delete()
    world.browser.visit(django_url('/'))
Calen Pennington committed
133
    world.browser.is_element_present_by_css('header.global', 10)
134
    world.browser.click_link_by_href('#login-modal')
135

136 137 138 139
    # Wait for the login dialog to load
    # This is complicated by the fact that sometimes a second #login_form
    # dialog loads, while the first one remains hidden.
    # We give them both time to load, starting with the second one.
140
    world.browser.is_element_present_by_css('section.content-wrapper form#login_form', wait_time=4)
141
    world.browser.is_element_present_by_css('form#login_form', wait_time=2)
142

143 144
    # For some reason, the page sometimes includes two #login_form
    # elements, the first of which is not visible.
145
    # To avoid this, we always select the last of the two #login_form dialogs
146 147 148 149
    login_form = world.browser.find_by_css('form#login_form').last

    login_form.find_by_name('email').fill(email)
    login_form.find_by_name('password').fill(password)
150 151 152
    login_form.find_by_name('submit').click()

    # wait for the page to redraw
153
    assert world.browser.is_element_present_by_css('.content-wrapper', wait_time=10)
154

Calen Pennington committed
155

156
@world.absorb
157 158 159 160
def register_by_course_id(course_id, is_staff=False):
    create_user('robot')
    u = User.objects.get(username='robot')
    if is_staff:
Calen Pennington committed
161 162
        u.is_staff = True
        u.save()
163 164
    CourseEnrollment.objects.get_or_create(user=u, course_id=course_id)

Calen Pennington committed
165

166
@world.absorb
167 168 169 170 171 172 173 174
def save_the_html(path='/tmp'):
    u = world.browser.url
    html = world.browser.html.encode('ascii', 'ignore')
    filename = '%s.html' % quote_plus(u)
    f = open('%s/%s' % (path, filename), 'w')
    f.write(html)
    f.close

Calen Pennington committed
175

176 177 178 179 180 181
@world.absorb
def save_the_course_content(path='/tmp'):
    html = world.browser.html.encode('ascii', 'ignore')
    soup = BeautifulSoup(html)

    # get rid of the header, we only want to compare the body
182
    soup.head.decompose()
183

Calen Pennington committed
184
    # for now, remove the data-id attributes, because they are
185 186 187 188
    # causing mismatches between cms-master and master
    for item in soup.find_all(attrs={'data-id': re.compile('.*')}):
        del item['data-id']

Calen Pennington committed
189
    # we also need to remove them from unrendered problems,
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
    # where they are contained in the text of divs instead of
    # in attributes of tags
    # Be careful of whether or not it was the last attribute
    # and needs a trailing space
    for item in soup.find_all(text=re.compile(' data-id=".*?" ')):
        s = unicode(item.string)
        item.string.replace_with(re.sub(' data-id=".*?" ', ' ', s))

    for item in soup.find_all(text=re.compile(' data-id=".*?"')):
        s = unicode(item.string)
        item.string.replace_with(re.sub(' data-id=".*?"', ' ', s))

    # prettify the html so it will compare better, with
    # each HTML tag on its own line
    output = soup.prettify()

    # use string slicing to grab everything after 'courseware/' in the URL
    u = world.browser.url
Calen Pennington committed
208
    section_url = u[u.find('courseware/') + 11:]
209 210 211

    if not os.path.exists(path):
        os.makedirs(path)
212

213 214 215 216
    filename = '%s.html' % (quote_plus(section_url))
    f = open('%s/%s' % (path, filename), 'w')
    f.write(output)
    f.close