Search in sources :

Example 1 with AdditionalItemsLoadable

use of com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.AdditionalItemsLoadable in project mosby by sockeqwe.

the class HomePresenter method viewStateReducer.

private HomeViewState viewStateReducer(HomeViewState previousState, PartialStateChanges partialChanges) {
    if (partialChanges instanceof PartialStateChanges.FirstPageLoading) {
        return previousState.builder().firstPageLoading(true).firstPageError(null).build();
    }
    if (partialChanges instanceof PartialStateChanges.FirstPageError) {
        return previousState.builder().firstPageLoading(false).firstPageError(((PartialStateChanges.FirstPageError) partialChanges).getError()).build();
    }
    if (partialChanges instanceof PartialStateChanges.FirstPageLoaded) {
        return previousState.builder().firstPageLoading(false).firstPageError(null).data(((PartialStateChanges.FirstPageLoaded) partialChanges).getData()).build();
    }
    if (partialChanges instanceof PartialStateChanges.NextPageLoading) {
        return previousState.builder().nextPageLoading(true).nextPageError(null).build();
    }
    if (partialChanges instanceof PartialStateChanges.NexPageLoadingError) {
        return previousState.builder().nextPageLoading(false).nextPageError(((PartialStateChanges.NexPageLoadingError) partialChanges).getError()).build();
    }
    if (partialChanges instanceof PartialStateChanges.NextPageLoaded) {
        List<FeedItem> data = new ArrayList<>(previousState.getData().size() + ((PartialStateChanges.NextPageLoaded) partialChanges).getData().size());
        data.addAll(previousState.getData());
        data.addAll(((PartialStateChanges.NextPageLoaded) partialChanges).getData());
        return previousState.builder().nextPageLoading(false).nextPageError(null).data(data).build();
    }
    if (partialChanges instanceof PartialStateChanges.PullToRefreshLoading) {
        return previousState.builder().pullToRefreshLoading(true).pullToRefreshError(null).build();
    }
    if (partialChanges instanceof PartialStateChanges.PullToRefeshLoadingError) {
        return previousState.builder().pullToRefreshLoading(false).pullToRefreshError(((PartialStateChanges.PullToRefeshLoadingError) partialChanges).getError()).build();
    }
    if (partialChanges instanceof PartialStateChanges.PullToRefreshLoaded) {
        List<FeedItem> data = new ArrayList<>(previousState.getData().size() + ((PartialStateChanges.PullToRefreshLoaded) partialChanges).getData().size());
        data.addAll(((PartialStateChanges.PullToRefreshLoaded) partialChanges).getData());
        data.addAll(previousState.getData());
        return previousState.builder().pullToRefreshLoading(false).pullToRefreshError(null).data(data).build();
    }
    if (partialChanges instanceof PartialStateChanges.ProductsOfCategoryLoading) {
        Pair<Integer, AdditionalItemsLoadable> found = findAdditionalItems(((PartialStateChanges.ProductsOfCategoryLoading) partialChanges).getCategoryName(), previousState.getData());
        AdditionalItemsLoadable foundItem = found.second;
        AdditionalItemsLoadable toInsert = new AdditionalItemsLoadable(foundItem.getMoreItemsAvailableCount(), foundItem.getCategoryName(), true, null);
        List<FeedItem> data = new ArrayList<>(previousState.getData().size());
        data.addAll(previousState.getData());
        data.set(found.first, toInsert);
        return previousState.builder().data(data).build();
    }
    if (partialChanges instanceof PartialStateChanges.ProductsOfCategoryLoadingError) {
        Pair<Integer, AdditionalItemsLoadable> found = findAdditionalItems(((PartialStateChanges.ProductsOfCategoryLoadingError) partialChanges).getCategoryName(), previousState.getData());
        AdditionalItemsLoadable foundItem = found.second;
        AdditionalItemsLoadable toInsert = new AdditionalItemsLoadable(foundItem.getMoreItemsAvailableCount(), foundItem.getCategoryName(), false, ((PartialStateChanges.ProductsOfCategoryLoadingError) partialChanges).getError());
        List<FeedItem> data = new ArrayList<>(previousState.getData().size());
        data.addAll(previousState.getData());
        data.set(found.first, toInsert);
        return previousState.builder().data(data).build();
    }
    if (partialChanges instanceof PartialStateChanges.ProductsOfCategoryLoaded) {
        Pair<Integer, AdditionalItemsLoadable> found = findAdditionalItems(((PartialStateChanges.ProductsOfCategoryLoaded) partialChanges).getCategoryName(), previousState.getData());
        List<FeedItem> data = new ArrayList<>(previousState.getData().size() + ((PartialStateChanges.ProductsOfCategoryLoaded) partialChanges).getData().size());
        data.addAll(previousState.getData());
        // Search for the section header
        int sectionHeaderIndex = -1;
        for (int i = found.first; i >= 0; i--) {
            FeedItem item = previousState.getData().get(i);
            if (item instanceof SectionHeader && ((SectionHeader) item).getName().equals(((PartialStateChanges.ProductsOfCategoryLoaded) partialChanges).getCategoryName())) {
                sectionHeaderIndex = i;
                break;
            }
            // Remove all items of that category. The new list of products will be added afterwards
            data.remove(i);
        }
        if (sectionHeaderIndex < 0) {
            throw new RuntimeException("Couldn't find the section header for category " + ((PartialStateChanges.ProductsOfCategoryLoaded) partialChanges).getCategoryName());
        }
        data.addAll(sectionHeaderIndex + 1, ((PartialStateChanges.ProductsOfCategoryLoaded) partialChanges).getData());
        return previousState.builder().data(data).build();
    }
    throw new IllegalStateException("Don't know how to reduce the partial state " + partialChanges);
}
Also used : ArrayList(java.util.ArrayList) FeedItem(com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.FeedItem) SectionHeader(com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.SectionHeader) AdditionalItemsLoadable(com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.AdditionalItemsLoadable)

