

package jetbrains.buildServer.nuget.tests.integration.feed.server;

import com.google.common.collect.Lists;
import jetbrains.buildServer.nuget.server.feed.server.index.NuGetIndexEntry;
import jetbrains.buildServer.nuget.server.util.FrameworkConstraints;
import jetbrains.buildServer.util.CollectionsUtil;
import org.testng.annotations.Test;

import static jetbrains.buildServer.nuget.server.feed.server.PackageAttributes.*;
import static jetbrains.buildServer.nuget.server.feed.server.index.PackagesIndex.TEAMCITY_FRAMEWORK_CONSTRAINTS;

/**
 * @author Evgeniy.Koshkin
 */
public class SearchFunctionIntegrationTest extends NuGetJavaFeedIntegrationTestBase {

  @Test(enabled = false)
  public void testBadRequest() throws Exception {
    addMockPackage("foo", "1.0.0.0");
    assert400("Search()").run();
    assert400("Search()?&searchTerm='foo'&includePrerelease=true").run();
    assert400("Search()?&targetFramework='net45'&includePrerelease=true").run();
    assert400("Search()?&searchTerm='foo'&targetFramework='net45'").run();
  }

  @Test(enabled = false)
  public void testNoPackagesFound() throws Exception {
    addMockPackage(new NuGetIndexEntry("foo", CollectionsUtil.asMap(ID, "foo", TEAMCITY_FRAMEWORK_CONSTRAINTS, FrameworkConstraints.convertToString(Lists.newArrayList("net45")), VERSION, "1")));
    assert404("Search()?&searchTerm='noSuchPackage'&targetFramework='net45'&includePrerelease=true").run();
  }

  @Test
  public void testEmptySearchTerm() throws Exception {
    addMockPackage(new NuGetIndexEntry("foo", CollectionsUtil.asMap(ID, "foo", TEAMCITY_FRAMEWORK_CONSTRAINTS, FrameworkConstraints.convertToString(Lists.newArrayList("net45")), VERSION, "1")));
    final String response = openRequest("Search()?&searchTerm=''&targetFramework='net45'&includePrerelease=true");
    assertContainsPackageVersion(response, "1.0");
  }

  @Test
  public void testVSRequests() throws Exception {
    addMockPackage("foo", "1.0.0.0");
    final String[] reqs = {
            "Search()/$count?$filter=IsAbsoluteLatestVersion&searchTerm='foo'&targetFramework='net45%7Cnet45%7Cnet45%7Cnet45%7Cnet45%7Cnet45%7Cnet45'&includePrerelease=true",
            "Search()?$filter=IsAbsoluteLatestVersion&$skip=0&$top=30&searchTerm='foo'&targetFramework='net45%7Cnet45%7Cnet45%7Cnet45%7Cnet45%7Cnet45%7Cnet45'&includePrerelease=true",
            "Search()/$count?$filter=IsAbsoluteLatestVersion&searchTerm=''&targetFramework='net45%7Cnet45%7Cnet45%7Cnet45%7Cnet45%7Cnet45%7Cnet45'&includePrerelease=true",
            "Search()?$filter=IsAbsoluteLatestVersion&$orderby=DownloadCount%20desc,Id&$skip=0&$top=30&searchTerm=''&targetFramework='net45%7Cnet45%7Cnet45%7Cnet45%7Cnet45%7Cnet45%7Cnet45'&includePrerelease=true"
    };
    for (String req : reqs) {
      assert200(req).run();
    }
  }

  @Test
  public void testTargetFramework() throws Exception {
    addMockPackage(new NuGetIndexEntry("foo", CollectionsUtil.asMap(ID, "foo", TEAMCITY_FRAMEWORK_CONSTRAINTS, "", VERSION, "1")));
    addMockPackage(new NuGetIndexEntry("foo", CollectionsUtil.asMap(ID, "foo", TEAMCITY_FRAMEWORK_CONSTRAINTS, FrameworkConstraints.convertToString(Lists.newArrayList("net45")), VERSION, "2")));
    addMockPackage(new NuGetIndexEntry("foo", CollectionsUtil.asMap(ID, "foo", TEAMCITY_FRAMEWORK_CONSTRAINTS, FrameworkConstraints.convertToString(Lists.newArrayList("MonoTouch")), VERSION, "3")));
    addMockPackage(new NuGetIndexEntry("foo", CollectionsUtil.asMap(ID, "foo", TEAMCITY_FRAMEWORK_CONSTRAINTS, FrameworkConstraints.convertToString(Lists.newArrayList("MonoTouch", "net45")), VERSION, "4")));

    final String response = openRequest("Search()?&searchTerm=''&targetFramework='net45%7Cnet45%7Cnet45%7Cnet45%7Cnet45%7Cnet45%7Cnet45'&includePrerelease=true");

    assertContainsPackageVersion(response, "1.0");
    assertContainsPackageVersion(response, "2.0");
    assertNotContainsPackageVersion(response, "3.0");
    assertContainsPackageVersion(response, "4.0");

    final String emptyTargetFrameworkresponse = openRequest("Search()?&searchTerm=''&targetFramework=''&includePrerelease=true");

    assertContainsPackageVersion(emptyTargetFrameworkresponse, "1.0");
    assertContainsPackageVersion(emptyTargetFrameworkresponse, "2.0");
    assertContainsPackageVersion(emptyTargetFrameworkresponse, "3.0");
    assertContainsPackageVersion(emptyTargetFrameworkresponse, "4.0");
  }

