GithubHelp home page GithubHelp logo

unic / scalawebtest Goto Github PK

View Code? Open in Web Editor NEW
29.0 9.0 9.0 95.79 MB

ScalaWebTest is a library for writing ScalaTest/Selenium based integration tests for web applications. It helps you with your basic setup and provides a new and very efficient approach to testing.

Home Page: https://scalawebtest.org

License: Apache License 2.0

Scala 80.33% Java 10.35% HTML 9.12% Dockerfile 0.20%
integration-testing selenium scalatest

scalawebtest's Introduction

ScalaWebTest

Build Status Join the chat at https://gitter.im/ScalaWebTest/Lobby

ScalaWebTest is a library for writing ScalaTest/Selenium based integration tests for websites. It helps you with your basic setup and provides a new and very efficient approach to testing.

In manufacturing, it is common to use gauges (also called checking gauges or testing gauges) to verify whether a workpiece meets predefined criteria and tolerances. ScalaWebTest transfers this concept to the world of web integration testing. You can define a gauge in HTML, and use it to verify your web application. This greatly improves the readability, simplicity of your integration tests.

Read the full documentation on our website https://www.scalawebtest.org

Getting Started with development

Prerequisites

Get familiar with the sbt build tool because this is used to manage the project.

See Getting Started Guide

Compile, test, package

$ sbt compile test package

Run whole integration test

Before running the integration tests, you will need to configure WEBDRIVER_CHROME_DRIVER environment variable. To do so, run the following command:

$ export WEBDRIVER_CHROME_DRIVER="$(which chromedriver)"

Then run the tests using the command below:

$ sbt inttest

This will start a Jetty server, executes the integration tests and stops the server again.

Start Jetty server and run single tests

If you would like to run the Jetty server and in parallel work on integration tests, and some code changes, you can do the following:

# Enter the sbt console first, enter 'sbt' in root folder
$ sbt

# Start Jetty server
sbt> jetty:start

# Or if you would like that sbt automatically restarts Jetty after code changes then do:
sbt> ~jetty:start

# Open separate command window and enter the sbt console agains
# Run a single integration tests
sbt> it:testOnly org.scalawebtest.integration.gauge.ContainsSpec

How to Release

Prerequisites

  1. Create the file ~/.sbt/1.0/plugins/gpg.sbt and add the following line addSbtPlugin("com.jsuereth" % "sbt-pgp" % "2.0.1")

  2. Create the file ~/sbt/1.0/global.sbt and add the following line Global / useGpg := false or install gpg according to the sbt-pgp documentation.

  3. Copy the private key (Sonatype PGP Private and Public Key from our company password store), to ~/.sbt/gpg/secring.asc

  4. Create the file ~/.sbt/1.0/sonatype.sbt and add the following content, then replace username and password with your personal oss.sonatype credentials

credentials += Credentials("Sonatype Nexus Repository Manager",
                           "oss.sonatype.org",
                           "<your username>",
                           "<your password>")

Release

The release process of ScalaWebTest is currently done manually. The process is as follows:

  1. Switch the version in build.sbt to that which is to be released (e.g. from 0.0.1-SNAPSHOT to 1.0.0)
  2. In your command line type in the following:
    1. navigate to the root folder of the ScalaWebTest git repository
    2. sbt - enters the sbt interactive mode
    3. + clean - deletes all generated files (target)
    4. + test - compiles and tests the main sources
    5. + doc - generate scaladoc
    6. mimaReportBinaryIssues - execute the Migration Manager to verify binary compatibility
    7. inttest - compile and run the integration tests
    8. + publishSigned - publishes all packages, sources and poms
    9. Enter the Sonatype PGP Key Password as stored in our company password store
    10. Go to https://oss.sonatype.org/#stagingRepositories close and release the staging repository
    11. exit - exits the sbt interactive mode
  3. Commit your changes with the commit message "Release x.x.x" (e.g. Release 1.0.0)
  4. Tag this commit with the release version git tag -a x.x.x -m "x.x.x"
  5. Switch the version in build.sbt to the snapshot version (e.g. from 1.0.0 to 1.0.0-SNAPSHOT) and update the documentation if needed
  6. Finally, commit those changes with the commit message "Bump version to x.x.x-SNAPSHOT" (e.g. Bump version to 1.0.0-SNAPSHOT)
  7. Push your changes, and the tag

Website

The website's parts are found in the docs-folder of this project. It is built using jekyll, please see the serve_local-files for local serving. Or use the following command:

