@Test
  public void shouldRenderDocStringInTagReport() throws Exception {
    File rd =
        new File(
            ReportBuilderTest.class
                .getClassLoader()
                .getResource("net/masterthought/cucumber")
                .toURI());
    List<String> jsonReports = new ArrayList<String>();
    jsonReports.add(
        new File(
                ReportBuilderTest.class
                    .getClassLoader()
                    .getResource("net/masterthought/cucumber/docstring.json")
                    .toURI())
            .getAbsolutePath());
    ReportBuilder reportBuilder =
        new ReportBuilder(
            jsonReports,
            rd,
            "/jenkins/",
            "1",
            "cucumber-reporting",
            false,
            false,
            false,
            false,
            true,
            true,
            false,
            "",
            false,
            false);
    reportBuilder.generateReports();

    File input = new File(rd, "tag-1.html");
    Document doc = Jsoup.parse(input, "UTF-8", "");
    assertThat(fromClass("doc-string", doc).get(0).text(), is("X _ X O X O _ O X"));
    Elements tableCells =
        doc.getElementsByClass("stats-table")
            .get(0)
            .getElementsByTag("tr")
            .get(2)
            .getElementsByTag("td");
    assertEquals("@tag:1", tableCells.get(0).text());
    assertEquals("1", tableCells.get(1).text());
    assertEquals("1", tableCells.get(2).text());
    assertEquals("0", tableCells.get(3).text());
    assertEquals("2", tableCells.get(4).text());
    assertEquals("2", tableCells.get(5).text());
    assertEquals("0", tableCells.get(6).text());
    assertEquals("0", tableCells.get(7).text());
    assertEquals("0", tableCells.get(8).text());
    assertEquals("0", tableCells.get(9).text());
    assertEquals("0", tableCells.get(10).text());
    assertEquals("106ms", tableCells.get(11).text());
    assertEquals("passed", tableCells.get(12).text());
  }
  @Test
  public void shouldRenderTheFeatureOverviewPageCorrectlyWithFlashCharts() throws Exception {
    File rd =
        new File(
            ReportBuilderTest.class
                .getClassLoader()
                .getResource("net/masterthought/cucumber")
                .toURI());
    List<String> jsonReports = new ArrayList<String>();
    jsonReports.add(
        new File(
                ReportBuilderTest.class
                    .getClassLoader()
                    .getResource("net/masterthought/cucumber/project3.json")
                    .toURI())
            .getAbsolutePath());
    ReportBuilder reportBuilder =
        new ReportBuilder(
            jsonReports,
            rd,
            "",
            "1",
            "cucumber-reporting",
            false,
            false,
            false,
            false,
            true,
            true,
            false,
            "",
            false,
            false);
    reportBuilder.generateReports();

    File input = new File(rd, "feature-overview.html");
    Document doc = Jsoup.parse(input, "UTF-8", "");
    assertThat(fromId("overview-title", doc).text(), is("Feature Overview for build: 1"));
    assertStatsHeader(doc);
    assertStatsFirstFeature(doc);
    Element flashchart = fromId("flash-charts", doc);
    assertNotNull(flashchart);
    String chart1 = flashchart.getElementsByTag("script").get(0).data();
    String chart2 = flashchart.getElementsByTag("script").get(1).data();
    assertThat(
        chart1,
        containsString(
            "library_path=charts/charts_library&xml_data=<chart><chart_data><row><null/><string>Passed</string><string>Failed</string><string>Skipped</string>"
                + "<string>Pending</string><string>Undefined</string><string>Missing</string></row>"));
    assertThat(
        chart2,
        containsString(
            "library_path=charts/charts_library&xml_data=<chart><chart_data><row><null/><string>Passed</string><string>Failed</string></row>"));
  }
  @Test
  public void shouldRenderErrorPageOnParsingError() throws Exception {
    File rd =
        new File(
            ReportBuilderTest.class
                .getClassLoader()
                .getResource("net/masterthought/cucumber")
                .toURI());
    List<String> jsonReports = new ArrayList<String>();
    jsonReports.add(
        new File(
                ReportBuilderTest.class
                    .getClassLoader()
                    .getResource("net/masterthought/cucumber/invalid_format.json")
                    .toURI())
            .getAbsolutePath());
    ReportBuilder reportBuilder =
        new ReportBuilder(
            jsonReports,
            rd,
            "",
            "1",
            "cucumber-reporting",
            false,
            false,
            false,
            false,
            true,
            true,
            false,
            "",
            false,
            false);
    reportBuilder.generateReports();

    File input = new File(rd, "feature-overview.html");
    Document doc = Jsoup.parse(input, "UTF-8", "");
    assertThat(
        fromId("overview-title", doc).text(),
        is("Oops Something went wrong with cucumber-reporting build: 1"));
    assertTrue(
        fromId("error-message", doc)
            .text()
            .contains(
                "com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Unterminated object at line 19 column 18 path $[0].elements[0].keyword"));
  }
  @Test
  public void shouldRenderTheFeaturePageCorrectly() throws Exception {
    File rd =
        new File(
            ReportBuilderTest.class
                .getClassLoader()
                .getResource("net/masterthought/cucumber")
                .toURI());
    List<String> jsonReports = new ArrayList<String>();
    jsonReports.add(
        new File(
                ReportBuilderTest.class
                    .getClassLoader()
                    .getResource("net/masterthought/cucumber/project3.json")
                    .toURI())
            .getAbsolutePath());
    ReportBuilder reportBuilder =
        new ReportBuilder(
            jsonReports,
            rd,
            "",
            "1",
            "cucumber-reporting",
            false,
            false,
            false,
            false,
            true,
            true,
            false,
            "",
            false,
            false);
    reportBuilder.generateReports();

    File input = new File(rd, "net-masterthought-example-ATM.feature.html");
    Document doc = Jsoup.parse(input, "UTF-8", "");
    assertThat(
        fromId("feature-title", doc).text(),
        is("Result for Account Holder withdraws cash in build: 1"));
    assertStatsHeader(doc);
    assertStatsFirstFeature(doc);
    assertFeatureContent(doc);
  }
  @Test
  public void shouldRenderTheFeatureOverviewPageCorrectlyWithJSCharts() throws Exception {
    File rd =
        new File(
            ReportBuilderTest.class
                .getClassLoader()
                .getResource("net/masterthought/cucumber")
                .toURI());
    List<String> jsonReports = new ArrayList<String>();
    jsonReports.add(
        new File(
                ReportBuilderTest.class
                    .getClassLoader()
                    .getResource("net/masterthought/cucumber/project3.json")
                    .toURI())
            .getAbsolutePath());
    ReportBuilder reportBuilder =
        new ReportBuilder(
            jsonReports,
            rd,
            "",
            "1",
            "cucumber-reporting",
            false,
            false,
            false,
            false,
            false,
            true,
            false,
            "",
            false,
            false);
    reportBuilder.generateReports();

    File input = new File(rd, "feature-overview.html");
    Document doc = Jsoup.parse(input, "UTF-8", "");
    assertThat(fromId("overview-title", doc).text(), is("Feature Overview for build: 1"));
    assertStatsHeader(doc);
    assertStatsFirstFeature(doc);
    assertStatsTotals(doc);
    assertNotNull(fromId("js-charts", doc));
  }
  @Test
  public void shouldRenderErrorPageOnReportGenerationError() throws Exception {
    File rd =
        new File(
            ReportBuilderTest.class
                .getClassLoader()
                .getResource("net/masterthought/cucumber")
                .toURI());
    List<String> jsonReports = new ArrayList<String>();
    jsonReports.add(
        new File(
                ReportBuilderTest.class
                    .getClassLoader()
                    .getResource("net/masterthought/cucumber/missing_elements.json")
                    .toURI())
            .getAbsolutePath());
    ReportBuilder reportBuilder =
        new ReportBuilder(
            jsonReports,
            rd,
            "",
            "1",
            "cucumber-reporting",
            false,
            false,
            false,
            false,
            true,
            true,
            false,
            "",
            false,
            false);
    reportBuilder.generateReports();

    File input = new File(rd, "feature-overview.html");
    Document doc = Jsoup.parse(input, "UTF-8", "");
    assertThat(
        fromId("overview-title", doc).text(),
        is("Oops Something went wrong with cucumber-reporting build: 1"));
    assertTrue(fromId("error-message", doc).text().contains("java.lang.NullPointerException"));
  }
  @Override
  public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener)
      throws IOException, InterruptedException {

    listener.getLogger().println("[CucumberReportPublisher] Compiling Cucumber Html Reports ...");

    File workspaceJsonReportDirectory = new File(build.getWorkspace().toURI().getPath());
    if (!jsonReportDirectory.isEmpty()) {
      workspaceJsonReportDirectory =
          new File(build.getWorkspace().toURI().getPath(), jsonReportDirectory);
    }
    File targetBuildDirectory = new File(build.getRootDir(), "cucumber-html-reports");

    String buildNumber = Integer.toString(build.getNumber());
    String buildProject = build.getProject().getName();

    if (!targetBuildDirectory.exists()) {
      targetBuildDirectory.mkdirs();
    }

    boolean buildResult = true;

    // if we are on a slave
    if (Computer.currentComputer() instanceof SlaveComputer) {
      listener
          .getLogger()
          .println("[CucumberReportPublisher] detected this build is running on a slave ");
      FilePath projectWorkspaceOnSlave = build.getProject().getSomeWorkspace();
      FilePath masterJsonReportDirectory = new FilePath(targetBuildDirectory);
      listener
          .getLogger()
          .println(
              "[CucumberReportPublisher] copying json from: "
                  + projectWorkspaceOnSlave.toURI()
                  + "to reports directory: "
                  + masterJsonReportDirectory.toURI());
      projectWorkspaceOnSlave.copyRecursiveTo("**/*.json", "", masterJsonReportDirectory);
    } else {
      // if we are on the master
      listener
          .getLogger()
          .println("[CucumberReportPublisher] detected this build is running on the master ");
      String[] files = findJsonFiles(workspaceJsonReportDirectory);

      if (files.length != 0) {
        listener
            .getLogger()
            .println(
                "[CucumberReportPublisher] copying json to reports directory: "
                    + targetBuildDirectory);
        for (String file : files) {
          FileUtils.copyFile(
              new File(workspaceJsonReportDirectory.getPath() + "/" + file),
              new File(targetBuildDirectory, file));
        }
      } else {
        listener
            .getLogger()
            .println(
                "[CucumberReportPublisher] there were no json results found in: "
                    + workspaceJsonReportDirectory);
      }
    }

    // generate the reports from the targetBuildDirectory
    String[] jsonReportFiles = findJsonFiles(targetBuildDirectory);
    if (jsonReportFiles.length != 0) {

      listener
          .getLogger()
          .println(
              "[CucumberReportPublisher] Found the following number of json files: "
                  + jsonReportFiles.length);
      int jsonIndex = 0;
      for (String jsonReportFile : jsonReportFiles) {
        listener
            .getLogger()
            .println(
                "[CucumberReportPublisher] "
                    + jsonIndex
                    + ". Found a json file: "
                    + jsonReportFile);
        jsonIndex++;
      }
      listener.getLogger().println("[CucumberReportPublisher] Generating HTML reports");

      try {
        ReportBuilder reportBuilder =
            new ReportBuilder(
                fullPathToJsonFiles(jsonReportFiles, targetBuildDirectory),
                targetBuildDirectory,
                pluginUrlPath,
                buildNumber,
                buildProject,
                skippedFails,
                undefinedFails,
                !noFlashCharts,
                true,
                false,
                "",
                false);
        reportBuilder.generateReports();
        buildResult = reportBuilder.getBuildStatus();
      } catch (Exception e) {
        e.printStackTrace();
        listener
            .getLogger()
            .println("[CucumberReportPublisher] there was an error generating the reports: " + e);
        for (StackTraceElement error : e.getStackTrace()) {
          listener.getLogger().println(error);
        }
      }
    } else {
      listener
          .getLogger()
          .println(
              "[CucumberReportPublisher] there were no json results found in: "
                  + targetBuildDirectory);
    }

    build.addAction(new CucumberReportBuildAction(build));
    return buildResult;
  }
  @Override
  public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener)
      throws IOException, InterruptedException {

    listener.getLogger().println("[CucumberReportPublisher] Compiling Cucumber Html Reports ...");

    // source directory (possibly on slave)
    FilePath workspaceJsonReportDirectory;
    if (jsonReportDirectory.isEmpty()) {
      workspaceJsonReportDirectory = build.getWorkspace();
    } else {
      workspaceJsonReportDirectory = new FilePath(build.getWorkspace(), jsonReportDirectory);
    }

    // target directory (always on master)
    File targetBuildDirectory = new File(build.getRootDir(), "cucumber-html-reports");
    if (!targetBuildDirectory.exists()) {
      targetBuildDirectory.mkdirs();
    }

    String buildNumber = Integer.toString(build.getNumber());
    String buildProject = build.getProject().getName();

    if (Computer.currentComputer() instanceof SlaveComputer) {
      listener
          .getLogger()
          .println(
              "[CucumberReportPublisher] Copying all json files from slave: "
                  + workspaceJsonReportDirectory.getRemote()
                  + " to master reports directory: "
                  + targetBuildDirectory);
    } else {
      listener
          .getLogger()
          .println(
              "[CucumberReportPublisher] Copying all json files from: "
                  + workspaceJsonReportDirectory.getRemote()
                  + " to reports directory: "
                  + targetBuildDirectory);
    }
    workspaceJsonReportDirectory.copyRecursiveTo(
        DEFAULT_FILE_INCLUDE_PATTERN, new FilePath(targetBuildDirectory));

    // generate the reports from the targetBuildDirectory
    Result result = Result.NOT_BUILT;
    String[] jsonReportFiles =
        findJsonFiles(targetBuildDirectory, fileIncludePattern, fileExcludePattern);
    if (jsonReportFiles.length > 0) {
      listener
          .getLogger()
          .println(
              String.format(
                  "[CucumberReportPublisher] Found %d json files.", jsonReportFiles.length));
      int jsonIndex = 0;
      for (String jsonReportFile : jsonReportFiles) {
        listener
            .getLogger()
            .println(
                "[CucumberReportPublisher] "
                    + jsonIndex
                    + ". Found a json file: "
                    + jsonReportFile);
        jsonIndex++;
      }
      listener.getLogger().println("[CucumberReportPublisher] Generating HTML reports");

      try {
        ReportBuilder reportBuilder =
            new ReportBuilder(
                fullPathToJsonFiles(jsonReportFiles, targetBuildDirectory),
                targetBuildDirectory,
                pluginUrlPath,
                buildNumber,
                buildProject,
                skippedFails,
                pendingFails,
                undefinedFails,
                missingFails,
                !noFlashCharts,
                true,
                false,
                parallelTesting);
        reportBuilder.generateReports();

        boolean buildSuccess = reportBuilder.getBuildStatus();

        if (buildSuccess) {
          result = Result.SUCCESS;
        } else {
          result = ignoreFailedTests ? Result.UNSTABLE : Result.FAILURE;
        }

      } catch (Exception e) {
        e.printStackTrace();
        result = Result.FAILURE;
        listener
            .getLogger()
            .println("[CucumberReportPublisher] there was an error generating the reports: " + e);
        for (StackTraceElement error : e.getStackTrace()) {
          listener.getLogger().println(error);
        }
      }
    } else {
      result = Result.SUCCESS;
      listener
          .getLogger()
          .println(
              "[CucumberReportPublisher] there were no json results found in: "
                  + targetBuildDirectory);
    }

    build.addAction(new CucumberReportBuildAction(build));
    build.setResult(result);

    return true;
  }