Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,12 @@ <h3 class="text-lg">Test Results</h3>
>
</p-tag>
}
@if (
(testCase.combinedFailureRate && testCase.combinedFailureRate > 0.5) ||
(testCase.defaultBranchFailureRate && testCase.defaultBranchFailureRate > 0.5)
) {
<p-tag severity="danger" value="Broken" styleClass="mt-2 text-xs" pTooltip="This test has failure rate over 50% and might be broken" />
}
}
</div>
</div>
Expand Down Expand Up @@ -264,6 +270,17 @@ <h4 class="font-medium mb-2">Stack Trace</h4>
<div class="border border-muted-color p-4 rounded overflow-auto max-h-[400px]">
<pre class="font-mono text-sm">{{ selectedTestCase()?.stackTrace?.trimStart() }}</pre>
</div>
<div class="flex justify-end mt-2">
<button
pButton
class="p-button-sm p-button-secondary"
(click)="downloadLogs(selectedTestCase()?.stackTrace?.trimStart() || '', selectedTestCase()?.name + '_stack_trace.txt')"
[disabled]="!selectedTestCase()?.stackTrace"
>
<i-tabler name="download" class="mr-2"></i-tabler>
Download Stack Trace
</button>
</div>
</div>
}

Expand Down Expand Up @@ -294,6 +311,17 @@ <h4 class="font-medium mb-2">Test Case Logs</h4>
}
}
</div>
<div class="flex justify-end mt-2">
<button
pButton
class="p-button-sm p-button-secondary"
(click)="downloadLogs(filteredTestCaseLogs(), selectedTestCase()?.name + '_case_logs.txt')"
[disabled]="!filteredTestCaseLogs()"
>
<i-tabler name="download" class="mr-2"></i-tabler>
Download Logs
</button>
</div>
</div>
}

Expand All @@ -307,6 +335,17 @@ <h4 class="font-medium mb-2">Test Suite Logs</h4>
}
}
</div>
<div class="flex justify-end mt-2">
<button
pButton
class="p-button-sm p-button-secondary"
(click)="downloadLogs(filteredTestSuiteLogs(), selectedTestCase()?.name + '_suite_logs.txt')"
[disabled]="!filteredTestSuiteLogs()"
>
<i-tabler name="download" class="mr-2"></i-tabler>
Download Logs
</button>
</div>
</div>
}
</div>
Expand All @@ -320,7 +359,7 @@ <h4 class="font-medium mb-2">Test Suite Logs</h4>
</ng-template>
<div class="flex flex-col gap-4">
<p>
The <b>flakiness score</b> shows how unpredictable a test is, ranging from <b>0</b> (not flaky) to <b>100</b> (highly flaky). Its based on failure rates from the default
The <b>flakiness score</b> shows how unpredictable a test is, ranging from <b>0</b> (not flaky) to <b>100</b> (highly flaky). It's based on failure rates from the default
branch and all branches combined.
</p>
<p>
Expand All @@ -331,7 +370,7 @@ <h4 class="font-medium mb-2">Test Suite Logs</h4>
<b>Flakiness per Branch:</b><br />
&nbsp;&nbsp;&nbsp;&nbsp;If the failure rate is between 0% and 50%, we calculate:<br />
&nbsp;&nbsp;&nbsp;&nbsp;<code>flakiness = (50% - failure rate) / 50%</code><br />
&nbsp;&nbsp;&nbsp;&nbsp;If its 0% or over 50%, flakiness is 0.
&nbsp;&nbsp;&nbsp;&nbsp;If it's 0% or over 50%, flakiness is 0.
</li>
<li>
<b>Weighted Score:</b><br />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import { SliderModule } from 'primeng/slider';
import { provideTablerIcons, TablerIconComponent } from 'angular-tabler-icons';
import {
IconCheck,
IconCircleX,
IconCircleChevronsRight,
IconDownload,
IconChevronDown,
IconChevronsRight,
IconChevronUp,
Expand All @@ -43,7 +46,7 @@ interface LogLevel {
}

const LOG_LEVELS: LogLevel[] = [
{ value: 0, name: 'OFF', label: 'OFF', color: 'text-gray-900', includes: ['OFF'] },
{ value: 0, name: 'OFF', label: 'OFF', color: '', includes: ['OFF'] },
{ value: 1, name: 'FATAL', label: 'FATAL+', color: 'text-red-800', includes: ['FATAL', 'OFF'] },
{ value: 2, name: 'ERROR', label: 'ERROR+', color: 'text-red-600', includes: ['ERROR', 'FATAL', 'OFF'] },
{ value: 3, name: 'WARN', label: 'WARN+', color: 'text-amber-600', includes: ['WARN', 'ERROR', 'FATAL', 'OFF'] },
Expand Down Expand Up @@ -78,6 +81,9 @@ const LOG_LEVELS: LogLevel[] = [
provideTablerIcons({
IconProgress,
IconCheck,
IconDownload,
IconCircleX,
IconCircleChevronsRight,
IconX,
IconChevronsRight,
IconClock,
Expand All @@ -104,11 +110,11 @@ export class PipelineTestResultsComponent {
selectedTestCase = signal<(TestCaseDto & { suiteSystemOut: string | undefined }) | null>(null);

// Log level filtering
selectedLogLevelValue = signal<number>(7); // Default to ALL
selectedLogLevelValue = signal<number>(2); // Default to ERROR

// Get the current log level object based on the selected value
selectedLogLevel = computed(() => {
return LOG_LEVELS.find(level => level.value === this.selectedLogLevelValue()) || LOG_LEVELS[7];
return LOG_LEVELS.find(level => level.value === this.selectedLogLevelValue()) || LOG_LEVELS[2];
});

// Get the array of log level names that should be included based on the selection
Expand Down Expand Up @@ -151,6 +157,27 @@ export class PipelineTestResultsComponent {
return this.filterLogsByLevel(this.selectedTestCase()?.suiteSystemOut);
});

// Function to download logs with current filter applied
downloadLogs(logContent: string, fileName: string): void {
if (!logContent) return;

const blob = new Blob([logContent], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');

// Create the download link
link.href = url;
link.download = fileName;
document.body.appendChild(link);

// Trigger the download
link.click();

// Clean up
document.body.removeChild(link);
URL.revokeObjectURL(url);
}

// Helper function for log level styling (colors)
getLogLevelClass(line: string): string {
// Use the same regex pattern as in filterLogsByLevel
Expand Down
Loading