bundle exec jekyll build

The website is deployed through Netlify. It's deployment configurations are found in netlify.tom. Please find the login in our company password store.

scalawebtest's People

Contributors

danirey avatar fabianmum avatar fabianpage avatar gitter-badger avatar marcel-wiedemeier avatar marcospereira avatar olaf-otto avatar remo-vonarx avatar yannisgu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

scalawebtest's Issues

Improve build

Prefereably the build wouldn't need a seperate alias "inttest" to execut jetty:start; it:test; jetty:stop.

I would rather have jetty:start attached to the Tests.Setup of IntegrationTest and jetty:stop to Tests.Cleanup.

Only report the closest match which didn't fit

In case we have the following HtmlElement

<select>
 <option value="foo">foo</option>
 <option value="bar1">bar</option>
</select>

and the following Gauge definition

elem fits(<option value="bar">bar</option>)

It would currently report
Misfitting Attribute: [value] in [HtmlOption[<option value="foo">]] with value[bar] didn't equal [bar]
Misfitting Attribute: [value] in [HtmlOption[<option value="bar1">]] with value[bar1] didn't equal [bar]

A human would immediately see, that the second element is what we where looking for, because the text is correct, but only the value attribute is off. While with the first candidate, both text and value are off.

If we would try every attribute instead of reporting a misfit, as soon as an attribute of the gauge definition doesn't fit, we could provide better Misfit reports.

In case we find a solution for this, we have to make sure it doesn't hurt performance too much. Maybe one could only execute the deeper analysis of misfits, in case the gauge doesn't fit.

execute navigateTo automatically for every test

Often multiple tests are chained together using the it keyword. When doing so, usually only the first spec contains a navigateTo(url) call. When only starting a single test, which isn't the first one, the test fails, because navigateTo is not called.

We should provide an easy way to configure a URL which is then used for all tests. Depending on the situation, the test suite should automatically call navigateTo befor the test, no matter wheter all or only a single test is executed.

HTML Gauges can't handle ID-less sibling elements of the same type

Using ScalaWebTest 1.1.0 (but the issue occurred with previous versions as well), HTML gauges seem to have a problem with sibling elements without IDs.

Page HTML:

...
<select name="foobar" class="select">
  <option value="foo" selected="selected">foo</option>
  <option value="bar">bar</option>
  <option value="baz">baz</option>
</select>
...

ScalaWebTest gauge:

fits(
  <select name="foobar" class="select">
    <option value="foo" selected="selected">foo</option>
    <option value="bar">bar</option>
    <option value="baz">baz</option>
  </select>
)

Result:

Misfitting Attribute: [value] in [HtmlOption[<option value="foo" selected="selected">]] with value[foo] didn't equal [baz]
Misfitting Attribute: [value] in [HtmlOption[<option value="bar">]] with value[bar] didn't equal [baz]

This also happens with other elements like div and li.

Provide Dockerfile

In a containerized environment it makes sense to run ScalaWebTest within a container as well. In this case a multi-stage would make sense.

In the first stage the Tests would be compiled.
In the second stage the Test would be executed.

The resulting docker image should be reasonably small and fast to build. When executed on a container orchestration platform, it is easier to automate, when the tests are executed on the platform as well.

Add Migration Manager to verify binary compatibility

