qualityfolio/group-detail.sql
SELECT 'dynamic' AS component, sqlpage.run_sql('shell/shell.sql') AS properties;
-- not including breadcrumbs from sqlpage_aide_navigation
-- not including page title from sqlpage_aide_navigation
SELECT 'title' AS component, (SELECT COALESCE(title, caption)
FROM sqlpage_aide_navigation
WHERE namespace = 'prime' AND path = 'qualityfolio/group-detail.sql/index.sql') as contents;
;
select
'breadcrumb' as component;
select
'Home' as title,
sqlpage.environment_variable('SQLPAGE_SITE_PREFIX') || '/' as link;
select
'Test Management System' as title,
sqlpage.environment_variable('SQLPAGE_SITE_PREFIX') || '/qualityfolio/index.sql' as link;
select
s."name" as title,
sqlpage.environment_variable('SQLPAGE_SITE_PREFIX') || '/qualityfolio/suite-data.sql?id=' || s.id as link
from groups g
inner join test_suites s on s.id = g.suite_id where g.id = $id;
select
g."name" as title from groups g
inner join test_suites s on s.id = g.suite_id where g.id = $id;
SELECT 'title'AS component,
name as contents FROM groups where id = $id;
-- Custom CSS for accordion styling (same as suite-data)
SELECT 'html' AS component,
'<style>
.custom-accordion {
margin: 20px 0;
border: 1px solid #ddd;
border-radius: 4px;
overflow: hidden;
}
.custom-accordion details {
border: none;
margin: 0;
}
.custom-accordion details + details {
border-top: 1px solid #ddd;
}
.custom-accordion summary {
background-color: #f5f5f5;
padding: 15px 20px;
cursor: pointer;
font-weight: 500;
color: #333;
border: none;
outline: none;
position: relative;
user-select: none;
list-style: none;
}
.custom-accordion summary::-webkit-details-marker {
display: none;
}
.custom-accordion summary::after {
content: "+";
position: absolute;
right: 20px;
top: 50%;
transform: translateY(-50%);
font-size: 18px;
font-weight: bold;
color: #666;
}
.custom-accordion details[open] summary::after {
content: "−";
}
.custom-accordion summary:hover {
background-color: #ebebeb;
}
.custom-accordion .content {
padding: 20px;
background-color: white;
border-top: 1px solid #ddd;
}
tr td.test_status {
color: blue !important;
}
tr.rowClass-passed td.test_status {
color: green !important;
}
tr.rowClass-failed td.test_status {
color: red !important;
}
tr.rowClass-TODO td.test_status {
color: orange !important;
}
/* Test Case Accordion Styles */
.test-cases-accordion-container {
margin: 20px 0;
}
.test-case-accordion {
border: 1px solid #ddd;
border-radius: 8px;
margin-bottom: 10px;
overflow: hidden;
}
.test-case-summary {
background-color: #f5f5f5;
padding: 15px 20px;
cursor: pointer;
font-weight: 600;
color: #333;
border: none;
outline: none;
user-select: none;
list-style: none;
position: relative;
transition: background-color 0.2s;
}
.test-case-summary::-webkit-details-marker {
display: none;
}
.test-case-summary::after {
content: "+";
position: absolute;
right: 20px;
top: 50%;
transform: translateY(-50%);
font-size: 18px;
font-weight: bold;
color: #666;
}
.test-case-accordion[open] .test-case-summary::after {
content: "−";
}
.test-case-summary:hover {
background-color: #ebebeb;
}
.test-case-content {
padding: 0;
background-color: white;
border-top: 1px solid #ddd;
}
.test-case-info-card {
padding: 20px;
}
.test-case-info-card h4 {
margin: 0 0 15px 0;
color: #333;
font-size: 16px;
border-bottom: 1px solid #eee;
padding-bottom: 8px;
}
.test-case-info-card p {
margin: 8px 0;
line-height: 1.5;
}
.execution-stats {
display: grid;
grid-template-columns: 1fr;
gap: 8px;
margin: 15px 0;
}
.exec-stat-item {
display: flex;
justify-content: space-between;
padding: 10px 15px;
background-color: #f8f9fa;
border-radius: 4px;
border-left: 3px solid #dee2e6;
}
.exec-stat-label {
color: #666;
font-weight: 500;
}
.exec-stat-value {
font-weight: bold;
}
.status-passed {
color: #28a745;
}
.exec-stat-item:has(.status-passed) {
border-left-color: #28a745;
}
.status-failed {
color: #dc3545;
}
.exec-stat-item:has(.status-failed) {
border-left-color: #dc3545;
}
.status-TODO {
color: #ffc107;
}
.exec-stat-item:has(.status-TODO) {
border-left-color: #ffc107;
}
.action-buttons {
margin-top: 20px;
padding-top: 15px;
border-top: 1px solid #eee;
}
.view-details-btn {
display: inline-block;
padding: 10px 20px;
background-color: #007bff;
color: white;
text-decoration: none;
border-radius: 5px;
font-weight: 500;
transition: background-color 0.2s;
}
.view-details-btn:hover {
background-color: #0056b3;
color: white;
text-decoration: none;
}
@media (max-width: 768px) {
.execution-stats {
grid-template-columns: 1fr;
}
}
</style>' AS html;
-- Accordion container
SELECT 'html' AS component,
'<div class="custom-accordion">' AS html;
-- Group Details Section (open by default)
SELECT 'html' AS component,
'<details open>
<summary>Group Details</summary>
<div class="content">' AS html;
SELECT 'card' AS component,
1 as columns;
SELECT
'**Group ID:** ' || rn.id ||
'
**Name:** ' || rn."name" ||
'
**Description:** ' || COALESCE(rn."description", 'No description available') ||
'
**Created By:** ' || COALESCE(rn."created_by", 'Unknown') ||
'
**Created On:** ' || strftime('%d-%m-%Y', rn."created_at") ||
CASE
WHEN rn.body IS NOT NULL AND rn.body != ''
THEN '
**Additional Details:**
' || rn.body
ELSE ''
END AS description_md
FROM groups rn
INNER JOIN test_suites st ON st.id = rn.suite_id
WHERE rn.id = $id;
SELECT 'html' AS component,
'</div></details>' AS html;
-- Test Cases Section (closed by default)
SELECT 'html' AS component,
'<details>
<summary>Test Cases (' || COUNT(*) || ')</summary>
<div class="content">' AS html
FROM test_cases WHERE group_id = $id;
SELECT 'text' AS component,
'This section displays all test cases associated with this group, including their current status and execution details.' AS contents;
-- Show test case count for this group
SELECT 'alert' AS component,
'info' AS color,
'Test Cases Summary' AS title,
'Total: ' || COUNT(*) ||
' | Passed: ' || SUM(CASE WHEN test_status = 'passed' THEN 1 ELSE 0 END) ||
' | Failed: ' || SUM(CASE WHEN test_status = 'failed' THEN 1 ELSE 0 END) ||
' | Pending: ' || SUM(CASE WHEN test_status IS NULL OR test_status = 'TODO' THEN 1 ELSE 0 END) AS description
FROM test_cases WHERE group_id = $id;
-- Create individual accordion for each test case
SELECT 'html' AS component,
'<div class="test-cases-accordion-container">' AS html;
-- Generate accordion for each test case
SELECT 'html' AS component,
'<details class="test-case-accordion">
<summary class="test-case-summary">' || tc.test_case_id || ' - ' || tc.test_case_title || '</summary>
<div class="test-case-content">
<div class="test-case-info-card">
<h4>Test Case Information</h4>
<p><strong>Test Case ID:</strong> ' || tc.test_case_id || '</p>
<p><strong>Title:</strong> ' || tc.test_case_title || '</p>
<p><strong>Group:</strong> ' || tc.group_name || '</p>
<p><strong>Type:</strong> ' || COALESCE(tc.test_type, 'Not specified') || '</p>
<p><strong>Priority:</strong> ' || COALESCE(tc.priority, 'Not specified') || '</p>
<p><strong>Created by:</strong> ' || COALESCE(tc.created_by, 'Unknown') || '</p>
<p><strong>Created on:</strong> ' || tc.formatted_test_case_created_at || '</p>
<h4>Test Execution Details</h4>
<div class="execution-stats">
<div class="exec-stat-item">
<span class="exec-stat-label">Current Status:</span>
<span class="exec-stat-value status-' || COALESCE(tc.test_status, 'TODO') || '">' ||
CASE
WHEN tc.test_status IS NOT NULL THEN tc.test_status
ELSE 'TODO'
END || '</span>
</div>
<div class="exec-stat-item">
<span class="exec-stat-label">Execution Count:</span>
<span class="exec-stat-value">' ||
COALESCE((SELECT COUNT(*) FROM test_execution_log WHERE test_case_id = tc.test_case_id), 0) || '</span>
</div>
</div>
<div class="action-buttons">
<a href="' || sqlpage.environment_variable('SQLPAGE_SITE_PREFIX') || '/qualityfolio/test-detail.sql?tab=actual-result&id=' || tc.test_case_id || '" class="view-details-btn">View Full Details</a>
</div>
</div>
</div>
</details>' AS html
FROM test_cases tc
WHERE tc.group_id = $id
ORDER BY tc.test_case_id;
SELECT 'html' AS component,
'</div>' AS html;
SELECT 'html' AS component,
'</div></details>' AS html;
-- Close accordion container
SELECT 'html' AS component,
'</div>' AS html;