<commit_before>/*
 * Copyright 2021 <NAME>, <NAME>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package gwen.core.report.html.format

import gwen.core._
import gwen.core.Formatting._
import gwen.core.node.FeatureUnit
import gwen.core.node.NodeType
import gwen.core.node.gherkin.Background
import gwen.core.node.gherkin.Examples
import gwen.core.node.gherkin.Rule
import gwen.core.node.gherkin.Scenario
import gwen.core.node.gherkin.Step
import gwen.core.report.html.HtmlReportConfig
import gwen.core.result.ResultsSummary
import gwen.core.result.SpecResult
import gwen.core.status._

import scala.io.Source
import scalatags.Text.all._
import scalatags.Text.TypedTag

import java.io.File

/** Formats the feature summary and detail reports in HTML. */
trait DetaiFormatter {
  this: HtmlReportFormatter =>

  import HtmlReportFormatter._

  /**
    * Formats the feature detail report as HTML.
    *
    * @param options     gwen command line options
    * @param unit        the feature input
    * @param result      the feature result to report
    * @param breadcrumbs names and references for linking back to parent reports
    * @param reportFiles the target report files (head = detail, tail = metas)
    */
  override def formatDetail(options: GwenOptions, unit: FeatureUnit, result: SpecResult, breadcrumbs: List[(String, File)], reportFiles: List[File]): Option[String] = {

    val reportDir = HtmlReportConfig.reportDir(options).get
    val featureName = result.spec.specFile.map(_.getPath()).getOrElse(result.spec.feature.name)
    val title = s"${result.spec.specType} Detail"
    val rootPath = relativePath(reportFiles.head, reportDir).filter(_ == File.separatorChar).flatMap(_ => "../")

    val htmlPage = 
      html(lang := "en",
        formatHtmlHead(s"$title - $featureName", rootPath),
        body(
          formatReportHeader(title, featureName, rootPath, this),
          DetailFormatter.formatDetailStatusBar(unit, result, rootPath, breadcrumbs, result.screenshots, true),
          formatDetailMetrics(result, result.summary),
          formatMetaResults(result.metaResults, reportFiles),
          for {
            scenario <- result.spec.scenarios
          } yield {
            formatScenario(scenario)
          },
          for {
            rule <- result.spec.rules
          } yield {
            formatRule(rule)
          }
        )
      )
    Some(Formatting.prettyPrintHTML("<!DOCTYPE html>" + htmlPage.render))

  }

  private def formatDetailMetrics(result: SpecResult, summary: ResultsSummary): TypedTag[String] = {
    val language = result.spec.feature.language
    val tags = result.spec.feature.tags
    div(`class` := "panel panel-default",
      div(`class` := "panel-heading", style := "padding-right: 20px; padding-bottom: 0px; border-style: none;",
        formatTags(tags),
        for {
          opt <- Option(language != "en")
          if opt
        } yield {
          span(`class` := "grayed",
            p(
              small(
                s"# language: $language"
              )
            )
          )
        },
        span(`class` := "label label-black",
          result.spec.specType.toString
        ),
        raw(escapeHtml(result.spec.feature.name)),
        formatDescriptionLines(result.spec.feature.description, None),
        div(`class` := "panel-body", style := "padding-left: 0px; padding-right: 0px; margin-right: -10px;",
          span(`class` := "pull-right grayed", style := "padding-right: 10px;",
            small(
              s"Overhead: ${formatDuration(result.overhead)}"
            )
          ),
          table(width := "100%", attr("cellpadding") := "5",
            formatProgressBar(NodeType.Rule, summary.ruleCounts),<commit_msg>fix feature name in report for i18n<commit_after>/*
 * Copyright 2021 <NAME>, <NAME>
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package gwen.core.report.html.format

import gwen.core._
import gwen.core.Formatting._
import gwen.core.node.FeatureUnit
import gwen.core.node.NodeType
import gwen.core.node.gherkin.Background
import gwen.core.node.gherkin.Examples
import gwen.core.node.gherkin.Rule
import gwen.core.node.gherkin.Scenario
import gwen.core.node.gherkin.Step
import gwen.core.report.html.HtmlReportConfig
import gwen.core.result.ResultsSummary
import gwen.core.result.SpecResult
import gwen.core.status._

import scala.io.Source
import scalatags.Text.all._
import scalatags.Text.TypedTag

import java.io.File
import gwen.core.node.gherkin.SpecType

/** Formats the feature summary and detail reports in HTML. */
trait DetaiFormatter {
  this: HtmlReportFormatter =>

  import HtmlReportFormatter._

  /**
    * Formats the feature detail report as HTML.
    *
    * @param options     gwen command line options
    * @param unit        the feature input
    * @param result      the feature result to report
    * @param breadcrumbs names and references for linking back to parent reports
    * @param reportFiles the target report files (head = detail, tail = metas)
    */
  override def formatDetail(options: GwenOptions, unit: FeatureUnit, result: SpecResult, breadcrumbs: List[(String, File)], reportFiles: List[File]): Option[String] = {

    val reportDir = HtmlReportConfig.reportDir(options).get
    val featureName = result.spec.specFile.map(_.getPath()).getOrElse(result.spec.feature.name)
    val title = s"${result.spec.specType} Detail"
    val rootPath = relativePath(reportFiles.head, reportDir).filter(_ == File.separatorChar).flatMap(_ => "../")

    val htmlPage = 
      html(lang := "en",
        formatHtmlHead(s"$title - $featureName", rootPath),
        body(
          formatReportHeader(title, featureName, rootPath, this),
          DetailFormatter.formatDetailStatusBar(unit, result, rootPath, breadcrumbs, result.screenshots, true),
          formatDetailMetrics(result, result.summary),
          formatMetaResults(result.metaResults, reportFiles),
          for {
            scenario <- result.spec.scenarios
          } yield {
            formatScenario(scenario)
          },
          for {
            rule <- result.spec.rules
          } yield {
            formatRule(rule)
          }
        )
      )
    Some(Formatting.prettyPrintHTML("<!DOCTYPE html>" + htmlPage.render))

  }

  private def formatDetailMetrics(result: SpecResult, summary: ResultsSummary): TypedTag[String] = {
    val language = result.spec.feature.language
    val tags = result.spec.feature.tags
    div(`class` := "panel panel-default",
      div(`class` := "panel-heading", style := "padding-right: 20px; padding-bottom: 0px; border-style: none;",
        formatTags(tags),
        for {
          opt <- Option(language != "en")
          if opt
        } yield {
          span(`class` := "grayed",
            p(
              small(
                s"# language: $language"
              )
            )
          )
        },
        span(`class` := "label label-black",
          if (result.spec.specType.isFeature) {
            result.spec.feature.keyword
          } else {
            result.spec.specType.toString
          }
        ),
        raw(escapeHtml(result.spec.feature.name)),
        formatDescriptionLines(result.spec.feature.description, None),
        div(`class` := "panel-body", style := "padding-left: 0px; padding-right: 0px; margin-right: -10px;",
          span(`class` := "pull-right grayed", style := "padding-right: 10px;",
            small(
              s"Overhead: ${formatDuration(result.overhead)}"
            )
          ),
          table(width := "100%", attr("cellpadding") := "5",
            formatProgressBar(NodeType.Rule, summary.ruleCounts),
{'fraction_non_alphanumeric': 0.11210659315414656, 'fraction_numerical': 0.00505398575694923, 'mean_word_length': 2.748170469220835, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1087816', 'n_tokens_mistral': 2503, 'n_tokens_neox': 2435, 'n_words': 641}