Asserting binary compatibility is a quality for frameworks. The Migration Manager for Scala helps asserting binary compatibility. Therefore ScalaWebTest should start using Migration Manager and start to use binary compatibility for minor versions (http://semver.org/)

A thorough documentation of binary compatibility in the official Scala documentation is currently underway, see https://github.com/scala/docs.scala-lang/pull/881/files#diff-555d4a5d3e8f97eac0ac4050b659fe18

The Migration Manager is available as SBT plugin and may be executed with sbt mimaReportBinaryIssues
(https://github.com/typesafehub/migration-manager/wiki/Sbt-plugin)

Add support for checking http codes

Adding support for checking http codes.

This is useful if you want to check for example the existence of some resource.

This is also useful to test pure Web APIs with proper REST-oriented http codes.

There is for example a possibility to get it like this:

webRespone = webDriver.getClient.getCurrentWindow.getEnclosedPage.getWebResponse
webResponse.getStatusCode

Maybe this is a starting point.

Update Documentation for 3.0.0

Following parts of the documentation require an update

  • JSON module #67
  • Getting started and Download (update the version numbers)
  • new chapter describing how to use other browsers #74
  • search for references regarding Scala 2.10
  • write the release notes, including migration description
  • document which env variables or -D parameters are available
  • document how configuration changed in general #12
  • document how and when we can access response codes and response headers #21
  • improve visualization of gauges

Make ScalaWebTest compatible with all implementations of Selenium WebDriver

If we do not depend on HtmlUnits HTML parsing, we can use other Drivers as well and even extract the gauge logic completely. Ideally, we can compile this for Scala.js and use it in other tools like TestCafé. This will not be possible, as we have to parse HTML (see next comment). Most probably a rewrite for JS is the better option, if we want to use Gauges in TestCafé.

Provide fits/doesntFit for Element

Create a variant of fits/doesntFit, which allows the caller to provide the element which he expects to fit/notFit.

This allows for tests like the following

"Every gallery image" should "use the expected HTML" in {
    for (image <- findAll(CssSelectorQuery("ul div.image_columns"))) {
      image fits
        <div class="columns image_columns">
          <a href="@regex \/gallery\/image\/\d">
            <figure class="obj_aspect_ratio">
              <img class="obj_full" src="@regex \/image\/\d\.jpg\?w=600"></img>
            </figure>
          </a>
        </div>
    }
  }

This is very interesting when verifying a group of similar elements within a page.

Current version as jekyll property for website

All examples on the website should reference the current version. Currently, when releasing a new version of ScalaWebTest, all version numbers have to be updated. Using a jekyll property, would simplify this process and prevent mistakes.

Improve the TextMatcher

When matching text now with the ExactMatcher as default, the behavior isn't quite correct because the text from all the child tags of the selected tag is included. This needs to be fixed by excluding all the text except for what is directly in the tag wanted.

configuration "it" don't exists and comma is missing.

Hi,
i'm not so skilled with scala,
but i think there is something wrong with "Getting Started" in https://www.scalawebtest.org/documentation.html .

  1. i think a comma is missing

image

  1. even if i add the comma, i obtain this error
java.lang.IllegalArgumentException: Cannot add dependency 'org.scalawebtest#scalawebtest-core_2.12;2.0.1' to configuration 'it' of module default#scalawebtestexample_2.12;0.1 because this configuration doesn't exist!

that can be solved removing "it" configuration.

follow the complete log.

Error while importing sbt project:


[info] Loading settings for project global-plugins from idea.sbt ...
[info] Loading global plugins from C:\Users\andrea.bisello\.sbt\1.0\plugins
[info] Loading project definition from C:\src\scalawebtestexample\project
[info] Loading settings for project scalawebtestexample from build.sbt ...
[info] Set current project to scalawebtestexample (in build file:/C:/src/scalawebtestexample/)
[info] sbt server started at local:sbt-server-b7bda8432ba60dde419c
sbt:scalawebtestexample>
[info] Defining Global / sbtStructureOptions, Global / sbtStructureOutputFile, shellPrompt
[info] The new values will be used by no settings or tasks.
[info] Reapplying settings...
[info] Set current project to scalawebtestexample (in build file:/C:/src/scalawebtestexample/)
[info] Applying State transformations org.jetbrains.sbt.CreateTasks from C:/Users/andrea.bisello/.IdeaIC2018.2/config/plugins/Scala/launcher/sbt-structure-1.0.jar
[info] Reapplying settings...
[info] Set current project to scalawebtestexample (in build file:/C:/src/scalawebtestexample/)
[info] Updating ...
[error] java.lang.IllegalArgumentException: Cannot add dependency 'org.scalawebtest#scalawebtest-core_2.12;2.0.1' to configuration 'it' of module default#scalawebtestexample_2.12;0.1 because this configuration doesn't exist!
[error] 	at org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor.addDependencyConfiguration(DefaultDependencyDescriptor.java:565)
[error] 	at org.apache.ivy.plugins.parser.AbstractModuleDescriptorParser$AbstractParser.parseDepsConfs(AbstractModuleDescriptorParser.java:157)
[error] 	at org.apache.ivy.plugins.parser.AbstractModuleDescriptorParser$AbstractParser.parseDepsConfs(AbstractModuleDescriptorParser.java:128)
[error] 	at org.apache.ivy.plugins.parser.AbstractModuleDescriptorParser$AbstractParser.parseDepsConfs(AbstractModuleDescriptorParser.java:118)
[error] 	at org.apache.ivy.plugins.parser.AbstractModuleDescriptorParser$AbstractParser.parseDepsConfs(AbstractModuleDescriptorParser.java:113)
[error] 	at sbt.internal.librarymanagement.CustomXmlParser$CustomParser.parseDepsConfs(CustomXmlParser.scala:36)
[error] 	at sbt.internal.librarymanagement.IvySbt$.convertDependency(Ivy.scala:925)
[error] 	at sbt.internal.librarymanagement.IvySbt$.$anonfun$addDependencies$1(Ivy.scala:862)
[error] 	at scala.collection.TraversableLike.$anonfun$map$1(TraversableLike.scala:233)
[error] 	at scala.collection.Iterator.foreach(Iterator.scala:937)
[error] 	at scala.collection.Iterator.foreach$(Iterator.scala:937)
[error] 	at scala.collection.AbstractIterator.foreach(Iterator.scala:1425)
[error] 	at scala.collection.IterableLike.foreach(IterableLike.scala:70)
[error] 	at scala.collection.IterableLike.foreach$(IterableLike.scala:69)
[error] 	at scala.collection.AbstractIterable.foreach(Iterable.scala:54)
[error] 	at scala.collection.TraversableLike.map(TraversableLike.scala:233)
[error] 	at scala.collection.TraversableLike.map$(TraversableLike.scala:226)
[error] 	at scala.collection.AbstractTraversable.map(Traversable.scala:104)
[error] 	at sbt.internal.librarymanagement.IvySbt$.addDependencies(Ivy.scala:861)
[error] 	at sbt.internal.librarymanagement.IvySbt$Module.configureInline(Ivy.scala:288)
[error] 	at sbt.internal.librarymanagement.IvySbt$Module.x$7$lzycompute(Ivy.scala:253)
[error] 	at sbt.internal.librarymanagement.IvySbt$Module.x$7(Ivy.scala:250)
[error] 	at sbt.internal.librarymanagement.IvySbt$Module.moduleDescriptor0$lzycompute(Ivy.scala:250)
[error] 	at sbt.internal.librarymanagement.IvySbt$Module.moduleDescriptor0(Ivy.scala:250)
[error] 	at sbt.internal.librarymanagement.IvySbt$Module.$anonfun$withModule$1(Ivy.scala:239)
[error] 	at sbt.internal.librarymanagement.IvySbt.$anonfun$withIvy$1(Ivy.scala:204)
[error] 	at sbt.internal.librarymanagement.IvySbt.sbt$internal$librarymanagement$IvySbt$$action$1(Ivy.scala:70)
[error] 	at sbt.internal.librarymanagement.IvySbt$$anon$3.call(Ivy.scala:77)
[error] 	at xsbt.boot.Locks$GlobalLock.withChannel$1(Locks.scala:95)
[error] 	at xsbt.boot.Locks$GlobalLock.xsbt$boot$Locks$GlobalLock$$withChannelRetries$1(Locks.scala:80)
[error] 	at xsbt.boot.Locks$GlobalLock$$anonfun$withFileLock$1.apply(Locks.scala:99)
[error] 	at xsbt.boot.Using$.withResource(Using.scala:10)
[error] 	at xsbt.boot.Using$.apply(Using.scala:9)
[error] 	at xsbt.boot.Locks$GlobalLock.ignoringDeadlockAvoided(Locks.scala:60)
[error] 	at xsbt.boot.Locks$GlobalLock.withLock(Locks.scala:50)
[error] 	at xsbt.boot.Locks$.apply0(Locks.scala:31)
[error] 	at xsbt.boot.Locks$.apply(Locks.scala:28)
[error] 	at sbt.internal.librarymanagement.IvySbt.withDefaultLogger(Ivy.scala:77)
[error] 	at sbt.internal.librarymanagement.IvySbt.withIvy(Ivy.scala:199)
[error] 	at sbt.internal.librarymanagement.IvySbt.withIvy(Ivy.scala:196)
[error] 	at sbt.internal.librarymanagement.IvySbt$Module.withModule(Ivy.scala:238)
[error] 	at sbt.internal.librarymanagement.IvyActions$.updateEither(IvyActions.scala:193)
[error] 	at sbt.librarymanagement.ivy.IvyDependencyResolution.update(IvyDependencyResolution.scala:20)
[error] 	at sbt.librarymanagement.DependencyResolution.update(DependencyResolution.scala:56)
[error] 	at sbt.internal.LibraryManagement$.resolve$1(LibraryManagement.scala:45)
[error] 	at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$12(LibraryManagement.scala:93)
[error] 	at sbt.util.Tracked$.$anonfun$lastOutput$1(Tracked.scala:68)
[error] 	at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$19(LibraryManagement.scala:106)
[error] 	at scala.util.control.Exception$Catch.apply(Exception.scala:224)
[error] 	at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$11(LibraryManagement.scala:106)
[error] 	at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$11$adapted(LibraryManagement.scala:89)
[error] 	at sbt.util.Tracked$.$anonfun$inputChanged$1(Tracked.scala:149)
[error] 	at sbt.internal.LibraryManagement$.cachedUpdate(LibraryManagement.scala:120)
[error] 	at sbt.Classpaths$.$anonfun$updateTask$5(Defaults.scala:2556)
[error] 	at scala.Function1.$anonfun$compose$1(Function1.scala:44)
[error] 	at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:40)
[error] 	at sbt.std.Transform$$anon$4.work(System.scala:67)
[error] 	at sbt.Execute.$anonfun$submit$2(Execute.scala:269)
[error] 	at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:16)
[error] 	at sbt.Execute.work(Execute.scala:278)
[error] 	at sbt.Execute.$anonfun$submit$1(Execute.scala:269)
[error] 	at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:178)
[error] 	at sbt.CompletionService$$anon$2.call(CompletionService.scala:37)
[error] 	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error] 	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
[error] 	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error] 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
[error] 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
[error] 	at java.lang.Thread.run(Thread.java:748)
[error] java.lang.IllegalArgumentException: Cannot add dependency 'org.scalawebtest#scalawebtest-core_2.12;2.0.1' to configuration 'it' of module default#scalawebtestexample_2.12;0.1 because this configuration doesn't exist!
[error] 	at org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor.addDependencyConfiguration(DefaultDependencyDescriptor.java:565)
[error] 	at org.apache.ivy.plugins.parser.AbstractModuleDescriptorParser$AbstractParser.parseDepsConfs(AbstractModuleDescriptorParser.java:157)
[error] 	at org.apache.ivy.plugins.parser.AbstractModuleDescriptorParser$AbstractParser.parseDepsConfs(AbstractModuleDescriptorParser.java:128)
[error] 	at org.apache.ivy.plugins.parser.AbstractModuleDescriptorParser$AbstractParser.parseDepsConfs(AbstractModuleDescriptorParser.java:118)
[error] 	at org.apache.ivy.plugins.parser.AbstractModuleDescriptorParser$AbstractParser.parseDepsConfs(AbstractModuleDescriptorParser.java:113)
[error] 	at sbt.internal.librarymanagement.CustomXmlParser$CustomParser.parseDepsConfs(CustomXmlParser.scala:36)
[error] 	at sbt.internal.librarymanagement.IvySbt$.convertDependency(Ivy.scala:925)
[error] 	at sbt.internal.librarymanagement.IvySbt$.$anonfun$addDependencies$1(Ivy.scala:862)
[error] 	at scala.collection.TraversableLike.$anonfun$map$1(TraversableLike.scala:233)
[error] 	at scala.collection.Iterator.foreach(Iterator.scala:937)
[error] 	at scala.collection.Iterator.foreach$(Iterator.scala:937)
[error] 	at scala.collection.AbstractIterator.foreach(Iterator.scala:1425)
[error] 	at scala.collection.IterableLike.foreach(IterableLike.scala:70)
[error] 	at scala.collection.IterableLike.foreach$(IterableLike.scala:69)
[error] 	at scala.collection.AbstractIterable.foreach(Iterable.scala:54)
[error] 	at scala.collection.TraversableLike.map(TraversableLike.scala:233)
[error] 	at scala.collection.TraversableLike.map$(TraversableLike.scala:226)
[error] 	at scala.collection.AbstractTraversable.map(Traversable.scala:104)
[error] 	at sbt.internal.librarymanagement.IvySbt$.addDependencies(Ivy.scala:861)
[error] 	at sbt.internal.librarymanagement.IvySbt$Module.configureInline(Ivy.scala:288)
[error] 	at sbt.internal.librarymanagement.IvySbt$Module.x$7$lzycompute(Ivy.scala:253)
[error] 	at sbt.internal.librarymanagement.IvySbt$Module.x$7(Ivy.scala:250)
[error] 	at sbt.internal.librarymanagement.IvySbt$Module.moduleDescriptor0$lzycompute(Ivy.scala:250)
[error] 	at sbt.internal.librarymanagement.IvySbt$Module.moduleDescriptor0(Ivy.scala:250)
[error] 	at sbt.internal.librarymanagement.IvySbt$Module.$anonfun$withModule$1(Ivy.scala:239)
[error] 	at sbt.internal.librarymanagement.IvySbt.$anonfun$withIvy$1(Ivy.scala:204)
[error] 	at sbt.internal.librarymanagement.IvySbt.sbt$internal$librarymanagement$IvySbt$$action$1(Ivy.scala:70)
[error] 	at sbt.internal.librarymanagement.IvySbt$$anon$3.call(Ivy.scala:77)
[error] 	at xsbt.boot.Locks$GlobalLock.withChannel$1(Locks.scala:95)
[error] 	at xsbt.boot.Locks$GlobalLock.xsbt$boot$Locks$GlobalLock$$withChannelRetries$1(Locks.scala:80)
[error] 	at xsbt.boot.Locks$GlobalLock$$anonfun$withFileLock$1.apply(Locks.scala:99)
[error] 	at xsbt.boot.Using$.withResource(Using.scala:10)
[error] 	at xsbt.boot.Using$.apply(Using.scala:9)
[error] 	at xsbt.boot.Locks$GlobalLock.ignoringDeadlockAvoided(Locks.scala:60)
[error] 	at xsbt.boot.Locks$GlobalLock.withLock(Locks.scala:50)
[error] 	at xsbt.boot.Locks$.apply0(Locks.scala:31)
[error] 	at xsbt.boot.Locks$.apply(Locks.scala:28)
[error] 	at sbt.internal.librarymanagement.IvySbt.withDefaultLogger(Ivy.scala:77)
[error] 	at sbt.internal.librarymanagement.IvySbt.withIvy(Ivy.scala:199)
[error] 	at sbt.internal.librarymanagement.IvySbt.withIvy(Ivy.scala:196)
[error] 	at sbt.internal.librarymanagement.IvySbt$Module.withModule(Ivy.scala:238)
[error] 	at sbt.internal.librarymanagement.IvyActions$.updateEither(IvyActions.scala:193)
[error] 	at sbt.librarymanagement.ivy.IvyDependencyResolution.update(IvyDependencyResolution.scala:20)
[error] 	at sbt.librarymanagement.DependencyResolution.update(DependencyResolution.scala:56)
[error] 	at sbt.internal.LibraryManagement$.resolve$1(LibraryManagement.scala:45)
[error] 	at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$12(LibraryManagement.scala:93)
[error] 	at sbt.util.Tracked$.$anonfun$lastOutput$1(Tracked.scala:68)
[error] 	at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$19(LibraryManagement.scala:106)
[error] 	at scala.util.control.Exception$Catch.apply(Exception.scala:224)
[error] 	at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$11(LibraryManagement.scala:106)
[error] 	at sbt.internal.LibraryManagement$.$anonfun$cachedUpdate$11$adapted(LibraryManagement.scala:89)
[error] 	at sbt.util.Tracked$.$anonfun$inputChanged$1(Tracked.scala:149)
[error] 	at sbt.internal.LibraryManagement$.cachedUpdate(LibraryManagement.scala:120)
[error] 	at sbt.Classpaths$.$anonfun$updateTask$5(Defaults.scala:2556)
[error] 	at scala.Function1.$anonfun$compose$1(Function1.scala:44)
[error] 	at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:40)
[error] 	at sbt.std.Transform$$anon$4.work(System.scala:67)
[error] 	at sbt.Execute.$anonfun$submit$2(Execute.scala:269)
[error] 	at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:16)
[error] 	at sbt.Execute.work(Execute.scala:278)
[error] 	at sbt.Execute.$anonfun$submit$1(Execute.scala:269)
[error] 	at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:178)
[error] 	at sbt.CompletionService$$anon$2.call(CompletionService.scala:37)
[error] 	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error] 	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
[error] 	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error] 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
[error] 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
[error] 	at java.lang.Thread.run(Thread.java:748)
[error] (update) java.lang.IllegalArgumentException: Cannot add dependency 'org.scalawebtest#scalawebtest-core_2.12;2.0.1' to configuration 'it' of module default#scalawebtestexample_2.12;0.1 because this configuration doesn't exist!
[error] (ssExtractDependencies) java.lang.IllegalArgumentException: Cannot add dependency 'org.scalawebtest#scalawebtest-core_2.12;2.0.1' to configuration 'it' of module default#scalawebtestexample_2.12;0.1 because this configuration doesn't exist!
[error] Total time: 0 s, completed 22-ott-2018 17.36.25
[info] shutting down server


