im.yagni.flyby.Spike.scala Maven / Gradle / Ivy
The newest version!
package im.yagni.flyby
import im.yagni.driveby.browser.Browser
import im.yagni.driveby.{Condition, By, BrowserType, BrowserFactory}
//TODO:
//- add dependency on FlyScala_2.9.1-1.3.9
//iteration 1:
//- have a seperate process which starts up 1 browser
//- makes it available via the pool
//- have a spec in driveby which runs using a browser in that pool
//- closes browser on shutdown
//how does this work:
//- client says take browser
//- do a take from fly space with template AvailableBrowser
//- marks it as in use and wraps it in a RemoteBrowser
//- client says goto - RemoteBrowser puts a Goto(browser:1) in space
//- server looks for commands for that browser - so will need a thread for each browser - while true take()
//- server runs command put's result back in space
//- etc
//- client says write browser
//- (client or server) marks it available again
//other:
//- polling is on the server - i.e. the browser does it not the pool
//- client/server is confusing here - agent perhaps?
//iteration 2:
//- support multiple browsers
//iteration 3:
//- support multiple browser types
//iteration x:
//- embed portable profile
//- make easy to distribute an agent
//- handle browsers dieing
//- restart after x commands for example
//- have pool on different machine to the tests are running
//- discover pools automatically
trait TupleSpace {
// def write()
// def take()
}
object FlySpace extends TupleSpace {
}
//aka the tuple - needs to have browser id in it
//later will need the machine id and browser type as well
trait BrowserCommand
//put this in
case class BrowserTake()
//get this back
case class BrowserWrite(/* id, Long */)
case class Goto(/* id, Long */ url: String) extends BrowserCommand
case class Enter(/* id, Long */ by: By, value: String) extends BrowserCommand
case class Click(/* id, Long */ by: By) extends BrowserCommand
case class Assert(/* id, Long */ condition: Condition, message: String = "") extends BrowserCommand
case class Refresh(/* id, Long */) extends BrowserCommand
case class Html(/* id, Long */ /* result: String*/) extends BrowserCommand
//TODO: should be SelectOption
case class Select(/* id, Long */ by: By, value: String) extends BrowserCommand
//should webdriver implement these directly instead? WebDriverCommandProcessor
//should the local browser create these commands as well
//def close() - should not available remotely
//def id: Long - should all command's have
//def screenshot(file: File) - should probably stream the bytes and write on the client instead
class RemoteBrowserPoolServer(/*space: TupleSpace*/) {
def add(browser: String, instances: Int = 1) {
val browser = BrowserFactory.create(BrowserType.firefox)
//TODO: put into space - actually no because it will get serialised
//instead store them here, just like the LocalBrowserPool
//but, do store a tuple that is an available browser
//actually ...
//in a thread
//create an browser, put an entry in the space to say its there
//then loop on take - running each command
//and putting the response back in
//also ...
//store the browsers in a list
//to iterate on closedown
while (true) {
// val command = space.take(/*template*/)
// browser.execute(command)
//so how do we convert template into the right command
// space.write(/*result*/)
}
}
}
class RemoteBrowserPoolClient(space: TupleSpace) {
//TODO: write/take - need to stamp browsers as being (un/)available etc
}
class RemoteBrowser /*extends Browser*/ {
}
//TODO: possibly this will become RemoteBrowserPool
//TODO: ensure that all tracking is consistent between pool implementations
object Spike extends App {
val pool = new RemoteBrowserPoolServer()
pool.add(BrowserType.firefox)
// OnShutdown.execute("Close browsers", () =>
// allBrowsers.map(browser => {
// try {
// browser.close()
// Tracker.add(BrowserClosed(browser.id))
// } catch {
// case e => Tracker.add(BrowserCloseFailed(browser.id))
// }
// }))
}