Merge branch 'develop'
This commit is contained in:
commit
c7e4224e3b
|
@ -17,6 +17,10 @@ profiles.clj
|
||||||
*.iml
|
*.iml
|
||||||
*.ipr
|
*.ipr
|
||||||
*.log
|
*.log
|
||||||
|
*.pyc
|
||||||
|
*result.xml
|
||||||
|
.cache
|
||||||
|
.idea
|
||||||
resources/contracts
|
resources/contracts
|
||||||
node_modules
|
node_modules
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
|
@ -1,27 +1,72 @@
|
||||||
(ns commiteth.util.crypto-fiat-value
|
(ns commiteth.util.crypto-fiat-value
|
||||||
(:require [clj-http.client :as http]
|
(:require [clj-http.client :as http]
|
||||||
[clojure.string :as str]
|
[mount.core :as mount]
|
||||||
|
[clojure.tools.logging :as log]
|
||||||
|
[commiteth.config :refer [env]]
|
||||||
[clojure.data.json :as json]))
|
[clojure.data.json :as json]))
|
||||||
|
|
||||||
|
|
||||||
(defn get-token-usd-price
|
(defn fiat-api-provider []
|
||||||
|
(env :fiat-api-provider :coinmarketcap))
|
||||||
|
|
||||||
|
(defn json-api-request [url]
|
||||||
|
(->> (http/get url)
|
||||||
|
(:body)
|
||||||
|
(json/read-str)))
|
||||||
|
|
||||||
|
|
||||||
|
(defn get-token-usd-price-cryptonator
|
||||||
"Get current USD value for a token using cryptonator API"
|
"Get current USD value for a token using cryptonator API"
|
||||||
[token]
|
[tla]
|
||||||
(let [url (str "https://api.cryptonator.com/api/ticker/"
|
(let [token (subs (str tla) 1)
|
||||||
|
url (str "https://api.cryptonator.com/api/ticker/"
|
||||||
token
|
token
|
||||||
"-usd")
|
"-usd")
|
||||||
m (->> (http/get url)
|
m (json-api-request url)]
|
||||||
(:body)
|
|
||||||
(json/read-str))]
|
|
||||||
(-> (get-in m ["ticker" "price"])
|
(-> (get-in m ["ticker" "price"])
|
||||||
(read-string))))
|
(read-string))))
|
||||||
|
|
||||||
|
|
||||||
|
(def tla-to-id-mapping (atom {}))
|
||||||
|
|
||||||
|
(defn make-tla-to-id-mapping
|
||||||
|
"Coinmarketcap API uses it's own IDs for tokens instead of TLAs"
|
||||||
|
[]
|
||||||
|
(let [data (json-api-request "https://api.coinmarketcap.com/v1/ticker/?limit=0")]
|
||||||
|
(into {} (map
|
||||||
|
(fn [x] [(keyword (get x "symbol")) (get x "id")])
|
||||||
|
data))))
|
||||||
|
|
||||||
|
(defn get-token-usd-price-coinmarketcap
|
||||||
|
"Get current USD value for a token using coinmarketcap API"
|
||||||
|
[tla]
|
||||||
|
(let [token-id (get @tla-to-id-mapping tla)
|
||||||
|
url (format "https://api.coinmarketcap.com/v1/ticker/%s" token-id)
|
||||||
|
data (json-api-request url)]
|
||||||
|
(-> (first data)
|
||||||
|
(get "price_usd")
|
||||||
|
(read-string))))
|
||||||
|
|
||||||
|
(defn- get-price-fn []
|
||||||
|
(let [fns {:cryptonator get-token-usd-price-cryptonator
|
||||||
|
:coinmarketcap get-token-usd-price-coinmarketcap}]
|
||||||
|
(get fns (fiat-api-provider))))
|
||||||
|
|
||||||
(defn bounty-usd-value
|
(defn bounty-usd-value
|
||||||
"Get current USD value of a bounty. bounty is a map of token-tla (keyword) to value"
|
"Get current USD value of a bounty. bounty is a map of token-tla (keyword) to value"
|
||||||
[bounty]
|
[bounty]
|
||||||
(reduce + (map (fn [[token value]]
|
(let [get-token-usd-price (get-price-fn)]
|
||||||
(let [tla (subs (str token) 1)
|
(reduce + (map (fn [[tla value]]
|
||||||
usd-price (get-token-usd-price tla)]
|
(let [usd-price (get-token-usd-price tla)]
|
||||||
(* usd-price value)))
|
(* usd-price value)))
|
||||||
bounty)))
|
bounty))))
|
||||||
|
|
||||||
|
|
||||||
|
(mount/defstate
|
||||||
|
crypto-fiat-util
|
||||||
|
:start
|
||||||
|
(do
|
||||||
|
(reset! tla-to-id-mapping (make-tla-to-id-mapping))
|
||||||
|
(log/info "crypto-fiat-util started"))
|
||||||
|
:stop
|
||||||
|
(log/info "crypto-fiat-util stopped"))
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
import logging
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.common.exceptions import TimeoutException
|
||||||
|
from selenium.webdriver.support.wait import WebDriverWait
|
||||||
|
from selenium.webdriver.support import expected_conditions
|
||||||
|
|
||||||
|
|
||||||
|
class BaseElement(object):
|
||||||
|
|
||||||
|
class Locator(object):
|
||||||
|
|
||||||
|
def __init__(self, by, value):
|
||||||
|
self.by = by
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def xpath_selector(locator, value):
|
||||||
|
return locator(By.XPATH, value)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def css_selector(locator, value):
|
||||||
|
return locator(By.CSS_SELECTOR, value)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def id(locator, value):
|
||||||
|
return locator(By.ID, value)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def name(locator, value):
|
||||||
|
return locator(By.NAME, value)
|
||||||
|
|
||||||
|
def __str__(self, *args):
|
||||||
|
return "%s:%s" % (self.by, self.value)
|
||||||
|
|
||||||
|
def __init__(self, driver):
|
||||||
|
self.driver = driver
|
||||||
|
self.locator = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return self.__class__.__name__
|
||||||
|
|
||||||
|
def navigate(self):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def find_element(self):
|
||||||
|
logging.info('Looking for %s' % self.name)
|
||||||
|
return self.wait_for_element()
|
||||||
|
|
||||||
|
def find_elements(self):
|
||||||
|
logging.info('Looking for %s' % self.name)
|
||||||
|
return self.driver.find_elements(self.locator.by,
|
||||||
|
self.locator.value)
|
||||||
|
|
||||||
|
def wait_for_element(self, seconds=5):
|
||||||
|
return WebDriverWait(self.driver, seconds).until(
|
||||||
|
expected_conditions.presence_of_element_located((self.locator.by, self.locator.value)))
|
||||||
|
|
||||||
|
def wait_for_clickable(self, seconds=5):
|
||||||
|
return WebDriverWait(self.driver, seconds).until(
|
||||||
|
expected_conditions.element_to_be_clickable((self.locator.by, self.locator.value)))
|
||||||
|
|
||||||
|
def is_element_present(self, sec=5):
|
||||||
|
try:
|
||||||
|
self.wait_for_element(sec)
|
||||||
|
return True
|
||||||
|
except TimeoutException:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class BaseEditBox(BaseElement):
|
||||||
|
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(BaseEditBox, self).__init__(driver)
|
||||||
|
|
||||||
|
def send_keys(self, value):
|
||||||
|
self.find_element().send_keys(value)
|
||||||
|
logging.info('Type %s to %s' % (value, self.name))
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
self.find_element().clear()
|
||||||
|
logging.info('Clear text in %s' % self.name)
|
||||||
|
|
||||||
|
|
||||||
|
class BaseText(BaseElement):
|
||||||
|
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(BaseText, self).__init__(driver)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def text(self):
|
||||||
|
text = self.find_element().text
|
||||||
|
logging.info('%s is %s' % (self.name, text))
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
class BaseButton(BaseElement):
|
||||||
|
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(BaseButton, self).__init__(driver)
|
||||||
|
|
||||||
|
def click(self):
|
||||||
|
self.wait_for_clickable().click()
|
||||||
|
logging.info('Tap on %s' % self.name)
|
||||||
|
return self.navigate()
|
|
@ -0,0 +1,17 @@
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
class BasePageObject(object):
|
||||||
|
|
||||||
|
def __init__(self, driver):
|
||||||
|
self.driver = driver
|
||||||
|
|
||||||
|
def get_url(self, url):
|
||||||
|
self.driver.get(url)
|
||||||
|
|
||||||
|
def refresh(self):
|
||||||
|
self.driver.refresh()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def time_now(self):
|
||||||
|
return datetime.now().strftime('%-m%-d%-H%-M%-S')
|
|
@ -0,0 +1,25 @@
|
||||||
|
from pages.base_page import BasePageObject
|
||||||
|
from pages.base_element import *
|
||||||
|
|
||||||
|
|
||||||
|
class BountiesHeader(BaseText):
|
||||||
|
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(BountiesHeader, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.css_selector('.open-bounties-header')
|
||||||
|
|
||||||
|
|
||||||
|
class TopHuntersHeader(BaseText):
|
||||||
|
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(TopHuntersHeader, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.css_selector('.top-hunters-header')
|
||||||
|
|
||||||
|
|
||||||
|
class BountiesPage(BasePageObject):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(BountiesPage, self).__init__(driver)
|
||||||
|
self.driver = driver
|
||||||
|
|
||||||
|
self.bounties_header = BountiesHeader(self.driver)
|
||||||
|
self.top_hunters_header = TopHuntersHeader(self.driver)
|
|
@ -0,0 +1,23 @@
|
||||||
|
from pages.base_page import BasePageObject
|
||||||
|
from pages.base_element import *
|
||||||
|
|
||||||
|
|
||||||
|
class LoginButton(BaseButton):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(LoginButton, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.id('button-login')
|
||||||
|
|
||||||
|
def navigate(self):
|
||||||
|
from pages.thirdparty.github import GithubPage
|
||||||
|
return GithubPage(self.driver)
|
||||||
|
|
||||||
|
|
||||||
|
class LandingPage(BasePageObject):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(LandingPage, self).__init__(driver)
|
||||||
|
self.driver = driver
|
||||||
|
|
||||||
|
self.login_button = LoginButton(self.driver)
|
||||||
|
|
||||||
|
def get_landing_page(self):
|
||||||
|
self.driver.get('https://openbounty.status.im:444/')
|
|
@ -0,0 +1,173 @@
|
||||||
|
import time, pytest
|
||||||
|
from pages.base_element import *
|
||||||
|
from pages.base_page import BasePageObject
|
||||||
|
|
||||||
|
|
||||||
|
class EmailEditbox(BaseEditBox):
|
||||||
|
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(EmailEditbox, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.id('login_field')
|
||||||
|
|
||||||
|
|
||||||
|
class PasswordEditbox(BaseEditBox):
|
||||||
|
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(PasswordEditbox, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.id('password')
|
||||||
|
|
||||||
|
|
||||||
|
class SignInButton(BaseButton):
|
||||||
|
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(SignInButton, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.name('commit')
|
||||||
|
|
||||||
|
|
||||||
|
class AuthorizeStatusOpenBounty(BaseButton):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(AuthorizeStatusOpenBounty, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.css_selector('[data-octo-click="oauth_application_authorization"]')
|
||||||
|
|
||||||
|
def navigate(self):
|
||||||
|
from pages.openbounty.bounties import BountiesPage
|
||||||
|
return BountiesPage(self.driver)
|
||||||
|
|
||||||
|
|
||||||
|
class PermissionTypeText(BaseText):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(PermissionTypeText, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.css_selector('.permission-title')
|
||||||
|
|
||||||
|
|
||||||
|
class InstallButton(BaseButton):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(InstallButton, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.css_selector('.btn-primary')
|
||||||
|
|
||||||
|
|
||||||
|
class OrganizationButton(BaseButton):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(OrganizationButton, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.css_selector('[alt="@Org4"]')
|
||||||
|
|
||||||
|
|
||||||
|
class AllRepositoriesButton(BaseButton):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(AllRepositoriesButton, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.id('install_target_all')
|
||||||
|
|
||||||
|
|
||||||
|
class IntegrationPermissionsGroup(BaseText):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(IntegrationPermissionsGroup, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.css_selector('.integrations-permissions-group')
|
||||||
|
|
||||||
|
|
||||||
|
class NewIssueButton(BaseButton):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(NewIssueButton, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.css_selector(".subnav [role='button']")
|
||||||
|
|
||||||
|
|
||||||
|
class IssueTitleEditBox(BaseEditBox):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(IssueTitleEditBox, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.id("issue_title")
|
||||||
|
|
||||||
|
|
||||||
|
class LabelsButton(BaseButton):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(LabelsButton, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.css_selector("button[aria-label='Apply labels to this issue']")
|
||||||
|
|
||||||
|
class BountyLabel(BaseButton):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(LabelsButton.BountyLabel, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.css_selector("[data-name='bounty']")
|
||||||
|
|
||||||
|
class CrossButton(BaseButton):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(LabelsButton.CrossButton, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.xpath_selector(
|
||||||
|
"//span[text()='Apply labels to this issue']/../*[@aria-label='Close']")
|
||||||
|
|
||||||
|
|
||||||
|
class SubmitNewIssueButton(BaseButton):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(SubmitNewIssueButton, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.xpath_selector("//button[contains(text(), "
|
||||||
|
"'Submit new issue')]")
|
||||||
|
|
||||||
|
|
||||||
|
class ContractBody(BaseText):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(ContractBody, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.xpath_selector("//tbody//p[contains(text(), "
|
||||||
|
"'Current balance: 0.000000 ETH')]")
|
||||||
|
|
||||||
|
|
||||||
|
class GithubPage(BasePageObject):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(GithubPage, self).__init__(driver)
|
||||||
|
|
||||||
|
self.driver = driver
|
||||||
|
|
||||||
|
self.email_input = EmailEditbox(self.driver)
|
||||||
|
self.password_input = PasswordEditbox(self.driver)
|
||||||
|
self.sign_in_button = SignInButton(self.driver)
|
||||||
|
|
||||||
|
self.authorize_sob = AuthorizeStatusOpenBounty(self.driver)
|
||||||
|
self.permission_type = PermissionTypeText(self.driver)
|
||||||
|
|
||||||
|
self.install_button = InstallButton(self.driver)
|
||||||
|
self.organization_button = OrganizationButton(self.driver)
|
||||||
|
self.all_repositories_button = AllRepositoriesButton(self.driver)
|
||||||
|
self.integration_permissions_group = IntegrationPermissionsGroup(self.driver)
|
||||||
|
|
||||||
|
self.new_issue_button = NewIssueButton(self.driver)
|
||||||
|
self.issue_title_input = IssueTitleEditBox(self.driver)
|
||||||
|
self.labels_button = LabelsButton(self.driver)
|
||||||
|
self.bounty_label = LabelsButton.BountyLabel(self.driver)
|
||||||
|
self.cross_button = LabelsButton.CrossButton(self.driver)
|
||||||
|
self.submit_new_issue_button = SubmitNewIssueButton(self.driver)
|
||||||
|
self.contract_body = ContractBody(self.driver)
|
||||||
|
|
||||||
|
def get_issues_page(self):
|
||||||
|
self.driver.get('https://github.com/Org4/nov13/issues')
|
||||||
|
|
||||||
|
def get_sob_plugin_page(self):
|
||||||
|
self.driver.get('http://github.com/apps/status-open-bounty-app-test')
|
||||||
|
|
||||||
|
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()
|
||||||
|
self.install_button.click()
|
||||||
|
self.organization_button.click()
|
||||||
|
self.all_repositories_button.click()
|
||||||
|
self.install_button.click()
|
||||||
|
self.driver.get(initial_url)
|
||||||
|
|
||||||
|
def create_new_bounty(self):
|
||||||
|
self.get_issues_page()
|
||||||
|
self.new_issue_button.click()
|
||||||
|
self.issue_title_input.send_keys('auto_test_bounty_%s' % self.time_now)
|
||||||
|
self.labels_button.click()
|
||||||
|
self.bounty_label.click()
|
||||||
|
self.cross_button.click()
|
||||||
|
self.submit_new_issue_button.click()
|
||||||
|
|
||||||
|
def get_deployed_contract(self, wait=120):
|
||||||
|
for i in range(wait):
|
||||||
|
self.refresh()
|
||||||
|
try:
|
||||||
|
return self.contract_body.text
|
||||||
|
except TimeoutException:
|
||||||
|
time.sleep(10)
|
||||||
|
pass
|
||||||
|
pytest.fail('Contract is not deployed in %s minutes!' % str(wait/60))
|
|
@ -0,0 +1,88 @@
|
||||||
|
import time
|
||||||
|
from pages.base_page import BasePageObject
|
||||||
|
from pages.base_element import *
|
||||||
|
from selenium.webdriver import ActionChains
|
||||||
|
|
||||||
|
|
||||||
|
class BasePluginButton(BaseButton):
|
||||||
|
|
||||||
|
def click(self):
|
||||||
|
time.sleep(2)
|
||||||
|
self.find_element().click()
|
||||||
|
|
||||||
|
|
||||||
|
class AcceptButton(BasePluginButton):
|
||||||
|
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(AcceptButton, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.xpath_selector("//button[.='Accept']")
|
||||||
|
|
||||||
|
|
||||||
|
class PrivacyText(BaseText):
|
||||||
|
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(PrivacyText, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.xpath_selector("//a[.='Privacy']")
|
||||||
|
|
||||||
|
|
||||||
|
class ExportDenButton(BaseButton):
|
||||||
|
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(ExportDenButton, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.xpath_selector("//p[.='Import Existing DEN']")
|
||||||
|
|
||||||
|
|
||||||
|
class SecretPhraseEditBox(BaseEditBox):
|
||||||
|
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(SecretPhraseEditBox, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.xpath_selector("//textarea")
|
||||||
|
|
||||||
|
|
||||||
|
class PasswordEditBox(BaseEditBox):
|
||||||
|
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(PasswordEditBox, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.id('password-box')
|
||||||
|
|
||||||
|
|
||||||
|
class PasswordConfirmEditBox(BaseEditBox):
|
||||||
|
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(PasswordConfirmEditBox, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.id('password-box-confirm')
|
||||||
|
|
||||||
|
|
||||||
|
class OkButton(BasePluginButton):
|
||||||
|
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(OkButton, self).__init__(driver)
|
||||||
|
self.locator = self.Locator.xpath_selector("//button[.='OK']")
|
||||||
|
|
||||||
|
|
||||||
|
class MetaMaskPlugin(BasePageObject):
|
||||||
|
def __init__(self, driver):
|
||||||
|
super(MetaMaskPlugin, self).__init__(driver)
|
||||||
|
self.driver = driver
|
||||||
|
|
||||||
|
self.accept_button = AcceptButton(self.driver)
|
||||||
|
self.privacy_text = PrivacyText(self.driver)
|
||||||
|
self.enter_secret_phrase = SecretPhraseEditBox(self.driver)
|
||||||
|
self.export_den_button = ExportDenButton(self.driver)
|
||||||
|
self.password_edit_box = PasswordEditBox(self.driver)
|
||||||
|
self.password_box_confirm = PasswordConfirmEditBox(self.driver)
|
||||||
|
self.ok_button = OkButton(self.driver)
|
||||||
|
|
||||||
|
def recover_access(self, passphrase, password, confirm_password):
|
||||||
|
|
||||||
|
self.get_url('chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/popup.html')
|
||||||
|
self.accept_button.click()
|
||||||
|
ActionChains(self.driver).move_to_element(self.privacy_text.find_element()).perform()
|
||||||
|
self.accept_button.click()
|
||||||
|
|
||||||
|
self.export_den_button.click()
|
||||||
|
self.enter_secret_phrase.send_keys(passphrase)
|
||||||
|
self.password_edit_box.send_keys(password)
|
||||||
|
self.password_box_confirm.send_keys(confirm_password)
|
||||||
|
self.ok_button.click()
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
[pytest]
|
||||||
|
norecursedirs = .git pages
|
||||||
|
addopts = -s -v --junitxml=result.xml --tb=short
|
|
@ -0,0 +1,18 @@
|
||||||
|
allpairspy==2.3.0
|
||||||
|
apipkg==1.4
|
||||||
|
certifi==2017.7.27.1
|
||||||
|
chardet==3.0.4
|
||||||
|
execnet==1.4.1
|
||||||
|
idna==2.5
|
||||||
|
lxml==3.8.0
|
||||||
|
multidict==3.1.3
|
||||||
|
namedlist==1.7
|
||||||
|
py==1.4.34
|
||||||
|
pytest==3.2.1
|
||||||
|
pytest-forked==0.2
|
||||||
|
pytest-xdist==1.20.0
|
||||||
|
requests==2.18.3
|
||||||
|
selenium==2.53.6
|
||||||
|
six==1.10.0
|
||||||
|
urllib3==1.22
|
||||||
|
yarl==0.12.0
|
Binary file not shown.
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
|
||||||
|
class TestData(object):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.test_name = None
|
||||||
|
|
||||||
|
test_data = TestData()
|
|
@ -0,0 +1,70 @@
|
||||||
|
import pytest, sys
|
||||||
|
from selenium import webdriver
|
||||||
|
from selenium.common.exceptions import WebDriverException
|
||||||
|
from tests.postconditions import remove_application, remove_installation
|
||||||
|
from os import environ, path
|
||||||
|
from tests import test_data
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
def setup_method(self):
|
||||||
|
|
||||||
|
self.errors = []
|
||||||
|
|
||||||
|
# options = webdriver.ChromeOptions()
|
||||||
|
# options.add_argument('--start-fullscreen')
|
||||||
|
# options.add_extension(path.abspath('/resources/metamask3_12_0.crx'))
|
||||||
|
|
||||||
|
self.driver = webdriver.Remote(self.executor_sauce_lab,
|
||||||
|
desired_capabilities=self.capabilities_sauce_lab)
|
||||||
|
self.driver.implicitly_wait(5)
|
||||||
|
|
||||||
|
def verify_no_errors(self):
|
||||||
|
if self.errors:
|
||||||
|
msg = ''
|
||||||
|
for error in self.errors:
|
||||||
|
msg += (error + '\n')
|
||||||
|
pytest.fail(msg, pytrace=False)
|
||||||
|
|
||||||
|
def teardown_method(self):
|
||||||
|
|
||||||
|
remove_application(self.driver)
|
||||||
|
remove_installation(self.driver)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.print_sauce_lab_info(self.driver)
|
||||||
|
self.driver.quit()
|
||||||
|
except WebDriverException:
|
||||||
|
pass
|
|
@ -0,0 +1,23 @@
|
||||||
|
from tests import test_data
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
def pytest_addoption(parser):
|
||||||
|
parser.addoption("--build",
|
||||||
|
action="store",
|
||||||
|
default='SOB-' + datetime.now().strftime('%d-%b-%Y-%H-%M'),
|
||||||
|
help="Specify build name")
|
||||||
|
parser.addoption('--log',
|
||||||
|
action='store',
|
||||||
|
default=True,
|
||||||
|
help='Display each test step in terminal as plain text: True/False')
|
||||||
|
|
||||||
|
|
||||||
|
def pytest_configure(config):
|
||||||
|
if config.getoption('log'):
|
||||||
|
import logging
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
|
||||||
|
def pytest_runtest_setup(item):
|
||||||
|
test_data.test_name = item.name
|
|
@ -0,0 +1,22 @@
|
||||||
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.common.exceptions import NoSuchElementException
|
||||||
|
|
||||||
|
|
||||||
|
def remove_application(driver):
|
||||||
|
try:
|
||||||
|
driver.get('https://github.com/settings/applications')
|
||||||
|
driver.find_element(By.CSS_SELECTOR, '.BtnGroup-item').click()
|
||||||
|
driver.find_element(By.CSS_SELECTOR, '.facebox-popup .btn-danger').click()
|
||||||
|
except NoSuchElementException:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def remove_installation(driver):
|
||||||
|
try:
|
||||||
|
driver.get('https://github.com/organizations/Org4/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()
|
||||||
|
except NoSuchElementException:
|
||||||
|
pass
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
import pytest
|
||||||
|
from os import environ
|
||||||
|
from pages.openbounty.landing import LandingPage
|
||||||
|
from tests.basetestcase import BaseTestCase
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sanity
|
||||||
|
class TestLogin(BaseTestCase):
|
||||||
|
|
||||||
|
def test_deploy_new_contract(self):
|
||||||
|
landing = LandingPage(self.driver)
|
||||||
|
landing.get_landing_page()
|
||||||
|
github = landing.login_button.click()
|
||||||
|
github.sign_in('anna04test',
|
||||||
|
'f@E23D3H15Rd')
|
||||||
|
assert github.permission_type.text == 'Personal user data'
|
||||||
|
bounties_page = github.authorize_sob.click()
|
||||||
|
github.install_sob_plugin()
|
||||||
|
assert bounties_page.bounties_header.text == 'Bounties'
|
||||||
|
assert bounties_page.top_hunters_header.text == 'Top hunters'
|
||||||
|
github.create_new_bounty()
|
||||||
|
github.get_deployed_contract()
|
Loading…
Reference in New Issue