Example 2 with AdditionalItemsLoadable

use of com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.AdditionalItemsLoadable in project mosby by sockeqwe.

the class HomePresenterTest method loadingFirstPageAndMoreOfCategoryFails.

@Test
public void loadingFirstPageAndMoreOfCategoryFails() throws IOException {
    //
    // Prepare mock server to deliver mock response on incoming http request
    //
    List<Product> mockProducts = Arrays.asList(new Product(1, "image", "name", "category1", "description", 21.9), new Product(2, "image", "name", "category1", "description", 21.9), new Product(3, "image", "name", "category1", "description", 21.9), new Product(4, "image", "name", "category1", "description", 21.9), new Product(5, "image", "name", "category1", "description", 21.9));
    // first page response
    mockWebServer.enqueue(new MockResponse().setBody(adapter.toJson(mockProducts)));
    // more of category responses
    mockWebServer.enqueue(new MockResponse().setBody(adapter.toJson(mockProducts)));
    mockWebServer.enqueue(new MockResponse().setBody(adapter.toJson(Collections.emptyList())));
    mockWebServer.enqueue(new MockResponse().setBody(adapter.toJson(Collections.emptyList())));
    mockWebServer.enqueue(new MockResponse().setBody(adapter.toJson(Collections.emptyList())));
    //
    // init the robot to drive to View which triggers intents on the presenter
    //
    HomePresenter presenter = // In a real app you could use dagger or instantiate the Presenter manually like new HomePresenter(...)
    new DependencyInjection().newHomePresenter();
    HomeViewRobot robot = new HomeViewRobot(presenter);
    //
    // We are ready, so let's start: fire an intent
    //
    robot.fireLoadFirstPageIntent();
    //
    // we expect that 2 view.render() events happened with the following HomeViewState:
    // 1. show loading indicator
    // 2. show the items with the first page
    //
    List<FeedItem> expectedData = Arrays.asList(new SectionHeader("category1"), mockProducts.get(0), mockProducts.get(1), mockProducts.get(2), new AdditionalItemsLoadable(2, "category1", false, null));
    HomeViewState loadingFirstPage = new HomeViewState.Builder().firstPageLoading(true).build();
    HomeViewState firstPage = new HomeViewState.Builder().data(expectedData).build();
    // Check if as expected
    robot.assertViewStateRendered(loadingFirstPage, firstPage);
    //
    // Load more of category
    //
    mockWebServer.shutdown();
    robot.fireLoadAllProductsFromCategory("category1");
    //
    // we expect that 4 view.render() events happened with the following HomeViewState:
    // 1. show loading indicator
    // 2. show the items with the first page
    // 3. show indicator load more of category
    // 4. show loading all items of the category failed
    //
    List<FeedItem> expectedDataWhileLoadingMoreOfCategory = Arrays.asList(new SectionHeader("category1"), mockProducts.get(0), mockProducts.get(1), mockProducts.get(2), new AdditionalItemsLoadable(2, "category1", true, null));
    List<FeedItem> expectedDataAfterLoadingMoreOfCategoryError = Arrays.asList(new SectionHeader("category1"), mockProducts.get(0), mockProducts.get(1), mockProducts.get(2), new AdditionalItemsLoadable(2, "category1", false, new ConnectException()));
    HomeViewState loadingMoreOfCategory = new HomeViewState.Builder().data(expectedDataWhileLoadingMoreOfCategory).build();
    HomeViewState moreOfCategoryError = new HomeViewState.Builder().data(expectedDataAfterLoadingMoreOfCategoryError).build();
    robot.assertViewStateRendered(loadingFirstPage, firstPage, loadingMoreOfCategory, moreOfCategoryError);
}
Also used : MockResponse(okhttp3.mockwebserver.MockResponse) Product(com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.Product) DependencyInjection(com.hannesdorfmann.mosby3.sample.mvi.dependencyinjection.DependencyInjection) FeedItem(com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.FeedItem) SectionHeader(com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.SectionHeader) AdditionalItemsLoadable(com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.AdditionalItemsLoadable) ConnectException(java.net.ConnectException) Test(org.junit.Test)

