Merge branch 'develop' of https://github.com/status-im/open-bounty into 193-hide-myself

This commit is contained in:
Ivan Grishaev 2018-02-08 12:54:18 +03:00
commit 596e6c9439
11 changed files with 291 additions and 102 deletions

View File

@ -12,16 +12,17 @@
:on-change #(reset! val-ratom (-> % .-target .-value))})]))
(defn dropdown [props title val-ratom items]
"If val-ratom is set, preselect it in the dropdown.
Otherwise, prepend title as a disabled option."
(fn []
(if (= 1 (count items))
(reset! val-ratom (first items)))
[:select.ui.basic.selection.dropdown
(merge props {:on-change
#(reset! val-ratom (-> % .-target .-value))})
(doall (for [item items]
^{:key item} [:option
{:value item}
item]))]))
#(reset! val-ratom (-> % .-target .-value))
:default-value (or @val-ratom title)})
(for [item items]
^{:key item} [:option {:value item
:disabled (= item title)}
item])]))
(defn moment-timestamp [time]
(let [now (.now js/Date.)

View File

@ -3,6 +3,7 @@
[commiteth.common :refer [input dropdown]]
[reagent.core :as r]
[reagent.crypt :as crypt]
[clojure.string :as str]
[cljs-web3.eth :as web3-eth]))
(defn update-address-page []
@ -21,13 +22,25 @@
[:p "Insert your Ethereum address in hex format."]
[:div.field
(if-not (empty? web3-accounts)
[dropdown {:class "address-input"} "Select address"
address
(vec
(for [acc web3-accounts]
acc))]
; Add value of address if it's missing from items list.
; If address is empty, add title
(let [accounts (map str/lower-case web3-accounts)
addr @address
title "Select address"
addr-not-in-web3? (and addr (as-> web3-accounts acc
(map str/lower-case acc)
(set acc)
(contains? acc addr)
(not acc)))
items (cond->> web3-accounts
addr-not-in-web3? (into [addr])
(not addr) (into [title]))]
[dropdown {:class "address-input"}
title
address
items])
[:div.ui.input.address-input
[input address {:placeholder "0x0000000000000000000000000000000000000000"
[input address {:placeholder "0x0000000000000000000000000000000000000000"
:auto-complete "off"
:auto-correct "off"
:spell-check "false"

View File

@ -516,7 +516,10 @@ label[for="input-hidden"] {
margin: 14.5px 0;
}
input[type=range]:focus {
outline: none;
outline: 0;
}
input[type=range]::-moz-focus-outer {
border: 0;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
@ -643,11 +646,6 @@ label[for="input-hidden"] {
outline: none;
}
input {
background: green;
transform: scale(1.3);
}
input:hover {
cursor: pointer;
}

View File

@ -15,3 +15,4 @@ class BasePageObject(object):
@property
def time_now(self):
return datetime.now().strftime('%-m%-d%-H%-M%-S')

View File

@ -2,6 +2,10 @@ import time, pytest
from pages.base_element import *
from pages.base_page import BasePageObject
from tests import test_data
from git import Repo
import os
import shutil
import logging
class EmailEditbox(BaseEditBox):
@ -106,7 +110,46 @@ class ContractBody(BaseText):
super(ContractBody, self).__init__(driver)
self.locator = self.Locator.xpath_selector("//tbody//p[contains(text(), "
"'Current balance: 0.000000 ETH')]")
class IssueId(BaseText):
def __init__(self, driver):
super(IssueId, self).__init__(driver)
self.locator = self.Locator.css_selector(".gh-header-number")
class ForkButton(BaseButton):
def __init__(self, driver):
super(ForkButton, self).__init__(driver)
self.locator = self.Locator.css_selector("[href='#fork-destination-box']")
class HeaderInForkPopup(BaseText):
def __init__(self, driver):
super(HeaderInForkPopup, self).__init__(driver)
self.locator = self.Locator.css_selector("#facebox-header")
class UserAccountInForkPopup(BaseButton):
def __init__(self, driver):
super(UserAccountInForkPopup, self).__init__(driver)
self.locator = self.Locator.css_selector("[value=%s]"%test_data.config['DEV']['gh_username'])
class ForkedRepoText(BaseText):
def __init__(self, driver):
super(ForkedRepoText, self).__init__(driver)
self.locator = self.Locator.css_selector(".commit-tease")
class DeleteRepo(BaseButton):
def __init__(self, driver):
super(DeleteRepo, self).__init__(driver)
self.locator = self.Locator.xpath_selector("//button[text()[contains(.,' Delete this repository')]]")
class RepoNameBoxInPopup(BaseEditBox):
def __init__(self, driver):
super(RepoNameBoxInPopup, self).__init__(driver)
self.locator = self.Locator.css_selector("input[aria-label='Type in the name of the repository to confirm that you want to delete this repository.']")
class ConfirmDeleteButton(BaseButton):
def __init__(self, driver):
super(ConfirmDeleteButton, self).__init__(driver)
self.locator = self.Locator.xpath_selector("//button[text()[contains(.,'I understand the consequences, delete')]]")
class GithubPage(BasePageObject):
def __init__(self, driver):
@ -133,18 +176,32 @@ class GithubPage(BasePageObject):
self.cross_button = LabelsButton.CrossButton(self.driver)
self.submit_new_issue_button = SubmitNewIssueButton(self.driver)
self.contract_body = ContractBody(self.driver)
self.issue_id = IssueId(self.driver)
self.fork_button = ForkButton(self.driver)
self.header_in_fork_popup = HeaderInForkPopup(self.driver)
self.user_account_in_fork_popup = UserAccountInForkPopup(self.driver)
self.forked_repo_text = ForkedRepoText(self.driver)
self.delete_repo = DeleteRepo(self.driver)
self.repo_name_confirm_delete = RepoNameBoxInPopup(self.driver)
self.confirm_delete = ConfirmDeleteButton(self.driver)
def get_issues_page(self):
self.driver.get('https://github.com/Org4/nov13/issues')
self.driver.get(test_data.config['ORG']['gh_repo'] + 'issues')
def get_issue_page(self, issue_id):
self.driver.get(test_data.config['ORG']['gh_repo'] + 'issues/' + issue_id)
def get_sob_plugin_page(self):
self.driver.get('http://github.com/apps/status-open-bounty-app-test')
self.driver.get(test_data.config['Common']['sob_test_app'])
def sign_in(self, email, password):
self.email_input.send_keys(email)
self.password_input.send_keys(password)
self.sign_in_button.click()
def install_sob_plugin(self):
initial_url = self.driver.current_url
self.get_sob_plugin_page()
@ -164,7 +221,18 @@ class GithubPage(BasePageObject):
self.bounty_label.click()
self.cross_button.click()
self.submit_new_issue_button.click()
return test_data.issue['title']
test_data.issue['id'] = self.issue_id.text[1:]
logging.info("Issue title is %s" % test_data.issue['title'])
def fork_repo(self, initial_repo, wait=60):
self.driver.get(initial_repo)
self.fork_button.click()
if self.header_in_fork_popup.text == 'Where should we fork this repository?':
self.user_account_in_fork_popup.click()
self.forked_repo_text.wait_for_element(wait)
def get_login_page(self):
self.driver.get(test_data.config['Common']['gh_login'])
def get_deployed_contract(self, wait=120):
for i in range(wait):
@ -175,3 +243,34 @@ class GithubPage(BasePageObject):
time.sleep(10)
pass
pytest.fail('Contract is not deployed in %s minutes!' % str(wait/60))
#cloning via HTTPS
def clone_repo(self, initial_repo=None, username=None, repo_name=None, repo_path='git_repo'):
os.mkdir(repo_path)
os.chdir(repo_path)
test_data.local_repo_path = os.getcwd()
fork = 'https://github.com/%s/%s.git' % (username, repo_name)
logging.info(('Cloning from %s to %s' % (fork, repo_path)))
r = Repo.clone_from(fork, repo_path)
logging.info(('Successefully cloned to: %s' % test_data.local_repo_path))
logging.info('Set upstream to %s'% initial_repo)
upstream = r.create_remote('upstream', initial_repo)
upstream.fetch()
assert upstream.exists()
r.heads.master.checkout()
def clean_repo_local_folder(self):
logging.info('Removing %s' % test_data.local_repo_path)
if test_data.local_repo_path:
shutil.rmtree(test_data.local_repo_path)
def delete_fork(self):
self.get_url(test_data.config['DEV']['gh_forked_repo'] + 'settings')
self.delete_repo.click()
self.repo_name_confirm_delete.send_keys(test_data.config['ORG']['gh_repo_name'])
self.confirm_delete.click()

View File

@ -16,3 +16,6 @@ selenium==2.53.6
six==1.10.0
urllib3==1.22
yarl==0.12.0
gitpython==2.1.8
gitdb2==2.0.3
smmap2==2.0.3

View File

@ -7,11 +7,14 @@ class TestData(object):
self.config = configparser.ConfigParser()
# define here path to your config.ini file
#example - config_example.ini
# example - config_example.ini
self.config.read('config.ini')
self.base_case_issue = dict()
self.base_case_issue['title'] = 'Very first auto_test_bounty'
# self.issue['title'] is set in GithubPage::create_new_bounty
# self.issue['id'] is set in GithubPage::create_new_bounty
# self.local_repo_path is set in GithubPage::clone_repo
test_data = TestData()

View File

@ -4,63 +4,25 @@ from selenium.common.exceptions import WebDriverException
from tests.postconditions import remove_application, remove_installation
from os import environ, path
from tests import test_data
from pages.thirdparty.github import GithubPage
from pages.openbounty.landing import LandingPage
class BaseTestCase:
@property
def sauce_username(self):
return environ.get('SAUCE_USERNAME')
@property
def sauce_access_key(self):
return environ.get('SAUCE_ACCESS_KEY')
@property
def executor_sauce_lab(self):
return 'http://%s:%s@ondemand.saucelabs.com:80/wd/hub' % (self.sauce_username, self.sauce_access_key)
def print_sauce_lab_info(self, driver):
sys.stdout = sys.stderr
print("SauceOnDemandSessionID=%s job-name=%s" % (driver.session_id,
pytest.config.getoption('build')))
@property
def capabilities_sauce_lab(self):
desired_caps = dict()
desired_caps['name'] = test_data.test_name
desired_caps['build'] = pytest.config.getoption('build')
desired_caps['platform'] = "MAC"
desired_caps['browserName'] = 'Chrome'
desired_caps['screenResolution'] = '2048x1536'
desired_caps['captureHtml'] = False
return desired_caps
@property
def environment(self):
return pytest.config.getoption('env')
def setup_method(self):
self.errors = []
self.cleanup = None
if self.environment == 'local':
options = webdriver.ChromeOptions()
options.add_argument('--start-fullscreen')
options.add_extension(
path.abspath(test_data.config['Paths']['tests_absolute'] + 'resources/metamask3_12_0.crx'))
# for chromedriver 2.35
self.driver = webdriver.Chrome(chrome_options=options)
if self.environment == 'sauce':
self.driver = webdriver.Remote(self.executor_sauce_lab,
desired_capabilities=self.capabilities_sauce_lab)
self.driver.implicitly_wait(5)
def get_remote_caps(self):
sauce_lab_cap = dict()
sauce_lab_cap['name'] = test_data.test_name
sauce_lab_cap['build'] = pytest.config.getoption('build')
sauce_lab_cap['platform'] = "MAC"
sauce_lab_cap['browserName'] = 'Chrome'
sauce_lab_cap['screenResolution'] = '2048x1536'
sauce_lab_cap['captureHtml'] = False
return sauce_lab_cap
def verify_no_errors(self):
if self.errors:
@ -69,13 +31,115 @@ class BaseTestCase:
msg += (error + '\n')
pytest.fail(msg, pytrace=False)
def teardown_method(self):
if self.cleanup:
remove_application(self.driver)
remove_installation(self.driver)
@classmethod
def setup_class(cls):
cls.errors = []
cls.environment = pytest.config.getoption('env')
###################################################################################################################
######### Drivers setup
###################################################################################################################
#
# Dev Chrome options
#
cls.capabilities_dev = webdriver.ChromeOptions()
cls.capabilities_dev.add_argument('--start-fullscreen')
#
# Org Chrome options
#
cls.capabilities_org = webdriver.ChromeOptions()
# doesn't work on sauce env
# cls.capabilities_org.add_extension(path.abspath(test_data.config['Paths']['tests_absolute'] + 'resources/metamask3_12_0.crx'))
#
# SauceLab capabilities
#
cls.executor_sauce_lab = 'http://%s:%s@ondemand.saucelabs.com:80/wd/hub' % (
environ.get('SAUCE_USERNAME'), environ.get('SAUCE_ACCESS_KEY'))
drivers = []
if cls.environment == 'local':
for caps in cls.capabilities_dev, cls.capabilities_org:
driver = webdriver.Chrome(chrome_options=caps)
drivers.append(driver)
if cls.environment == 'sauce':
for caps in cls.capabilities_dev, cls.capabilities_org:
cls.get_remote_caps(cls)
new_caps = caps.to_capabilities()
driver = webdriver.Remote(cls.executor_sauce_lab,
desired_capabilities=new_caps)
drivers.append(driver)
for driver in drivers:
cls.print_sauce_lab_info(cls, driver)
cls.driver_dev = drivers[0]
cls.driver_org = drivers[1]
for driver in drivers:
driver.implicitly_wait(10)
###################################################################################################################
######### Actions for each driver before class
###################################################################################################################
######ORG
landing = LandingPage(cls.driver_org)
landing.get_landing_page()
# Sign Up to SOB
cls.github_org = landing.login_button.click()
cls.github_org.sign_in(test_data.config['ORG']['gh_login'],
test_data.config['ORG']['gh_password'])
assert cls.github_org.permission_type.text == 'Personal user data'
bounties_page = cls.github_org.authorize_sob.click()
# SOB Plugin installation and navigate to "Open bounties"
cls.github_org.install_sob_plugin()
assert bounties_page.bounties_header.text == 'Bounties'
assert bounties_page.top_hunters_header.text == 'Top 5 hunters'
######DEV
cls.github_dev = GithubPage(cls.driver_dev)
# Sign In to GH as Developer
cls.github_dev.get_login_page()
cls.github_dev.sign_in(test_data.config['DEV']['gh_login'],
test_data.config['DEV']['gh_password'])
# Fork repo as Developer from Organization
cls.github_dev.fork_repo(test_data.config['ORG']['gh_repo'])
# Cloning repo to local git as Developer and set upstream to Organization (via HTTPS)
cls.github_dev.clone_repo(test_data.config['ORG']['gh_repo'],
test_data.config['DEV']['gh_username'],
test_data.config['ORG']['gh_repo_name'],
'git_repo')
cls.verify_no_errors(cls)
@classmethod
def teardown_class(cls):
######ORG
# SOB Plugin remove installation
remove_application(cls.driver_org)
remove_installation(cls.driver_org)
######DEV
cls.github_dev.delete_fork()
cls.github_dev.clean_repo_local_folder()
try:
self.print_sauce_lab_info(self.driver)
self.driver.quit()
cls.driver_dev.quit()
cls.driver_org.quit()
except WebDriverException:
pass

View File

@ -1,13 +1,30 @@
[Common]
;app URL
url = https://openbounty.status.im:444/
;URL to GH openbounty app
sob_test_app = http://github.com/apps/status-open-bounty-app-test
gh_login = https://github.com/login
[Paths]
;AbsolutePath to 'tests' folder
tests_absolute = /usr/dir/open-bounty/test/end-to-end/tests/
;AbsolutePath to 'end-to-end' folder
tests_absolute = /usr/dir/open-bounty/test/end-to-end/
[ORG]
;GitHub credentials for organization
;GitHub credentials for organization owner
gh_login = login
gh_password = password
;GitHub organization path
gh_org_profile = https://github.com/organizations/organization/
;GitHub repo path
gh_repo = https://github.com/org_name/repo_name/
;GitHub repo name
gh_repo_name = repo_name
;MetaMask password for organization
mm_password = password
[DEV]
;GitHub credentials for developer
gh_login = login
gh_password = password
gh_username = username
gh_forked_repo = https://github.com/username/reponame/

View File

@ -1,5 +1,6 @@
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
from tests import test_data
def remove_application(driver):
@ -13,7 +14,7 @@ def remove_application(driver):
def remove_installation(driver):
try:
driver.get('https://github.com/organizations/Org4/settings/installations')
driver.get(test_data.config['ORG']['gh_org_profile'] + 'settings/installations')
driver.find_element(By.CSS_SELECTOR, '.iconbutton').click()
driver.find_element(By.XPATH, "//a[@class='btn btn-danger']").click()
driver.find_element(By.CSS_SELECTOR, '.facebox-popup .btn-danger').click()

View File

@ -2,6 +2,7 @@ import pytest
from os import environ
from pages.openbounty.landing import LandingPage
from pages.openbounty.bounties import BountiesPage
from pages.thirdparty.github import GithubPage
from tests.basetestcase import BaseTestCase
from tests import test_data
@ -10,28 +11,13 @@ from tests import test_data
class TestLogin(BaseTestCase):
def test_deploy_new_contract(self):
self.cleanup = True
landing = LandingPage(self.driver)
landing.get_landing_page()
# Sign Up to SOB
github = landing.login_button.click()
github.sign_in(test_data.config['ORG']['gh_login'],
test_data.config['ORG']['gh_password'])
assert github.permission_type.text == 'Personal user data'
bounties_page = github.authorize_sob.click()
# SOB Plugin installation and navigate to "Open bounties"
github.install_sob_plugin()
assert bounties_page.bounties_header.text == 'Bounties'
assert bounties_page.top_hunters_header.text == 'Top 5 hunters'
# Waiting for deployed contract; test_data.issue created here
github.create_new_bounty()
github.get_deployed_contract()
self.github_org.create_new_bounty()
self.github_org.get_deployed_contract()
# Navigate and check top bounty in "Open bounties"
bounties_page = BountiesPage(self.driver)
bounties_page = BountiesPage(self.driver_org)
bounties_page.get_bounties_page()
titles = bounties_page.bounty_titles.find_elements()
assert titles[0].text == test_data.issue['title']
@ -40,3 +26,6 @@ class TestLogin(BaseTestCase):