JsonGauge: fit values but ignoring the order of array elements

Json arrays are ordered. Therefore when using the JsonGauge in ScalaWebTest with

jsonGauge fits values of json the order of elements in an array matters.

Sometimes we do not care about the order in a test. To support this use case, a "matcher" valuesIgnoringArrayOrder should be added.

Given

val ordered = Json.parse("""["a", "b", "c"]""")
val unordered = """["b", "c", "a"]"""

The following should throw
ordered fits values of unordered

"[a]" did not equal "[b]" in 
ScalaTestFailureLocation: ...
Expected :"[b]" in 
Actual   :"[a]"

While valuesIgnoringArrayOrder ignores the order and is happy

ordered fits valuesIgnoringArrayOrder of unordered

Should be totally fine with the unorderedhaving a different order then ordered gauge.

Upgrade dependencies

Play JSON was released for 2.12, upgrade to 2.6.6
Play JSON for Scala 2.11 2.5.9 -> 2.6.6
Play JSON for Scala 2.12 2.6.0-M4 -> 2.6.6
ScalaTest 3.0.1 -> 3.0.4
Selenium-Java 3.3.0- -> 3.6.0
HTML Unit 2.25 -> 2.27
Slf4j API 1.7.24 -> 1.7.25

Add support for Scala 2.13, remove support for Scala 2.10

