Skip to main content

Home/ GWT - MVP/ Group items tagged testing

Rss Feed Group items tagged

Esfand S

Issue 5275 - google-web-toolkit - All widgets should implement some kind of interface f... - 0 views

  • if your concern is testing your presenter, then how about changing your MVP from the "Passive View" pattern (the one showed by Ray Ryan at I/0 2009) to the "Supervising Controller" pattern (the one used by Cell widgets internally and by applications generated by Spring Roo): http://martinfowler.com/eaaDev/uiArchs.html Sure you test a bit less things as you leave more of the logic into the view than with a "Passive View", but in my experience it also makes tests much more easier to write and more readable, as you need far less mocks and stubs (no MockButton, MockTextBox, etc. only a MockView).
Esfand S

Testing complex Widgets without interface ? - Google Web Toolkit | Google Groups - 0 views

  • Have a look at the Cell widgets' internals, they use MVP internally so the presenter can be tested independently from the views.
Esfand S

Large scale application development and MVP - Part II - 0 views

  • segment the code that declares the UI from the code that drives the UI.
  • we want the our ContactsPresenter to implement a Presenter interface that allows our ContactsView to callback into the presenter when it receives a click, select or other event. The Presenter interface defines the following:   public interface Presenter<T> {    void onAddButtonClicked();    void onDeleteButtonClicked();    void onItemClicked(T clickedItem);    void onItemSelected(T selectedItem);  }
  • The first part of wiring everything up is to have our ContactsPresenter implement the Presenter interface, and then register itself with the underlying view. To register itself, we'll need our ContactsView to expose a setPresenter() method:   private Presenter<T> presenter;  public void setPresenter(Presenter<T> presenter) {    this.presenter = presenter;  }
  • ...8 more annotations...
  • With the ColumnDefinition(s) in place, we will start to see the fruits of our labor. Mainly in the way we pass model data to the view. As mentioned above we were previously dumbing down the model into a list of Strings. With our ColumnDefinition(s) we can pass the model untouched.   public class ContactsPresenter implements Presenter,    ...    private void fetchContactDetails() {      rpcService.getContactDetails(new AsyncCallback<ArrayList<ContactDetails>>() {        public void onSuccess(ArrayList<ContactDetails> result) {            contactDetails = result;            sortContactDetails();            view.setRowData(contactDetails);        }        ...      });    }    ...  } And our ContactsViewImpl has the following setRowData() implementation:   public class ContactsViewImpl<T> extends Composite implements ContactsView<T> {    ...    public void setRowData(List<T> rowData) {      contactsTable.removeAllRows();      this.rowData = rowData;      for (int i = 0; i < rowData.size(); ++i) {        T t = rowData.get(i);        for (int j = 0; j < columnDefinitions.size(); ++j) {          ColumnDefinition<T> columnDefinition = columnDefinitions.get(j);          contactsTable.setWidget(i, j, columnDefinition.render(t));        }      }    }    ...  } A definite improvement; the presenter can pass the model untouched and the view has no rendering code that we would otherwise need to test.
  • Note that our ContactsView is now ContactsViewImpl<T> and implements ContactsView<T>. This is so that we can pass in a mocked ContactsView instance when testing our ContactsPresenter. Now in our AppController, when we create the ContactsView, we can initialize it with the necessary ColumnDefinition(s).
  • Our current solution is to have our presenters pass a dumbed down version of the model to our views. In the case of our ContactsView, the presenter takes a list of DTOs (Data Transfer Objects) and constructs a list of Strings that it then passes to the view. public ContactsPresenter implements Presenter {  ...  public void onSuccess(ArrayList<ContactDetails> result) {    contactDetails = result;    sortContactDetails();    List<String> data = new ArrayList<String>();    for (int i = 0; i < result.size(); ++i) {      data.add(contactDetails.get(i).getDisplayName());    }    display.setData(data);  }  ...} The "data" object that is passed to the view is a very (and I mean very) simplistic ViewModel — basically a representation of a more complex data model using primitives. This is fine for a simplistic view, but as soon as you start to do something more complex, you quickly realize that something has to give. Either the presenter needs to know more about the view (making it hard to swap out views for other platforms), or the view needs to know more about the data model (ultimately making your view smarter, thus requiring more GwtTestCases). The solution is to use generics along with a third party that abstracts any knowledge of a cell's data type, as well as how that data type is rendered.
  • We've figured out how to create the foundation for complex UIs while sticking to our requirement that the view remain as dumb (and minimally testable) as possible, but that's no reason to stop. While functionality is decoupled, there is still room for optimization. Having the ColumnDefinition create a new widget for each cell is too heavy, and can quickly lead to performance degradation as your application grows. The two leading factors of this degradation are: Inefficiencies related to inserting new elements via DOM manipulation Overhead associated with sinking events per Widget To overcome this we will update our application to do the following (in respective order): Replace our FlexTable implementation with an HTML widget that we'll populate by calling setHTML(), effectively batching all DOM manipulation into a single call. Reduce the event overhead by sinking events on the HTML widget, rather than the individual cells. The changes are encompassed within our ContactsView.ui.xml file, as well as our setRowData() and onTableClicked() methods. First we'll need to update our ContactsView.ui.xml file to use a HTML widget rather than a FlexTable widget.
  • The above code is similar to our original setRowData() method, we iterate through the rowData and for each item ask our column definitions to render accordingly. The main differences being that a) we're expecting each column definition to render itself into the StringBuilder rather than passing back a full-on widget, and b) we're calling setHTML on a HTML widget rather than calling setWidget on a FlexTable. This will decrease your load time, especially as your tables start to grow.
  • To reiterate, we're reducing the overhead of sinking events on per-cell widgets, and instead sinking on a single container, our HTML widget. The ClickEvents are still wired up via our UiHandler annotations, but with this approach, we're going to get the Element that was clicked on and walk the DOM until we find a parent TableCellElement. From there we can determine the row, and thus the corresponding rowData.
  • Code Splitting is the act of wrapping segmented pieces of your application into "split" points by declaring them within a runAsync() call. As long as the split portion of your code is purely segmented, and not referenced by other parts of the app, it will be downloaded and executed at the point that it needs to run.
  •         // TODO: Really total hack! There's gotta be a better way...        Element child = cell.getFirstChildElement();        if (child != null) {          Event.sinkEvents(child, Event.ONFOCUS | Event.ONBLUR);        }
