1 2 3 Previous Next 41 Replies Latest reply on Dec 5, 2012 4:15 PM by dan.j.allen Go to original post
      • 15. Re: Warp: fluent API for request execution - naming
        lfryc

        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

          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

            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

              Other than that we should really consider writing it in other JVM language

              • 19. Re: Warp: fluent API for request execution - naming
                aslak

                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

                  Bartosz Majsak wrote:

                   

                  request().uri().contains("/rest/service")

                  +1

                  • 21. Re: Warp: fluent API for request execution - naming
                    lfryc

                    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

                      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

                        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

                          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

                            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

                              Ken, I think you nailed it!

                              • 27. Re: Warp: fluent API for request execution - naming
                                aslak

                                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

                                  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
                                    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")