Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
86f1eb4
commit ac12372
Showing
2 changed files
with
165 additions
and
128 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,153 @@ | ||
module Test.E2E.Helpers (retrieveJQuery) where | ||
module Test.E2E.Helpers | ||
( js | ||
, tryJs | ||
, hasSelector | ||
, injectJQuery | ||
, injectJQueryAll | ||
, findNamiPage | ||
, doJQ | ||
, click | ||
, enable | ||
, setAttr | ||
, buttonWithText | ||
, password | ||
, jqStr | ||
, jqSet | ||
, setText | ||
, setValue | ||
, trigger | ||
, clickButton | ||
, testPassword | ||
, reactSetValue | ||
, retrieveJQuery | ||
, Selector(..) | ||
, Action(..) | ||
, NoShowPage(..) | ||
) where | ||
|
||
import Toppokki as Toki | ||
import Control.Monad.Error.Class (catchError) | ||
import Data.Array (head, filter, zip) | ||
import Data.Newtype (class Newtype, wrap, unwrap) | ||
import Data.Tuple (fst, snd) | ||
import Effect.Aff (Aff) | ||
import Effect.Class (liftEffect) | ||
import Effect.Class.Console (log) | ||
import Effect (Effect) | ||
import Data.Maybe (Maybe(..), isJust) | ||
import Foreign (Foreign) | ||
import Prelude | ||
import Control.Promise (Promise, toAffE) | ||
import Data.Traversable (for, traverse, fold) | ||
|
||
foreign import _retrieveJQuery :: Toki.Page -> Effect (Promise String) | ||
|
||
retrieveJQuery :: Toki.Page -> Aff String | ||
retrieveJQuery = toAffE <<< _retrieveJQuery | ||
|
||
js :: String -> Toki.Page -> Aff Unit | ||
js str = void <$> Toki.unsafeEvaluateStringFunction str | ||
|
||
tryJs :: Toki.Selector -> String -> Toki.Page -> Aff (Maybe Unit) | ||
tryJs selector function page = catchError eval $ \e -> do | ||
log $ show e | ||
pure Nothing | ||
where | ||
eval :: Aff (Maybe Unit) | ||
eval = do | ||
_ <- Toki.unsafePageEval selector function page | ||
pure $ Just unit | ||
|
||
hasSelector :: Toki.Selector -> Toki.Page -> Aff (Maybe Unit) | ||
hasSelector selector page = tryJs selector "(x)=>{}" page | ||
|
||
{-retrieveJQuery :: Toki.Page -> Aff String | ||
retrieveJQuery page = Foreign.unsafeFromForeign <$> Toki.unsafeEvaluateStringFunction fetch page | ||
where fetch = "window.fetch('https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js')" | ||
-} | ||
|
||
injectJQuery :: String -> Toki.Page -> Aff Foreign | ||
injectJQuery = Toki.unsafeEvaluateStringFunction | ||
|
||
findNamiPage :: Toki.Browser -> Aff (Maybe Toki.Page) | ||
findNamiPage browser = do | ||
pages <- Toki.pages browser | ||
results <- traverse (hasSelector $ wrap "button") pages | ||
pure $ map snd $ head $ filter (isJust <<< fst) $ zip results pages | ||
|
||
-- | Wrapper for Page so it can be used in `shouldSatisfy` | ||
newtype NoShowPage = NoShowPage Toki.Page | ||
|
||
derive instance Newtype NoShowPage _ | ||
|
||
instance Show NoShowPage where | ||
show _ = "Toppoki.Page" | ||
|
||
newtype Selector = Selector String | ||
|
||
derive instance Newtype Selector _ | ||
|
||
newtype Action = Action String | ||
|
||
derive instance Newtype Action _ | ||
|
||
doJQ :: Selector -> Action -> Toki.Page -> Aff Unit | ||
doJQ selector action page = do | ||
log jq | ||
void $ Toki.unsafeEvaluateStringFunction jq page | ||
where | ||
jq :: String | ||
jq = "$('" <> unwrap selector <> "')." <> unwrap action | ||
|
||
click :: Action | ||
click = wrap "click()" | ||
|
||
enable :: Action | ||
enable = wrap "prop(\"disabled\", false)" | ||
|
||
setAttr :: String -> String -> Action | ||
setAttr attr value = wrap $ "attr(" <> jqStr attr <> ", " <> value <> ")" | ||
|
||
buttonWithText :: String -> Selector | ||
buttonWithText text = wrap $ "button:contains(" <> text <> ")" | ||
|
||
password :: Selector | ||
password = wrap ":password" | ||
|
||
jqStr :: String -> String | ||
jqStr str = "\"" <> str <> "\"" | ||
|
||
jqSet :: String -> String -> Action | ||
jqSet what value = wrap $ what <> "(" <> value <> ")" | ||
|
||
setText :: String -> Action | ||
setText = jqSet "text" <<< jqStr | ||
|
||
setValue :: String -> Action | ||
setValue = jqSet "val" <<< jqStr | ||
|
||
trigger :: String -> Action | ||
trigger event = wrap $ "trigger(" <> jqStr event <> ")" | ||
|
||
clickButton :: String -> Toki.Page -> Aff Unit | ||
clickButton buttonText = doJQ (buttonWithText buttonText) click | ||
|
||
injectJQueryAll :: String -> Toki.Browser -> Aff Unit | ||
injectJQueryAll jQuery browser = do | ||
pages <- Toki.pages browser | ||
void $ for pages $ Toki.unsafeEvaluateStringFunction jQuery | ||
|
||
testPassword :: String | ||
testPassword = "ctlctlctl" | ||
|
||
reactSetValue :: Selector -> String -> Toki.Page -> Aff Unit | ||
reactSetValue selector value page = void | ||
$ flip Toki.unsafeEvaluateStringFunction page | ||
$ fold | ||
[ -- https://stackoverflow.com/questions/23892547/what-is-the-best-way-to-trigger-onchange-event-in-react-js | ||
-- Nami uses react, which complicates things a bit | ||
"var input = $('" <> unwrap selector <> "').get(0);" | ||
, "var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set;" | ||
, "nativeInputValueSetter.call(input, '" <> value <> "');" | ||
, "var ev2 = new Event('input', { bubbles: true});" | ||
, "input.dispatchEvent(ev2);" | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,150 +1,47 @@ | ||
module Test.Examples.Pkh2Pkh where | ||
|
||
import Control.Monad.Maybe.Trans | ||
import Data.Traversable | ||
import Debug | ||
import Effect.Aff | ||
import Mote | ||
import Effect.Aff (delay) | ||
import Mote (test) | ||
import Prelude | ||
import Test.E2E.Wallet | ||
import TestM | ||
import Test.E2E.Wallet (Mode(..), launchWithNami) | ||
import TestM (TestPlanM) | ||
|
||
import Control.Category (identity) | ||
import Control.Monad.Error.Class (catchError) | ||
import Data.Array (head, filter, zip) | ||
import Data.Functor (void) | ||
import Data.Maybe (Maybe(..), isJust, fromMaybe) | ||
import Data.Newtype (class Newtype, wrap, unwrap) | ||
import Data.Tuple (fst, snd) | ||
import Effect.Class (liftEffect) | ||
import Effect.Class.Console (log) | ||
import Effect.Exception (throw) | ||
import Foreign (Foreign) | ||
import Foreign as Foreign | ||
import Test.E2E.Helpers (retrieveJQuery) | ||
import Test.Examples.Config (host) | ||
import Data.Maybe (isJust, Maybe(..)) | ||
import Data.Newtype (wrap) | ||
import Test.E2E.Helpers | ||
( clickButton | ||
, findNamiPage | ||
, injectJQueryAll | ||
, password | ||
, testPassword | ||
, reactSetValue | ||
, retrieveJQuery | ||
, NoShowPage(NoShowPage) | ||
) | ||
import Test.Spec.Assertions (shouldSatisfy) | ||
import Test.Toppoki (example) | ||
import Toppokki as Toki | ||
|
||
js :: String -> Toki.Page -> Aff Unit | ||
js str = void <$> Toki.unsafeEvaluateStringFunction str | ||
|
||
tryJs :: Toki.Selector -> String -> Toki.Page -> Aff (Maybe Unit) | ||
tryJs selector function page = catchError eval $ \e -> do | ||
log $ show e | ||
pure Nothing | ||
where | ||
eval :: Aff (Maybe Unit) | ||
eval = do | ||
_ <- Toki.unsafePageEval selector function page | ||
pure $ Just unit | ||
|
||
hasSelector :: Toki.Selector -> Toki.Page -> Aff (Maybe Unit) | ||
hasSelector selector page = tryJs selector "(x)=>{}" page | ||
|
||
{-retrieveJQuery :: Toki.Page -> Aff String | ||
retrieveJQuery page = Foreign.unsafeFromForeign <$> Toki.unsafeEvaluateStringFunction fetch page | ||
where fetch = "window.fetch('https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js')" | ||
-} | ||
|
||
injectJQuery :: String -> Toki.Page -> Aff Foreign | ||
injectJQuery = Toki.unsafeEvaluateStringFunction | ||
|
||
findNamiPage :: Toki.Browser -> Aff (Maybe Toki.Page) | ||
findNamiPage browser = do | ||
pages <- Toki.pages browser | ||
results <- traverse (hasSelector $ wrap "button") pages | ||
pure $ map snd $ head $ filter (isJust <<< fst) $ zip results pages | ||
|
||
-- | Wrapper for Page so it can be used in `shouldSatisfy` | ||
newtype NoShowPage = NoShowPage Toki.Page | ||
|
||
derive instance Newtype NoShowPage _ | ||
|
||
instance Show NoShowPage where | ||
show _ = "Toppoki.Page" | ||
|
||
newtype Selector = Selector String | ||
derive instance Newtype Selector _ | ||
|
||
newtype Action = Action String | ||
derive instance Newtype Action _ | ||
|
||
doJQ :: Selector -> Action -> Toki.Page -> Aff Unit | ||
doJQ selector action page = do | ||
log jq | ||
void $ Toki.unsafeEvaluateStringFunction jq page | ||
where jq :: String | ||
jq = "$('" <> unwrap selector <> "')." <> unwrap action | ||
|
||
click :: Action | ||
click = wrap "click()" | ||
|
||
enable :: Action | ||
enable = wrap "prop(\"disabled\", false)" | ||
|
||
setAttr :: String -> String -> Action | ||
setAttr attr value = wrap $ "attr(" <> jqStr attr <> ", " <> value <> ")" | ||
|
||
buttonWithText :: String -> Selector | ||
buttonWithText text = wrap $ "button:contains(" <> text <> ")" | ||
|
||
password :: Selector | ||
password = wrap ":password" | ||
|
||
jqStr :: String -> String | ||
jqStr str = "\"" <> str <> "\"" | ||
|
||
jqSet :: String -> String -> Action | ||
jqSet what value = wrap $ what <> "(" <> value <> ")" | ||
|
||
setText :: String -> Action | ||
setText = jqSet "text" <<< jqStr | ||
|
||
setValue :: String -> Action | ||
setValue = jqSet "val" <<< jqStr | ||
|
||
trigger :: String -> Action | ||
trigger event = wrap $ "trigger(" <> jqStr event <> ")" | ||
|
||
clickButton :: String -> Toki.Page -> Aff Unit | ||
clickButton buttonText = doJQ (buttonWithText buttonText) click | ||
|
||
injectJQueryAll :: String -> Toki.Browser -> Aff Unit | ||
injectJQueryAll jQuery browser = do | ||
pages <- Toki.pages browser | ||
void $ for pages $ Toki.unsafeEvaluateStringFunction jQuery | ||
|
||
testPassword :: String | ||
testPassword = "ctlctlctl" | ||
|
||
reactSetValue :: Selector -> String -> Toki.Page -> Aff Unit | ||
reactSetValue selector value page = void $ flip Toki.unsafeEvaluateStringFunction page $ fold | ||
[ -- https://stackoverflow.com/questions/23892547/what-is-the-best-way-to-trigger-onchange-event-in-react-js | ||
-- Nami uses react, which complicates things a bit | ||
"var input = $('" <> unwrap selector <> "').get(0);" | ||
, "var nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set;" | ||
, "nativeInputValueSetter.call(input, '" <> value <> "');" | ||
, "var ev2 = new Event('input', { bubbles: true});" | ||
, "input.dispatchEvent(ev2);" | ||
] | ||
|
||
testPkh2Pkh :: TestPlanM Unit | ||
testPkh2Pkh = test "Pkh2Pkh" do | ||
browser <- launchWithNami Visible | ||
page <- Toki.newPage browser | ||
jQuery <- retrieveJQuery page | ||
Toki.goto (wrap example) page | ||
-- find a nicer way for waiting | ||
delay (wrap 5000.0) | ||
injectJQueryAll jQuery browser | ||
namiPage <- findNamiPage browser | ||
shouldSatisfy (NoShowPage <$> namiPage) isJust | ||
case namiPage of | ||
-- I'm really unsure how to deal with this re. code guidelines... | ||
Nothing -> liftEffect $ throw "Impossible" | ||
Just np -> do clickButton "Access" np -- this matches when the wallet is used the first time | ||
clickButton "Sign" np | ||
reactSetValue password testPassword np | ||
clickButton "Confirm" np | ||
Just np -> do | ||
clickButton "Access" np -- this matches when the wallet is used the first time | ||
clickButton "Sign" np | ||
reactSetValue password testPassword np | ||
clickButton "Confirm" np | ||
delay (wrap 600000.0) | ||
|