Example 3 with AdditionalItemsLoadable

use of com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.AdditionalItemsLoadable in project mosby by sockeqwe.

the class HomePresenterTest method loadingFirstPage.

@Test
public void loadingFirstPage() {
    //
    // Prepare mock server to deliver mock response on incoming http request
    //
    List<Product> mockProducts = Arrays.asList(new Product(1, "image", "name", "category1", "description", 21.9), new Product(2, "image", "name", "category1", "description", 21.9), new Product(3, "image", "name", "category1", "description", 21.9), new Product(4, "image", "name", "category1", "description", 21.9), new Product(5, "image", "name", "category1", "description", 21.9));
    mockWebServer.enqueue(new MockResponse().setBody(adapter.toJson(mockProducts)));
    //
    // init the robot to drive to View which triggers intents on the presenter
    //
    HomePresenter presenter = // In a real app you could use dagger or instantiate the Presenter manually like new HomePresenter(...)
    new DependencyInjection().newHomePresenter();
    HomeViewRobot robot = new HomeViewRobot(presenter);
    //
    // We are ready, so let's start: fire an intent
    //
    robot.fireLoadFirstPageIntent();
    //
    // we expect that 2 view.render() events happened with the following HomeViewState:
    // 1. show loading indicator
    // 2. show the items with the first page
    //
    List<FeedItem> expectedData = Arrays.asList(new SectionHeader("category1"), mockProducts.get(0), mockProducts.get(1), mockProducts.get(2), new AdditionalItemsLoadable(2, "category1", false, null));
    HomeViewState loadingFirstPage = new HomeViewState.Builder().firstPageLoading(true).build();
    HomeViewState firstPage = new HomeViewState.Builder().data(expectedData).build();
    // Check if as expected
    robot.assertViewStateRendered(loadingFirstPage, firstPage);
}
Also used : MockResponse(okhttp3.mockwebserver.MockResponse) FeedItem(com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.FeedItem) SectionHeader(com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.SectionHeader) Product(com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.Product) AdditionalItemsLoadable(com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.AdditionalItemsLoadable) DependencyInjection(com.hannesdorfmann.mosby3.sample.mvi.dependencyinjection.DependencyInjection) Test(org.junit.Test)

Example 4 with AdditionalItemsLoadable

use of com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.AdditionalItemsLoadable in project mosby by sockeqwe.

the class HomePresenterTest method loadingFirstPageAndNextPageAndPullToRefresh.

