Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

working for WinXP FF13

  • Loading branch information...
commit 72331ddd9cbd8e3e72491597006466622e5d55d2 1 parent 4e7a4b8
@klrmn klrmn authored 6a68 committed
View
1  .gitignore
@@ -17,3 +17,4 @@ Thumbs.db
/automation-tests/results
/automation-tests/credentials.yaml
/automation-tests/sauce.yaml
+automation-tests/persona_server/results/*
View
0  automation-tests/persona_server/__init__.py
No changes.
View
0  automation-tests/persona_server/pages/__init__.py
No changes.
View
115 automation-tests/persona_server/pages/account_manager.py
@@ -0,0 +1,115 @@
+#!/usr/bin/env python
+
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support.ui import WebDriverWait
+
+from base import Base
+
+
+class AccountManager(Base):
+ '''AccountManager is used when logged in. Use HomePage page if not logged in.'''
+
+ _page_url = '/'
+ _emails_locator = (By.CSS_SELECTOR, '#emailList .email')
+ _edit_password_button_locator = (By.CSS_SELECTOR, '#edit_password button.edit')
+ _old_password_field_locator = (By.ID, 'old_password')
+ _new_password_field_locator = (By.ID, 'new_password')
+ _change_password_done_locator = (By.ID, 'changePassword')
+ _sign_in_locator = (By.CSS_SELECTOR, 'a.signIn')
+ _sign_out_locator = (By.CSS_SELECTOR, 'a.signOut')
+ _cancel_account_locator = (By.ID, 'cancelAccount')
+
+ def load_page(self):
+ Base.load_page(self)
+ self.wait_for_page_to_load()
+
+ def wait_for_page_to_load(self):
+ WebDriverWait(self.selenium, self.timeout).until(
+ lambda s: s.find_element(*self._emails_locator).is_displayed())
+
+ @property
+ def emails(self):
+ """Returns a textual list of email addresses associated with the currently signed in user."""
+ return [element.text for element in self.selenium.find_elements(*self._emails_locator)]
+
+ def click_edit_password(self):
+ """Click edit password to show the new/old password fields"""
+ self.selenium.find_element(*self._edit_password_button_locator).click()
+ WebDriverWait(self.selenium, self.timeout).until(
+ lambda s: s.find_element(*self._old_password_field_locator).is_displayed())
+
+ @property
+ def old_password(self):
+ """Get the value of the old password field."""
+ return self.selenium.find_element(*self._old_password_field_locator).text
+
+ @old_password.setter
+ def old_password(self, value):
+ """Set the value of the old password field."""
+ password = self.selenium.find_element(*self._old_password_field_locator)
+ password.clear()
+ password.send_keys(value)
+
+ @property
+ def new_password(self):
+ """Get the value of the new password field."""
+ return self.selenium.find_element(*self._new_password_field_locator).text
+
+ @new_password.setter
+ def new_password(self, value):
+ """Set the value of the new password field."""
+ password = self.selenium.find_element(*self._new_password_field_locator)
+ password.clear()
+ password.send_keys(value)
+
+ def click_password_done(self):
+ """Click password done to save the new password."""
+ self.selenium.find_element(*self._change_password_done_locator).click()
+ WebDriverWait(self.selenium, self.timeout).until(
+ lambda s: s.find_element(*self._edit_password_button_locator).is_displayed())
+
+ def click_sign_out(self):
+ """Click the Sign Out button"""
+ self.selenium.find_element(*self._sign_out_locator).click()
+ WebDriverWait(self.selenium, self.timeout).until(
+ lambda s: not self.signed_in)
+
+ def click_cancel_account(self):
+ """Click the cancel account link."""
+ self.selenium.find_element(*self._cancel_account_locator).click()
+
+ def change_password(self, old_password, new_password):
+ """
+ Helper function change_password(old_password, new_password) performs the
+ series of actions necessary to change the password.
+ """
+
+ self.click_edit_password()
+ self.old_password = old_password
+ self.new_password = new_password
+ self.click_password_done()
+
+ def sign_out(self):
+ """
+ Helper function sign_out() performs the series of actions necessary to
+ sign out.
+ """
+
+ self.click_sign_out()
+ from home import HomePage # circular reference
+ return HomePage(self.mozwebqa)
+
+ def cancel_account(self):
+ """
+ Helper function cancel_account() performs the series of actions necessary
+ to cancel the account of the currently signed in user.
+ """
+
+ self.click_cancel_account()
+ self.selenium.switch_to_alert().accept()
+ from home import HomePage # circular reference
+ return HomePage(self.mozwebqa)
View
35 automation-tests/persona_server/pages/base.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support.ui import WebDriverWait
+
+
+class Base(object):
+
+ _body_locator = (By.TAG_NAME, 'body')
+
+ def __init__(self, mozwebqa):
+ self.mozwebqa = mozwebqa
+ self.selenium = mozwebqa.selenium
+ self.timeout = mozwebqa.timeout
+ self.base_url = mozwebqa.base_url
+
+ @property
+ def signed_in(self):
+ """Returns True/False whether a user is signed in."""
+ return 'not_authenticated' not in self.selenium.find_element(*self._body_locator).get_attribute('class')
+
+ def load_page(self):
+ if self._page_url:
+ self.selenium.get(self.base_url + self._page_url)
+ self.wait_for_ajax()
+
+ def wait_for_ajax(self):
+ """Waits for the script 'jQuery.active == 0'."""
+ WebDriverWait(self.selenium, self.timeout).until(
+ lambda s: s.execute_script("return jQuery.active == 0"),
+ "Wait for AJAX timed out after %s seconds" % self.timeout)
View
77 automation-tests/persona_server/pages/complete_registration.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python
+
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from base import Base
+
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support.ui import WebDriverWait
+
+
+class CompleteRegistration(Base):
+
+ _page_title = 'Mozilla Persona: Complete Registration'
+ _email_locator = (By.ID, 'email')
+ _password_locator = (By.ID, 'password')
+ _finish_locator = (By.CSS_SELECTOR, 'div.submit > button')
+ _thank_you_locator = (By.ID, 'congrats')
+
+ def __init__(self, mozwebqa, url, expect='redirect'):
+ """
+ class init method
+ :Args:
+ - url - the confirmation url from the email
+ - expect - redirect/success/reset/verify (default redirect)
+ """
+ Base.__init__(self, mozwebqa)
+
+ self.selenium.get(url)
+
+ if expect == 'redirect':
+ WebDriverWait(self.selenium, self.timeout).until(
+ lambda s: s.title != self._page_title,
+ "Complete Registration page did not redirect")
+ elif expect == 'success':
+ WebDriverWait(self.selenium, self.timeout).until(
+ lambda s: 'Thank you' in s.find_element(*self._thank_you_locator).text,
+ "Complete Registration did not succeed")
+ elif expect == 'reset':
+ WebDriverWait(self.selenium, self.timeout).until(
+ lambda s: 'verified' in s.find_element(*self._thank_you_locator).text,
+ "Complete Registration did not succeed")
+ elif expect == 'verify':
+ WebDriverWait(self.selenium, self.timeout).until(
+ lambda s: s.find_element(*self._password_locator).is_displayed(),
+ "password field did not become visible")
+ else:
+ raise Exception('Unknown expect value: %s' % expect)
+
+ @property
+ def email(self):
+ """Get the value of the email field."""
+ return self.selenium.find_element(*self._email_locator).text
+
+ @property
+ def password(self):
+ """Get the value of the password field."""
+ return self.selenium.find_element(*self._password_locator).text
+
+ @password.setter
+ def password(self, value):
+ """Set the value of the password field."""
+ password = self.selenium.find_element(*self._password_locator)
+ password.clear()
+ password.send_keys(value)
+
+ def click_finish(self):
+ """Clicks the 'finish' button."""
+ self.selenium.find_element(*self._finish_locator).click()
+ WebDriverWait(self.selenium, self.timeout).until(
+ lambda s: s.find_element(*self._thank_you_locator).is_displayed())
+
+ @property
+ def thank_you(self):
+ """Returns the 'thank you' message."""
+ return self.selenium.find_element(*self._thank_you_locator).text
View
41 automation-tests/persona_server/pages/home.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import time
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support.ui import WebDriverWait
+
+from base import Base
+from sign_in import SignIn
+
+
+class HomePage(Base):
+ '''HomePage is used when not logged in. Use AccountManager page if logged in.'''
+
+ _page_title = 'Mozilla Persona: A Better Way to Sign In'
+ _page_url = '/'
+ _sign_in_locator = (By.CSS_SELECTOR, 'a.signIn')
+ _sign_up_locator = (By.CSS_SELECTOR, 'a.button.create')
+ _manage_section_locator = (By.ID, 'manage')
+ _sign_out_locator = (By.CSS_SELECTOR, 'a.signOut')
+
+ def __init__(self, mozwebqa):
+ Base.__init__(self, mozwebqa)
+
+ WebDriverWait(self.selenium, self.timeout * 2).until(
+ lambda s: s.find_element(*self._sign_in_locator) and \
+ s.find_element(*self._sign_in_locator).is_displayed(),
+ "the sign in button has not appeared within %s" % self.timeout * 2)
+
+ def click_sign_up(self):
+ """Clicks the Sign Up button."""
+ self.selenium.find_element(*self._sign_up_locator).click()
+ return SignIn(self.mozwebqa)
+
+ def click_sign_in(self):
+ """Clicks the Sign In button."""
+ self.selenium.find_element(*self._sign_in_locator).click()
+ return SignIn(self.mozwebqa)
View
162 automation-tests/persona_server/pages/sign_in.py
@@ -0,0 +1,162 @@
+#!/usr/bin/env python
+
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support.ui import WebDriverWait
+
+from base import Base
+from account_manager import AccountManager
+
+
+class SignIn(Base):
+
+ _email_locator = (By.ID, 'email')
+ _next_locator = (By.ID, 'next')
+ _sign_in_locator = (By.ID, 'signIn')
+ _verify_email_locator = (By.ID, 'verifyEmail')
+ _password_locator = (By.ID, 'password')
+ _password_verify_locator = (By.ID, 'vpassword')
+ _forgot_password_locator = (By.CSS_SELECTOR, 'a.forgot')
+ _reset_password_locator = (By.CSS_SELECTOR, '#signUpForm button')
+ _check_your_email_locator = (By.CSS_SELECTOR, '.notification.emailsent > h2')
+
+ def __init__(self, mozwebqa):
+ Base.__init__(self, mozwebqa)
+
+ WebDriverWait(self.selenium, self.timeout).until(
+ lambda s: s.find_element(*self._email_locator) and \
+ s.find_element(*self._email_locator).is_displayed(),
+ "email field did not appear within %s" % self.timeout)
+
+ @property
+ def email(self):
+ """Get the value of the email field."""
+ return self.selenium.find_element(*self._email_locator).get_attribute('value')
+
+ @email.setter
+ def email(self, value):
+ """Set the value of the email field."""
+ field = self.selenium.find_element(*self._email_locator)
+ field.clear()
+ field.send_keys(value)
+
+ def click_next(self):
+ """Click the 'next' button (after filling in email)."""
+ WebDriverWait(self.selenium, self.timeout).until(
+ lambda s: s.find_element(*self._next_locator) and \
+ s.find_element(*self._next_locator).is_displayed(),
+ "next button is not found / not visible")
+ self.selenium.find_element(*self._next_locator).click()
+ WebDriverWait(self.selenium, self.timeout).until(
+ lambda s: s.find_element(*self._password_locator).is_displayed(),
+ "Password field did not appear within %s" % self.timeout
+ )
+
+ def click_sign_in(self):
+ """Click the 'Sign In' button (after filling in password in the sign-in flow)."""
+ WebDriverWait(self.selenium, self.timeout).until(
+ lambda s: s.find_element(*self._sign_in_locator) and \
+ s.find_element(*self._sign_in_locator).is_displayed(),
+ "sign in button not found / not visible")
+ self.selenium.find_element(*self._sign_in_locator).click()
+ self.wait_for_ajax()
+ print "clicked sign in"
+
+ def click_verify_email(self):
+ """Click the 'Verify Email' button (after filling in password and verify in the sign-up flow)."""
+ WebDriverWait(self.selenium, self.timeout).until(
+ lambda s: s.find_element(*self._verify_email_locator) and \
+ s.find_element(*self._verify_email_locator).is_displayed(),
+ "verify email button not found / not visible")
+ self.selenium.find_element(*self._verify_email_locator).click()
+ WebDriverWait(self.selenium, self.timeout).until(
+ lambda s: s.find_element(*self._check_your_email_locator).is_displayed(),
+ "check your email message did not appear")
+
+ @property
+ def password(self):
+ """Get the value of the password field."""
+ return self.selenium.find_element(*self._password_locator).get_attribute('value')
+
+ @password.setter
+ def password(self, value):
+ """Sets the value of the password field."""
+ field = self.selenium.find_element(*self._password_locator)
+ field.clear()
+ field.send_keys(value)
+
+ @property
+ def verify_password(self):
+ """Get the value of the verify password field."""
+ return self.selenium.find_element(*self._password_verify_locator).get_attribute('value')
+
+ @verify_password.setter
+ def verify_password(self, value):
+ """Set the value of the verify password field."""
+ field = self.selenium.find_element(*self._password_verify_locator)
+ field.clear()
+ field.send_keys(value)
+
+ def click_forgot_password(self):
+ """Clicks the forgot password link."""
+ self.selenium.find_element(*self._forgot_password_locator).click()
+ WebDriverWait(self.selenium, self.timeout).until(
+ lambda s: s.find_element(*self._password_verify_locator).is_displayed(),
+ "verify password field did not appear within %s" % self.timeout)
+
+ def click_reset_password(self):
+ """Clicks the reset password button."""
+ self.selenium.find_element(*self._reset_password_locator).click()
+ WebDriverWait(self.selenium, self.timeout).until(
+ lambda s: s.find_element(*self._check_your_email_locator).is_displayed(),
+ "check your email message did not appear")
+
+ @property
+ def check_your_email_title_text(self):
+ """Get the text of the result notification title."""
+ return self.selenium.find_element(*self._check_your_email_locator).text
+
+ @property
+ def is_sign_up_flow(self):
+ """Returns true if the current page has the password verify field"""
+ return self.selenium.find_element(*self._password_verify_locator).is_displayed()
+
+ def sign_in(self, email, password):
+ """
+ Helper method sign_in(email, password) signs in with the provided email
+ address and password.
+ """
+ self.email = email
+ self.click_next()
+ self.password = password
+ self.click_sign_in()
+ # should redirect to Account Manager (home, logged in) page
+ account_manager = AccountManager(self.mozwebqa)
+ account_manager.wait_for_page_to_load()
+ return account_manager
+
+ def sign_up(self, email, password):
+ """
+ Helper method sign_up(email, password) signs up with the provided email
+ address and password.
+ """
+ self.email = email
+ self.click_next()
+ self.password = password
+ self.verify_password = password
+ self.click_verify_email()
+ # does not redirect to anywhere
+
+ def forgot_password(self, email, new_password):
+ """
+ Helper method forgot_password(email, new_password) performs the series of
+ actions required to reset the user's password.
+ """
+ self.click_forgot_password()
+ self.password = new_password
+ self.verify_password = new_password
+ self.click_reset_password()
+ # does not redirect to anywhere
View
0  automation-tests/persona_server/tests/__init__.py
No changes.
View
49 automation-tests/persona_server/tests/base.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+import re
+
+from browserid.mocks.user import MockUser
+from browserid.tests import restmail
+from persona_server.pages.home import HomePage
+from persona_server.pages.complete_registration import CompleteRegistration
+from persona_server.pages.account_manager import AccountManager
+
+
+class BaseTest(object):
+
+ # move this to BrowserID when personatestuser.org comes online
+ def create_verified_user(self, mozwebqa):
+ user = MockUser()
+
+ # create the user
+ home = HomePage(mozwebqa)
+ signup = home.click_sign_up()
+ signup.sign_up(user.primary_email, user.password)
+
+ # do email verification
+ complete_registration = CompleteRegistration(mozwebqa,
+ self.get_confirm_url_from_email(user.primary_email),
+ expect='success')
+ assert 'Thank you' in complete_registration.thank_you
+
+ # go sign out and reload page for preconditions
+ account_manager = AccountManager(mozwebqa)
+ account_manager.load_page()
+ account_manager.sign_out()
+ home.load_page() # test will instantiate HomePage
+
+ return user
+
+ def get_confirm_url_from_email(self, email, message_count=1, regex='(https?:.*?token=.{48})'):
+ '''
+ Checks the restmail inbox for the specified address
+ and returns the confirm url.
+ Specify message_count if you expect there to be more than one message for the user.
+ Specify regex if you wish to use a specific regex. By default searches for a url with a 48 char token."
+ '''
+ mail = restmail.get_mail(email, message_count=message_count, timeout=60)
+ message_text = mail[message_count - 1]['text']
+ return re.search(regex, message_text).group(0)
View
11 automation-tests/persona_server/tests/conftest.py
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+
+def pytest_funcarg__mozwebqa(request):
+ mozwebqa = request.getfuncargvalue('mozwebqa')
+ mozwebqa.selenium.get('%s/' % mozwebqa.base_url)
+ return mozwebqa
View
124 automation-tests/persona_server/tests/test_manage_account.py
@@ -0,0 +1,124 @@
+#!/usr/bin/env python
+
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import pytest
+from unittestzero import Assert
+
+from persona_server.pages.home import HomePage
+from persona_server.pages.complete_registration import CompleteRegistration
+from persona_server.pages.account_manager import AccountManager
+from browserid.mocks.user import MockUser
+from browserid.tests import restmail
+
+from base import BaseTest
+
+
+class TestManageAccount(BaseTest):
+
+ @pytest.mark.moztrap(272)
+ def test_can_create_new_user_account(self, mozwebqa):
+ user = MockUser()
+ home = HomePage(mozwebqa)
+
+ # sign up
+ signup = home.click_sign_up()
+ signup.sign_up(user.primary_email, user.password)
+ Assert.equal(signup.check_your_email_title_text, 'Confirm your email address')
+
+ # do email verification
+ CompleteRegistration(mozwebqa,
+ self.get_confirm_url_from_email(user.primary_email),
+ expect='success')
+
+ # verify now logged in
+ account_manager = AccountManager(mozwebqa)
+ account_manager.load_page()
+ Assert.true(account_manager.signed_in)
+
+ @pytest.mark.moztrap(273)
+ @pytest.mark.nondestructive
+ def test_that_user_can_sign_in_and_out(self, mozwebqa):
+ # the dev server is being continually wiped, verified user must be fresh
+ user = self.create_verified_user(mozwebqa)
+ home = HomePage(mozwebqa)
+
+ # sign in
+ signin = home.click_sign_in()
+ account_manager = signin.sign_in(user.primary_email, user.password)
+ Assert.true(account_manager.signed_in)
+
+ # sign out
+ home = account_manager.sign_out()
+ Assert.false(home.signed_in)
+
+ @pytest.mark.moztrap(274)
+ def test_that_user_can_change_password(self, mozwebqa):
+ user = self.create_verified_user(mozwebqa)
+
+ # sign in with old password
+ home = HomePage(mozwebqa)
+ signin = home.click_sign_in()
+ account_manager = signin.sign_in(user.primary_email, user.password)
+ Assert.contains(user.primary_email, account_manager.emails)
+
+ # change password
+ old_password = user.password
+ user.password += '_new'
+ account_manager.change_password(old_password, user.password)
+
+ # sign out
+ home = account_manager.sign_out()
+
+ # sign in with new password
+ signin = home.click_sign_in()
+ account_manager = signin.sign_in(user.primary_email, user.password)
+ Assert.true(account_manager.signed_in)
+ Assert.contains(user.primary_email, account_manager.emails)
+
+ @pytest.mark.moztrap(275)
+ def test_that_user_can_cancel_account_with_one_email(self, mozwebqa):
+ user = self.create_verified_user(mozwebqa)
+
+ # sign in
+ home = HomePage(mozwebqa)
+ signin = home.click_sign_in()
+ account_manager = signin.sign_in(user.primary_email, user.password)
+
+ # cancel account
+ home = account_manager.cancel_account()
+
+ # verify email not recognized
+ signin = home.click_sign_in()
+ signin.email = user.primary_email
+ signin.click_next()
+ Assert.true(signin.is_sign_up_flow)
+
+ def test_that_user_can_reset_password(self, mozwebqa):
+ user = self.create_verified_user(mozwebqa)
+
+ # start to sign in
+ home = HomePage(mozwebqa)
+ signin = home.click_sign_in()
+
+ # forgot password
+ user.password += '_new'
+ signin.forgot_password(user.primary_email, user.password)
+ Assert.equal(signin.check_your_email_title_text, 'Confirm your email address')
+
+ # confirm email
+ CompleteRegistration(mozwebqa,
+ self.get_confirm_url_from_email(user.primary_email, message_count=2),
+ expect='reset')
+
+ # sign out
+ account_manager = AccountManager(mozwebqa)
+ account_manager.load_page()
+ home = account_manager.sign_out()
+
+ # sign in with new password
+ signin = home.click_sign_in()
+ account_manager = signin.sign_in(user.primary_email, user.password)
+ Assert.true(account_manager.signed_in)
View
42 automation-tests/persona_server/tests/test_sign_in_unit.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import pytest
+from unittestzero import Assert
+
+from persona_server.pages.home import HomePage
+from browserid.mocks.user import MockUser
+
+from base import BaseTest
+
+
+class TestSignInUnit(BaseTest):
+
+ def test_getters_sign_in(self, mozwebqa):
+ user = self.create_verified_user(mozwebqa)
+ home = HomePage(mozwebqa)
+
+ # sign in
+ signin = home.click_sign_in()
+ signin.email = user.primary_email
+ Assert.equal(signin.email, user.primary_email)
+ signin.click_next()
+ signin.password = user.password
+ Assert.equal(signin.password, user.password)
+
+ def test_getters_sign_up(self, mozwebqa):
+ user = MockUser()
+ home = HomePage(mozwebqa)
+
+ # sign up
+ signup = home.click_sign_up()
+ signup.email = user.primary_email
+ Assert.equal(signup.email, user.primary_email)
+ signup.click_next()
+ signup.password = user.password
+ signup.verify_password = user.password
+ Assert.equal(signup.password, user.password)
+ Assert.equal(signup.verify_password, user.password)
Please sign in to comment.
Something went wrong with that request. Please try again.