  @Test
  public void testIncludePreRelease() throws Exception {
    addMockPackage(new NuGetIndexEntry("pre-release", CollectionsUtil.asMap(ID, "foo", IS_PRERELEASE, Boolean.TRUE.toString(), VERSION, "1")));
    addMockPackage(new NuGetIndexEntry("release", CollectionsUtil.asMap(ID, "foo", IS_PRERELEASE, Boolean.FALSE.toString(), VERSION, "2")));
    addMockPackage(new NuGetIndexEntry("release", CollectionsUtil.asMap(ID, "foo", VERSION, "3")));

    final String preReleaseIncludedFeedResponse = openRequest("Search()?&searchTerm=''&targetFramework='net45'&includePrerelease=true");
    assertContainsPackageVersion(preReleaseIncludedFeedResponse, "1.0");
    assertContainsPackageVersion(preReleaseIncludedFeedResponse, "2.0");
    assertContainsPackageVersion(preReleaseIncludedFeedResponse, "3.0");

    final String preReleaseNotIncludedFeedResponse = openRequest("Search()?&searchTerm=''&targetFramework='net45'&includePrerelease=false");
    assertNotContainsPackageVersion(preReleaseNotIncludedFeedResponse, "1.0");
    assertContainsPackageVersion(preReleaseNotIncludedFeedResponse, "2.0");
    assertContainsPackageVersion(preReleaseNotIncludedFeedResponse, "3.0");
  }

  @Test
  public void testFilterIsAbsoluteLatestVersion() throws Exception {
    addMockPackage(new NuGetIndexEntry("pre-release-old", CollectionsUtil.asMap(ID, "foo", IS_PRERELEASE, Boolean.TRUE.toString(), VERSION, "1")));
    addMockPackage(new NuGetIndexEntry("release-old", CollectionsUtil.asMap(ID, "foo", IS_PRERELEASE, Boolean.FALSE.toString(), VERSION, "2")));
    addMockPackage(new NuGetIndexEntry("release-latest", CollectionsUtil.asMap(ID, "foo", VERSION, "3")));
    addMockPackage(new NuGetIndexEntry("pre-release-latest", CollectionsUtil.asMap(ID, "foo", IS_PRERELEASE, Boolean.TRUE.toString(), VERSION, "4")), true);
    addMockPackage(new NuGetIndexEntry("pre-release-old", CollectionsUtil.asMap(ID, "boo", IS_PRERELEASE, Boolean.TRUE.toString(), VERSION, "5")));
    addMockPackage(new NuGetIndexEntry("pre-release-latest", CollectionsUtil.asMap(ID, "boo", IS_PRERELEASE, Boolean.TRUE.toString(), VERSION, "6")));
    addMockPackage(new NuGetIndexEntry("release-old", CollectionsUtil.asMap(ID, "boo", IS_PRERELEASE, Boolean.FALSE.toString(), VERSION, "7")));
    addMockPackage(new NuGetIndexEntry("release-latest", CollectionsUtil.asMap(ID, "boo", VERSION, "8")), true);

    final String includedPrereleaseResponse = openRequest("Search()?$filter=IsAbsoluteLatestVersion&searchTerm=''&targetFramework='net45'&includePrerelease=true");

    assertContainsPackageVersion(includedPrereleaseResponse, "4.0");
    assertContainsPackageVersion(includedPrereleaseResponse, "8.0");
    assertNotContainsPackageVersion(includedPrereleaseResponse, "1.0");
    assertNotContainsPackageVersion(includedPrereleaseResponse, "2.0");
    assertNotContainsPackageVersion(includedPrereleaseResponse, "3.0");
    assertNotContainsPackageVersion(includedPrereleaseResponse, "5.0");
    assertNotContainsPackageVersion(includedPrereleaseResponse, "6.0");
    assertNotContainsPackageVersion(includedPrereleaseResponse, "7.0");

    final String stableOnlyResponse = openRequest("Search()?$filter=IsAbsoluteLatestVersion&searchTerm=''&targetFramework='net45'&includePrerelease=false");

    assertContainsPackageVersion(stableOnlyResponse, "8.0");
    assertNotContainsPackageVersion(stableOnlyResponse, "1.0");
    assertNotContainsPackageVersion(stableOnlyResponse, "2.0");
    assertNotContainsPackageVersion(stableOnlyResponse, "3.0");
    assertNotContainsPackageVersion(stableOnlyResponse, "4.0");
    assertNotContainsPackageVersion(stableOnlyResponse, "5.0");
    assertNotContainsPackageVersion(stableOnlyResponse, "6.0");
    assertNotContainsPackageVersion(stableOnlyResponse, "7.0");
  }

