#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
#

name: 'Test Summary Report'
description: 'Parses JUnit test reports and publishes them to the GitHub workflow summary'
inputs:
  test-report-xml-base-dir:
    description: 'The base directory from which to search for JUnit XML reports'
    required: true
    default: '.'
  test-report-xml-includes:
    description: 'The path glob for files to examine when generating the test report summary'
    required: true
    default: '**/target/*-reports/TEST-*.xml'

runs:
  using: "composite"
  steps:
    - name: Setup Node
      uses: actions/setup-node@v4
      with:
        node-version: 20
    - name: Install script dependencies
      shell: bash
      run: |
        npm install junit2json@3.1.7
    - name: Generate test summary
      uses: actions/github-script@v7
      with:
        script: |
          const fs = require('fs');
          const junit = require('junit2json');
          const testReportGlobPattern = "${{ inputs.test-report-xml-base-dir }}/${{ inputs.test-report-xml-includes }}".replace(/\.+\/+/g, "")
          const summaryData = [];

          // Configure test summary table headers
          summaryData.push([
            {data: 'Test Class', header: true},
            {data: 'Test Name', header: true},
            {data: 'Failure', header: true},
            {data: 'Details', header: true}
          ]);

          // Iterate and parse surefire / failsafe reports and use the info to build the summary
          const globber = await glob.create(testReportGlobPattern);
          for await (const reportFile of globber.globGenerator()) {
            const file = fs.readFileSync(reportFile);
            const report = junit.parse(file).then((report) => {
              if (report.errors > 0 || report.failures > 0) {
                report.testcase.forEach((testCase) => {
                  const failure = testCase.failure !== undefined ? testCase.failure : testCase.error;
                  if (failure !== undefined) {
                    const shortClassName = `<code>${testCase.classname.substring(testCase.classname.lastIndexOf('.') + 1)}</code>`;
                    const className = `<details><summary>${shortClassName}</summary>\n<code>${testCase.classname}</code></details>`;
                    const details = `<details><summary>View</summary>\n<pre>${failure[0].inner}</pre></details>`;

                    let testName = "";
                    if ((typeof testCase.name === 'string' || testCase.name instanceof String) && (testCase.name.trim().length > 0)) {
                      testName = `<code>${testCase.name}</code>`;
                      if (testCase.name.trim().length > 25) {
                        testName = `<details><summary>View</summary>\n<code>${testCase.name}</code></details>`;
                      }
                    } else {
                      // Some JUnit extensions do odd things to the test name on failure, so it may be null or empty
                      testName = `<code>Unknown</code>`;
                    }

                    let message = `<pre>${failure[0].message}</pre>`;
                    if (message.length > 50) {
                      message = `<details><summary>View</summary>\n${message}</details>`;
                    }
                    summaryData.push([className, testName, message, details]);
                  }
                });
              }
            });
          }

          // Write the summary data if there were test failures
          if (summaryData.length > 1) {
            await core.summary
              .addHeading("Test Failures", "3")
              .addTable(summaryData)
              .write();
          }
