Invited Capybara to the party 🎉 Taking browser tests to the next level 🚀.

This commit is contained in:
Thorsten Eckel 2018-12-19 15:47:15 +01:00
parent 0fd2efa0cf
commit 5491b1b910
22 changed files with 933 additions and 22 deletions

View file

@ -24,6 +24,7 @@ variables:
when: on_failure when: on_failure
paths: paths:
- tmp/screenshot* - tmp/screenshot*
- tmp/screenshots/*
- log/*.log - log/*.log
# Workaround to enable usage of mixed SSH and Docker GitLab CI runners # Workaround to enable usage of mixed SSH and Docker GitLab CI runners
@ -67,6 +68,7 @@ stages:
pre:rubocop: pre:rubocop:
<<: *pre_stage <<: *pre_stage
script: script:
- bundle install -j $(nproc)
- bundle exec rubocop - bundle exec rubocop
pre:coffeelint: pre:coffeelint:
@ -98,7 +100,7 @@ pre:github:
RAILS_ENV: "test" RAILS_ENV: "test"
script: script:
- rake zammad:db:init - rake zammad:db:init
- bundle exec rspec - bundle exec rspec -t ~type:system
test:rspec:mysql: test:rspec:mysql:
stage: test stage: test
@ -320,6 +322,67 @@ browser:build:
- public/assets/application-* - public/assets/application-*
- public/assets/print-* - public/assets/print-*
.services_browser_postgresql_template: &services_browser_postgresql_definition
services:
- name: registry.znuny.com/docker/zammad-postgresql:latest
alias: postgresql
- name: registry.znuny.com/docker/zammad-elasticsearch:latest
alias: elasticsearch
- name: docker.io/elgalu/selenium:latest
alias: selenium
- name: registry.znuny.com/docker/docker-imap-devel:latest
alias: mail
.services_browser_mysql_template: &services_browser_mysql_definition
services:
- name: registry.znuny.com/docker/zammad-mysql:latest
alias: mysql
- name: registry.znuny.com/docker/zammad-elasticsearch:latest
alias: elasticsearch
- name: docker.io/elgalu/selenium:latest
alias: selenium
- name: registry.znuny.com/docker/docker-imap-devel:latest
alias: mail
## Capybara
.test_capybara_template: &test_capybara_definition
<<: *base_env
stage: browser-core
script:
- rake zammad:ci:test:prepare[with_elasticsearch]
- bundle exec rspec --fail-fast -t type:system
.variables_capybara_chrome_template: &variables_capybara_chrome_definition
<<: *test_capybara_definition
variables:
RAILS_ENV: "test"
NO_RESET_BEFORE_SUITE: "true"
BROWSER: "chrome"
.variables_capybara_ff_template: &variables_capybara_ff_definition
<<: *test_capybara_definition
variables:
RAILS_ENV: "test"
NO_RESET_BEFORE_SUITE: "true"
BROWSER: "firefox"
test:browser:core:capybara_chrome_postgresql:
<<: *variables_capybara_chrome_definition
<<: *services_browser_postgresql_definition
test:browser:core:capybara_chrome_mysql:
<<: *variables_capybara_chrome_definition
<<: *services_browser_mysql_definition
test:browser:core:capybara_ff_postgresql:
<<: *variables_capybara_ff_definition
<<: *services_browser_postgresql_definition
test:browser:core:capybara_ff_mysql:
<<: *variables_capybara_ff_definition
<<: *services_browser_mysql_definition
## Browser core tests ## Browser core tests
.variables_browser_template: &variables_browser_definition .variables_browser_template: &variables_browser_definition
@ -387,28 +450,12 @@ test:browser:integration:api_client_php:
.test_browser_core_postgresql_template: &test_browser_core_postgresql_definition .test_browser_core_postgresql_template: &test_browser_core_postgresql_definition
<<: *test_browser_core_definition <<: *test_browser_core_definition
<<: *script_browser_slice_definition <<: *script_browser_slice_definition
services: <<: *services_browser_postgresql_definition
- name: registry.znuny.com/docker/zammad-postgresql:latest
alias: postgresql
- name: registry.znuny.com/docker/zammad-elasticsearch:latest
alias: elasticsearch
- name: docker.io/elgalu/selenium:latest
alias: selenium
- name: registry.znuny.com/docker/docker-imap-devel:latest
alias: mail
.test_browser_core_mysql_template: &test_browser_core_mysql_definition .test_browser_core_mysql_template: &test_browser_core_mysql_definition
<<: *test_browser_core_definition <<: *test_browser_core_definition
<<: *script_browser_slice_definition <<: *script_browser_slice_definition
services: <<: *services_browser_mysql_definition
- name: registry.znuny.com/docker/zammad-mysql:latest
alias: mysql
- name: registry.znuny.com/docker/zammad-elasticsearch:latest
alias: elasticsearch
- name: docker.io/elgalu/selenium:latest
alias: selenium
- name: registry.znuny.com/docker/docker-imap-devel:latest
alias: mail
#### Firefox #### Firefox

View file

@ -145,6 +145,7 @@ group :development, :test do
gem 'simplecov-rcov' gem 'simplecov-rcov'
# UI tests w/ Selenium # UI tests w/ Selenium
gem 'capybara', '~> 2.13'
gem 'selenium-webdriver' gem 'selenium-webdriver'
# livereload on template changes (html, js, css) # livereload on template changes (html, js, css)

View file

@ -104,6 +104,13 @@ GEM
buftok (0.2.0) buftok (0.2.0)
builder (3.2.3) builder (3.2.3)
byebug (10.0.2) byebug (10.0.2)
capybara (2.18.0)
addressable
mini_mime (>= 0.1.3)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (>= 2.0, < 4.0)
childprocess (0.9.0) childprocess (0.9.0)
ffi (~> 1.0, >= 1.0.11) ffi (~> 1.0, >= 1.0.11)
clavius (1.0.3) clavius (1.0.3)
@ -255,6 +262,7 @@ GEM
mime-types (3.2.2) mime-types (3.2.2)
mime-types-data (~> 3.2015) mime-types-data (~> 3.2015)
mime-types-data (3.2018.0812) mime-types-data (3.2018.0812)
mini_mime (1.0.1)
mini_portile2 (2.3.0) mini_portile2 (2.3.0)
minitest (5.11.3) minitest (5.11.3)
multi_json (1.12.2) multi_json (1.12.2)
@ -499,6 +507,8 @@ GEM
websocket-extensions (>= 0.1.0) websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.3) websocket-extensions (0.1.3)
writeexcel (1.0.5) writeexcel (1.0.5)
xpath (3.2.0)
nokogiri (~> 1.8)
zendesk_api (1.16.0) zendesk_api (1.16.0)
faraday (~> 0.9) faraday (~> 0.9)
hashie (>= 3.5.2, < 4.0.0) hashie (>= 3.5.2, < 4.0.0)
@ -519,6 +529,7 @@ DEPENDENCIES
biz biz
browser browser
byebug byebug
capybara (~> 2.13)
clearbit clearbit
coffee-rails coffee-rails
coffee-script-source coffee-script-source

View file

@ -5,7 +5,8 @@ namespace :zammad do
namespace :test do namespace :test do
desc 'Stops all of Zammads services and exists the rake task with exit code 1' desc 'Stops all of Zammads services and exists the rake task with exit code 1'
task fail: %i[zammad:ci:test:stop] do task :fail, [:no_app] do |_task, args|
Rake::Task['zammad:ci:test:stop'].invoke if args[:no_app].blank?
abort('Abort further test processing') abort('Abort further test processing')
end end
end end

View file

@ -5,7 +5,7 @@ namespace :zammad do
namespace :test do namespace :test do
desc 'Stop of all Zammad services and cleans up the database(s)' desc 'Stop of all Zammad services and cleans up the database(s)'
task :stop do task :stop, [:no_app] do |_task, args|
ENV['RAILS_ENV'] ||= 'production' ENV['RAILS_ENV'] ||= 'production'
ENV['DISABLE_DATABASE_ENVIRONMENT_CHECK'] = 'true' ENV['DISABLE_DATABASE_ENVIRONMENT_CHECK'] = 'true'
@ -13,7 +13,7 @@ namespace :zammad do
# otherwise it will fallback to default (develop) # otherwise it will fallback to default (develop)
Rails.env = ENV['RAILS_ENV'] Rails.env = ENV['RAILS_ENV']
Rake::Task['zammad:ci:app:stop'].invoke Rake::Task['zammad:ci:app:stop'].invoke if args[:no_app].blank?
Rake::Task['db:drop:all'].invoke Rake::Task['db:drop:all'].invoke
next if !SearchIndexBackend.enabled? next if !SearchIndexBackend.enabled?

View file

@ -0,0 +1,25 @@
# This file registers a hook before each system test
# which logs in with/authenticates the master@example.com account.
# we need to make sure that Capybara is configured/started before
# this hook. Otherwise a login try is performed while the app/puma
# hasn't started yet.
require_relative './driven_by'
RSpec.configure do |config|
config.before(:each, type: :system) do |example|
# there is no way to authenticated in a not set up system
next if !example.metadata.fetch(:set_up, true)
# check if authentication should be performed
next if example.metadata.fetch(:authenticated, true).blank?
# authenticate
login(
username: 'master@example.com',
password: 'test',
)
end
end

View file

@ -0,0 +1,72 @@
module BrowserTestHelper
# Finds an element and clicks it - wrapped in one method.
#
# @example
# click('.js-channel .btn.email')
#
# click(:href, '#settings/branding')
#
def click(*args)
find(*args).click
end
# This is a wrapper around the Selenium::WebDriver::Wait class
# with additional methods.
# @see BrowserTestHelper::Waiter
#
# @example
# wait(5).until { ... }
#
# @example
# wait(5, interval: 0.5).until { ... }
#
def wait(seconds = Capybara.default_max_wait_time, **kargs)
wait_args = Hash(kargs).merge(timeout: seconds)
wait_handle = Selenium::WebDriver::Wait.new(wait_args)
Waiter.new(wait_handle)
end
class Waiter < SimpleDelegator
# This method is a derivation of Selenium::WebDriver::Wait#until
# which ignores Capybara::ElementNotFound exceptions raised
# in the given block.
#
# @example
# wait(5).until_exists { find('[data-title="example"]') }
#
def until_exists
self.until do
begin
yield
rescue Capybara::ElementNotFound # rubocop:disable Lint/HandleExceptions
end
end
rescue Selenium::WebDriver::Error::TimeOutError => e
# cleanup backtrace
e.set_backtrace(e.backtrace.drop(3))
raise e
end
# This method loops a given block until the result of it is constant.
#
# @example
# wait(5).until_constant { find('.total').text }
#
def until_constant
previous = nil
loop do
sleep __getobj__.instance_variable_get(:@interval)
latest = yield
break if latest == previous
previous = latest
end
end
end
end
RSpec.configure do |config|
config.include BrowserTestHelper, type: :system
end

View file

@ -0,0 +1,131 @@
module CommonActions
delegate :app_host, to: Capybara
# Performs a login with the given credentials and closes the clues (if present).
# The 'remember me' can optionally be checked.
#
# @example
# login(
# username: 'master@example.com',
# password: 'test',
# )
#
# @example
# login(
# username: 'master@example.com',
# password: 'test',
# remember_me: true,
# )
#
# return [nil]
def login(username:, password:, remember_me: false)
visit '/'
within('#login') do
fill_in 'username', with: username
fill_in 'password', with: password
# check via label because checkbox is hidden
click('.checkbox-replacement') if remember_me
# submit
click_button
end
wait(4).until_exists do
current_login
end
return if User.find_by(login: current_login).preferences[:intro]
find(:clues_close, wait: 3).in_fixed_postion.click
end
# Checks if the current session is logged in.
#
# @example
# logged_in?
# => true
#
# @return [true, false]
def logged_in?
current_login.present?
rescue Capybara::ElementNotFound
false
end
# Returns the login of the currently logged in user.
#
# @example
# current_login
# => 'master@example.com'
#
# @return [String] the login of the currently logged in user.
def current_login
find('.user-menu .user a')[:title]
end
# Logs out the currently logged in user.
#
# @example
# logout
#
def logout
visit('logout')
end
# Overwrites the Capybara::Session#visit method to allow SPA navigation.
# All routes not starting with `/` will be handled as SPA routes.
#
# @see Capybara::Session#visit
#
# @example
# visit('logout')
# => visited SPA route '/#logout'
#
# @example
# visit('/test/ui')
# => visited regular route '/test/ui'
#
def visit(route)
if !route.start_with?('/')
route = "/##{route}"
end
super(route)
end
# This method is equivalent to Capybara::RSpecMatchers#have_current_path
# but checks the SPA route instead of the actual path.
#
# @see Capybara::RSpecMatchers#have_current_path
#
# @example
# expect(page).to have_current_route('login')
# => checks for SPA route '/#login'
#
def have_current_route(route, **options)
if route.is_a?(String)
route = Regexp.new(Regexp.quote("/##{route}"))
end
options.reverse_merge!(wait: 0, url: true)
have_current_path("/##{route}", **options)
end
# This is a convenient wrapper method around #have_current_route
# which requires no previous `expect(page).to ` call.
#
# @example
# expect_current_routes('login')
# => checks for SPA route '/#login'
#
def expect_current_route(route, **options)
expect(page).to have_current_route(route, **options)
end
end
RSpec.configure do |config|
config.include CommonActions, type: :system
end

View file

@ -0,0 +1,4 @@
Capybara.configure do |config|
config.always_include_port = true
config.default_max_wait_time = 16
end

View file

@ -0,0 +1,34 @@
class Capybara::Node::Element
# This is an extension to each node to check if the element
# is moving or in a fixed position. This is especially helpful
# for animated elements that cause flanky tests.
# NOTE: In CI env a special sleep is performed between checks
# because animations can be slow.
#
# @param [Integer] checks the number of performed movement checks
#
# @example
# find('.clues-close').in_fixed_postion.click
# => waits till clues moved to final position and performs click afterwards
#
# @raise [RuntimeError] raised in case the element is
# still moving after max number of checks was passed
#
# @return [Capybara::Node::Element] the element/node
def in_fixed_postion(checks: 100)
previous = native.location
(checks + 1).times do |check|
raise "Element still moving after #{checks} checks" if check == checks
current = native.location
sleep 0.2 if ENV['CI']
break if previous == current
previous = current
end
self
end
end

View file

@ -0,0 +1,19 @@
require_relative './set_up'
RSpec.configure do |config|
config.before(:each, type: :system) do
# start a silenced Puma as application server
Capybara.server = :puma, { Silent: true, Host: '0.0.0.0' }
# set the Host from gather container IP for CI runs
if ENV['CI'].present?
ip_address = Socket.ip_address_list.detect(&:ipv4_private?).ip_address
host!("http://#{ip_address}")
end
# set custom Zammad driver (e.g. zammad_chrome) for special
# functionalities and CI requirements
driven_by("zammad_#{ENV.fetch('BROWSER', 'firefox')}".to_sym)
end
end

View file

@ -0,0 +1,21 @@
# This file defines custom Capybara selectors for DRYed specs.
Capybara.add_selector(:href) do
css { |href| %(a[href="#{href}"]) }
end
Capybara.add_selector(:active_content) do
css { |content_class| ['.content.active', content_class].compact.join(' ') }
end
Capybara.add_selector(:manage) do
css { 'a[href="#manage"]' }
end
Capybara.add_selector(:clues_close) do
css { '.js-modal--clue .js-close' }
end
Capybara.add_selector(:richtext) do
css { |name| "div[data-name=#{name}]" }
end

View file

@ -0,0 +1,49 @@
# This file registers the custom Zammad chrome and firefox drivers.
# The options check if a REMOTE_URL ENV is given and change the
# configurations accordingly.
Capybara.register_driver(:zammad_chrome) do |app|
# Turn on browser logs
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
loggingPrefs: {
browser: 'ALL'
},
)
options = {
browser: :chrome,
desired_capabilities: capabilities,
}
if ENV['REMOTE_URL'].present?
options[:browser] = :remote
options[:url] = ENV['REMOTE_URL']
end
Capybara::Selenium::Driver.new(app, options)
end
Capybara.register_driver(:zammad_firefox) do |app|
profile = Selenium::WebDriver::Firefox::Profile.new
profile['intl.locale.matchOS'] = false
profile['intl.accept_languages'] = 'en-US'
profile['general.useragent.locale'] = 'en-US'
capabilities = Selenium::WebDriver::Remote::Capabilities.firefox(
firefox_profile: profile,
)
options = {
browser: :firefox,
desired_capabilities: capabilities,
}
if ENV['REMOTE_URL'].present?
options[:browser] = :remote
options[:url] = ENV['REMOTE_URL']
end
Capybara::Selenium::Driver.new(app, options)
end

View file

@ -0,0 +1,24 @@
RSpec.configure do |config|
config.before(:each, type: :system) do |example|
# make sure system is in a fresh state
Cache.clear
Setting.reload
# check if system is already set up
next if Setting.get('system_init_done')
# check if system should get set up
next if !example.metadata.fetch(:set_up, true)
# perform setup via auto_wizard
Rake::Task['zammad:setup:auto_wizard'].execute
# skip intro/clues for created agents/admins
%w[master@example.com agent1@example.com].each do |login|
user = User.find_by(login: login)
user.preferences[:intro] = true
user.save!
end
end
end

View file

@ -0,0 +1,24 @@
RSpec.configure do |config|
config.around(:each, type: :system) do |example|
server_required = example.metadata.fetch(:websocket, true)
if server_required
websocket_server = Thread.new do
WebsocketServer.run(
p: ENV['WS_PORT'] || 6042,
b: '0.0.0.0',
s: false,
v: false,
d: false,
)
end
end
example.run
next if !server_required
Thread.kill(websocket_server)
end
end

View file

@ -0,0 +1,18 @@
require 'rails_helper'
RSpec.describe 'Authentication', type: :system do
scenario 'Login', authenticated: false do
login(
username: 'master@example.com',
password: 'test',
)
have_current_route 'dashboard'
end
scenario 'Logout' do
logout
have_current_route 'login', wait: 2
end
end

View file

@ -0,0 +1,24 @@
require 'rails_helper'
RSpec.describe 'Unauthenticated redirect', type: :system, authenticated: false do
scenario 'Sessions' do
visit 'system/sessions'
have_current_route 'login'
end
scenario 'Profile' do
visit 'profile/linked'
have_current_route 'login'
end
scenario 'Ticket' do
visit 'ticket/zoom/1'
have_current_route 'login'
end
scenario 'Not existing route' do
visit 'not_existing'
have_current_route 'not_existing'
end
end

View file

@ -0,0 +1,55 @@
require 'rails_helper'
RSpec.describe 'Richtext', type: :system do
before(:each) do
click(:href, '#current_user')
click(:href, '#layout_ref')
click(:href, '#layout_ref/richtext')
end
context 'Richtext' do
scenario 'Single line mode' do
element = find('#content .text-1')
element.send_keys(
'some test for browser ',
:enter,
'and some other for browser'
)
expect(element).to have_content('some test for browser and some other for browser')
end
scenario 'Multi line mode' do
element = find('#content .text-5')
element.send_keys(
'some test for browser ',
:enter,
'and some other for browser'
)
expect(element).to have_content("some test for browser \nand some other for browser")
end
end
context 'Regular text' do
scenario 'Multi line mode' do
element = find('#content .text-3')
element.send_keys(
'some test for browser ',
:enter,
'and some other for browser'
)
expect(element).to have_content("some test for browser \nand some other for browser")
end
end
end

View file

@ -0,0 +1,112 @@
require 'rails_helper'
RSpec.describe 'QUnit', type: :system, authenticated: false, set_up: true, websocket: false do
def q_unit_tests(test_name)
visit "/tests_#{test_name}"
yield if block_given?
expect(page).to have_css('.result', text: 'Tests completed')
expect(page).to have_css('.result .failed', text: '0')
end
def async_q_unit_tests(*args)
q_unit_tests(*args) do
wait(10, interval: 4).until_constant do
find('.total').text
end
end
end
scenario 'Core' do
async_q_unit_tests('core')
end
context 'UI' do
scenario 'Base' do
q_unit_tests('ui')
end
scenario 'Model' do
async_q_unit_tests('model')
end
scenario 'Model binding' do
q_unit_tests('model_binding')
end
scenario 'Model UI' do
if !ENV['CI']
skip("Can't run locally because of dependence of special Timezone")
end
q_unit_tests('model_ui')
end
scenario 'Ticket selector' do
q_unit_tests('ticket_selector')
end
end
context 'Form' do
scenario 'Base' do
async_q_unit_tests('form')
end
scenario 'Trim' do
q_unit_tests('form_trim')
end
scenario 'Find' do
q_unit_tests('form_find')
end
scenario 'Timer' do
q_unit_tests('form_timer')
end
scenario 'Extended' do
q_unit_tests('form_extended')
end
scenario 'Searchable select' do
q_unit_tests('form_searchable_select')
end
scenario 'Tree select' do
q_unit_tests('form_tree_select')
end
scenario 'Column select' do
q_unit_tests('form_column_select')
end
scenario 'Validation' do
q_unit_tests('form_validation')
end
end
context 'Table' do
scenario 'Base' do
q_unit_tests('table')
end
scenario 'Extended' do
q_unit_tests('table_extended')
end
scenario 'HTML utils' do
q_unit_tests('html_utils')
end
scenario 'Taskbar' do
q_unit_tests('taskbar')
end
end
end

View file

@ -0,0 +1,17 @@
require 'rails_helper'
RSpec.describe 'Auto wizard', type: :system, set_up: false do
scenario 'Automatic setup and login' do
FileUtils.ln(
Rails.root.join('contrib', 'auto_wizard_test.json'),
Rails.root.join('auto_wizard.json'),
force: true
)
visit 'getting_started/auto_wizard'
expect(current_login).to eq('master@example.com')
end
end

View file

@ -0,0 +1,109 @@
require 'rails_helper'
RSpec.describe 'Mail accounts', type: :system do
def perform_check
# getting started - auto mail
visit 'getting_started/channel'
click('.js-channel .btn.email')
yield
# wait for verification process to finish
expect(page).to have_css('.js-agent h2', text: 'Invite Colleagues', wait: 4.minutes)
have_current_route 'getting_started/agents'
end
def fill_in_credentials(account)
within('.js-intro') do
fill_in 'realname', with: account[:realname]
fill_in 'email', with: account[:email]
fill_in 'password', with: account[:password]
click_on('Connect')
end
end
scenario 'Auto detectable configurations' do
skip('NOTICE: This test is currently disabled because of collisions with other non Capybara browser tests')
accounts = (1..10).each_with_object([]) do |count, result|
next if !ENV["MAILBOX_AUTO#{count}"]
email, password = ENV["MAILBOX_AUTO#{count}"].split(':')
result.push(
realname: 'auto account',
email: email,
password: password,
)
end
if accounts.blank?
skip("NOTICE: Need min. MAILBOX_AUTO1 as ENV variable like export MAILBOX_AUTO1='nicole.braun2015@gmail.com:somepass'")
end
accounts.each do |account|
perform_check do
fill_in_credentials(account)
end
end
end
scenario 'Manual configurations' do
accounts = (1..10).each_with_object([]) do |count, result|
next if !ENV["MAILBOX_MANUAL#{count}"]
email, password, inbound, outbound = ENV["MAILBOX_MANUAL#{count}"].split(':')
result.push(
realname: 'manual account',
email: email,
password: password,
inbound: {
'options::host' => inbound,
},
outbound: {
'options::host' => outbound,
},
)
end
if accounts.blank?
skip("NOTICE: Need min. MAILBOX_MANUAL1 as ENV variable like export MAILBOX_MANUAL1='nicole.bauer2015@yahoo.de:somepass:imap.mail.yahoo.com:smtp.mail.yahoo.com'")
end
accounts.each do |account|
perform_check do
fill_in_credentials(account)
within('.js-inbound') do
expect(page).to have_css('h2', text: 'inbound', wait: 4.minutes)
expect(page).to have_css('body', text: 'manual')
fill_in 'options::host', with: account[:inbound]['options::host']
click_on('Connect')
end
within('.js-outbound') do
expect(page).to have_css('h2', text: 'outbound', wait: 4.minutes)
select('SMTP - configure your own outgoing SMTP settings', from: 'adapter')
fill_in 'options::host', with: account[:outbound]['options::host']
click_on('Connect')
end
end
end
end
end

View file

@ -0,0 +1,113 @@
require 'rails_helper'
RSpec.describe 'System setup process', type: :system, set_up: false do
def fqdn
match_data = %r{://(.+?)(:.+?|/.+?|)$}.match(app_host)
return match_data.captures.first if match_data.present?
raise "Unable to get fqdn based on #{app_host}"
end
scenario 'Setting up a new system', authenticated: false do
if !ENV['MAILBOX_INIT']
skip("NOTICE: Need MAILBOX_INIT as ENV variable like export MAILBOX_INIT='unittest01@znuny.com:somepass'")
end
mailbox_user = ENV['MAILBOX_INIT'].split(':')[0]
mailbox_password = ENV['MAILBOX_INIT'].split(':')[1]
visit '/'
expect(page).to have_css('.setup.wizard', text: 'Setup new System')
# choose setup (over migration)
click_on('Setup new System')
# admin user form
expect(page).to have_css('.js-admin h2', text: 'Administrator Account')
within('.js-admin') do
fill_in 'firstname', with: 'Test Master'
fill_in 'lastname', with: 'Agent'
fill_in 'email', with: 'master@example.com'
fill_in 'password', with: 'test1234äöüß'
fill_in 'password_confirm', with: 'test1234äöüß'
click_on('Create')
end
# configure Organization
expect(page).to have_css('.js-base h2', text: 'Organization')
within('.js-base') do
fill_in 'organization', with: 'Some Organization'
# fill in wrong URL
fill_in 'url', with: 'some host'
click_on('Next')
expect(page).to have_css('.alert', text: 'A URL looks like')
# fill in valild/current URL
fill_in 'url', with: app_host
click_on('Next')
end
# configure Email Notification
expect(page).to have_css('.js-outbound h2', text: 'Email Notification')
have_current_route 'getting_started/email_notification'
click_on('Continue')
# create email account
expect(page).to have_css('.js-channel h2', text: 'Connect Channels')
have_current_route 'getting_started/channel'
click('.js-channel .btn.email')
within('.js-intro') do
fill_in 'realname', with: 'Some Realname'
fill_in 'email', with: mailbox_user
fill_in 'password', with: mailbox_password
click_on('Connect')
end
# wait for verification process to start
expect(page).to have_css('body', text: 'Verify sending and receiving', wait: 20)
# wait for verification process to finish
expect(page).to have_css('.js-agent h2', text: 'Invite Colleagues', wait: 2.minutes)
have_current_route 'getting_started/agents'
# invite agent1
within('.js-agent') do
fill_in 'firstname', with: 'Agent 1'
fill_in 'lastname', with: 'Test'
fill_in 'email', with: 'agent12@example.com'
click_on('Invite')
end
expect(page).to have_css('body', text: 'Invitation sent!')
# expect to still be on the same page
have_current_route 'getting_started/agents'
within('.js-agent') do
click_on('Continue')
end
# expect Dashboard of a fresh system
expect(page).to have_css('body', text: 'My Stats')
have_current_route 'clues'
find(:clues_close, wait: 4).in_fixed_postion.click
# verify organization and fqdn
click(:manage)
within(:active_content) do
click(:href, '#settings/branding')
expect(page).to have_field('organization', with: 'Some Organization')
click(:href, '#settings/system')
expect(page).to have_field('fqdn', with: fqdn)
end
end
end