Scala 2.13 will be released soon, ScalaTest is already cross-compiled for 2.13.

It is a good point in time to add support for 2.13 and remove 2.10.

Simultaneously we can (Java libraries) and or have to (Scala libraries) upgrade all dependencies.

As soon as we have a stable version, we can relase a release candidate, and then short after Scala 2.13 is released the final ScalaWebTest 3.0.0 release.

Misfitting Element Order can be misleading

Assume the following HtmlElement

<h2 class="title">foo</h2>
<p>text</p>

and the following gauge definition

element fits(
<h2 class="title">foo</h2>
<p>text</p>
<h2 class="title"></h2>
)

This will lead to the following error

Misfitting Element Order: Wrong order of elements [<h2 class="title">foo</h2>] was found before [<p>text</p>] but expected the other way round.

The last part of the gauge definition <h2 class="title"></h2> also matches <h2 class="title">foo</h2> but in this case it is at the wrong position and therefore a misfit is reported.

The error message should be improved to point out the fact, that the element is either not found, or only found in the wrong position. We should guide the user, by not only showing the element which was found, but also the gauge definition which led to that element being found.

Create Website

Create a website (gh-pages) for ScalaWebTest, mainly hosting the documentation.

Update to SBT 1.x

Update from sbt 0.13.18 to sbt 1.2.8 and simplify build as far as possible.