Esfand S

MVP vs MVC - 0 views

  •  
    In MVC, the model is heavy with business rules and data access, the view contains the presentation logic, and the controller is typically a framework component with an XML configuration to drive it. In MVP, the model is lightweight POJO value objects, the view is mockable, and the presentation is specific to the model and the view. It is the presentation that has all the dependencies and glue code for the model\nand the view. You get more code coverage in your unit testing with MVP so MVP and TDD go together.
Esfand S

Feedback on "Large scale app development MVP article" - Google Web Toolkit | Google Groups - 1 views

  • There are a few things that you should keep in mind before you try to understand the MVP pattern    1. You don't have reflection or observer/observable pattern on the client    side.    2. Views depend on DOM and GWT UI Libraries, and are difficult to    mock/emulate in a pure java test case Now, to answer some of your questions
Esfand S

Feedback on "Large scale app development MVP article" - Google Web Toolkit | Google Groups - 0 views

  • There are a few things that you should keep in mind before you try to understand the MVP pattern    1. You don't have reflection or observer/observable pattern on the client    side.    2. Views depend on DOM and GWT UI Libraries, and are difficult to    mock/emulate in a pure java test case Now, to answer some of your questions
Esfand S

MKDev » Blog Archive » Comments on GWT MVP - Technical yabberings from me to you - 1 views

  • keeping History management abstracted in it’s own right
  • the need for Presenters to be capable of responding to History tokens
  • Presenters are decoupled from token managemen
  • ...3 more annotations...
  • History system is no longer required for unit testing
  • Presenters now have a clear opportunity to be lazy-loaded from a RunAsync call!
  • By adding this ViewModel (basically a Map<String, Object>), Presenters can now pass information from one to the other with zero knowledge of each other. They can also look in the model for information necessary to render the current Location properly.
Marco Antonio Almeida

Sanjiv Jivan's Blog - 0 views

  • Once a DataSource has been defined to describe your entity / domain class, data can be read into a DataSource from a wide variety of sources. For example local array data, XML or JSON, data from the server, or you can even point to sample test data. The DataSource has a build-in mechanism to communicate with the source of the data, whether local or the backend server, for the four key operations : FETCH, ADD, UPDATE and REMOVE.
Esfand S

GWT MVP Development with Activities and Places - Google Web Toolkit - Google Code - 1 views

  • Views A key concept of MVP development is that a view is defined by an interface. This allows multiple view implementations based on client characteristics (such as mobile vs. desktop) and also facilitates lightweight unit testing by avoiding the time-consuming GWTTestCase. There is no View interface or class in GWT which views must implement or extend; however, GWT 2.1 introduces an IsWidget interface that is implemented by most Widgets as well as Composite. It is useful for views to extend IsWidget if they do in fact provide a Widget. Here is a simple view from our sample app. public interface GoodbyeView extends IsWidget {    void setName(String goodbyeName);} The corresponding implementation extends Composite, which keeps dependencies on a particular Widget from leaking out. public class GoodbyeViewImpl extends Composite implements GoodbyeView {    SimplePanel viewPanel = new SimplePanel();    Element nameSpan = DOM.createSpan();    public GoodbyeViewImpl() {        viewPanel.getElement().appendChild(nameSpan);        initWidget(viewPanel);    }    @Override    public void setName(String name) {        nameSpan.setInnerText("Good-bye, " + name);    }}
  • A place in GWT 2.1 is a Java object representing a particular state of the UI. A Place can be converted to and from a URL history token (see GWT's History object) by defining a PlaceTokenizer for each Place, and the PlaceHistoryHandler automatically updates the browser URL corresponding to each Place in your app.
  • Place
  • ...2 more annotations...
  • new GoodbyePlace(name)
  • view factory
1 - 20 of 21 Next ›
Showing 20 items per page