@Test
public void loadingFirstPageAndNextPageAndPullToRefresh() {
    //
    // Prepare mock server to deliver mock response on incoming http request
    //
    List<Product> mockProductsFirstPage = Arrays.asList(new Product(1, "image", "name", "category1", "description", 21.9), new Product(2, "image", "name", "category1", "description", 21.9), new Product(3, "image", "name", "category1", "description", 21.9), new Product(4, "image", "name", "category1", "description", 21.9), new Product(5, "image", "name", "category1", "description", 21.9));
    List<Product> mockProductsNextPage = Arrays.asList(new Product(6, "image", "name", "category2", "description", 21.9), new Product(7, "image", "name", "category2", "description", 21.9), new Product(8, "image", "name", "category2", "description", 21.9), new Product(9, "image", "name", "category2", "description", 21.9));
    List<Product> mockProductsPullToRefresh = Arrays.asList(new Product(10, "image", "name", "category3", "description", 21.9), new Product(11, "image", "name", "category3", "description", 21.9), new Product(12, "image", "name", "category3", "description", 21.9));
    mockWebServer.enqueue(new MockResponse().setBody(adapter.toJson(mockProductsFirstPage)));
    mockWebServer.enqueue(new MockResponse().setBody(adapter.toJson(mockProductsNextPage)));
    mockWebServer.enqueue(new MockResponse().setBody(adapter.toJson(mockProductsPullToRefresh)));
    //
    // init the robot to drive to View which triggers intents on the presenter
    //
    HomePresenter presenter = // In a real app you could use dagger or instantiate the Presenter manually like new HomePresenter(...)
    new DependencyInjection().newHomePresenter();
    HomeViewRobot robot = new HomeViewRobot(presenter);
    //
    // We are ready, so let's start: fire intents
    //
    robot.fireLoadFirstPageIntent();
    //
    // we expect that 2 view.render() events happened with the following HomeViewState:
    // 1. show loading indicator
    // 2. show the items with the first page
    //
    List<FeedItem> expectedDataAfterFristPage = Arrays.asList(new SectionHeader("category1"), mockProductsFirstPage.get(0), mockProductsFirstPage.get(1), mockProductsFirstPage.get(2), new AdditionalItemsLoadable(2, "category1", false, null));
    HomeViewState loadingFirstPage = new HomeViewState.Builder().firstPageLoading(true).build();
    HomeViewState firstPage = new HomeViewState.Builder().data(expectedDataAfterFristPage).build();
    // Check if as expected
    robot.assertViewStateRendered(loadingFirstPage, firstPage);
    //
    // Fire next page intent
    //
    robot.fireLoadNextPageIntent();
    //
    // we expect that 4 view.render() events happened with the following HomeViewState:
    // 1. show loading indicator (caused by loadFirstPageIntent)
    // 2. show the items with the first page (caused by loadFirstPageIntent)
    // 3. show loading next page indicator
    // 4. show next page content (plus original first page content)
    //
    List<FeedItem> expectedDataAfterNextPage = Arrays.asList(new SectionHeader("category1"), mockProductsFirstPage.get(0), mockProductsFirstPage.get(1), mockProductsFirstPage.get(2), new AdditionalItemsLoadable(2, "category1", false, null), new SectionHeader("category2"), mockProductsNextPage.get(0), mockProductsNextPage.get(1), mockProductsNextPage.get(2), new AdditionalItemsLoadable(1, "category2", false, null));
    HomeViewState nextPageLoading = new HomeViewState.Builder().data(expectedDataAfterFristPage).nextPageLoading(true).build();
    HomeViewState nextPage = new HomeViewState.Builder().data(expectedDataAfterNextPage).build();
    // Check if as expected
    robot.assertViewStateRendered(loadingFirstPage, firstPage, nextPageLoading, nextPage);
    //
    // fire pull to refresh intent
    //
    robot.firePullToRefreshIntent();
    //
    // we expect that 6 view.render() events happened with the following HomeViewState:
    // 1. show loading indicator (caused by loadFirstPageIntent)
    // 2. show the items with the first page (caused by loadFirstPageIntent)
    // 3. show loading next page indicator
    // 4. show next page content (plus original first page content)
    // 5. show loading - pull to refresh indicator
    // 6. show pull to refresh content (plus original first page + next page content)
    //
    List<FeedItem> expectedDataAfterPullToRefresh = Arrays.asList(new SectionHeader("category3"), mockProductsPullToRefresh.get(0), mockProductsPullToRefresh.get(1), mockProductsPullToRefresh.get(2), // No additional items loadable for category3
    new SectionHeader("category1"), mockProductsFirstPage.get(0), mockProductsFirstPage.get(1), mockProductsFirstPage.get(2), new AdditionalItemsLoadable(2, "category1", false, null), new SectionHeader("category2"), mockProductsNextPage.get(0), mockProductsNextPage.get(1), mockProductsNextPage.get(2), new AdditionalItemsLoadable(1, "category2", false, null));
    HomeViewState pullToRefreshLoading = new HomeViewState.Builder().data(expectedDataAfterNextPage).pullToRefreshLoading(true).build();
    HomeViewState pullToRefreshPage = new HomeViewState.Builder().data(expectedDataAfterPullToRefresh).build();
    robot.assertViewStateRendered(loadingFirstPage, firstPage, nextPageLoading, nextPage, pullToRefreshLoading, pullToRefreshPage);
}
Also used : MockResponse(okhttp3.mockwebserver.MockResponse) Product(com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.Product) DependencyInjection(com.hannesdorfmann.mosby3.sample.mvi.dependencyinjection.DependencyInjection) FeedItem(com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.FeedItem) SectionHeader(com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.SectionHeader) AdditionalItemsLoadable(com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.AdditionalItemsLoadable) Test(org.junit.Test)

