-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathSeleniumJSEnv.scala
130 lines (108 loc) · 4.67 KB
/
SeleniumJSEnv.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package org.scalajs.jsenv.selenium
import org.scalajs.jsenv._
import java.net.URL
import java.nio.file.{Path, Paths}
import org.openqa.selenium.Capabilities
import org.openqa.selenium.remote.DesiredCapabilities
import org.openqa.selenium.WebDriver
import org.openqa.selenium.JavascriptExecutor
import org.openqa.selenium.Platform
import SeleniumJSEnv.DriverFactory
final class SeleniumJSEnv(driverFactory: DriverFactory, config: SeleniumJSEnv.Config) extends JSEnv {
val name: String = s"SeleniumJSEnv ($config)"
def start(input: Seq[Input], runConfig: RunConfig): JSRun =
SeleniumRun.start(newDriver _, input, config, runConfig)
def startWithCom(input: Seq[Input], runConfig: RunConfig, onMessage: String => Unit): JSComRun =
SeleniumRun.startWithCom(newDriver _, input, config, runConfig, onMessage)
private def newDriver() = {
val driver: WebDriver =
driverFactory()
/* The first `asInstanceOf`s are a fail-fast for the second one, which
* scalac partially erases, so that we're sure right now that the last
* cast is correct, as opposed to crashing when we call a method of
* JavascriptExecutor on the driver.
*
* We are "allowed" to cast since we explicitly request JavascriptEnabled in
* the capabilities.
*/
driver.asInstanceOf[JavascriptExecutor]
driver.asInstanceOf[WebDriver with JavascriptExecutor]
}
def this(driverFactory: DriverFactory) = this(driverFactory, SeleniumJSEnv.Config())
}
object SeleniumJSEnv {
type DriverFactory = () => WebDriver
final class Config private (
val keepAlive: Boolean,
val materialization: Config.Materialization
) {
import Config.Materialization
private def this() = this(
keepAlive = false,
materialization = Config.Materialization.Temp)
/** Materializes purely virtual files into a temp directory.
*
* Materialization is necessary so that virtual files can be referred to by
* name. If you do not know/care how your files are referred to, this is a
* good default choice. It is also the default of [[SeleniumJSEnv.Config]].
*/
def withMaterializeInTemp: Config =
copy(materialization = Materialization.Temp)
/** Materializes files in a static directory of a user configured server.
*
* This can be used to bypass cross origin access policies.
*
* @param contentDir Static content directory of the server. The files will
* be put here. Will get created if it doesn't exist.
* @param webRoot URL making `contentDir` accessible thorugh the server.
* This must have a trailing slash to be interpreted as a directory.
*
* @example
*
* The following will make the browser fetch files using the http:// schema
* instead of the file:// schema. The example assumes a local webserver is
* running and serving the ".tmp" directory at http://localhost:8080.
*
* {{{
* jsSettings(
* jsEnv := new SeleniumJSEnv(
* new org.openqa.selenium.firefox.FirefoxOptions(),
* SeleniumJSEnv.Config()
* .withMaterializeInServer(".tmp", "http://localhost:8080/")
* )
* )
* }}}
*/
def withMaterializeInServer(contentDir: String, webRoot: String): Config =
withMaterializeInServer(Paths.get(contentDir), new URL(webRoot))
/** Materializes files in a static directory of a user configured server.
*
* Version of `withMaterializeInServer` with stronger typing.
*
* @param contentDir Static content directory of the server. The files will
* be put here. Will get created if it doesn't exist.
* @param webRoot URL making `contentDir` accessible thorugh the server.
* This must have a trailing slash to be interpreted as a directory.
*/
def withMaterializeInServer(contentDir: Path, webRoot: URL): Config =
copy(materialization = Materialization.Server(contentDir, webRoot))
def withMaterialization(materialization: Materialization): Config =
copy(materialization = materialization)
def withKeepAlive(keepAlive: Boolean): Config =
copy(keepAlive = keepAlive)
private def copy(keepAlive: Boolean = keepAlive,
materialization: Config.Materialization = materialization) = {
new Config(keepAlive, materialization)
}
}
object Config {
def apply(): Config = new Config()
abstract class Materialization private ()
object Materialization {
final case object Temp extends Materialization
final case class Server(contentDir: Path, webRoot: URL) extends Materialization {
require(webRoot.getPath().endsWith("/"), "webRoot must end with a slash (/)")
}
}
}
}