/** Tests that we are able to add a basic starter. */
  @Test
  public void addStarter() throws Exception {
    IProject project = harness.createBootProject("foo", withStarters("web"));
    final ISpringBootProject bootProject = springBootCore.project(project);
    EditStartersModel wizard = createWizard(project);
    assertEquals(bootProject.getBootVersion(), wizard.getBootVersion());
    assertStarterDeps(wizard.dependencies.getCurrentSelection(), "web");

    PopularityTracker popularities = new PopularityTracker(prefs);
    assertUsageCounts(bootProject, popularities /*none*/);

    wizard.addDependency("actuator");
    assertStarterDeps(wizard.dependencies.getCurrentSelection(), "web", "actuator");
    wizard.performOk();

    Job.getJobManager().join(EditStartersModel.JOB_FAMILY, null);

    assertUsageCounts(bootProject, popularities, "actuator:1");

    StsTestUtil.assertNoErrors(project); // force project build

    assertStarters(bootProject.getBootStarters(), "web", "actuator");

    // check that the 'scope' is not set in the pom.xml:
    IDOMDocument pom = parsePom(project);

    Element depEl = findDependency(bootProject, pom, "actuator");
    assertEquals("org.springframework.boot", getGroupId(depEl));
    assertEquals("spring-boot-starter-actuator", getArtifactId(depEl));
    assertEquals(null, getScope(depEl));
  }
  /**
   * Tests that the EditStartersModel is parsed and that existing starters already present on the
   * project are initially selected.
   */
  @Test
  public void existingStartersSelected() throws Exception {
    IProject project = harness.createBootProject("foo", withStarters("web", "actuator"));
    ISpringBootProject bootProject = springBootCore.project(project);
    EditStartersModel wizard = createWizard(project);
    assertTrue(wizard.isSupported());

    assertEquals(bootProject.getBootVersion(), wizard.getBootVersion());
    assertStarterDeps(wizard.dependencies.getCurrentSelection(), "web", "actuator");
  }
  /** Tests that we are able to remove a starter. */
  @Test
  public void removeStarter() throws Exception {
    IProject project = harness.createBootProject("foo", withStarters("web", "actuator"));
    final ISpringBootProject bootProject = springBootCore.project(project);
    EditStartersModel wizard = createWizard(project);
    assertEquals(bootProject.getBootVersion(), wizard.getBootVersion());
    assertStarterDeps(wizard.dependencies.getCurrentSelection(), "web", "actuator");

    wizard.removeDependency("web");
    assertStarterDeps(wizard.dependencies.getCurrentSelection(), /* removed: "web",*/ "actuator");
    wizard.performOk();

    StsTestUtil.assertNoErrors(project); // force project build

    assertStarters(bootProject.getBootStarters(), "actuator");
  }
 private Element findDependency(ISpringBootProject project, Document pom, String id) {
   SpringBootStarters starters = project.getStarterInfos();
   MavenId mid = starters.getMavenId(id);
   if (mid != null) {
     return findDependency(pom, mid);
   }
   return null;
 }
  @Test
  public void addStarterWithBom() throws Exception {
    // We'll be adding this starter:
    //	      "id": "cloud-eureka",
    //	      "groupId": "org.springframework.cloud",
    //	      "artifactId": "spring-cloud-starter-eureka",
    //	      "scope": "compile",
    //	      "bom": "cloud-bom"

    IProject project = harness.createBootProject("foo", withStarters("web"));
    final ISpringBootProject bootProject = springBootCore.project(project);
    EditStartersModel wizard = createWizard(project);
    wizard.addDependency("cloud-eureka");
    wizard.performOk();

    Job.getJobManager().join(EditStartersModel.JOB_FAMILY, null);
    StsTestUtil.assertNoErrors(project); // force project build

    assertStarters(bootProject.getBootStarters(), "web", "cloud-eureka");
  }
  @Test
  public void addStarterWithTestScope() throws Exception {
    IProject project = harness.createBootProject("foo", withStarters("web"));
    final ISpringBootProject bootProject = springBootCore.project(project);
    EditStartersModel wizard = createWizard(project);
    wizard.addDependency("restdocs");
    wizard.performOk();

    Job.getJobManager().join(EditStartersModel.JOB_FAMILY, null);

    StsTestUtil.assertNoErrors(project); // force project build

    assertStarters(bootProject.getBootStarters(), "web", "restdocs");

    // check that the 'scope' is set properly
    IDOMDocument pom = parsePom(project);
    Element depEl = findDependency(bootProject, pom, "restdocs");
    assertEquals("spring-restdocs-mockmvc", getArtifactId(depEl));
    assertEquals("test", getScope(depEl));
  }
  @Test
  public void addMultipleStartersWithSameBom() throws Exception {
    // This test uses more 'controlled' parameters:
    IProject project =
        harness.createBootProject(
            "foo",
            bootVersion(BOOT_1_3_X_RELEASE), // boot version fixed
            withStarters("web"));
    initializr.setInputs("sample"); // sample intializr json captured for this version
    final ISpringBootProject bootProject = springBootCore.project(project);
    int initialBomCount = getBomCount(parsePom(project));

    EditStartersModel wizard = createWizard(project);
    wizard.addDependency("cloud-eureka");
    wizard.addDependency("cloud-config-client");
    wizard.performOk();

    Job.getJobManager().join(EditStartersModel.JOB_FAMILY, null);
    StsTestUtil.assertNoErrors(project); // force project build

    assertStarters(bootProject.getBootStarters(), "web", "cloud-eureka", "cloud-config-client");

    IDOMDocument pom = parsePom(project);
    int finalBomCount = getBomCount(pom);
    assertEquals(initialBomCount + 1, finalBomCount);

    // check that both repos got added
    assertRepoCount(2, pom);

    Element repo = getRepo(pom, "spring-snapshots");
    assertNotNull(repo);
    assertEquals("Spring Snapshots", getTextChild(repo, "name"));
    assertEquals("https://repo.spring.io/snapshot", getTextChild(repo, "url"));
    assertEquals("true", getSnapshotsEnabled(repo));

    repo = getRepo(pom, "spring-milestones");
    assertNotNull(repo);
    assertEquals("Spring Milestones", getTextChild(repo, "name"));
    assertEquals("https://repo.spring.io/milestone", getTextChild(repo, "url"));
    assertEquals("false", getSnapshotsEnabled(repo));
  }
  @Test
  public void addMultipleStartersWithDifferentBom() throws Exception {
    // This test uses more 'controlled' parameters:
    IProject project =
        harness.createBootProject(
            "foo",
            bootVersion(BOOT_1_3_X_RELEASE), // boot version fixed
            withStarters("web"));
    initializr.setInputs("sample"); // sample intializr json captured for this version
    final ISpringBootProject bootProject = springBootCore.project(project);
    int initialBomCount = getBomCount(parsePom(project));

    EditStartersModel wizard = createWizard(project);
    wizard.addDependency("cloud-eureka");
    wizard.addDependency("vaadin");
    wizard.performOk();

    Job.getJobManager().join(EditStartersModel.JOB_FAMILY, null);
    StsTestUtil.assertNoErrors(project); // force project build

    assertStarters(bootProject.getBootStarters(), "web", "cloud-eureka", "vaadin");

    IDOMDocument pom = parsePom(project);
    int finalBomCount = getBomCount(pom);
    assertEquals(initialBomCount + 2, finalBomCount);
    {
      Element bom = getBom(pom, "spring-cloud-starter-parent");
      assertEquals("org.springframework.cloud", getTextChild(bom, GROUP_ID));
      assertEquals("Brixton.M3", getTextChild(bom, VERSION));
      assertEquals("pom", getTextChild(bom, TYPE));
      assertEquals("import", getTextChild(bom, SCOPE));
    }
    {
      Element bom = getBom(pom, "vaadin-bom");
      assertEquals("com.vaadin", getTextChild(bom, GROUP_ID));
      assertEquals("7.5.5", getTextChild(bom, VERSION));
      assertEquals("pom", getTextChild(bom, TYPE));
      assertEquals("import", getTextChild(bom, SCOPE));
    }
  }
  private void assertUsageCounts(
      ISpringBootProject project, PopularityTracker popularities, String... idAndCount)
      throws Exception {
    Map<String, Integer> expect = new HashMap<>();
    for (String pair : idAndCount) {
      String[] pieces = pair.split(":");
      assertEquals(2, pieces.length);
      String id = pieces[0];
      int count = Integer.parseInt(pieces[1]);
      expect.put(id, count);
    }

    List<SpringBootStarter> knownStarters = project.getKnownStarters();
    assertFalse(knownStarters.isEmpty());
    for (SpringBootStarter starter : knownStarters) {
      String id = starter.getId();
      Integer expectedCountOrNull = expect.get(id);
      int expectedCount = expectedCountOrNull == null ? 0 : expectedCountOrNull;
      assertEquals("Usage count for '" + id + "'", expectedCount, popularities.getUsageCount(id));
      expect.remove(id);
    }

    assertTrue("Expected usage counts not found: " + expect, expect.isEmpty());
  }