Example 5 with AdditionalItemsLoadable

use of com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.AdditionalItemsLoadable in project mosby by sockeqwe.

the class HomePresenterTest method loadingFirstPageAndMoreOfCategory.

@Test
public void loadingFirstPageAndMoreOfCategory() {
    //
    // Prepare mock server to deliver mock response on incoming http request
    //
    List<Product> mockProducts = Arrays.asList(new Product(1, "image", "name", "category1", "description", 21.9), new Product(2, "image", "name", "category1", "description", 21.9), new Product(3, "image", "name", "category1", "description", 21.9), new Product(4, "image", "name", "category1", "description", 21.9), new Product(5, "image", "name", "category1", "description", 21.9));
    // first page response
    mockWebServer.enqueue(new MockResponse().setBody(adapter.toJson(mockProducts)));
    // more of category responses
    mockWebServer.enqueue(new MockResponse().setBody(adapter.toJson(mockProducts)));
    mockWebServer.enqueue(new MockResponse().setBody(adapter.toJson(Collections.emptyList())));
    mockWebServer.enqueue(new MockResponse().setBody(adapter.toJson(Collections.emptyList())));
    mockWebServer.enqueue(new MockResponse().setBody(adapter.toJson(Collections.emptyList())));
    //
    // init the robot to drive to View which triggers intents on the presenter
    //
    HomePresenter presenter = // In a real app you could use dagger or instantiate the Presenter manually like new HomePresenter(...)
    new DependencyInjection().newHomePresenter();
    HomeViewRobot robot = new HomeViewRobot(presenter);
    //
    // We are ready, so let's start: fire an intent
    //
    robot.fireLoadFirstPageIntent();
    //
    // we expect that 2 view.render() events happened with the following HomeViewState:
    // 1. show loading indicator
    // 2. show the items with the first page
    //
    List<FeedItem> expectedData = Arrays.asList(new SectionHeader("category1"), mockProducts.get(0), mockProducts.get(1), mockProducts.get(2), new AdditionalItemsLoadable(2, "category1", false, null));
    HomeViewState loadingFirstPage = new HomeViewState.Builder().firstPageLoading(true).build();
    HomeViewState firstPage = new HomeViewState.Builder().data(expectedData).build();
    // Check if as expected
    robot.assertViewStateRendered(loadingFirstPage, firstPage);
    //
    // Load more of category
    //
    robot.fireLoadAllProductsFromCategory("category1");
    //
    // we expect that 4 view.render() events happened with the following HomeViewState:
    // 1. show loading indicator
    // 2. show the items with the first page
    // 3. show indicator load more of category
    // 4. show all items of the category
    //
    List<FeedItem> expectedDataWhileLoadingMoreOfCategory = Arrays.asList(new SectionHeader("category1"), mockProducts.get(0), mockProducts.get(1), mockProducts.get(2), new AdditionalItemsLoadable(2, "category1", true, null));
    List<FeedItem> expectedDataAfterAllOfCategoryCompleted = Arrays.asList(new SectionHeader("category1"), mockProducts.get(0), mockProducts.get(1), mockProducts.get(2), mockProducts.get(3), mockProducts.get(4));
    HomeViewState loadingMoreOfCategory = new HomeViewState.Builder().data(expectedDataWhileLoadingMoreOfCategory).build();
    HomeViewState moreOfCategoryLoaded = new HomeViewState.Builder().data(expectedDataAfterAllOfCategoryCompleted).build();
    robot.assertViewStateRendered(loadingFirstPage, firstPage, loadingMoreOfCategory, moreOfCategoryLoaded);
}
Also used : MockResponse(okhttp3.mockwebserver.MockResponse) FeedItem(com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.FeedItem) SectionHeader(com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.SectionHeader) Product(com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.Product) AdditionalItemsLoadable(com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.AdditionalItemsLoadable) DependencyInjection(com.hannesdorfmann.mosby3.sample.mvi.dependencyinjection.DependencyInjection) Test(org.junit.Test)

Aggregations

AdditionalItemsLoadable (com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.AdditionalItemsLoadable)8 FeedItem (com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.FeedItem)8 SectionHeader (com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.SectionHeader)8 Product (com.hannesdorfmann.mosby3.sample.mvi.businesslogic.model.Product)7 DependencyInjection (com.hannesdorfmann.mosby3.sample.mvi.dependencyinjection.DependencyInjection)7 MockResponse (okhttp3.mockwebserver.MockResponse)7 Test (org.junit.Test)7 ConnectException (java.net.ConnectException)3 ArrayList (java.util.ArrayList)1