AAE-50678 Fix: report test coverage to SonarCloud (#12181),

* fix: enable LCOV coverage reporting for SonarCloud

Add lcov reporter to all karma configs, upload coverage artifacts from
unit test matrix jobs, and add a SonarCloud scan job that merges
coverage reports and runs the sonar-scanner with proper LCOV paths.

Co-authored-by: eromano <1030050+eromano@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix: pass secrets to unit-test-workflow and set SONAR_HOST_URL for SonarCloud

Co-authored-by: eromano <1030050+eromano@users.noreply.github.com>

* fix: add test outputs to nx.json so NX caches and restores coverage reports

Co-authored-by: eromano <1030050+eromano@users.noreply.github.com>

* test: add unit tests for Chart model to verify coverage reporting

* fix: use find to locate lcov.info in downloaded artifacts for SonarCloud coverage

Co-authored-by: eromano <1030050+eromano@users.noreply.github.com>

* test: add fake file with unit test to verify coverage reporting

Co-authored-by: eromano <1030050+eromano@users.noreply.github.com>

* ci: add full SonarCloud scan workflow on develop push

Co-authored-by: eromano <1030050+eromano@users.noreply.github.com>

* test: remove fake coverage-canary file and its spec

Co-authored-by: eromano <1030050+eromano@users.noreply.github.com>

* fix: replace secrets inherit with explicit SONAR_TOKEN in workflow call

Co-authored-by: eromano <1030050+eromano@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: eromano <1030050+eromano@users.noreply.github.com>
Co-authored-by: Eugenio Romano <eromano@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Copilot
2026-08-19 19:44:15 +02:00
committed by GitHub
co-authored by eromano Copilot Autofix powered by AI Eugenio Romano
parent f915c813f0
commit 7b8d616a9f
12 changed files with 256 additions and 9 deletions
+1 -1
View File
@@ -56,7 +56,7 @@ module.exports = function (config) {
coverageReporter: {
dir: join(__dirname, '../../coverage/content-services'),
subdir: '.',
reporters: [{ type: 'html' }, { type: 'text-summary' }, { type: 'text-summary', subdir: '.', file: 'summary.txt' }],
reporters: [{ type: 'html' }, { type: 'lcov' }, { type: 'text-summary' }, { type: 'text-summary', subdir: '.', file: 'summary.txt' }],
check: {
global: {
statements: 75,
+1 -1
View File
@@ -69,7 +69,7 @@ module.exports = function (config) {
coverageReporter: {
dir: join(__dirname, '../../coverage/core'),
subdir: '.',
reporters: [{ type: 'html' }, { type: 'text-summary' }, { type: 'text-summary', subdir: '.', file: 'summary.txt' }],
reporters: [{ type: 'html' }, { type: 'lcov' }, { type: 'text-summary' }, { type: 'text-summary', subdir: '.', file: 'summary.txt' }],
check: {
global: {
statements: 75,
+1 -1
View File
@@ -23,7 +23,7 @@ module.exports = function (config) {
coverageReporter: {
dir: join(__dirname, '../../coverage/extensions'),
subdir: '.',
reporters: [{ type: 'html' }, { type: 'text-summary' }, { type: 'text-summary', subdir: '.', file: 'summary.txt' }],
reporters: [{ type: 'html' }, { type: 'lcov' }, { type: 'text-summary' }, { type: 'text-summary', subdir: '.', file: 'summary.txt' }],
check: {
global: {
statements: 75,
+1 -1
View File
@@ -44,7 +44,7 @@ module.exports = function (config) {
coverageReporter: {
dir: join(__dirname, '../../coverage/insights'),
subdir: '.',
reporters: [{ type: 'html' }, { type: 'text-summary' }, { type: 'text-summary', subdir: '.', file: 'summary.txt' }],
reporters: [{ type: 'html' }, { type: 'lcov' }, { type: 'text-summary' }, { type: 'text-summary', subdir: '.', file: 'summary.txt' }],
check: {
global: {
statements: 75,
@@ -0,0 +1,148 @@
/*!
* @license
* Copyright © 2005-2026 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* 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.
*/
import { Chart } from './chart.model';
describe('Chart Model', () => {
describe('constructor', () => {
it('should create with default values when no argument is provided', () => {
const chart = new Chart();
expect(chart.labels).toEqual([]);
expect(chart.data).toEqual([]);
expect(chart.datasets).toEqual([]);
expect(chart.showDetails).toBe(false);
});
it('should populate properties from input object', () => {
const chart = new Chart({
id: '1',
title: 'Test Chart',
titleKey: 'KEY',
labels: ['a', 'b'],
data: [1, 2],
datasets: [{ data: [1] }],
showDetails: true,
detailsTable: { key: 'value' },
options: { responsive: true }
});
expect(chart.id).toBe('1');
expect(chart.title).toBe('Test Chart');
expect(chart.titleKey).toBe('KEY');
expect(chart.labels).toEqual(['a', 'b']);
expect(chart.data).toEqual([1, 2]);
expect(chart.datasets).toEqual([{ data: [1] }]);
expect(chart.showDetails).toBe(true);
expect(chart.detailsTable).toEqual({ key: 'value' });
expect(chart.options).toEqual({ responsive: true });
});
it('should convert type and set icon for pieChart', () => {
const chart = new Chart({ type: 'pieChart' });
expect(chart.type).toBe('pie');
expect(chart.icon).toBe('pie_chart');
});
it('should convert type and set icon for barChart', () => {
const chart = new Chart({ type: 'barChart' });
expect(chart.type).toBe('bar');
expect(chart.icon).toBe('equalizer');
});
it('should convert type and set icon for line', () => {
const chart = new Chart({ type: 'line' });
expect(chart.type).toBe('line');
expect(chart.icon).toBe('show_chart');
});
it('should convert type and set icon for table', () => {
const chart = new Chart({ type: 'table' });
expect(chart.type).toBe('table');
expect(chart.icon).toBe('web');
});
it('should convert type and set icon for multiBarChart', () => {
const chart = new Chart({ type: 'multiBarChart' });
expect(chart.type).toBe('multiBar');
expect(chart.icon).toBe('poll');
});
it('should convert type and set icon for processDefinitionHeatMap', () => {
const chart = new Chart({ type: 'processDefinitionHeatMap' });
expect(chart.type).toBe('HeatMap');
expect(chart.icon).toBe('share');
});
it('should convert type and set icon for masterDetailTable', () => {
const chart = new Chart({ type: 'masterDetailTable' });
expect(chart.type).toBe('masterDetailTable');
expect(chart.icon).toBe('subtitles');
});
it('should default to table type for unknown types', () => {
const chart = new Chart({ type: 'unknown' });
expect(chart.type).toBe('table');
expect(chart.icon).toBe('web');
});
});
describe('hasData', () => {
it('should return true when data is not empty', () => {
const chart = new Chart({ data: [1, 2, 3] });
expect(chart.hasData()).toBe(true);
});
it('should return false when data is empty', () => {
const chart = new Chart({ data: [] });
expect(chart.hasData()).toBe(false);
});
it('should return false when no data is provided', () => {
const chart = new Chart();
expect(chart.hasData()).toBe(false);
});
});
describe('hasDatasets', () => {
it('should return true when datasets is not empty', () => {
const chart = new Chart({ datasets: [{ data: [1] }] });
expect(chart.hasDatasets()).toBe(true);
});
it('should return false when datasets is empty', () => {
const chart = new Chart({ datasets: [] });
expect(chart.hasDatasets()).toBe(false);
});
});
describe('hasZeroValues', () => {
it('should return true when all data values are zero', () => {
const chart = new Chart({ data: [0, 0, 0] });
expect(chart.hasZeroValues()).toBe(true);
});
it('should return false when at least one value is non-zero', () => {
const chart = new Chart({ data: [0, 1, 0] });
expect(chart.hasZeroValues()).toBe(false);
});
it('should return false when data is empty', () => {
const chart = new Chart({ data: [] });
expect(chart.hasZeroValues()).toBe(false);
});
});
});
+1 -1
View File
@@ -48,7 +48,7 @@ module.exports = function (config) {
coverageReporter: {
dir: join(__dirname, '../../coverage/process-services-cloud'),
subdir: '.',
reporters: [{ type: 'html' }, { type: 'text-summary' }, { type: 'text-summary', subdir: '.', file: 'summary.txt' }],
reporters: [{ type: 'html' }, { type: 'lcov' }, { type: 'text-summary' }, { type: 'text-summary', subdir: '.', file: 'summary.txt' }],
check: {
global: {
statements: 75,
+1 -1
View File
@@ -43,7 +43,7 @@ module.exports = function (config) {
coverageReporter: {
dir: join(__dirname, '../../coverage/process-services'),
subdir: '.',
reporters: [{ type: 'html' }, { type: 'text-summary' }, { type: 'text-summary', subdir: '.', file: 'summary.txt' }],
reporters: [{ type: 'html' }, { type: 'lcov' }, { type: 'text-summary' }, { type: 'text-summary', subdir: '.', file: 'summary.txt' }],
check: {
global: {
statements: 75,