-
15. Re: Warp: fluent API for request execution - naming
lfryc Nov 21, 2012 10:04 AM (in response to aslak)Aslak Knutsen wrote:
I would also avoid using given() as a Activity builder to keep the Warp API clean and follow it's original design goal of being client library independent. given(driver).click() will bind the Warp API to WebDriver. It's not that much harder to write given(web(button).click()).
Indeed, it is user-friendly,
but we would need to mimic WebDriver API which returns ClientActivity instead of Void.
It would be quite a pain considering how much methods this API have, but we could provide shortcuts for most useful ones.
-
16. Re: Warp: fluent API for request execution - naming
bmajsak Nov 21, 2012 11:25 AM (in response to lfryc)One short side note: I would rather prefer fluent API rather than "onioning". One simple reason : IDE support => improved productivity. So instead of having:
request().uri(contains("/rest/service")
how about:
request().uri().contains("/rest/service")
-
17. Re: Warp: fluent API for request execution - naming
bmajsak Nov 21, 2012 11:24 AM (in response to bmajsak)Another thing is that GWT trio is actually slightly different conceptually than
given(Activity).when(Filter).then(Inspect);
it's more about
given : initial context / test fixture / preconditions, you name it
when : something happens (we excercise our SUT/CUT whatever)
then : we verify some state or behaviour.
Maybe I don't understand the concept of Filter in this case, but it does not sound to me like an interaction, more some precondition / narrowing scope etc.
-
18. Re: Warp: fluent API for request execution - naming
bmajsak Nov 21, 2012 11:26 AM (in response to bmajsak)Other than that we should really consider writing it in other JVM language
-
19. Re: Warp: fluent API for request execution - naming
aslak Nov 21, 2012 11:46 AM (in response to bmajsak)Bartosz Majsak wrote:
Another thing is that GWT trio is actually slightly different conceptually than
given(Activity).when(Filter).then(Inspect);
it's more about
given : initial context / test fixture / preconditions, you name it
when : something happens (we excercise our SUT/CUT whatever)
then : we verify some state or behaviour.
Maybe I don't understand the concept of Filter in this case, but it does not sound to me like an interaction, more some precondition / narrowing scope etc.
Yea, it's a little bit backwards.
Given - You click a link
When - The HTTP Request matching *.jsp
Then - Inspect the behavior
Given / When doesn't match fully.
Given - This is a HTTP Request matching *.jsp
When - You click a link
Then - Inspect the behavior
?
That would make it:
given(Filter).when(Activity).then(Inspect)
-
20. Re: Warp: fluent API for request execution - naming
lfryc Nov 21, 2012 12:20 PM (in response to bmajsak)Bartosz Majsak wrote:
request().uri().contains("/rest/service")
+1
-
21. Re: Warp: fluent API for request execution - naming
lfryc Nov 21, 2012 1:00 PM (in response to aslak)Let me illustrate it:
@Test public void testGlobalMessageIsIgnored() { Warp .given(request().uri().contains(".jsf")) .when(drive(button).click()) .then(new InspectServer() { @BeforePhase(Phase.RENDER_RESPONSE) public void addGlobalMessage() { FacesContext context = FacesContext.getCurrentInstance(); context.addMessage(null, new FacesMessage("global message")); } @AfterPhase(Phase.RENDER_RESPONSE) public void verifyGlobalMessageIsIgnored() { FacesContext context = FacesContext.getCurrentInstance(); AbstractFocus component = bean.getComponent(); FocusRendererBase renderer = bean.getRenderer(); String candidates = renderer.getFocusCandidatesAsString(context, component); assertEquals("form", candidates); } }); }
I don't like the flow is broken:
RequestConditions (Filter) -> Activity -> Inspection
Do you feel that too? The filter is logically followed by conditions under which should be selected what request should be inspected.
In GWT, G is about PreConditions..
Maybe we should stick with when(...).then(...) and come with something in the middle. ;-)
Warp.when(ClientActivity).whilst(Conditions).then(Inspection);
@Test public void testGlobalMessageIsIgnored() { Warp .when(drive(button).click()) .whilst(request().uri().contains(".jsf")) .then(new InspectServer() { @BeforePhase(Phase.RENDER_RESPONSE) public void addGlobalMessage() { FacesContext context = FacesContext.getCurrentInstance(); context.addMessage(null, new FacesMessage("global message")); } @AfterPhase(Phase.RENDER_RESPONSE) public void verifyGlobalMessageIsIgnored() { FacesContext context = FacesContext.getCurrentInstance(); AbstractFocus component = bean.getComponent(); FocusRendererBase renderer = bean.getRenderer(); String candidates = renderer.getFocusCandidatesAsString(context, component); assertEquals("form", candidates); } }); }
- while(...)
- whilst(...)
- atTime(...)
We can stick with last GWT proposal ^, if nobody feels it's wrong here!
-
22. Re: Warp: fluent API for request execution - naming
dan.j.allen Nov 21, 2012 2:33 PM (in response to aslak)Aslak Knutsen wrote:
Dan Allen wrote:
@RunWith(ArquillianWarp.class) // implies @RunAsClient public class MyTest { ... }
-1
This force Warp to care about the TestRunner. It shouldn't.
Dan Allen wrote:
@RunWith(Arquillian.class) @WarpEnabled // implies @RunAsClient
This should be possible, but not in current impl. Run mode is infered by @Deployment.testable=false or @RunAsClient on class/method level. Warp require testable=true to invoke the Packagaing SPIs, and RunAsClient is read directly from the Metohd / Class.
This features besically needs the same as the alternative language, a metadata layer for the TestClass/TestMethod: https://issues.jboss.org/browse/ARQ-472
Cool. Let's get it fixed in core then, and require @RunAsClient for Arquillian <= 1.0.3.Final. I think this annotation really throws people off, esp when it's the only reasonable mode as is the case w/ Warp.
-
23. Re: Warp: fluent API for request execution - naming
dan.j.allen Nov 21, 2012 2:52 PM (in response to lfryc)I did some more thinking about this last night and I have an alternate to the GWT style to consider.
Instead of when and then, we can look at it from a functional standpoint by using the terms client and server.
Warp.client(Activity).intercept(LifecycleInterceptor).server(Inspect);
As in:
Warp .client(new Activity() { public void perform() { browser.findElement(By.id("order")).click(); } }) .intercept(FacesLifecycle.class) .server(new Inspect() { @BeforePhase(Phase.RENDER_RESPONSE) public void checkOrder() { FacesContext context = FacesContext.getCurrentInstance(); assertEquals(getMessageList().size(), 1); }); }); }
We could also make it read like a sentence that would fit with "Warp" as the verb.
Warp .fromClient(new Activity() { public void perform() { browser.findElement(By.id("order")).click(); } }) .toServer(new Inspect() { @BeforePhase(Phase.RENDER_RESPONSE) public void checkOrder() { FacesContext context = FacesContext.getCurrentInstance(); assertEquals(getMessageList().size(), 1); }); }) .via(FacesLifecycle.class); }
I also like the idea of being able to check the response, coming back from the server, so we could add to that:
Warp.fromClient(Activity).toServer(Inspect).via(FacesLifecycle.class).onReturn(Inspect);
I'm having the most trouble with where to stick (or communicate) the interceptor / monitor / observer bit. Aside from that, I'm really keen on using the chain methods to describe where we are in the interaction (and letting the developer handle the GWT semantics).
-
24. Re: Warp: fluent API for request execution - naming
dan.j.allen Nov 21, 2012 4:09 PM (in response to dan.j.allen)As an alternative to the via() method, I'm also considering:
Warp .fromClient(new Activity() { public void perform() { browser.findElement(By.id("order")).click(); } }) .toServer(new Inspect() { @BeforePhase(Phase.RENDER_RESPONSE) public void checkOrder() { FacesContext context = FacesContext.getCurrentInstance(); assertEquals(getMessageList().size(), 1); }); }) .probe(FacesLifecycle.class); }
or
Warp .fromClient(new Activity() { public void perform() { browser.findElement(By.id("order")).click(); } }) .toServer().probe(FacesLifecycle.class).inspect(new Inspector() { @BeforePhase(Phase.RENDER_RESPONSE) public void checkOrder() { FacesContext context = FacesContext.getCurrentInstance(); assertEquals(getMessageList().size(), 1); }); }); }
One thing that might help, Lukas, is to clarify what role the "filter" (in my case the probe) is playing. That should help us fit it into the sentence.
(No matter how this turns out, I can't get over how powerful Warp is going to be. It's just...warping my mind )
-
25. Re: Warp: fluent API for request execution - naming
kenfinni Nov 21, 2012 3:15 PM (in response to dan.j.allen)Definitely like this flow, seems a bit more natural for what Warp is doing.
I'm wondering whether there need to be a few name changes such as:
Warp .fromClient(new Activity() { public void perform() { browser.findElement(By.id("order")).click(); } }) .toServer(new Inspector() { @BeforePhase(Phase.RENDER_RESPONSE) public void checkOrder() { FacesContext context = FacesContext.getCurrentInstance(); assertEquals(getMessageList().size(), 1); }); }) .inspect(FacesLifecycle.class);
Basically change .via to .inspect, and to improve clarity change new Inspect() to new Inspector().
Seems like .via is saying what is to be inspected, so this seemed natural to me, but could be way off base.
-
26. Re: Warp: fluent API for request execution - naming
dan.j.allen Nov 21, 2012 4:09 PM (in response to kenfinni)Ken, I think you nailed it!
-
27. Re: Warp: fluent API for request execution - naming
aslak Nov 21, 2012 4:22 PM (in response to kenfinni)fromClient toServer doesn't sound right to me.
onClient inServer maybe..
The idea behind Filter is to limit which request to 'enrich' with the server side inspection. A single webdriver.click can trigger multiple requests to the server, e.g. css, js, images, ajax, jsp.
Warp only only activate the "toServer" inspection if the request match the filter.
-
28. Re: Warp: fluent API for request execution - naming
dan.j.allen Nov 21, 2012 4:54 PM (in response to aslak)The idea behind Filter is to limit which request to 'enrich' with the server side inspection. A single webdriver.click can trigger multiple requests to the server, e.g. css, js, images, ajax, jsp.
Warp only only activate the "toServer" inspection if the request match the filter.
Got it, so inspect is the right idea (even if not the ideal word).
Another way to write it is:
Warp.fromClient(Activity).toServer(Inspector).observing(FacesLifecycle.class, URLPatternFilter("*.jsf"));
"observing" indicates both which requests to intercept and which events to expose to the inspector.
fromClient toServer doesn't sound right to me.
onClient inServer maybe..
By themselves, it may not make sense. But if you think about how it plays into the theme / spirit of "Warp", then it reads as:
Warp.fromClient().toServer()
read as "Warp from client to server"
to include all bits:
Warp.fromClient(Activity).toServer(Inspector).observing(FacesLifecycle.class, URLPatternMatcher("*.jsf"))
read as "Warp from client activity to server inspector observing faces lifecycle on urls matching *.jsf"
(the matching part could be more fluent)
If that doesn't fit, then I would just drop down to Warp.client().server().inspect().
-
29. Re: Warp: fluent API for request execution - naming
dan.j.allen Nov 21, 2012 4:58 PM (in response to dan.j.allen)Warp .fromClient(new Activity() { public void perform() { browser.findElement(By.id("order")).click(); } }) .toServer(new Inspector() { @BeforePhase(Phase.RENDER_RESPONSE) public void checkOrder() { FacesContext context = FacesContext.getCurrentInstance(); assertEquals(getMessageList().size(), 1); }); }) .observing(FacesLifecycle.class, forURLs("*.jsf"));
(If we decide to drop the "from" and "to" prefixes, then "observing" should be changed to "observe")