mirror of
https://github.com/mail-in-a-box/mailinabox.git
synced 2026-03-12 17:07:23 +01:00
qa: add core code for browser-based testing and tests for changing user passwords and adding contacts in roundcube
This commit is contained in:
1
tests/suites/.gitignore
vendored
Normal file
1
tests/suites/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
screenshot.png
|
||||
@@ -17,11 +17,14 @@ set +eu
|
||||
. suites/_mail-functions.sh || exit 1
|
||||
. suites/_mgmt-functions.sh || exit 1
|
||||
. suites/_zpush-functions.sh || exit 1
|
||||
. suites/_ui-functions.sh || exit 1
|
||||
|
||||
|
||||
MIAB_DIR=".."
|
||||
PYMAIL="./test_mail.py"
|
||||
EDITCONF="../tools/editconf.py"
|
||||
UI_TESTS_PYTHONPATH=$(realpath "lib/python")
|
||||
UI_TESTS_VERBOSITY=2
|
||||
|
||||
# options
|
||||
SKIP_REMOTE_SMTP_TESTS=no
|
||||
|
||||
44
tests/suites/_ui-functions.sh
Normal file
44
tests/suites/_ui-functions.sh
Normal file
@@ -0,0 +1,44 @@
|
||||
#####
|
||||
##### This file is part of Mail-in-a-Box-LDAP which is released under the
|
||||
##### terms of the GNU Affero General Public License as published by the
|
||||
##### Free Software Foundation, either version 3 of the License, or (at
|
||||
##### your option) any later version. See file LICENSE or go to
|
||||
##### https://github.com/downtownallday/mailinabox-ldap for full license
|
||||
##### details.
|
||||
#####
|
||||
|
||||
run_browser_test() {
|
||||
local assert=false
|
||||
if [ "$1" = "assert" ]; then
|
||||
assert=true
|
||||
shift
|
||||
fi
|
||||
local path="$1" # relative to suites directory. eg "roundcube/mytest.py"
|
||||
shift; # remaining arguments are passed to the test
|
||||
|
||||
record "[launching ui test $path $*]"
|
||||
record "PYTHONPATH=$UI_TESTS_PYTHONPATH"
|
||||
record "BROWSER_TESTS_VERBOSITY=${UI_TESTS_VERBOSITY:-1}"
|
||||
record "BROWSER_TESTS_OUTPUT_PATH=${TEST_OF}_ui"
|
||||
|
||||
local output
|
||||
output=$(
|
||||
export PYTHONPATH="$UI_TESTS_PYTHONPATH";
|
||||
export BROWSER_TESTS_VERBOSITY=${UI_TESTS_VERBOSITY:-1};
|
||||
export BROWSER_TESTS_OUTPUT_PATH="${TEST_OF}_ui";
|
||||
python3 suites/$path "$@" 2>&1
|
||||
)
|
||||
local code=$?
|
||||
record "RESULT: $code"
|
||||
record "OUTPUT:"; record "$output"
|
||||
if [ $code -ne 0 ] && $assert; then
|
||||
test_failure "ui test failed: $(python_error "$output")"
|
||||
fi
|
||||
return $code
|
||||
}
|
||||
|
||||
|
||||
assert_browser_test() {
|
||||
run_browser_test "assert" "$@"
|
||||
return $?
|
||||
}
|
||||
88
tests/suites/nextcloud/contacts.py
Normal file
88
tests/suites/nextcloud/contacts.py
Normal file
@@ -0,0 +1,88 @@
|
||||
#####
|
||||
##### This file is part of Mail-in-a-Box-LDAP which is released under the
|
||||
##### terms of the GNU Affero General Public License as published by the
|
||||
##### Free Software Foundation, either version 3 of the License, or (at
|
||||
##### your option) any later version. See file LICENSE or go to
|
||||
##### https://github.com/downtownallday/mailinabox-ldap for full license
|
||||
##### details.
|
||||
#####
|
||||
|
||||
from browser.automation import (
|
||||
TestDriver,
|
||||
TimeoutException,
|
||||
NoSuchElementException,
|
||||
ElementNotInteractableException,
|
||||
)
|
||||
from browser.NextcloudAutomation import NextcloudAutomation
|
||||
import sys
|
||||
|
||||
op = sys.argv[1]
|
||||
login = sys.argv[2]
|
||||
pw = sys.argv[3]
|
||||
contact = {
|
||||
'givenname': sys.argv[4],
|
||||
'surname': sys.argv[5],
|
||||
'email': sys.argv[6],
|
||||
}
|
||||
|
||||
d = TestDriver()
|
||||
nc = NextcloudAutomation(d)
|
||||
|
||||
try:
|
||||
#
|
||||
# open the browser to Nextcloud
|
||||
#
|
||||
# these tests work for both remote and local Nextclouds. nginx
|
||||
# will redirect to a remote nextcloud during get(), if configured
|
||||
#
|
||||
d.start("Opening Nextcloud")
|
||||
d.get("/cloud/")
|
||||
nc.wait_for_login_screen()
|
||||
d.say_verbose('url: ' + d.current_url())
|
||||
|
||||
#
|
||||
# login, then open the contacts app
|
||||
#
|
||||
nc.login(login, pw)
|
||||
nc.wait_for_app_load()
|
||||
nc.open_contacts()
|
||||
nc.wait_for_app_load()
|
||||
|
||||
#
|
||||
# handle selected operation
|
||||
#
|
||||
if op=='exists':
|
||||
d.start("Check that contact %s exists", contact['email'])
|
||||
nc.click_contact(contact) # raises NoSuchElementException if not found
|
||||
|
||||
elif op=='delete':
|
||||
d.start("Delete contact %s", contact['email'])
|
||||
nc.click_contact(contact)
|
||||
nc.wait_contact_loaded()
|
||||
# click "..." menu
|
||||
d.find_el('.contact-header__actions button.action-item__menutoggle').click()
|
||||
d.wait_for_el('.popover', must_be_displayed=True, secs=2)
|
||||
# click "delete"
|
||||
d.find_el('.popover span.icon-delete').parent().click()
|
||||
d.wait_for_el('div.empty-content', secs=2)
|
||||
|
||||
else:
|
||||
raise ValueError('Invalid operation: %s' % op)
|
||||
|
||||
#
|
||||
# logout
|
||||
#
|
||||
nc.logout()
|
||||
nc.wait_for_login_screen()
|
||||
|
||||
#
|
||||
# done
|
||||
#
|
||||
d.say("Success!")
|
||||
|
||||
except Exception as e:
|
||||
d.fail(e)
|
||||
raise
|
||||
|
||||
finally:
|
||||
d.quit()
|
||||
@@ -127,12 +127,6 @@ test_nextcloud_contacts() {
|
||||
carddav_delete_contact "$alice" "$alice_pw" "$c_uid" 2>>$TEST_OF || \
|
||||
test_failure "Unable to delete contact for $alice in Nextcloud"
|
||||
|
||||
|
||||
#
|
||||
# 2. create contact in Roundcube - ensure contact appears in Nextcloud
|
||||
#
|
||||
# TODO
|
||||
|
||||
|
||||
# clean up
|
||||
mgmt_assert_delete_user "$alice"
|
||||
|
||||
126
tests/suites/roundcube.sh
Normal file
126
tests/suites/roundcube.sh
Normal file
@@ -0,0 +1,126 @@
|
||||
#####
|
||||
##### This file is part of Mail-in-a-Box-LDAP which is released under the
|
||||
##### terms of the GNU Affero General Public License as published by the
|
||||
##### Free Software Foundation, either version 3 of the License, or (at
|
||||
##### your option) any later version. See file LICENSE or go to
|
||||
##### https://github.com/downtownallday/mailinabox-ldap for full license
|
||||
##### details.
|
||||
#####
|
||||
|
||||
|
||||
test_password_change() {
|
||||
# ensure user passwords can be changed from roundcube
|
||||
test_start "password-change"
|
||||
|
||||
# create regular user alice
|
||||
local alice="alice@somedomain.com"
|
||||
local alice_old_pw="alice_1234"
|
||||
local alice_new_pw="123_new_alice"
|
||||
create_user "$alice" "$alice_old_pw"
|
||||
|
||||
# change the password using roundcube's ui
|
||||
assert_browser_test \
|
||||
roundcube/change_pw.py \
|
||||
"$alice" \
|
||||
"$alice_old_pw" \
|
||||
"$alice_new_pw"
|
||||
|
||||
# test login using new password
|
||||
if ! have_test_failures; then
|
||||
get_attribute "$LDAP_USERS_BASE" "mail=$alice" "dn"
|
||||
assert_r_access "$ATTR_DN" "$ATTR_DN" "$alice_new_pw" read mail
|
||||
fi
|
||||
|
||||
# clean up
|
||||
delete_user "$alice"
|
||||
test_end
|
||||
}
|
||||
|
||||
|
||||
test_create_contact() {
|
||||
#
|
||||
# ensure contacts can be created in Roundcube and that those
|
||||
# contacts appears in Nextcloud (support both local and remote
|
||||
# Nextcloud setups)
|
||||
#
|
||||
# we're not going to check that a contact created in Nextcloud is
|
||||
# available in Roundcube because there's already a test for that
|
||||
# in the suite remote-nextcloud.sh
|
||||
#
|
||||
test_start "create-contact"
|
||||
|
||||
# create regular user alice
|
||||
local alice="alice@somedomain.com"
|
||||
local alice_pw="$(generate_password 16)"
|
||||
create_user "$alice" "$alice_pw"
|
||||
|
||||
# which address book in roundcube?
|
||||
# .. local nextcloud: the name is "ownCloud (Contacts)
|
||||
# .. remote nextcloud: the name is the remote server name
|
||||
#
|
||||
# RCM_PLUGIN_DIR is defined in lib/locations.sh
|
||||
record "[get address book name]"
|
||||
local code address_book
|
||||
address_book=$(php${PHP_VER} -r "require '$RCM_PLUGIN_DIR/carddav/config.inc.php'; isset(\$prefs['cloud']) ? print \$prefs['cloud']['name'] : print \$prefs['ownCloud']['name'];" 2>>$TEST_OF)
|
||||
record "name: $address_book"
|
||||
code=$?
|
||||
if [ $code -ne 0 ]; then
|
||||
test_failure "Could not determine the address book name to use"
|
||||
|
||||
else
|
||||
# generate an email address - the contact's email must be
|
||||
# unique or it can't be created
|
||||
local contact_email="bob_bacon$(generate_uuid | awk -F- '{print $1 }')@example.com"
|
||||
|
||||
# create a contact using roundcube's ui
|
||||
record "[create contact in Roundcube]"
|
||||
if assert_browser_test \
|
||||
roundcube/create_contact.py \
|
||||
"$alice" \
|
||||
"$alice_pw" \
|
||||
"$address_book" \
|
||||
"Bob" \
|
||||
"Bacon" \
|
||||
"$contact_email"
|
||||
then
|
||||
# ensure the contact exists in Nextcloud.
|
||||
#
|
||||
# skip explicitly checking for existance - when we delete
|
||||
# the contact we're also checking that it exists (delete
|
||||
# will fail otherwise)
|
||||
|
||||
# record "[ensure contact exists in Nextcloud]"
|
||||
# assert_browser_test \
|
||||
# nextcloud/contacts.py \
|
||||
# "exists" \
|
||||
# "$alice" \
|
||||
# "$alice_pw" \
|
||||
# "Bob" \
|
||||
# "Bacon" \
|
||||
# "$contact_email"
|
||||
|
||||
# delete the contact
|
||||
record "[delete the contact in Nextcloud]"
|
||||
assert_browser_test \
|
||||
nextcloud/contacts.py \
|
||||
"delete" \
|
||||
"$alice" \
|
||||
"$alice_pw" \
|
||||
"Bob" \
|
||||
"Bacon" \
|
||||
"$contact_email"
|
||||
fi
|
||||
fi
|
||||
|
||||
test_end
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
suite_start "roundcube"
|
||||
|
||||
test_password_change
|
||||
test_create_contact
|
||||
|
||||
suite_end
|
||||
70
tests/suites/roundcube/change_pw.py
Normal file
70
tests/suites/roundcube/change_pw.py
Normal file
@@ -0,0 +1,70 @@
|
||||
#####
|
||||
##### This file is part of Mail-in-a-Box-LDAP which is released under the
|
||||
##### terms of the GNU Affero General Public License as published by the
|
||||
##### Free Software Foundation, either version 3 of the License, or (at
|
||||
##### your option) any later version. See file LICENSE or go to
|
||||
##### https://github.com/downtownallday/mailinabox-ldap for full license
|
||||
##### details.
|
||||
#####
|
||||
|
||||
from browser.automation import (
|
||||
TestDriver,
|
||||
TimeoutException,
|
||||
NoSuchElementException
|
||||
)
|
||||
from browser.RoundcubeAutomation import RoundcubeAutomation
|
||||
import sys
|
||||
|
||||
login = sys.argv[1]
|
||||
old_pw = sys.argv[2]
|
||||
new_pw = sys.argv[3]
|
||||
|
||||
d = TestDriver()
|
||||
rcm = RoundcubeAutomation(d)
|
||||
|
||||
try:
|
||||
#
|
||||
# open the browser to roundcube
|
||||
#
|
||||
d.start("Opening roundcube")
|
||||
d.get("/mail/")
|
||||
rcm.wait_for_login_screen(secs=10)
|
||||
|
||||
#
|
||||
# login
|
||||
#
|
||||
rcm.login(login, old_pw)
|
||||
rcm.wait_for_inbox()
|
||||
|
||||
#
|
||||
# change password
|
||||
#
|
||||
d.start("Change password")
|
||||
rcm.open_settings()
|
||||
rcm.wait_for_settings()
|
||||
|
||||
d.say("Enter new password")
|
||||
d.find_el('a.password').click() # open the change password section
|
||||
d.wait_for_el('button[value=Save]') # wait for it to load
|
||||
d.find_el('#curpasswd').send_text(old_pw) # fill old password
|
||||
d.find_el('#newpasswd').send_text(new_pw) # fill new password
|
||||
d.find_el('#confpasswd').send_text(new_pw) # fill confirm password
|
||||
d.find_el('button[value=Save]').click() # save new password
|
||||
d.wait_for_text("Successfully saved", secs=5, case_sensitive=False)
|
||||
|
||||
#
|
||||
# logout
|
||||
#
|
||||
rcm.logout()
|
||||
|
||||
#
|
||||
# done
|
||||
#
|
||||
d.say("Success!")
|
||||
|
||||
except Exception as e:
|
||||
d.fail(e)
|
||||
raise
|
||||
|
||||
finally:
|
||||
d.quit()
|
||||
88
tests/suites/roundcube/create_contact.py
Normal file
88
tests/suites/roundcube/create_contact.py
Normal file
@@ -0,0 +1,88 @@
|
||||
#####
|
||||
##### This file is part of Mail-in-a-Box-LDAP which is released under the
|
||||
##### terms of the GNU Affero General Public License as published by the
|
||||
##### Free Software Foundation, either version 3 of the License, or (at
|
||||
##### your option) any later version. See file LICENSE or go to
|
||||
##### https://github.com/downtownallday/mailinabox-ldap for full license
|
||||
##### details.
|
||||
#####
|
||||
|
||||
from browser.automation import (
|
||||
TestDriver,
|
||||
TimeoutException,
|
||||
NoSuchElementException,
|
||||
ElementNotInteractableException,
|
||||
)
|
||||
from browser.RoundcubeAutomation import RoundcubeAutomation
|
||||
import sys
|
||||
|
||||
login = sys.argv[1]
|
||||
pw = sys.argv[2]
|
||||
address_book = sys.argv[3]
|
||||
contact = {
|
||||
'givenname': sys.argv[4],
|
||||
'surname': sys.argv[5],
|
||||
'email': sys.argv[6],
|
||||
}
|
||||
|
||||
d = TestDriver()
|
||||
rcm = RoundcubeAutomation(d)
|
||||
|
||||
try:
|
||||
#
|
||||
# open the browser to roundcube
|
||||
#
|
||||
d.start("Opening roundcube")
|
||||
d.get("/mail/")
|
||||
rcm.wait_for_login_screen(secs=10)
|
||||
|
||||
#
|
||||
# login
|
||||
#
|
||||
rcm.login(login, pw)
|
||||
rcm.wait_for_inbox()
|
||||
|
||||
#
|
||||
# add contact
|
||||
#
|
||||
d.start("Add contact")
|
||||
rcm.open_contacts()
|
||||
rcm.wait_for_contacts()
|
||||
|
||||
d.say("Select address book '%s'", address_book)
|
||||
el = d.find_text(address_book, "a", exact=True, throws=False, case_sensitive=True)
|
||||
if not el:
|
||||
el = d.find_text(address_book + ' (Contacts)', "a", exact=True, case_sensitive=True)
|
||||
if not el.is_displayed():
|
||||
d.say_verbose("open sidebar to select address book")
|
||||
d.find_el('a.back-sidebar-button').click()
|
||||
el.click()
|
||||
|
||||
d.say("Create contact")
|
||||
d.find_el('a.create').click()
|
||||
iframe_el = d.wait_for_el('#contact-frame', secs=5)
|
||||
d.switch_to_frame(iframe_el)
|
||||
|
||||
d.find_el('#ff_firstname').send_text(contact['givenname'])
|
||||
d.find_el('#ff_surname').send_text(contact['surname'])
|
||||
d.find_el('#ff_email0').send_text(contact['email'])
|
||||
d.find_el('button[value=Save]').click() # save new password
|
||||
d.switch_to_window(d.get_current_window_handle())
|
||||
d.wait_for_text("Successfully saved", secs=5, case_sensitive=False)
|
||||
|
||||
#
|
||||
# logout
|
||||
#
|
||||
rcm.logout()
|
||||
|
||||
#
|
||||
# done
|
||||
#
|
||||
d.say("Success!")
|
||||
|
||||
except Exception as e:
|
||||
d.fail(e)
|
||||
raise
|
||||
|
||||
finally:
|
||||
d.quit()
|
||||
18
tests/suites/run_browser_test.sh
Executable file
18
tests/suites/run_browser_test.sh
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
#####
|
||||
##### This file is part of Mail-in-a-Box-LDAP which is released under the
|
||||
##### terms of the GNU Affero General Public License as published by the
|
||||
##### Free Software Foundation, either version 3 of the License, or (at
|
||||
##### your option) any later version. See file LICENSE or go to
|
||||
##### https://github.com/downtownallday/mailinabox-ldap for full license
|
||||
##### details.
|
||||
#####
|
||||
|
||||
|
||||
# use this to run a browser test from the command line
|
||||
|
||||
mydir=$(dirname "$0")
|
||||
export PYTHONPATH=$(realpath "$mydir/../lib/python"):$PYTHONPATH
|
||||
export BROWSER_TESTS_VERBOSITY=3
|
||||
|
||||
python3 "$@"
|
||||
Reference in New Issue
Block a user