Move the build base trait

Building you own base trait is done too early in the documentation. Move it further down, to clarify that this isn't mandatory and that extending the IntegrationSpec isn't mandatory.

There is no connection between using Gauges and the IntegrationSpec base trait.

Provide BOM

A bill-of-materials should be provided to improve the dependency management for projects using ScalaWebTests. With a BOM the user can control his dependencies, instead of using hoping for all transitive dependencies to align.

Misfit relevance calculation is wrong

When trying to fit a HtmlPage or HtmlElement into a gauge, many so-called misfits will be reported during the process.

For example with the following HtmlElement

<ul>
  <li>foo</li>
  <li>bar<li>
</ul>

And the gauge
elem fits (<li>bar</li>)

The Gauge will first try to match <li>foo</li> and report a misfit. In case another candidate matches the gauge (as it is the case in our example), the misfit will be thrown away and the Gauge reports a fit.

In case no matching element is found, the Gauge will fail and report the most relevant misfits. To do so, a misfit relevance is attached to every misfit. The misfit relevance should increase the further down we go into the gauge definition.

Recent tests showed that it increases when the element is nested deeper, but doesn't if it is further down. Assume the following gauge definition

<div>
 <ul>
  <li>
   <a href="#">link</a>
  </li>
 </ul>
 <p>text</p>