  @Test
  public void testSkipTop() throws Exception {
    addMockPackage(new NuGetIndexEntry("pre-release", CollectionsUtil.asMap(ID, "foo", IS_PRERELEASE, Boolean.TRUE.toString(), VERSION, "1")));
    addMockPackage(new NuGetIndexEntry("release", CollectionsUtil.asMap(ID, "foo", IS_PRERELEASE, Boolean.FALSE.toString(), VERSION, "2")));
    addMockPackage(new NuGetIndexEntry("release", CollectionsUtil.asMap(ID, "foo", VERSION, "3")));

    final String skipResponse = openRequest("Search()?$skip=1&searchTerm=''&targetFramework='net45'&includePrerelease=true");
    assertNotContainsPackageVersion(skipResponse, "1.0");
    assertContainsPackageVersion(skipResponse, "2.0");
    assertContainsPackageVersion(skipResponse, "3.0");

    final String skipZeroResponse = openRequest("Search()?$skip=0&searchTerm=''&targetFramework='net45'&includePrerelease=true");
    assertContainsPackageVersion(skipZeroResponse, "1.0");
    assertContainsPackageVersion(skipZeroResponse, "2.0");
    assertContainsPackageVersion(skipZeroResponse, "3.0");

    final String topResponse = openRequest("Search()?$top=2&searchTerm=''&targetFramework='net45'&includePrerelease=true");
    assertContainsPackageVersion(topResponse, "1.0");
    assertContainsPackageVersion(topResponse, "2.0");
    assertNotContainsPackageVersion(topResponse, "3.0");

    final String topZeroResponse = openRequest("Search()?$top=0&searchTerm=''&targetFramework='net45'&includePrerelease=true");
    assertNotContainsPackageVersion(topZeroResponse, "1.0");
    assertNotContainsPackageVersion(topZeroResponse, "2.0");
    assertNotContainsPackageVersion(topZeroResponse, "3.0");

    final String skipTopResponse = openRequest("Search()?$skip=1&$top=1&searchTerm=''&targetFramework='net45'&includePrerelease=true");
    assertNotContainsPackageVersion(skipTopResponse, "1.0");
    assertContainsPackageVersion(skipTopResponse, "2.0");
    assertNotContainsPackageVersion(skipTopResponse, "3.0");
  }

  @Test
  public void testOrderBy() throws Exception {
    addMockPackage(new NuGetIndexEntry("1", CollectionsUtil.asMap(ID, "foo", IS_PRERELEASE, Boolean.TRUE.toString(), DESCRIPTION, "3", VERSION, "1")));
    addMockPackage(new NuGetIndexEntry("2", CollectionsUtil.asMap(ID, "foo", IS_PRERELEASE, Boolean.TRUE.toString(), DESCRIPTION, "2", VERSION, "2")));
    addMockPackage(new NuGetIndexEntry("3", CollectionsUtil.asMap(ID, "foo", IS_PRERELEASE, Boolean.TRUE.toString(), DESCRIPTION, "1", VERSION, "3")));

    final String defaultOrderingResponse = openRequest("Search()?&searchTerm=''&targetFramework='net45'&includePrerelease=true");
    final String orderByDescriptionDescResponse = openRequest("Search()?$orderby=Description%20desc,Id&searchTerm=''&targetFramework='net45'&includePrerelease=true");
    final String orderByDescriptionAscResponse = openRequest("Search()?$orderby=Description%20asc,Id&searchTerm=''&targetFramework='net45'&includePrerelease=true");

    assertPackageVersionsOrder(defaultOrderingResponse, "1.0", "2.0", "3.0");
    assertPackageVersionsOrder(orderByDescriptionDescResponse, "1.0", "2.0", "3.0");
    assertPackageVersionsOrder(orderByDescriptionAscResponse, "3.0", "2.0", "1.0");
  }

  @Test
  public void testCountRequest() throws Exception {
    addMockPackage(new NuGetIndexEntry("aaa", CollectionsUtil.asMap(ID, "foo", VERSION, "1")));
    addMockPackage(new NuGetIndexEntry("bbb", CollectionsUtil.asMap(ID, "foo", VERSION, "2")), true);

    assertEquals("2", openRequest("Search()/$count?&searchTerm=''&targetFramework='net45'&includePrerelease=true"));
    assertEquals("1", openRequest("Search()/$count?$filter=IsAbsoluteLatestVersion&searchTerm=''&targetFramework='net45'&includePrerelease=true"));
  }

}