Add bySelectorLabelContain
This commit is contained in:
parent
b28ee833d1
commit
bd86b4db7a
@ -170,6 +170,7 @@ module Yesod.Test
|
|||||||
, byLabelContain
|
, byLabelContain
|
||||||
, byLabelPrefix
|
, byLabelPrefix
|
||||||
, byLabelSuffix
|
, byLabelSuffix
|
||||||
|
, bySelectorLabelContain
|
||||||
, fileByLabel
|
, fileByLabel
|
||||||
, fileByLabelExact
|
, fileByLabelExact
|
||||||
, fileByLabelContain
|
, fileByLabelContain
|
||||||
@ -908,6 +909,54 @@ genericNameFromLabel match label = do
|
|||||||
name:_ -> return name
|
name:_ -> return name
|
||||||
_ -> failure $ "More than one label contained " <> label
|
_ -> failure $ "More than one label contained " <> label
|
||||||
|
|
||||||
|
-- |
|
||||||
|
-- This looks up the name of a field based on a CSS selector and the contents of the label pointing to it.
|
||||||
|
genericNameFromSelectorLabel :: HasCallStack => (T.Text -> T.Text -> Bool) -> T.Text -> T.Text -> RequestBuilder site T.Text
|
||||||
|
genericNameFromSelectorLabel match selector label = do
|
||||||
|
mres <- fmap rbdResponse getSIO
|
||||||
|
res <-
|
||||||
|
case mres of
|
||||||
|
Nothing -> failure "genericNameSelectorFromLabel: No response available"
|
||||||
|
Just res -> return res
|
||||||
|
let body = simpleBody res
|
||||||
|
html <-
|
||||||
|
case findBySelector body selector of
|
||||||
|
Left parseError -> failure $ "genericNameFromSelectorLabel: Parse error" <> T.pack parseError
|
||||||
|
Right [] -> failure $ "genericNameFromSelectorLabel: No fragments match selector " <> selector
|
||||||
|
Right [matchingFragment] -> pure $ BSL8.pack matchingFragment
|
||||||
|
Right _matchingFragments -> failure $ "genericNameFromSelectorLabel: Multiple fragments match selector " <> selector
|
||||||
|
let
|
||||||
|
parsedHTML = parseHTML html
|
||||||
|
mlabel = parsedHTML
|
||||||
|
$// C.element "label"
|
||||||
|
>=> isContentMatch label
|
||||||
|
mfor = mlabel >>= attribute "for"
|
||||||
|
|
||||||
|
isContentMatch x c
|
||||||
|
| x `match` T.concat (c $// content) = [c]
|
||||||
|
| otherwise = []
|
||||||
|
|
||||||
|
case mfor of
|
||||||
|
for:[] -> do
|
||||||
|
let mname = parsedHTML
|
||||||
|
$// attributeIs "id" for
|
||||||
|
>=> attribute "name"
|
||||||
|
case mname of
|
||||||
|
"":_ -> failure $ T.concat
|
||||||
|
[ "Label "
|
||||||
|
, label
|
||||||
|
, " resolved to id "
|
||||||
|
, for
|
||||||
|
, " which was not found. "
|
||||||
|
]
|
||||||
|
name:_ -> return name
|
||||||
|
[] -> failure $ "No input with id " <> for
|
||||||
|
[] ->
|
||||||
|
case filter (/= "") $ mlabel >>= (child >=> C.element "input" >=> attribute "name") of
|
||||||
|
[] -> failure $ "No label contained: " <> label
|
||||||
|
name:_ -> return name
|
||||||
|
_ -> failure $ "More than one label contained " <> label
|
||||||
|
|
||||||
byLabelWithMatch :: (T.Text -> T.Text -> Bool) -- ^ The matching method which is used to find labels (i.e. exact, contains)
|
byLabelWithMatch :: (T.Text -> T.Text -> Bool) -- ^ The matching method which is used to find labels (i.e. exact, contains)
|
||||||
-> T.Text -- ^ The text contained in the @\<label>@.
|
-> T.Text -- ^ The text contained in the @\<label>@.
|
||||||
-> T.Text -- ^ The value to set the parameter to.
|
-> T.Text -- ^ The value to set the parameter to.
|
||||||
@ -916,6 +965,15 @@ byLabelWithMatch match label value = do
|
|||||||
name <- genericNameFromLabel match label
|
name <- genericNameFromLabel match label
|
||||||
addPostParam name value
|
addPostParam name value
|
||||||
|
|
||||||
|
bySelectorLabelWithMatch :: (T.Text -> T.Text -> Bool) -- ^ The matching method which is used to find labels (i.e. exact, contains)
|
||||||
|
-> T.Text -- ^ The CSS selector.
|
||||||
|
-> T.Text -- ^ The text contained in the @\<label>@.
|
||||||
|
-> T.Text -- ^ The value to set the parameter to.
|
||||||
|
-> RequestBuilder site ()
|
||||||
|
bySelectorLabelWithMatch match selector label value = do
|
||||||
|
name <- genericNameFromSelectorLabel match selector label
|
||||||
|
addPostParam name value
|
||||||
|
|
||||||
-- How does this work for the alternate <label><input></label> syntax?
|
-- How does this work for the alternate <label><input></label> syntax?
|
||||||
|
|
||||||
-- | Finds the @\<label>@ with the given value, finds its corresponding @\<input>@, then adds a parameter
|
-- | Finds the @\<label>@ with the given value, finds its corresponding @\<input>@, then adds a parameter
|
||||||
@ -1029,6 +1087,18 @@ byLabelSuffix :: T.Text -- ^ The text in the @\<label>@.
|
|||||||
-> RequestBuilder site ()
|
-> RequestBuilder site ()
|
||||||
byLabelSuffix = byLabelWithMatch T.isSuffixOf
|
byLabelSuffix = byLabelWithMatch T.isSuffixOf
|
||||||
|
|
||||||
|
-- |
|
||||||
|
-- Note: This function throws an error if it finds multiple labels or if the
|
||||||
|
-- CSS selector fails to parse, doesn't match any fragment, or matches multiple
|
||||||
|
-- fragments.
|
||||||
|
--
|
||||||
|
-- @since 1.6.15
|
||||||
|
bySelectorLabelContain :: T.Text -- ^ The CSS selector.
|
||||||
|
-> T.Text -- ^ The text in the @\<label>@.
|
||||||
|
-> T.Text -- ^ The value to set the parameter to.
|
||||||
|
-> RequestBuilder site ()
|
||||||
|
bySelectorLabelContain = bySelectorLabelWithMatch T.isInfixOf
|
||||||
|
|
||||||
fileByLabelWithMatch :: (T.Text -> T.Text -> Bool) -- ^ The matching method which is used to find labels (i.e. exact, contains)
|
fileByLabelWithMatch :: (T.Text -> T.Text -> Bool) -- ^ The matching method which is used to find labels (i.e. exact, contains)
|
||||||
-> T.Text -- ^ The text contained in the @\<label>@.
|
-> T.Text -- ^ The text contained in the @\<label>@.
|
||||||
-> FilePath -- ^ The path to the file.
|
-> FilePath -- ^ The path to the file.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user