diff --git a/.gitignore b/.gitignore index d70050eb20..42bd720148 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,4 @@ shutdown.sh cscope* docs/_build/* deps +ghostdriver.log diff --git a/requirements.txt b/requirements.txt index 58106c562f..cf15b49d32 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,3 +4,5 @@ six Image Django==1.5.8 Djblets==0.6.14 +selenium==2.42.1 +requests==2.3.0 diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000000..324d47746c --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1,14 @@ +# Copyright 2014 seahub authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from common import common diff --git a/tests/casper/demo.js b/tests/casper/demo.js deleted file mode 100644 index 762093aa06..0000000000 --- a/tests/casper/demo.js +++ /dev/null @@ -1,49 +0,0 @@ -casper.test.begin('Add Library and remove library well', 7, function suite(test) { - //CSS3 selector since we running under phantomjs which is using WebKit inside - //document.querySelector - - casper.start('http://127.0.0.1:8000/accounts/login', function() { - test.assertExists('form', 'login form is found'); - this.fill('form', { - username: 'test@test.com', - password: 'testtest' - }, true); - }); - casper.then(function() { - test.assertUrlMatch(/home\/my\/$/, 'redirect url is at home page'); - this.click('#repo-create'); - test.assertExists('form#repo-create-form', 'repo create form is found'); - this.fill('form#repo-create-form', { - repo_name: 'Test Repo', - repo_desc: 'Test Desc' - }, false); - this.click('form#repo-create-form input.submit'); - this.waitWhileVisible('form#repo-create-form'); - this.reload(); - }); - casper.wait(500, function() { - }); - casper.then(function() { - test.assertExists('table.repo-list tr:nth-child(2)'); - test.assertSelectorHasText('table.repo-list tr:nth-child(2) td:nth-child(2) a', 'Test Repo'); - this.mouse.move('table.repo-list tr:nth-child(2) td:last-child div'); - this.captureSelector('table.png', 'table.repo-list'); - //TODO fix this - //this.waitUntilVisible('table.repo-list tr:nth-child(2) td:last-child span:nth-child(2)'); - this.click('table.repo-list tr:nth-child(2) td:last-child span:nth-child(2)'); - test.assertExists('table.repo-list tr:nth-child(2) .op-confirm'); - this.click('table.repo-list tr:nth-child(2) .op-confirm button.yes'); - this.waitWhileVisible('table.repo-list tr:nth-child(2) .op-confirm'); - this.reload(); - }); - casper.wait(500, function() { - }); - casper.then(function() { - test.assertSelectorDoesntHaveText('table.repo-list tr:nth-child(2) td:nth-child(2) a', 'Test Repo'); - this.click('a#logout'); - }); - casper.run(function() { - test.done(); - }); - -}); diff --git a/tests/casper/login.js b/tests/casper/login.js deleted file mode 100644 index 29e3b1e186..0000000000 --- a/tests/casper/login.js +++ /dev/null @@ -1,23 +0,0 @@ -casper.test.begin('Log in and out function well', 5, function suite(test) { - casper.start('http://127.0.0.1:8000/accounts/login', function() { - test.assertExists('form', 'login form is found'); - this.fill('form', { - username: 'test@test.com', - password: 'testtest' - }, true); - }); - // redirect - casper.then(function() { - test.assertUrlMatch(/home\/my\/$/, 'redirect url is at home page'); - test.assertNotVisible('#user-info-popup'); - this.click('#my-info'); - test.assertVisible('#user-info-popup'); - this.click('a#logout'); - }); - // logout - casper.run(function() { - test.assertUrlMatch(/accounts\/logout\/$/, 'redirect url is at logout page'); - test.done(); - }); - -}); diff --git a/tests/common/__init__.py b/tests/common/__init__.py new file mode 100644 index 0000000000..d027359e60 --- /dev/null +++ b/tests/common/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2014 seahub authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/tests/common/common.py b/tests/common/common.py new file mode 100644 index 0000000000..96471461eb --- /dev/null +++ b/tests/common/common.py @@ -0,0 +1,24 @@ +import os +if os.getenv('CI_BASE_URL'): + BASE_URL = os.getenv('CI_BASE_URL') +else: + BASE_URL = u'http://127.0.0.1:8000' + +if os.getenv('CI_USERNAME'): + USERNAME = os.getenv('CI_USERNAME') +else: + USERNAME = u'test@test.com' + +if os.getenv('CI_PASSWORD'): + PASSWORD = os.getenv('CI_PASSWORD') +else: + PASSWORD = u'testtest' + +def getBaseUrl(): + return BASE_URL + +def getUserName(): + return USERNAME + +def getPassword(): + return PASSWORD diff --git a/tests/install-deps.sh b/tests/install-deps.sh index 4dddcfedda..e542fd14ce 100755 --- a/tests/install-deps.sh +++ b/tests/install-deps.sh @@ -13,10 +13,3 @@ cd "$SEAHUB_SRCDIR" curl -L -o /tmp/phantomjs.tar.bz2 https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-1.9.7-linux-x86_64.tar.bz2 tar -C /tmp -xf /tmp/phantomjs.tar.bz2 sudo install -m 755 /tmp/phantomjs-1.9.7-linux-x86_64/bin/phantomjs /usr/bin/phantomjs - -# install casperjs -curl -L -o /tmp/casperjs.tar.gz https://github.com/n1k0/casperjs/archive/1.1-beta3.tar.gz -tar -C /tmp -xzf /tmp/casperjs.tar.gz -mkdir -p deps -mv /tmp/casperjs-1.1-beta3 deps/casperjs -sudo ln -s `readlink -f deps/casperjs/bin/casperjs` /usr/bin diff --git a/tests/integration/__init__.py b/tests/integration/__init__.py new file mode 100644 index 0000000000..d21c20111c --- /dev/null +++ b/tests/integration/__init__.py @@ -0,0 +1,36 @@ +# Copyright 2014 seahub authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from common import common +from selenium import webdriver +from selenium.webdriver.common.keys import Keys + +LOGIN_URL = common.getBaseUrl() + u'/accounts/login/' +HOME_URL = common.getBaseUrl() + u'/home/my/' +LOGOUT_URL = common.getBaseUrl() + u'/accounts/logout/' + +USERNAME = common.getUserName() +PASSWORD = common.getPassword() + +def getLoggedInstance(): + browser = webdriver.PhantomJS() + browser.get(LOGIN_URL) + username_input = browser.find_element_by_name('username') + password_input = browser.find_element_by_name('password') + username_input.send_keys(USERNAME) + password_input.send_keys(PASSWORD) + password_input.send_keys(Keys.RETURN) + if (browser.current_url != HOME_URL): + browser.quit() + return None + return browser diff --git a/tests/integration/login.py b/tests/integration/login.py new file mode 100644 index 0000000000..3153e4bef9 --- /dev/null +++ b/tests/integration/login.py @@ -0,0 +1,22 @@ +import integration as common +import unittest + +class LoginTestCase(unittest.TestCase): + + def setUp(self): + self.browser = common.getLoggedInstance() + self.assertIsNotNone(self.browser) + self.addCleanup(self.browser.quit) + + def testLogin(self): + self.assertRegexpMatches(self.browser.current_url, common.HOME_URL) + + def testLogout(self): + myinfo_bar = self.browser.find_element_by_css_selector('#my-info') + logout_input = self.browser.find_element_by_css_selector('a#logout') + myinfo_bar.click() + logout_input.click() + self.assertRegexpMatches(self.browser.current_url, common.LOGOUT_URL) + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/tests/integration_api/__init__.py b/tests/integration_api/__init__.py new file mode 100644 index 0000000000..ac7867a5de --- /dev/null +++ b/tests/integration_api/__init__.py @@ -0,0 +1,40 @@ +# Copyright 2014 seahub authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from common import common +import requests, re + +PING_URL = common.getBaseUrl() + u'/api2/ping/' +TOKEN_URL = common.getBaseUrl() + u'/api2/auth-token/' +AUTH_PING_URL = common.getBaseUrl() + u'/api2/auth/ping/' + +USERNAME = common.getUserName() +PASSWORD = common.getPassword() +META_AUTH = {'username': USERNAME, 'password': PASSWORD} + +def getAuthToken(): + res = requests.post(TOKEN_URL, data=META_AUTH) + if (res.status_code != 200): + return None + token = res.json()['token'] + if (re.match(r'(\w){40,40}', token) == None): + return None + return token + +def getAuthedInstance(): + token = getAuthToken() + if (token == None): + return None + s = requests.Session() + s.headers.update({'Authorization': 'Token ' + token}) + return s diff --git a/tests/integration_api/authping.py b/tests/integration_api/authping.py new file mode 100644 index 0000000000..88ec07fca5 --- /dev/null +++ b/tests/integration_api/authping.py @@ -0,0 +1,16 @@ +import integration_api as common +import unittest + +class AuthPingApiTestCase(unittest.TestCase): + + def setUp(self): + self.requests = common.getAuthedInstance() + self.assertIsNotNone(self.requests) + + def testAuthPingApi(self): + res = self.requests.get(common.AUTH_PING_URL) + self.assertEqual(res.status_code, 200) + self.assertRegexpMatches(res.text, u'"pong"') + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/tests/integration_api/ping.py b/tests/integration_api/ping.py new file mode 100644 index 0000000000..5b9d0156f3 --- /dev/null +++ b/tests/integration_api/ping.py @@ -0,0 +1,15 @@ +import integration_api as common +import requests +import unittest + +class PingApiTestCase(unittest.TestCase): + + def setUp(self): + self.res = requests.get(common.PING_URL) + + def testPingApi(self): + self.assertEqual(self.res.status_code, 200) + self.assertRegexpMatches(self.res.text, u'"pong"') + +if __name__ == '__main__': + unittest.main(verbosity=2) diff --git a/tests/integration_suite.py b/tests/integration_suite.py new file mode 100644 index 0000000000..c809302f04 --- /dev/null +++ b/tests/integration_suite.py @@ -0,0 +1,21 @@ +import unittest +import sys + +def suite(): + from integration.login import LoginTestCase + integration_suite = unittest.TestSuite((\ + unittest.makeSuite(LoginTestCase), + )) + + from integration_api.ping import PingApiTestCase + from integration_api.authping import AuthPingApiTestCase + integration_api_suite = unittest.TestSuite((\ + unittest.makeSuite(PingApiTestCase), + unittest.makeSuite(AuthPingApiTestCase), + )) + + return unittest.TestSuite([integration_api_suite, integration_suite]) + +if __name__ == "__main__": + result = unittest.TextTestRunner(verbosity=2).run(suite()) + sys.exit(not result.wasSuccessful()) diff --git a/tests/seahubtests.sh b/tests/seahubtests.sh index a1a4e2ac98..1214004eac 100755 --- a/tests/seahubtests.sh +++ b/tests/seahubtests.sh @@ -1,4 +1,8 @@ #!/bin/bash +: ${PYTHON=python} +# Change these if you run on local machine +export CI_USERNAME="test@test.com" +export CI_PASSWORD="testtest" # If you run this script on your local machine, you must set CCNET_CONF_DIR # and SEAFILE_CONF_DIR like this: @@ -23,17 +27,18 @@ function init() { ############################### # create database and a new user ############################### - ./manage.py syncdb - python -c "import ccnet; pool = ccnet.ClientPool('${CCNET_CONF_DIR}'); ccnet_threaded_rpc = ccnet.CcnetThreadedRpcClient(pool, req_pool=True); ccnet_threaded_rpc.add_emailuser('test@test.com', 'testtest', 1, 1);" + $PYTHON ./manage.py syncdb + $PYTHON -c "import ccnet; pool = ccnet.ClientPool('${CCNET_CONF_DIR}'); ccnet_threaded_rpc = ccnet.CcnetThreadedRpcClient(pool, req_pool=True); ccnet_threaded_rpc.add_emailuser('${CI_USERNAME}', '${CI_PASSWORD}', 1, 1);" } function start_seahub() { - ./manage.py runserver 1>/dev/null & + $PYTHON ./manage.py runserver 1>/dev/null & + sleep 5 } function run_tests() { - pushd tests/casper - casperjs test . + pushd tests + $PYTHON integration_suite.py popd }