Merge remote-tracking branch 'status/develop' into sort-and-filter
This commit is contained in:
commit
161cd7bd99
|
@ -23,4 +23,3 @@ profiles.clj
|
|||
.idea
|
||||
resources/contracts
|
||||
node_modules
|
||||
.DS_Store
|
||||
|
|
28
README.md
28
README.md
|
@ -1,11 +1,11 @@
|
|||
# Commiteth
|
||||
# Status Open Bounty
|
||||
|
||||
Allows you to set bounties for Github issues, paid out in Ether.
|
||||
Allows you to set bounties for Github issues, paid out in Ether or any ERC-20 token.
|
||||
|
||||
More information:
|
||||
http://wiki.status.im/proposals/commiteth/
|
||||
https://wiki.status.im/Status_Open_Bounty
|
||||
|
||||
Live beta version:
|
||||
Live production version:
|
||||
https://openbounty.status.im
|
||||
The `master` branch is automatically deployed here.
|
||||
|
||||
|
@ -20,6 +20,26 @@ The `develop` branch is automatically deployed here.
|
|||
You will need [Leiningen](https://github.com/technomancy/leiningen) 2.0 or above installed.
|
||||
|
||||
### PostgreSQL
|
||||
<<<<<<< HEAD
|
||||
|
||||
Make sure you install [PostgreSQL](https://www.postgresql.org/) and properly set it up:
|
||||
|
||||
```
|
||||
sudo -u postgres psql -c "CREATE USER commiteth WITH PASSWORD 'commiteth';"
|
||||
sudo -u postgres createdb commiteth
|
||||
```
|
||||
|
||||
## Running
|
||||
|
||||
Launch following commands each in its own shell:
|
||||
|
||||
```
|
||||
lein run
|
||||
lein figwheel
|
||||
lein less auto
|
||||
```
|
||||
|
||||
=======
|
||||
|
||||
Make sure you install [PostgreSQL](https://www.postgresql.org/) and properly set it up:
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ For testing you will need:
|
|||
* a Github account with administrative access to one or more repositories
|
||||
* for approving bounty payouts you will additionally need access to an Ethereum wallet. So far, Mist and [MetaMask](https://metamask.io/) have been used, but anything that provides the web3 javascript interface should work.
|
||||
|
||||
The developers can be reached on the `#commiteth` channel in the [Status slack](http://slack.status.im/).
|
||||
The developers can be reached on the `#openbounty` channel in the [Status slack](http://slack.status.im/).
|
||||
|
||||
### Signing up
|
||||
|
||||
|
@ -60,6 +60,6 @@ To remove issue from the Bounties list you can close it in GitHub.
|
|||
|
||||
### Reporting bugs
|
||||
|
||||
All bugs should be reported as issues in the [CommitETH Github repository](https://github.com/status-im/commiteth/issues).
|
||||
All bugs should be reported as issues in the [OpenBounty Github repository](https://github.com/status-im/open-bounty/issues).
|
||||
|
||||
Please first check that there is not already a duplicate issue. Issues should contain exact and minimal step-by-step instructions for reproducing the problem.
|
||||
|
|
|
@ -33,7 +33,11 @@
|
|||
<AppenderRef ref="FILE"/>
|
||||
</logger>
|
||||
<root level="DEBUG">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
<!-- <appender-ref ref="STDOUT"/> -->
|
||||
<appender-ref ref="FILE"/>
|
||||
</root>
|
||||
<root level="INFO">
|
||||
<!-- <appender-ref ref="STDOUT"/> -->
|
||||
<appender-ref ref="FILE"/>
|
||||
</root>
|
||||
</configuration>
|
||||
|
|
|
@ -69,7 +69,6 @@
|
|||
[lein-auto "0.1.2"]
|
||||
[lein-less "1.7.5"]
|
||||
[lein-shell "0.5.0"]
|
||||
[cider/cider-nrepl "0.15.0-SNAPSHOT"]
|
||||
[lein-sha-version "0.1.1"]]
|
||||
|
||||
|
||||
|
@ -144,7 +143,7 @@
|
|||
|
||||
:prep-tasks ["build-contracts" "javac"]
|
||||
:doo {:build "test"}
|
||||
:source-paths ["env/dev/clj" "test/clj"]
|
||||
:source-paths ["env/dev/clj" "test/clj" "src/cljs" "env/dev/cljs"]
|
||||
:resource-paths ["env/dev/resources"]
|
||||
:repl-options {:init-ns user
|
||||
:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||
<path fill="#57A7ED" fill-rule="evenodd" d="M7.223 11.293l7.068-7.067a.999.999 0 1 1 1.414 1.414l-6.377 6.377 6.377 6.376a.999.999 0 1 1-1.414 1.415L7.223 12.74a1.001 1.001 0 0 1-.288-.827 1 1 0 0 1 .288-.62z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 307 B |
|
@ -53,8 +53,8 @@
|
|||
new-user?)
|
||||
(try
|
||||
(hubspot/create-hubspot-contact (:email user)
|
||||
(:name user "")
|
||||
(:login user))
|
||||
(:name user "")
|
||||
(:login user))
|
||||
(catch Throwable t
|
||||
(log/error "Failed to create hubspot contact" t))))
|
||||
(assoc (found (str (env :server-address) "/app"))
|
||||
|
|
|
@ -312,12 +312,13 @@
|
|||
|
||||
(defn wrap-in-try-catch [func]
|
||||
(try
|
||||
(func)
|
||||
(catch Throwable t
|
||||
(log/error t))))
|
||||
|
||||
(defn run-tasks [tasks]
|
||||
(doall
|
||||
(map (fn [func] (wrap-in-try-catch (func)))
|
||||
(map (fn [func] (wrap-in-try-catch func))
|
||||
tasks)))
|
||||
|
||||
(defn run-1-min-interval-tasks [time]
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
(:require [re-frame.core :as rf]
|
||||
[reagent.core :as r]
|
||||
[commiteth.common :refer [moment-timestamp
|
||||
display-data-page
|
||||
issue-url]]))
|
||||
|
||||
|
||||
|
@ -56,21 +57,19 @@
|
|||
|
||||
|
||||
|
||||
(defn activity-list [activity-items]
|
||||
(defn activity-list [activity-page-data]
|
||||
[:div.ui.container.activity-container
|
||||
(if (empty? activity-items)
|
||||
(if (empty? (:items activity-page-data))
|
||||
[:div.view-no-data-container
|
||||
[:p "No recent activity yet"]]
|
||||
(into [:div.ui.items]
|
||||
(for [item activity-items]
|
||||
^{:key item} [activity-item item])))] )
|
||||
(display-data-page activity-page-data activity-item :set-activity-page-number))])
|
||||
|
||||
(defn activity-page []
|
||||
(let [activity-items (rf/subscribe [:activity-feed])
|
||||
(let [activity-page-data (rf/subscribe [:activities-page])
|
||||
activity-feed-loading? (rf/subscribe [:get-in [:activity-feed-loading?]])]
|
||||
(fn []
|
||||
(if @activity-feed-loading?
|
||||
[:div.view-loading-container
|
||||
[:div.ui.active.inverted.dimmer
|
||||
[:div.ui.text.loader.view-loading-label "Loading"]]]
|
||||
[activity-list @activity-items]))))
|
||||
[activity-list @activity-page-data]))))
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
(:require [reagent.core :as r]
|
||||
[re-frame.core :as rf]
|
||||
[commiteth.common :refer [moment-timestamp
|
||||
display-data-page
|
||||
items-per-page
|
||||
issue-url]]
|
||||
[commiteth.handlers :as handlers]
|
||||
[commiteth.db :as db]
|
||||
|
@ -203,26 +205,70 @@
|
|||
(rf/dispatch [::handlers/set-open-bounties-sorting-type sorting-type]))}
|
||||
(ui-model/bounty-sorting-type->name sorting-type)])])]))))
|
||||
|
||||
(defn bounties-list [open-bounties]
|
||||
;(defn bounties-list [open-bounties]
|
||||
; [:div.ui.container.open-bounties-container
|
||||
; [:div.open-bounties-header "Bounties"]
|
||||
; [:div.open-bounties-filter-and-sort
|
||||
; [bounty-filters-view]
|
||||
; [bounties-sort]]
|
||||
; (if (empty? open-bounties)
|
||||
; [:div.view-no-data-container
|
||||
; [:p "No matching bounties found."]]
|
||||
; (into [:div.ui.items]
|
||||
; (for [bounty open-bounties]
|
||||
; [bounty-item bounty])))])
|
||||
|
||||
(defn bounties-list [{:keys [items item-count page-number total-count]
|
||||
:as bounty-page-data}]
|
||||
[:div.ui.container.open-bounties-container
|
||||
[:div.open-bounties-header "Bounties"]
|
||||
[:div.open-bounties-filter-and-sort
|
||||
[bounty-filters-view]
|
||||
[bounties-sort]]
|
||||
(if (empty? open-bounties)
|
||||
(if (empty? items)
|
||||
[:div.view-no-data-container
|
||||
[:p "No matching bounties found."]]
|
||||
(into [:div.ui.items]
|
||||
(for [bounty open-bounties]
|
||||
[bounty-item bounty])))])
|
||||
|
||||
[:div
|
||||
(let [left (inc (* (dec page-number) items-per-page))
|
||||
right (dec (+ left item-count))]
|
||||
[:div.item-counts-label
|
||||
[:span (str "Showing " left "-" right " of " total-count)]])
|
||||
(display-data-page bounty-page-data bounty-item :set-bounty-page-number)])])
|
||||
|
||||
(defn bounties-page []
|
||||
(let [open-bounties (rf/subscribe [::subs/filtered-and-sorted-open-bounties])
|
||||
(let [bounty-page-data (rf/subscribe [:open-bounties-page])
|
||||
open-bounties-loading? (rf/subscribe [:get-in [:open-bounties-loading?]])]
|
||||
(fn []
|
||||
(if @open-bounties-loading?
|
||||
[:div.view-loading-container
|
||||
[:div.ui.active.inverted.dimmer
|
||||
[:div.ui.text.loader.view-loading-label "Loading"]]]
|
||||
[bounties-list @open-bounties]))))
|
||||
[bounties-list @bounty-page-data]))))
|
||||
;
|
||||
;(defn bounties-page []
|
||||
; (let [open-bounties (rf/subscribe [::subs/filtered-and-sorted-open-bounties])
|
||||
;=======
|
||||
;(defn bounties-list [{:keys [items item-count page-number total-count]
|
||||
; :as bounty-page-data}]
|
||||
; [:div.ui.container.open-bounties-container
|
||||
; [:div.open-bounties-header "Bounties"]
|
||||
; (if (empty? items)
|
||||
; [:div.view-no-data-container
|
||||
; [:p "No recent activity yet"]]
|
||||
; [:div
|
||||
; (let [left (inc (* (dec page-number) items-per-page))
|
||||
; right (dec (+ left item-count))]
|
||||
; [:div.item-counts-label
|
||||
; [:span (str "Showing " left "-" right " of " total-count)]])
|
||||
; (display-data-page bounty-page-data bounty-item :set-bounty-page-number)])])
|
||||
;
|
||||
;(defn bounties-page []
|
||||
; (let [bounty-page-data (rf/subscribe [:open-bounties-page])
|
||||
;>>>>>>> status/develop
|
||||
; open-bounties-loading? (rf/subscribe [:get-in [:open-bounties-loading?]])]
|
||||
; (fn []
|
||||
; (if @open-bounties-loading?
|
||||
; [:div.view-loading-container
|
||||
; [:div.ui.active.inverted.dimmer
|
||||
; [:div.ui.text.loader.view-loading-label "Loading"]]]
|
||||
; [bounties-list @bounty-page-data]))))
|
||||
|
|
|
@ -29,3 +29,87 @@
|
|||
|
||||
(defn issue-url [owner repo number]
|
||||
(str "https://github.com/" owner "/" repo "/issues/" number))
|
||||
|
||||
(def items-per-page 15)
|
||||
|
||||
(defn draw-page-numbers [page-number page-count set-page-kw]
|
||||
"Draw page numbers for the pagination component.
|
||||
Inserts ellipsis when list is too long, by default
|
||||
max 6 items are allowed"
|
||||
(let [draw-page-num-fn (fn [current? i]
|
||||
^{:key i}
|
||||
[:div.rectangle-rounded
|
||||
(cond-> {}
|
||||
(not current?)
|
||||
(assoc :class "grayed-out"
|
||||
:on-click #(rf/dispatch [set-page-kw i])))
|
||||
i])
|
||||
max-page-nums 6]
|
||||
[:div.page-nums-container
|
||||
(cond (<= page-count max-page-nums)
|
||||
(for [i (map inc (range page-count))]
|
||||
(draw-page-num-fn (= i page-number) i))
|
||||
(<= page-number (- max-page-nums 3))
|
||||
(concat
|
||||
(for [i (map inc (range (- max-page-nums 2)))]
|
||||
(draw-page-num-fn (= i page-number) i))
|
||||
[^{:key (dec max-page-nums)}
|
||||
[:div.page-nav-text [:span "..."]]]
|
||||
[(draw-page-num-fn false page-count)])
|
||||
(>= page-number (- page-count (- max-page-nums 4)))
|
||||
(concat
|
||||
[(draw-page-num-fn false 1)
|
||||
^{:key 2}
|
||||
[:div.page-nav-text [:span "..."]]]
|
||||
(for [i (map inc (range (- page-count 4) page-count))]
|
||||
(draw-page-num-fn (= i page-number) i))
|
||||
)
|
||||
:else
|
||||
(concat
|
||||
[(draw-page-num-fn false 1)
|
||||
^{:key 2} [:div.page-nav-text [:span "..."]]]
|
||||
(for [i [(dec page-number) page-number (inc page-number)]]
|
||||
(draw-page-num-fn (= i page-number) i))
|
||||
[^{:key (dec page-count)} [:div.page-nav-text [:span "..."]]
|
||||
(draw-page-num-fn false page-count)]))]))
|
||||
|
||||
(defn display-data-page [{:keys [items
|
||||
item-count
|
||||
total-count
|
||||
page-number
|
||||
page-count]}
|
||||
draw-item-fn
|
||||
set-page-kw]
|
||||
"Draw data items along with pagination controls"
|
||||
(let [draw-items (fn []
|
||||
(into [:div.ui.items]
|
||||
(for [item items]
|
||||
^{:key item} [draw-item-fn item])))
|
||||
on-direction-click (fn [forward?]
|
||||
#(when (or (and (< page-number page-count)
|
||||
forward?)
|
||||
(and (< 1 page-number)
|
||||
(not forward?)))
|
||||
(rf/dispatch [set-page-kw
|
||||
(if forward?
|
||||
(inc page-number)
|
||||
(dec page-number))])))
|
||||
draw-rect (fn [direction]
|
||||
(let [forward? (= direction :forward)]
|
||||
[:div.rectangle-rounded
|
||||
{:on-click (on-direction-click forward?)}
|
||||
[:img.icon-forward-gray
|
||||
(cond-> {:src "icon-forward-gray.svg"}
|
||||
forward? (assoc :class "flip-horizontal"))]]))]
|
||||
(cond (<= total-count items-per-page)
|
||||
[draw-items]
|
||||
:else
|
||||
[:div
|
||||
[draw-items]
|
||||
[:div.page-nav-container
|
||||
[draw-rect :backward]
|
||||
[draw-rect :forward]
|
||||
[:div.page-nav-text [:span (str "Page " page-number " of " page-count)]]
|
||||
[draw-page-numbers page-number page-count set-page-kw]]])))
|
||||
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
:activity-feed-loading? false
|
||||
:open-bounties-loading? false
|
||||
:open-bounties []
|
||||
:bounty-page-number 1
|
||||
:activity-page-number 1
|
||||
::open-bounties-sorting-type ::ui-model/bounty-sorting-type|most-recent
|
||||
::open-bounties-filters {::ui-model/bounty-filter-type|value nil
|
||||
::ui-model/bounty-filter-type|currency nil
|
||||
|
|
|
@ -68,6 +68,16 @@
|
|||
(fn [db [_ page]]
|
||||
(assoc db :page page)))
|
||||
|
||||
(reg-event-db
|
||||
:set-bounty-page-number
|
||||
(fn [db [_ page]]
|
||||
(assoc db :bounty-page-number page)))
|
||||
|
||||
(reg-event-db
|
||||
:set-activity-page-number
|
||||
(fn [db [_ page]]
|
||||
(assoc db :activity-page-number page)))
|
||||
|
||||
(reg-event-fx
|
||||
:set-flash-message
|
||||
(fn [{:keys [db]} [_ type text]]
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
(ns commiteth.subscriptions
|
||||
(:require [re-frame.core :refer [reg-sub]]
|
||||
[commiteth.db :as db]
|
||||
[commiteth.ui-model :as ui-model]))
|
||||
[commiteth.ui-model :as ui-model]
|
||||
[commiteth.common :refer [items-per-page]]))
|
||||
|
||||
(reg-sub
|
||||
:db
|
||||
|
@ -35,7 +36,28 @@
|
|||
(reg-sub
|
||||
:open-bounties
|
||||
(fn [db _]
|
||||
(:open-bounties db)))
|
||||
(vec (:open-bounties db))))
|
||||
|
||||
(reg-sub
|
||||
:bounty-page-number
|
||||
(fn [db _]
|
||||
(:bounty-page-number db)))
|
||||
|
||||
(reg-sub
|
||||
:open-bounties-page
|
||||
:<- [::filtered-and-sorted-open-bounties]
|
||||
:<- [:bounty-page-number]
|
||||
(fn [[open-bounties page-number] _]
|
||||
(let [total-count (count open-bounties)
|
||||
start (* (dec page-number) items-per-page)
|
||||
end (min total-count (+ items-per-page start))
|
||||
items (subvec open-bounties start end)]
|
||||
{:items items
|
||||
:item-count (count items)
|
||||
:total-count total-count
|
||||
:page-number page-number
|
||||
:page-count (Math/ceil (/ total-count items-per-page))})))
|
||||
|
||||
|
||||
(reg-sub
|
||||
:owner-bounties
|
||||
|
@ -55,7 +77,28 @@
|
|||
(reg-sub
|
||||
:activity-feed
|
||||
(fn [db _]
|
||||
(:activity-feed db)))
|
||||
(vec (:activity-feed db))))
|
||||
|
||||
(reg-sub
|
||||
:activity-page-number
|
||||
(fn [db _]
|
||||
(:activity-page-number db)))
|
||||
|
||||
(reg-sub
|
||||
:activities-page
|
||||
:<- [:activity-feed]
|
||||
:<- [:activity-page-number]
|
||||
(fn [[activities page-number] _]
|
||||
(let [total-count (count activities)
|
||||
start (* (dec page-number) items-per-page)
|
||||
end (min total-count (+ items-per-page start))
|
||||
items (subvec activities start end)]
|
||||
{:items items
|
||||
:item-count (count items)
|
||||
:total-count total-count
|
||||
:page-number page-number
|
||||
:page-count (Math/ceil (/ total-count items-per-page))})))
|
||||
|
||||
|
||||
(reg-sub
|
||||
:gh-admin-token
|
||||
|
@ -120,4 +163,5 @@
|
|||
(fn [[open-bounties filters sorting-type] _]
|
||||
(cond->> open-bounties
|
||||
filters (ui-model/filter-bounties filters)
|
||||
sorting-type (ui-model/sort-bounties-by-sorting-type sorting-type))))
|
||||
sorting-type (ui-model/sort-bounties-by-sorting-type sorting-type)
|
||||
filter vec)))
|
||||
|
|
|
@ -1166,3 +1166,85 @@ body {
|
|||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
.rectangle-rounded {
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
color: #57a7ed;
|
||||
/*opacity: 0.2;*/
|
||||
border-radius: 22.5px;
|
||||
/*background-color: #57a7ed;*/
|
||||
background-color: rgba(87,167,237,.2);
|
||||
font-family: "PostGrotesk-Medium";
|
||||
font-weight: 500;
|
||||
font-size: 13px;
|
||||
display: flex;
|
||||
margin: 0 6px;
|
||||
flex: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.grayed-out {
|
||||
color: #8d99a4;
|
||||
background-color: #f2f5f8;
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
.flip-horizontal {
|
||||
-moz-transform: scaleX(-1);
|
||||
-webkit-transform: scaleX(-1);
|
||||
-o-transform: scaleX(-1);
|
||||
transform: scaleX(-1);
|
||||
-ms-filter: fliph; /*IE*/
|
||||
filter: fliph;
|
||||
}
|
||||
|
||||
.pagination-text {
|
||||
width: 83px;
|
||||
height: 15px;
|
||||
font-family: PostGrotesk;
|
||||
font-size: 15px;
|
||||
text-align: center;
|
||||
color: #8d99a4;
|
||||
}
|
||||
|
||||
.icon-forward-gray {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.page-nav-container {
|
||||
display: flex;
|
||||
margin: 0 -6px;
|
||||
}
|
||||
|
||||
.page-nums-container {
|
||||
display: flex;
|
||||
margin-left: auto;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.page-nav-text {
|
||||
font-family: PostGrotesk-Book;
|
||||
font-size: 15px;
|
||||
color: #8d99a4;
|
||||
|
||||
display: flex;
|
||||
margin: 0 6px;
|
||||
flex: none;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.item-counts-label {
|
||||
margin: auto;
|
||||
font-family: "PostGrotesk-Book";
|
||||
font-size: 15px;
|
||||
color: #8d99a4;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from pages.base_page import BasePageObject
|
||||
from pages.base_element import *
|
||||
from tests import test_data
|
||||
|
||||
|
||||
class BountiesHeader(BaseText):
|
||||
|
@ -15,11 +16,38 @@ class TopHuntersHeader(BaseText):
|
|||
super(TopHuntersHeader, self).__init__(driver)
|
||||
self.locator = self.Locator.css_selector('.top-hunters-header')
|
||||
|
||||
class BountyTitles(BaseText):
|
||||
|
||||
def __init__(self, driver):
|
||||
super(BountyTitles, self).__init__(driver)
|
||||
self.locator = self.Locator.css_selector('.open-bounty-item-content .header')
|
||||
|
||||
|
||||
class BountyItemRows(BaseText):
|
||||
|
||||
def __init__(self, driver):
|
||||
super(BountyItemRows, self).__init__(driver)
|
||||
self.locator = self.Locator.css_selector('.open-bounty-item-content .bounty-item-row')
|
||||
|
||||
class BountyFooters(BaseText):
|
||||
|
||||
def __init__(self, driver):
|
||||
super(BountyFooters, self).__init__(driver)
|
||||
self.locator = self.Locator.css_selector('.open-bounty-item-content .footer-row')
|
||||
|
||||
|
||||
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)
|
||||
self.bounty_titles = BountyTitles(self.driver)
|
||||
self.bounty_item_rows = BountyItemRows(self.driver)
|
||||
self.bounty_footers = BountyFooters(self.driver)
|
||||
|
||||
def get_bounties_page(self):
|
||||
self.driver.get(test_data.config['Common']['url'] + 'app')
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from pages.base_page import BasePageObject
|
||||
from pages.base_element import *
|
||||
from tests import test_data
|
||||
|
||||
|
||||
class LoginButton(BaseButton):
|
||||
|
@ -20,4 +21,4 @@ class LandingPage(BasePageObject):
|
|||
self.login_button = LoginButton(self.driver)
|
||||
|
||||
def get_landing_page(self):
|
||||
self.driver.get('https://openbounty.status.im:444/')
|
||||
self.driver.get(test_data.config['Common']['url'])
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import time, pytest
|
||||
from pages.base_element import *
|
||||
from pages.base_page import BasePageObject
|
||||
from tests import test_data
|
||||
|
||||
|
||||
class EmailEditbox(BaseEditBox):
|
||||
|
@ -84,7 +85,7 @@ class LabelsButton(BaseButton):
|
|||
class BountyLabel(BaseButton):
|
||||
def __init__(self, driver):
|
||||
super(LabelsButton.BountyLabel, self).__init__(driver)
|
||||
self.locator = self.Locator.css_selector("[data-name='bounty']")
|
||||
self.locator = self.Locator.css_selector("[data-name='748942015']")
|
||||
|
||||
class CrossButton(BaseButton):
|
||||
def __init__(self, driver):
|
||||
|
@ -156,11 +157,14 @@ class GithubPage(BasePageObject):
|
|||
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)
|
||||
test_data.issue = dict()
|
||||
test_data.issue['title'] = 'auto_test_bounty_%s' % self.time_now
|
||||
self.issue_title_input.send_keys(test_data.issue['title'])
|
||||
self.labels_button.click()
|
||||
self.bounty_label.click()
|
||||
self.cross_button.click()
|
||||
self.submit_new_issue_button.click()
|
||||
return test_data.issue['title']
|
||||
|
||||
def get_deployed_contract(self, wait=120):
|
||||
for i in range(wait):
|
||||
|
|
|
@ -1,8 +1,17 @@
|
|||
|
||||
import configparser
|
||||
|
||||
class TestData(object):
|
||||
|
||||
def __init__(self):
|
||||
self.test_name = None
|
||||
self.config = configparser.ConfigParser()
|
||||
|
||||
# define here path to your config.ini file
|
||||
#example - config_example.ini
|
||||
|
||||
self.config.read('config.ini')
|
||||
self.base_case_issue = dict()
|
||||
self.base_case_issue['title'] = 'Very first auto_test_bounty'
|
||||
|
||||
|
||||
test_data = TestData()
|
||||
|
|
|
@ -39,18 +39,29 @@ class BaseTestCase:
|
|||
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
|
||||
|
||||
# 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)
|
||||
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 verify_no_errors(self):
|
||||
if self.errors:
|
||||
msg = ''
|
||||
|
@ -59,9 +70,9 @@ class BaseTestCase:
|
|||
pytest.fail(msg, pytrace=False)
|
||||
|
||||
def teardown_method(self):
|
||||
|
||||
remove_application(self.driver)
|
||||
remove_installation(self.driver)
|
||||
if self.cleanup:
|
||||
remove_application(self.driver)
|
||||
remove_installation(self.driver)
|
||||
|
||||
try:
|
||||
self.print_sauce_lab_info(self.driver)
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
[Common]
|
||||
;app URL
|
||||
url = https://openbounty.status.im:444/
|
||||
[Paths]
|
||||
;AbsolutePath to 'tests' folder
|
||||
tests_absolute = /usr/dir/open-bounty/test/end-to-end/tests/
|
||||
[ORG]
|
||||
;GitHub credentials for organization
|
||||
gh_login = login
|
||||
gh_password = password
|
||||
;MetaMask password for organization
|
||||
mm_password = password
|
||||
|
|
@ -11,6 +11,10 @@ def pytest_addoption(parser):
|
|||
action='store',
|
||||
default=True,
|
||||
help='Display each test step in terminal as plain text: True/False')
|
||||
parser.addoption('--env',
|
||||
action='store',
|
||||
default='sauce',
|
||||
help='Specify environment, sauce or local')
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
|
|
|
@ -1,22 +1,42 @@
|
|||
import pytest
|
||||
from os import environ
|
||||
from pages.openbounty.landing import LandingPage
|
||||
from pages.openbounty.bounties import BountiesPage
|
||||
from tests.basetestcase import BaseTestCase
|
||||
from tests import test_data
|
||||
|
||||
|
||||
@pytest.mark.sanity
|
||||
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('anna04test',
|
||||
'f@E23D3H15Rd')
|
||||
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 hunters'
|
||||
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()
|
||||
|
||||
# Navigate and check top bounty in "Open bounties"
|
||||
bounties_page = BountiesPage(self.driver)
|
||||
bounties_page.get_bounties_page()
|
||||
titles = bounties_page.bounty_titles.find_elements()
|
||||
assert titles[0].text == test_data.issue['title']
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue