summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorPliable Pixels <pliablepixels@users.noreply.github.com>2019-03-10 17:54:05 -0400
committerGitHub <noreply@github.com>2019-03-10 17:54:05 -0400
commit11cb0130fe95391805e07468191f40f10b7326d2 (patch)
tree47c4dbacbd3c32ba2c3d5ec9849e618c3e7632f5 /tests
parent05361719849c59d9e0a964b83d42696c783aacc7 (diff)
parent7c173fff14dd7278a79735a73ecfd71db4814fd5 (diff)
Merge pull request #790 from pliablepixels/appium
Appium
Diffstat (limited to 'tests')
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/README.TXT9
-rw-r--r--tests/chromedriver/.gitignore1
-rw-r--r--tests/chromedriver/README.TXT2
-rwxr-xr-xtests/startappium.sh2
-rw-r--r--tests/testcases/.gitignore3
-rw-r--r--tests/testcases/README.TXT1
-rw-r--r--tests/testcases/__init__.py0
-rw-r--r--tests/testcases/app.py25
-rw-r--r--tests/testcases/common.py113
-rw-r--r--tests/testcases/montage.py20
-rw-r--r--tests/testcases/test.py74
-rw-r--r--tests/testcases/wizard.py56
13 files changed, 307 insertions, 0 deletions
diff --git a/tests/.gitignore b/tests/.gitignore
new file mode 100644
index 00000000..fbfa7d1b
--- /dev/null
+++ b/tests/.gitignore
@@ -0,0 +1 @@
+**/*.pyc
diff --git a/tests/README.TXT b/tests/README.TXT
new file mode 100644
index 00000000..70cfeeba
--- /dev/null
+++ b/tests/README.TXT
@@ -0,0 +1,9 @@
+Appium install: http://appium.io/docs/en/about-appium/getting-started/
+Python Appium client install: https://github.com/appium/python-client
+
+I currently test on an Android 7.1.1 emulator. Change test.py config as needed
+
+./startappium.sh
+
+
+
diff --git a/tests/chromedriver/.gitignore b/tests/chromedriver/.gitignore
new file mode 100644
index 00000000..2004ae02
--- /dev/null
+++ b/tests/chromedriver/.gitignore
@@ -0,0 +1 @@
+chromedriver
diff --git a/tests/chromedriver/README.TXT b/tests/chromedriver/README.TXT
new file mode 100644
index 00000000..1c78b3b2
--- /dev/null
+++ b/tests/chromedriver/README.TXT
@@ -0,0 +1,2 @@
+Download the chrome driver version corresponding to the chrome browser version you are testing with
+from http://chromedriver.chromium.org/downloads and save it here as 'chromedriver'
diff --git a/tests/startappium.sh b/tests/startappium.sh
new file mode 100755
index 00000000..257dbfff
--- /dev/null
+++ b/tests/startappium.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+appium --chromedriver-executable ./chromedriver/chromedriver
diff --git a/tests/testcases/.gitignore b/tests/testcases/.gitignore
new file mode 100644
index 00000000..5f62c8e9
--- /dev/null
+++ b/tests/testcases/.gitignore
@@ -0,0 +1,3 @@
+screenshots
+*.png
+*.apk
diff --git a/tests/testcases/README.TXT b/tests/testcases/README.TXT
new file mode 100644
index 00000000..7cae6770
--- /dev/null
+++ b/tests/testcases/README.TXT
@@ -0,0 +1 @@
+python ./test.py
diff --git a/tests/testcases/__init__.py b/tests/testcases/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/tests/testcases/__init__.py
diff --git a/tests/testcases/app.py b/tests/testcases/app.py
new file mode 100644
index 00000000..b76f1edd
--- /dev/null
+++ b/tests/testcases/app.py
@@ -0,0 +1,25 @@
+'''
+App level functions for view interaction
+'''
+
+
+
+import common as c
+
+
+# tap global menu directly by invoking its controller JS
+# seems reliable
+def tap_menu_js():
+ c.log ('Tapping menu')
+ c.driver.execute_script("angular.element(document.getElementById('testaut-menu-controller')).scope().openMenu();")
+
+# bah, in some cases this won't work, when the menu is open,
+# there are two left items
+# so I'm probably not going to use this
+def tap_menu():
+ c.log ('Tapping menu')
+ element = c.driver.find_element_by_id('testaut_app_menu')
+ element = element.find_element_by_class_name('left-buttons')
+ element = element.find_element_by_tag_name('button')
+ element.click()
+
diff --git a/tests/testcases/common.py b/tests/testcases/common.py
new file mode 100644
index 00000000..6b3b2571
--- /dev/null
+++ b/tests/testcases/common.py
@@ -0,0 +1,113 @@
+'''
+Common functions used by test cases
+
+'''
+
+
+from time import sleep,strftime
+import os
+from selenium.webdriver.common.touch_actions import TouchActions
+from selenium.webdriver.common.action_chains import ActionChains
+from selenium.webdriver.support.ui import WebDriverWait
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support import expected_conditions as EC
+
+
+
+# global pointer to chrome driver
+driver = None
+
+# keeps incrementing by 1 for screenshots saved
+image_counter = 1
+
+# global ZM portal data
+testConfig = {
+ 'portal':None,
+ 'user':None,
+ 'password':None,
+ 'use_auth':False,
+ 'use_zm_auth':False,
+ 'use_basic_auth':False,
+ 'basic_user':None,
+ 'basic_password':None,
+ 'screenshot_dir':'./screenshots'
+
+}
+
+def log(s):
+ print (strftime("%H:%M:%S") + ": " + s)
+
+
+# central function to save a screenshot
+def take_screenshot(id,fname):
+ global image_counter
+ log ('Taking screenshot')
+ if fname == None:
+ fname = id+'-image.png'
+ fname = '{:03d}-'.format(image_counter)+fname
+ driver.get_screenshot_as_file(testConfig['screenshot_dir']+'/'+fname)
+ log ('Screenshot stored in '+fname)
+ image_counter = image_counter + 1
+
+
+# makes sure we can see the element to avoid out of view issues
+def _goto_element(e):
+ driver.execute_script("arguments[0].scrollIntoView();", e)
+
+# waits for an element to load
+# allows you to also specify if you want a screenshot after it comes in
+def _wait_for_id(id=id,dur=30, save_screenshot=False, save_screenshot_file=None):
+ log ('Waiting for '+id+'...')
+ WebDriverWait(driver, dur).until(EC.presence_of_element_located((By.ID, id)))
+ if save_screenshot:
+ take_screenshot(id,save_screenshot_file)
+
+
+def get_element_attributes(id=id, wait_dur=30, save_screenshot=False, save_screenshot_file=None):
+ _wait_for_id(id=id, save_screenshot=save_screenshot, save_screenshot_file = save_screenshot_file)
+ element = driver.find_element_by_id(id)
+ return element
+
+# handle ion-alerts. Only single button for now. May extend later if I need
+def click_popup(save_screenshot=False, save_screenshot_file=None):
+ log ('Waiting for popup...')
+ WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'popup-buttons')))
+ if save_screenshot:
+ take_screenshot(None,'wizard-save-results.png')
+ element = driver.find_element_by_class_name('popup-buttons')
+ element = element.find_element_by_tag_name('button')
+ element.click()
+
+
+# handle ion-toggle
+def tap_toggle(id, save_screenshot=False, save_screenshot_file=None):
+ _wait_for_id(id=id, save_screenshot=save_screenshot, save_screenshot_file = save_screenshot_file)
+ element = driver.find_element_by_id(id)
+ _goto_element(element)
+ element = element.find_element_by_tag_name('label')
+ element.click()
+
+# generates click event for any web element id
+def click_item(id=id, save_screenshot=False, save_screenshot_file=None):
+ _wait_for_id(id=id, save_screenshot=save_screenshot, save_screenshot_file = save_screenshot_file)
+ element = driver.find_element_by_id(id)
+ _goto_element(element)
+ element.click()
+ #sleep(wait)
+
+# generated double click event for any web element id
+def dbl_click_item(id=id, save_screenshot=False, save_screenshot_file=None):
+ _wait_for_id(id=id, save_screenshot=save_screenshot, save_screenshot_file = save_screenshot_file)
+ element = driver.find_element_by_id(id)
+ actions = TouchActions(driver)
+ actions.double_tap(element)
+ actions.perform()
+
+# handles text input
+def input_item(id=id,txt="you forgot to specify text", save_screenshot=False, save_screenshot_file=None):
+ _wait_for_id(id=id, save_screenshot=save_screenshot, save_screenshot_file = save_screenshot_file)
+ element = driver.find_element_by_id(id)
+ _goto_element(element)
+ element.send_keys(txt)
+ driver.hide_keyboard()
+ #sleep(wait)
diff --git a/tests/testcases/montage.py b/tests/testcases/montage.py
new file mode 100644
index 00000000..2b3f2c4d
--- /dev/null
+++ b/tests/testcases/montage.py
@@ -0,0 +1,20 @@
+'''
+Validates Montage view
+'''
+
+import common as c
+from time import sleep
+import app
+
+def run_tests(self):
+ app.tap_menu_js()
+ c.log ('Validating montage')
+ c.click_item('testaut_menu_montage')
+ c.click_item('img-1')
+ sleep(4)
+ c.take_screenshot(None,'montage-singleview.png')
+ c.dbl_click_item('singlemonitor')
+
+
+
+
diff --git a/tests/testcases/test.py b/tests/testcases/test.py
new file mode 100644
index 00000000..fff7c607
--- /dev/null
+++ b/tests/testcases/test.py
@@ -0,0 +1,74 @@
+'''
+Main zmNinja test driver
+Invokes other test cases
+'''
+
+import unittest
+from time import sleep
+from appium import webdriver
+import os
+import glob
+
+import common as c
+import wizard
+import app
+import montage
+
+class ZmninjaAndroidTests(unittest.TestCase):
+ 'Class to run tests against zmNinja'
+
+ def setUp(self):
+ c.log ('Setting up....')
+
+ desired_caps = {
+ 'platformName': 'Android',
+ 'automationName': 'UiAutomator2',
+ 'platformVersion': '7.1.1',
+ 'deviceName': 'Pixel',
+ 'nativeWebTap': True,
+ 'nativeWebScreenshot': True, # important, for screenshots
+ 'autoAcceptAlerts': True,
+ 'autoGrantPermissions': True,
+ 'appPackage': 'com.pliablepixels.zmninja_pro',
+ 'appActivity': 'com.pliablepixels.zmninja_pro.MainActivity'
+ }
+ # Returns abs path relative to this file and not cwd
+ desired_caps['app'] = os.path.abspath(os.path.join(os.path.dirname(__file__),'./zmNinja.apk'))
+ c.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
+ c.driver.switch_to.context('WEBVIEW_com.pliablepixels.zmninja_pro')
+
+
+ def tearDown(self):
+ c.log ('Test complete')
+ c.driver.quit()
+
+
+ def wait_for_app_start(self):
+ c.log ('Waiting for app to start')
+ #sleep (5)
+
+ def test_app(self):
+ c.testConfig['portal'] = 'https://demo.zoneminder.com/zm'
+ c.testConfig['user'] = 'zmuser'
+ c.testConfig['password'] = 'zmpass'
+ c.testConfig['use_auth'] = True
+ c.testConfig['use_zm_auth'] = True
+ c.testConfig['use_basic_auth'] = False
+ c.testConfig['screenshot_dir'] = './screenshots'
+
+ if not os.path.exists(c.testConfig['screenshot_dir']):
+ os.makedirs(c.testConfig['screenshot_dir'])
+ files = glob.glob(c.testConfig['screenshot_dir']+'/*')
+ for f in files:
+ os.remove(f)
+
+ self.wait_for_app_start()
+ wizard.run_tests(self)
+ montage.run_tests(self)
+
+
+
+#---START OF SCRIPT
+if __name__ == '__main__':
+ suite = unittest.TestLoader().loadTestsFromTestCase(ZmninjaAndroidTests)
+ unittest.TextTestRunner(verbosity=2).run(suite)
diff --git a/tests/testcases/wizard.py b/tests/testcases/wizard.py
new file mode 100644
index 00000000..cf73deab
--- /dev/null
+++ b/tests/testcases/wizard.py
@@ -0,0 +1,56 @@
+'''
+Validates Wizard view
+'''
+
+import common as c
+import app
+from time import sleep
+
+def run_tests(self):
+
+ success_color = 'rgba(22, 160, 133, 1)'
+ fail_color = 'rgba(231, 76, 60, 1)'
+
+ c.log ('Validating wizard test case')
+ c.click_item('testaut_wizard_button')
+
+ c.log ('Entering portal text')
+ c.input_item('testaut_portal_input', c.testConfig['portal'])
+
+ c.click_item('testaut_wiz1_next_button')
+
+ c.log ('Setting up auth parameters')
+ # fill in auth settings based on how you configured the server
+ if c.testConfig['use_auth']:
+ c.tap_toggle('testaut_useauth_toggle')
+ if c.testConfig['use_zm_auth']:
+ c.tap_toggle('testaut_usezmauth_toggle')
+ c.input_item('testaut_zmauthusername_input', c.testConfig['user'])
+ c.input_item('testaut_zmauthpassword_input', c.testConfig['password'])
+ if c.testConfig['use_basic_auth']:
+ c.tap_toggle('testaut_usebasicauth_toggle')
+ c.input_item('testaut_basicauthusername_input', c.testConfig['user'])
+ c.input_item('testaut_basicauthpassword_input', c.testConfig['password'])
+ c.click_item('testaut_wiz2_next_button')
+
+ # Now check wizard results
+ portal_ok = c.get_element_attributes('testaut_wizard_portal_results')
+ portal_color = portal_ok.value_of_css_property('color')
+ self.assertEqual(portal_color,success_color)
+ # don't do this before assert. If portal fails, api won't show
+ api_ok = c.get_element_attributes('testaut_wizard_api_results')
+ api_color = api_ok.value_of_css_property('color')
+ self.assertEqual(api_color,success_color)
+
+ # Wait for bit for cgi-bin. Don't really care, but hey if we catch it, cool
+ sleep(3)
+ c.take_screenshot(None,'wizard-detection-results.png')
+
+ c.click_item('testaut_wizard_goto_login')
+ c.click_item('testaut_settings_save')
+
+
+ # discard the popup and get to sane state
+ c.click_popup(save_screenshot=True, save_screenshot_file='./screenshots/wizard-save-report.png')
+ sleep(3)
+ app.tap_menu_js()