package com.bellini.recipecatalog.test.repository.ingredient;

import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.comparesEqualTo;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.emptyIterable;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.hamcrest.Matchers;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.context.jdbc.Sql.ExecutionPhase;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;

import com.bellini.recipecatalog.dao.v1.ingredient.IngredientRepository;
import com.bellini.recipecatalog.model.v1.Ingredient;

@SpringBootTest
@RunWith(SpringRunner.class)
@Transactional
@Sql(executionPhase = ExecutionPhase.BEFORE_TEST_METHOD, scripts = { "classpath:db_seed/ingredient/data.sql" })
@Sql(executionPhase = ExecutionPhase.AFTER_TEST_METHOD, scripts = { "classpath:db_seed/ingredient/clean-data.sql" })
public class IngredientRepositoryTest {

    @Autowired
    private IngredientRepository repo;

    @Test
    public void findAll_shouldReturnNotNull() {
        Page<Ingredient> result = repo.findAll(PageRequest.of(0, Integer.MAX_VALUE)); // retrieve all elements
        assertThat(result, notNullValue());
    }

    @Test
    public void findAll_shouldReturnNotEmptyAndCorrectPageSize() {
        Page<Ingredient> result = repo.findAll(PageRequest.of(0, 5)); // retrieve half of the elements
        final List<Ingredient> content = result.getContent();
        assertThat(result, not(emptyIterable()));
        assertThat(content, hasSize(5));
    }

    @Test
    public void findAll_shouldReturnEmptyForIncorrectPageSize() {
        Page<Ingredient> result = repo.findAll(PageRequest.of(50, 5)); // this page does not exist
        assertThat(result, emptyIterable());
    }

    @Test
    public void findAll_shouldHandlePaginationCorrectly() {
        final List<Ingredient> content = repo.findAll(PageRequest.of(0, Integer.MAX_VALUE)).getContent(); // retrieve all elements
        // fetch two items each time until no results are available
        int startFrom = 0, fetch = 2, total = 0;
        List<Ingredient> contentToCheck = new ArrayList<>();
        List<Ingredient> tmpContent = null;
        do {
            tmpContent = repo.findAll(PageRequest.of(startFrom, fetch)).getContent();
            total += tmpContent.size();
            contentToCheck.addAll(tmpContent);
            ++startFrom;
        } while (!tmpContent.isEmpty());

        // check for matching number of elements
        assertThat(total, comparesEqualTo(10));

        // check that the lists are equal
        assertThat(contentToCheck, is(content));
    }

    @Test
    public void findByNameIgnoreCase_shouldReturnTheSameResult() {
        Collection<Ingredient> resultUpperCase = repo.findByNameIgnoreCase("Chicken");
        Collection<Ingredient> resultLowerCase = repo.findByNameIgnoreCase("chicken");

        // collections should be equal
        assertThat(resultUpperCase, is(resultLowerCase));
    }

    @Test
    public void findByNameIgnoreCase_shouldReturnNotNullAndEmptyWhenNoMatch() {
        Collection<Ingredient> result = repo.findByNameIgnoreCase("UnknownIngredient");

        assertThat(result, notNullValue());
        assertThat(result, empty());
    }

    @Test
    public void findByNameIgnoreCaseContaining_shouldReturnCorrectResults() {
        Page<Ingredient> result = repo.findByNameIgnoreCaseContaining("ic", PageRequest.of(0, 10));

        assertThat(result, notNullValue());
        assertThat(result, allOf(
                hasItem(Matchers.<Ingredient>hasProperty("name", is("Rice"))),
                hasItem(Matchers.<Ingredient>hasProperty("name", is("Chicken"))),
                hasItem(Matchers.<Ingredient>hasProperty("name", is("Artichoke"))),
                hasItem(Matchers.<Ingredient>hasProperty("name", is("Ricotta")))));
    }

    @Test
    public void findByNameIgnoreCaseContaining_shouldHandlePaginationCorrectly() {
        final List<Ingredient> content = repo.findByNameIgnoreCaseContaining("ic", PageRequest.of(0, Integer.MAX_VALUE)).getContent(); // retrieve all elements
        // fetch two items each time until no results are available
        int startFrom = 0, fetch = 1, total = 0;
        List<Ingredient> contentToCheck = new ArrayList<>();
        List<Ingredient> tmpContent = null;
        do {
            tmpContent = repo.findByNameIgnoreCaseContaining("ic", PageRequest.of(startFrom, fetch)).getContent();
            total += tmpContent.size();
            contentToCheck.addAll(tmpContent);
            ++startFrom;
        } while (!tmpContent.isEmpty());

        // check for matching number of elements
        assertThat(total, comparesEqualTo(4));

        // check that the lists are equal
        assertThat(contentToCheck, is(content));
    }
}

@@ -389,23 +389,121 @@
 atchers.
-hasItem
+greaterThan;%0Aimport static org.hamcrest.Matchers.hasItem;%0Aimport static org.hamcrest.Matchers.hasProperty
 ;%0Aimport
@@ -5602,10 +5602,398 @@
 ;%0A    %7D%0A
+    %0A    @Test%0A    public void save_shouldStoreElement() %7B%0A        Ingredient ingr = testDishType();%0A        Ingredient stored = repo.save(ingr);%0A%0A        assertThat(stored, hasProperty(%22id%22, allOf(notNullValue(), greaterThan((long) 0))));%0A    %7D%0A%0A    private Ingredient testDishType() %7B%0A        Ingredient ingr = new Ingredient();%0A        ingr.setName(%22Tuna%22);%0A        return ingr;%0A    %7D%0A
 %7D%0A

Add test for save - ingredient