<div>

If a misfit is reported when trying to fit <p>text</p> it should have a higher misfit relevance than, when reporting a misfit for <a href="#">link</a>, as we obviously managed to match everything else. Unfortunately this is currently not the case.

Fix handling of empty class attribute in gauge definition

Currently, when an empty CSS selector is used in a gauge definition (which semantically equals no css attribute at all), an exception is thrown:

head of empty list
java.util.NoSuchElementException: head of empty list
	at scala.collection.immutable.Nil$.head(List.scala:417)
	at scala.collection.immutable.Nil$.head(List.scala:414)
	at org.scalawebtest.core.gauge.Gauge.classSelector$1(Gauge.scala:144)
	at org.scalawebtest.core.gauge.Gauge.nodeToCssSelector(Gauge.scala:149)
	at org.scalawebtest.core.gauge.Gauge.findFittingNode(Gauge.scala:227)
	at org.scalawebtest.core.gauge.Gauge.nodeFits(Gauge.scala:164)

In contrast, this is not the case for attributes other than "class".

Provide gauge functions via trait

Provide functions to build core.Gauge (HtmlGauge) and json.Gauge (JsonGauge), to releave users from having to manually tweak there imports.

Update versions of dependencies

There is new versions for almost everything

SBT
0.13.15 -> 0.13.16

