Skip to content

Commit

Permalink
Add file based DSL steps
Browse files Browse the repository at this point in the history
  • Loading branch information
bjuric committed Sep 23, 2024
1 parent 4abcfc1 commit 4f4a722
Show file tree
Hide file tree
Showing 12 changed files with 347 additions and 97 deletions.
45 changes: 38 additions & 7 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,34 @@
3.75.0
======
23 September 2024
- Deprecated DSL steps:
- `I wait <duration> second[s] when <element> is <actioned>`
- `I wait until <condition> when <element> is <actioned>`
- Update Gwen core from v3.63.2 to v[3.64.0](https://github.com/gwen-interpreter/gwen/releases/tag/v3.64.0)
- Add file based DSL steps
- `<step> if "<filepath>" file[ not] exists`
- `<step> if "<filepath>" file does not exist`
- `<step> if <filepathRef file>[ not] exists`
- `<step> if <filepathRef file> does not exist`
- `<step> if "<filepath>" file is[ not] empty`
- `<step> if <filepathRef file> is[ not] empty`
- `<step> <until|while> "<filepath>" file[ not] exists`
- `<step> <until|while> "<filepath>" file does not exist`
- `<step> <until|while> <filepathRef file>[ not] exists`
- `<step> <until|while> <filepathRef file> does not exist`
- `<step> <until|while> "<filepath>" file is[ not] empty`
- `<step> <until|while> <filepathRef file> is[ not] empty`
- `I wait until "<filepath>" file[ not] exists`
- `I wait until "<filepath>" file does not exist`
- `I wait until <filepathRef file>[ not] exists`
- `I wait until <filepathRef file> does not exist`
- `I wait until "<filepath>" file is[ not] empty`
- `I wait until <filepathRef file> is[ not] empty`
- `"<filepath>" file should[ not] exist`
- `<filepathRef file> should[ not] exist`
- `"<filepath>" file should[ not] be empty`
- `<filepathRef file> should[ not] be empty`

3.74.3
======
21 September 2024
Expand Down Expand Up @@ -487,9 +518,9 @@ Oct 28, 2023
Oct 24, 2023
- Add DSLs for downloading files from a URL
- `I download "<url>" to "<filepath>"`
- `I download "<url>" to <filepathRef>`
- `I download "<url>" to <filepathRef file>`
- `I download the current URL to "<filepath>"`
- `I download the current URL to <filepathRef>`
- `I download the current URL to <filepathRef file>`
- Update selenium from v4.14.0 to v4.14.1
- Update Gwen core from v3.49.2 to v[3.50.0](https://github.com/gwen-interpreter/gwen/releases/tag/v3.50.0)

Expand Down Expand Up @@ -1256,9 +1287,9 @@ Aug 24, 2022
- Update Gwen core from v3.26.1 to v[3.27.0](https://github.com/gwen-interpreter/gwen/releases/tag/v3.27.0)
- Introduce CSV lookup DSLs:
- `I lookup <name> in the "<filepath>" file where "<predicate>"`
- `I lookup <name> in <filepathRef> file where "<predicate>"`
- `I lookup <name> in <filepathRef file> file where "<predicate>"`
- `I lookup <column> in the "<filepath>" file as <name> where "<predicate>"`
- `I lookup <column> in <filepathRef> file as <name> where "<predicate>"`
- `I lookup <column> in <filepathRef file> file as <name> where "<predicate>"`

3.29.1
======
Expand Down Expand Up @@ -1339,9 +1370,9 @@ Jul 21, 2022
- `I <write|append> "<text>" to "<filepath>" file`
- `I <write|append> <textRef> to "<filepath>" file`
- `I <write|append> new line to "<filepath>" file`
- `I <write|append> "<text>" to <filepathRef> file`
- `I <write|append> <textRef> to <filepathRef> file`
- `I <write|append> new line to <filepathRef> file`
- `I <write|append> "<text>" to <filepathRef file> file`
- `I <write|append> <textRef> to <filepathRef file> file`
- `I <write|append> new line to <filepathRef file> file`

3.24.0
======
Expand Down
4 changes: 2 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
enablePlugins(GitVersioning)

// gwen core & web versions
val gwenVersion = "3.63.2"
val gwenWebVersion = "3.74.3"
val gwenVersion = "3.64.0"
val gwenWebVersion = "3.75.0"

git.baseVersion := gwenWebVersion
git.useGitDescribe := true
Expand Down
91 changes: 38 additions & 53 deletions src/main/resources/gwen-web.dsl
Original file line number Diff line number Diff line change
Expand Up @@ -516,51 +516,6 @@ I untick <element> of <context>
I move to <element> of <context>
I send "<keys>"
I send "<keys>" to <element>
I wait 1 second when <element> is clicked
I wait 1 second when <element> is right clicked
I wait 1 second when <element> is double clicked
I wait 1 second when <element> is moved to
I wait 1 second when <element> is submitted
I wait 1 second when <element> is checked
I wait 1 second when <element> is ticked
I wait 1 second when <element> is unchecked
I wait 1 second when <element> is unticked
I wait 1 second when <element> is selected
I wait 1 second when <element> is deselected
I wait 1 second when <element> is typed
I wait 1 second when <element> is entered
I wait 1 second when <element> is tabbed
I wait 1 second when <element> is cleared
I wait <duration> seconds when <element> is clicked
I wait <duration> seconds when <element> is right clicked
I wait <duration> seconds when <element> is double clicked
I wait <duration> seconds when <element> is moved to
I wait <duration> seconds when <element> is submitted
I wait <duration> seconds when <element> is checked
I wait <duration> seconds when <element> is ticked
I wait <duration> seconds when <element> is unchecked
I wait <duration> seconds when <element> is unticked
I wait <duration> seconds when <element> is selected
I wait <duration> seconds when <element> is deselected
I wait <duration> seconds when <element> is typed
I wait <duration> seconds when <element> is entered
I wait <duration> seconds when <element> is tabbed
I wait <duration> seconds when <element> is cleared
I wait until <condition> when <element> is clicked
I wait until <condition> when <element> is right clicked
I wait until <condition> when <element> is double clicked
I wait until <condition> when <element> is moved to
I wait until <condition> when <element> is submitted
I wait until <condition> when <element> is checked
I wait until <condition> when <element> is ticked
I wait until <condition> when <element> is unchecked
I wait until <condition> when <element> is unticked
I wait until <condition> when <element> is selected
I wait until <condition> when <element> is deselected
I wait until <condition> when <element> is typed
I wait until <condition> when <element> is entered
I wait until <condition> when <element> is tabbed
I wait until <condition> when <element> is cleared
I wait until "<javascript>"
I wait until <condition>
I wait until <element> is displayed
Expand All @@ -579,6 +534,16 @@ I wait until <element> is not unchecked
I wait until <element> is not unticked
I wait until <element> is not enabled
I wait until <element> is not disabled
I wait until "<filepath>" file exists
I wait until <filepathRef file> exists
I wait until "<filepath>" file not exists
I wait until <filepathRef file> not exists
I wait until "<filepath>" file does not exist
I wait until <filepathRef file> does not exist
I wait until "<filepath>" file is empty
I wait until <filepathRef file> is empty
I wait until "<filepath>" file is not empty
I wait until <filepathRef file> is not empty
I wait 1 second
I wait <duration> seconds
I highlight <element>
Expand Down Expand Up @@ -630,6 +595,16 @@ I base64 decode <reference>
<step> while <element> is not enabled
<step> until <element> is not disabled
<step> while <element> is not disabled
<step> while "<filepath>" file exists
<step> until <filepathRef file> exists
<step> while "<filepath>" file not exists
<step> until <filepathRef file> not exists
<step> while "<filepath>" file does not exist
<step> until <filepathRef file> does not exist
<step> while "<filepath>" file is empty
<step> until <filepathRef file> is empty
<step> while "<filepath>" file is not empty
<step> until <filepathRef file> is not empty
I close the current browser
I close the browser
I start a new browser
Expand Down Expand Up @@ -815,6 +790,16 @@ I maximise the window
<step> if <element> does not match json path "<expression>"
<step> if <element> does not match template "<expression>"
<step> if <element> does not match template file "<filepath>"
<step> if "<filepath>" file exists
<step> if "<filepath>" file not exists
<step> if "<filepath>" file does not exist
<step> if "<filepath>" file is empty
<step> if "<filepath>" file is not empty
<step> if <filepathRef file> exists
<step> if <filepathRef file> not exists
<step> if <filepathRef file> does not exist
<step> if <filepathRef file> is empty
<step> if <filepathRef file> is not empty
<step> for each <entry> in <textRef> delimited by "<delimiter>"
<step> for each <entry> in <arrayRef> array
I drag and drop <sourceElement> to <targetElement>
Expand All @@ -826,19 +811,19 @@ I attach "<filepath>" as <name>
I write "<text>" to "<filepath>" file
I write <reference> to "<filepath>" file
I write new line to "<filepath>" file
I write "<text>" to <filePathRef> file
I write <reference> to <filePathRef> file
I write new line to <filePathRef> file
I write "<text>" to <filepathRef file>
I write <reference> to <filepathRef file>
I write new line to <filepathRef file>
I append "<text>" to "<filepath>" file
I append <reference> to "<filepath>" file
I append new line to "<filepath>" file
I append "<text>" to <filePathRef> file
I append <reference> to <filePathRef> file
I append new line to <filePathRef> file
I append "<text>" to <filepathRef file>
I append <reference> to <filepathRef file>
I append new line to <filepathRef file>
I download "<url>" to "<filepath>"
I download "<url>" to <filepathRef>
I download "<url>" to <filepathRef file>
I download the current URL to "<filepath>"
I download the current URL to <filepathRef>
I download the current URL to <filepathRef file>
<textRef> should be <percentage>% similar to "<text>"
<textRef> should be less than <percentage>% similar to "<text>"
<textRef> should be at most <percentage>% similar to "<text>"
Expand Down
12 changes: 7 additions & 5 deletions src/main/scala/gwen/web/eval/WebEngine.scala
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,10 @@ class WebEngine extends EvalEngine[WebContext] {
case r"""I wait for (.+?)$element""" =>
new WaitForElement(element, None)
case r"""I wait ([0-9]+?)$duration second(?:s?) when (.+?)$element is (clicked|right clicked|double clicked|submitted|checked|ticked|unchecked|unticked|selected|deselected|typed|entered|tabbed|cleared|moved to)$event""" =>
Deprecation.log("DSL step", "I wait <duration> second[s] when <element> is <actioned>", None)
new WaitForElementOnEvent(element, ElementEvent.valueOf(event), duration.toLong)
case r"""I wait until (.+?)$condition when (.+?)$element is (clicked|right clicked|double clicked||submitted|checked|ticked|unchecked|unticked|selected|deselected|typed|entered|tabbed|cleared|moved to)$event""" =>
Deprecation.log("DSL step", "I wait until <condition> when <element> is <actioned>", None)
new WaitForConditionOnEvent(element, ElementEvent.valueOf(event), condition)
case r"""I wait until "(.+?)$javascript" using (.+?)$delayPeriod (second|millisecond)$delayUnit delay and (.+?)$timeoutPeriod (minute|second|millisecond)$timeoutUnit timeout""" =>
Deprecation.log("Overloaded step", s"using $delayPeriod $delayUnit delay and $timeoutPeriod $timeoutUnit timeout", Some(s"@Delay('$delayPeriod${Map("second" -> "s", "millisecond" -> "ms")(delayUnit)}') @Timeout('$timeoutPeriod${Map("minute" -> "m", "second" -> "s", "millisecond" -> "ms")(timeoutUnit)}') annotations"))
Expand All @@ -167,7 +169,7 @@ class WebEngine extends EvalEngine[WebContext] {
case r"""I wait until (.+?)$condition using (.+?)$timeoutPeriod (minute|second|millisecond)$timeoutUnit timeout""" =>
Deprecation.log("Overloaded step", s"using $timeoutPeriod $timeoutUnit timeout", Some(s"@Timeout('$timeoutPeriod${Map("minute" -> "m", "second" -> "s", "millisecond" -> "ms")(timeoutUnit)}') annotation"))
new WaitForBoundCondition(condition, step.delayOpt.map(_.toMillis), Some(Duration(timeoutPeriod.toLong, timeoutUnit).toSeconds))
case r"""I wait until (.+?)$condition""" =>
case r"""I wait until (.+?)$condition""" if !condition.matches(".+ file (exists|not exists|does not exist|is empty|is not empty)") =>
new WaitForBoundCondition(condition, step.delayOpt.map(_.toMillis), step.timeoutOpt.map(_.toSeconds))
case r"""I am on the (.+?)$page""" =>
new CreatePageScope(page)
Expand Down Expand Up @@ -329,13 +331,13 @@ class WebEngine extends EvalEngine[WebContext] {
new CompareValueOrSelectionToValue(element, Option(selection).map(_.trim).map(DropdownSelection.valueOf), expression, ComparisonOperator.valueOf(operator), Option(negation).isDefined, step.message, Some(Duration.create(timeout.toLong, TimeUnit.SECONDS)), step.isTrim, step.isIgnoreCase)
case r"""(.+?)$element( text| value)?$selection should( not)?$negation (be|contain|start with|end with|match regex|match xpath|match json path|match template|match template file)$operator "(.*?)"$expression""" if !element.matches(".+at (json path|xpath).+") =>
new CompareValueOrSelectionToValue(element, Option(selection).map(_.trim).map(DropdownSelection.valueOf), step.orDocString(expression), ComparisonOperator.valueOf(operator), Option(negation).isDefined, step.message, step.timeoutOpt, step.isTrim, step.isIgnoreCase)
case r"""(.+?)$element( text| value)?$selection should( not)?$negation (be|contain|start with|end with|match regex|match xpath|match json path)$operator (.+?)$attribute with no (timeout|wait)$timeoutLiteral""" if attribute != "absent" && attribute != "defined" && !element.matches(".+at (json path|xpath).+") && !attribute.contains("% similar to ") && attribute != "no accumulated errors" && !attribute.contains('"') =>
case r"""(.+?)$element( text| value)?$selection should( not)?$negation (be|contain|start with|end with|match regex|match xpath|match json path)$operator (.+?)$attribute with no (timeout|wait)$timeoutLiteral""" if !attribute.matches("(absent|defined|empty|no accumulated errors)") && !attribute.contains("% similar to ") && !attribute.contains('"') && !element.matches(".+at (json path|xpath).+") =>
Deprecation.log("Overloaded step", s"with no $timeoutLiteral", Some("@Timeout('0s') annotation"))
new CompareValueOrSelectionToBoundValue(element, Option(selection).map(_.trim).map(DropdownSelection.valueOf), attribute, ComparisonOperator.valueOf(operator), Option(negation).isDefined, step.message, Some(Duration.Zero), step.isTrim, step.isIgnoreCase)
case r"""(.+?)$element( text| value)?$selection should( not)?$negation (be|contain|start with|end with|match regex|match xpath|match json path)$operator (.+?)$attribute with (\d+)$timeout second (timeout|wait)$timeoutLiteral""" if attribute != "absent" && attribute != "defined" && !element.matches(".+at (json path|xpath).+") && !attribute.contains("% similar to ") && attribute != "no accumulated errors" && !attribute.contains('"') =>
case r"""(.+?)$element( text| value)?$selection should( not)?$negation (be|contain|start with|end with|match regex|match xpath|match json path)$operator (.+?)$attribute with (\d+)$timeout second (timeout|wait)$timeoutLiteral""" if !attribute.matches("(absent|defined|empty|no accumulated errors)") && !attribute.contains("% similar to ") && !attribute.contains('"') && !element.matches(".+at (json path|xpath).+") =>
Deprecation.log("Overloaded step", s"with $timeout second $timeoutLiteral", Some(s"@Timeout('${timeout}s') annotation"))
new CompareValueOrSelectionToBoundValue(element, Option(selection).map(_.trim).map(DropdownSelection.valueOf), attribute, ComparisonOperator.valueOf(operator), Option(negation).isDefined, step.message, Some(Duration.create(timeout.toLong, TimeUnit.SECONDS)), step.isTrim, step.isIgnoreCase)
case r"""(.+?)$element( text| value)?$selection should( not)?$negation (be|contain|start with|end with|match regex|match xpath|match json path)$operator (.+?)$attribute""" if attribute != "absent" && attribute != "defined" && !element.matches(".+at (json path|xpath).+") && !attribute.contains("% similar to ") && attribute != "no accumulated errors" && !attribute.contains('"') =>
case r"""(.+?)$element( text| value)?$selection should( not)?$negation (be|contain|start with|end with|match regex|match xpath|match json path)$operator (.+?)$attribute""" if !attribute.matches("(absent|defined|empty|no accumulated errors)") && !attribute.contains("% similar to ") && !attribute.contains('"') && !element.matches(".+at (json path|xpath).+") =>
new CompareValueOrSelectionToBoundValue(element, Option(selection).map(_.trim).map(DropdownSelection.valueOf), attribute, ComparisonOperator.valueOf(operator), Option(negation).isDefined, step.message, step.timeoutOpt, step.isTrim, step.isIgnoreCase)
case r"""I capture (.+?)$attribute (?:of|on|in) (.+?)$element by (?:javascript|js) "(.+?)"$expression""" =>
new CaptureElementAttribute(element, attribute, step.orDocString(expression))
Expand Down Expand Up @@ -447,7 +449,7 @@ class WebEngine extends EvalEngine[WebContext] {
new AppendNewLineToElement(element)
case r"""I download the current URL to "(.+?)"$filepath""" =>
new DownloadCurrentUrlToFile(Some(filepath), None, defaultConditionTimeoutSecs)
case r"""I download the current URL to (.+?)$filepathRef""" =>
case r"""I download the current URL to (.+? file)$filepathRef""" =>
new DownloadCurrentUrlToFile(None, Some(filepathRef), defaultConditionTimeoutSecs)

case _ =>
Expand Down
25 changes: 25 additions & 0 deletions src/test/features/file/FileAsserts.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Feature: File assertions

Scenario: Assert file exists
Given the file is defined by js "'src/test/features/file/file.txt'"
When I capture the file
Then "src/test/features/file" file should exist
And the file should exist

Scenario: Assert file does not exist
Given the file is defined by js "'src/test/features/file/missing.txt'"
When I capture the file
Then "src/test/features/file/missing.txt" file should not exist
And the file should not exist

Scenario: Assert file shoud be empty
Given the file is defined by js "'src/test/features/file/file2.txt'"
When I capture the file
Then "src/test/features/file/file2.txt" file should be empty
And the file should be empty

Scenario: Assert file shoud not be empty
Given the file is defined by js "'src/test/features/file/file.txt'"
When I capture the file
Then "src/test/features/file/file.txt" file should not be empty
And the file should not be empty
Empty file.
30 changes: 30 additions & 0 deletions src/test/features/flow/IfCondition.feature
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,33 @@ Feature: If Conditionals
Given the state code is "QLD"
When I navigate to "https://example.com/?state=Other" if the state code does not match regex "(VIC|NSW)"
Then the current URL should be "https://example.com/?state=Other"

Scenario: Perform this if filepath exists
Given the target is "this"
When I perform this if "gwen.conf" file exists
And I perform that if "gwen.conf" file does not exist
Then the called step should be "this step"
And the called step should not be "that step"

Scenario: Perform this if fileref exists
Given the target is "that"
And the file is "gwen.conf"
When I perform that if the file exists
And I perform this if the file not exists
Then the called step should be "that step"
And the called step should not be "this step"

Scenario: Perform this if file empty or not
Given the target is "this"
When I perform this if "gwen.conf" file is not empty
And I perform that if "gwen.conf" file is empty
Then the called step should be "this step"
And the called step should not be "that step"

Scenario: Perform this if fileref emtpy or not
Given the target is "that"
And the file is "gwen.conf"
When I perform that if the file is not empty
And I perform this if the file is empty
Then the called step should be "that step"
And the called step should not be "this step"
Loading

0 comments on commit 4f4a722

Please sign in to comment.