(Migration to SBT 1.0 might be quite an effort, because we use Plugins. Also the cross-version build
for the JSON module is not simple. Currently there is not much value in upgrading to 1.0
For an open-source project the build should mainly be in a way, that everyone can use it. Currently SBT 0.13.x is fine as build tool for an open-source project in the Scala community)

Scala

  • 2.12.3 -> 2.12.7
  • 2.11.11 -> 2.11.12
  • 2.10.6 -> 2.10.7

ScalaTest 3.0.4 -> 3.0.5
Selenium 3.6.0 -> 3.14.0
HtmlUnit 2.27 -> 2.32.1
Play JSON 2.6.6 -> 2.6.10

Plugins
xsbt-web-plugin (Jetty for integration tests) 2.1.0 -> 4.0.2
sbt-mima-plugin (Migration Manager) 0.1.18 -> 0.3.0

Only relevant for integration tests of ScalaWebTest itself
Javax Servlet API 3.01 -> 4.0.1

Make fits and doesNotFit consistent for matches in documents and parts of the DOM

Scala web test allows fitting gauges either against the DOM of the current page:

class ElementOrderSpec extends ScalaWebTestBaseSpec {
  path = "/elementsList.jsp"

  "List" should "contain three items in the correct order" in {
    fits(
      <ul>
        <a href="/test-link1.html"></a>
        <a href="/test-link2.html"></a>
        <a href="/test-link3.html"></a>
      </ul>
    )
  }
}

Or against sub-nodes in this DOM, like so:

class HtmlElementGaugeSpec extends ScalaWebTestBaseSpec with HtmlElementGauge {
  path = "/galleryOverview.jsp"

  def images = findAll(CssSelectorQuery("ul div.image_columns"))

  val imageGauge = <div class="columns image_columns">
    <a href="@regex \/gallery\/image\/\d">
      <figure class="obj_aspect_ratio">
        <noscript>
          <img class="obj_full" src="@regex \/image\/\d\.jpg\?w=600"></img>
        </noscript>
        <img class="obj_full lazyload" srcset="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-sizes="auto"></img>
      </figure>
    </a>
  </div>

  "The element gauge" should "successfully verify if single elements fit the given gauge" in {
    images.size should be > 5 withClue " - gallery didn't contain the expected amount of images"

    for (image <- images) {
      image fits imageGauge
    }
  }
}

In the current implementation, the behavior of these two fits() is inconsistent: fits(...) against the document will match any sub node in the DOM, whereas fits() against a sub node of the DOM must be an excat match, i.e. the gauge must start with the first child element of the sub node.

Here, it would be more usable and more consistent to have the same behavior, i.e. gauges applied to sub nodes of thee DOM should match any sub node of the sub node.

Simplify browser configuration

Three main goals for browser configuration

  1. Have a correct and sensible default configuration
  2. The configuration has to be extendable
  3. The configurations should be executed once per test

Idea: Gather configurations in a Map[String, () => Unit], execute all configurations during beforeAll

Upgrade Scala versions

New scala versions are available. Change the configuration of the cross-compilation.
2.12.1 -> 2.12.3
2.11.8 -> 2.11.11
2.10.6 remains current 2.10 release

Store document and screenshot on misfit

When a document doens't match the provided gauge, it would be helpful do get access to the document, as seen by the webdriver during the test, after the test was executed.

Therefore it would be good to store this document and if supported by the browser, also a screenshot.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.