@vizzly-testing/cli 0.13.1 → 0.13.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +552 -88
- package/claude-plugin/.claude-plugin/README.md +4 -0
- package/claude-plugin/.mcp.json +4 -0
- package/claude-plugin/CHANGELOG.md +27 -0
- package/claude-plugin/mcp/vizzly-docs-server/README.md +95 -0
- package/claude-plugin/mcp/vizzly-docs-server/docs-fetcher.js +110 -0
- package/claude-plugin/mcp/vizzly-docs-server/index.js +283 -0
- package/claude-plugin/mcp/vizzly-server/cloud-api-provider.js +26 -10
- package/claude-plugin/mcp/vizzly-server/index.js +14 -1
- package/claude-plugin/mcp/vizzly-server/local-tdd-provider.js +61 -28
- package/dist/cli.js +4 -4
- package/dist/commands/run.js +1 -1
- package/dist/commands/tdd-daemon.js +54 -8
- package/dist/commands/tdd.js +8 -8
- package/dist/container/index.js +34 -3
- package/dist/reporter/reporter-bundle.css +1 -1
- package/dist/reporter/reporter-bundle.iife.js +29 -59
- package/dist/server/handlers/tdd-handler.js +18 -16
- package/dist/server/http-server.js +473 -4
- package/dist/services/config-service.js +371 -0
- package/dist/services/project-service.js +245 -0
- package/dist/services/server-manager.js +32 -5
- package/dist/services/static-report-generator.js +208 -0
- package/dist/services/tdd-service.js +14 -6
- package/dist/types/reporter/src/components/ui/form-field.d.ts +16 -0
- package/dist/types/reporter/src/components/views/projects-view.d.ts +1 -0
- package/dist/types/reporter/src/components/views/settings-view.d.ts +1 -0
- package/dist/types/reporter/src/hooks/use-auth.d.ts +10 -0
- package/dist/types/reporter/src/hooks/use-config.d.ts +9 -0
- package/dist/types/reporter/src/hooks/use-projects.d.ts +10 -0
- package/dist/types/reporter/src/services/api-client.d.ts +7 -0
- package/dist/types/server/http-server.d.ts +1 -1
- package/dist/types/services/config-service.d.ts +98 -0
- package/dist/types/services/project-service.d.ts +103 -0
- package/dist/types/services/server-manager.d.ts +2 -1
- package/dist/types/services/static-report-generator.d.ts +25 -0
- package/dist/types/services/tdd-service.d.ts +2 -2
- package/dist/utils/console-ui.js +26 -2
- package/docs/tdd-mode.md +31 -15
- package/package.json +4 -4
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static Report Generator using React Reporter
|
|
3
|
+
* Generates a self-contained HTML file with the React dashboard and embedded data
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { writeFile, mkdir, copyFile } from 'fs/promises';
|
|
7
|
+
import { existsSync } from 'fs';
|
|
8
|
+
import { join, dirname } from 'path';
|
|
9
|
+
import { fileURLToPath } from 'url';
|
|
10
|
+
import { createServiceLogger } from '../utils/logger-factory.js';
|
|
11
|
+
const logger = createServiceLogger('STATIC-REPORT');
|
|
12
|
+
let __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
let __dirname = dirname(__filename);
|
|
14
|
+
let PROJECT_ROOT = join(__dirname, '..', '..');
|
|
15
|
+
export class StaticReportGenerator {
|
|
16
|
+
constructor(workingDir, config) {
|
|
17
|
+
this.workingDir = workingDir;
|
|
18
|
+
this.config = config;
|
|
19
|
+
this.reportDir = join(workingDir, '.vizzly', 'report');
|
|
20
|
+
this.reportPath = join(this.reportDir, 'index.html');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Generate static HTML report with React reporter bundle
|
|
25
|
+
* @param {Object} reportData - Complete report data (same format as live dashboard)
|
|
26
|
+
* @returns {Promise<string>} Path to generated report
|
|
27
|
+
*/
|
|
28
|
+
async generateReport(reportData) {
|
|
29
|
+
if (!reportData || typeof reportData !== 'object') {
|
|
30
|
+
throw new Error('Invalid report data provided');
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
// Ensure report directory exists
|
|
34
|
+
await mkdir(this.reportDir, {
|
|
35
|
+
recursive: true
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Copy React bundles to report directory
|
|
39
|
+
let bundlePath = join(PROJECT_ROOT, 'dist', 'reporter', 'reporter-bundle.iife.js');
|
|
40
|
+
let cssPath = join(PROJECT_ROOT, 'dist', 'reporter', 'reporter-bundle.css');
|
|
41
|
+
if (!existsSync(bundlePath) || !existsSync(cssPath)) {
|
|
42
|
+
throw new Error('Reporter bundles not found. Run "npm run build:reporter" first.');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Copy bundles to report directory for self-contained report
|
|
46
|
+
await copyFile(bundlePath, join(this.reportDir, 'reporter-bundle.js'));
|
|
47
|
+
await copyFile(cssPath, join(this.reportDir, 'reporter-bundle.css'));
|
|
48
|
+
|
|
49
|
+
// Generate HTML with embedded data
|
|
50
|
+
let htmlContent = this.generateHtmlTemplate(reportData);
|
|
51
|
+
await writeFile(this.reportPath, htmlContent, 'utf8');
|
|
52
|
+
logger.debug(`Static report generated: ${this.reportPath}`);
|
|
53
|
+
return this.reportPath;
|
|
54
|
+
} catch (error) {
|
|
55
|
+
logger.error(`Failed to generate static report: ${error.message}`);
|
|
56
|
+
throw new Error(`Report generation failed: ${error.message}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Generate HTML template with embedded React app
|
|
62
|
+
* @param {Object} reportData - Report data to embed
|
|
63
|
+
* @returns {string} HTML content
|
|
64
|
+
*/
|
|
65
|
+
generateHtmlTemplate(reportData) {
|
|
66
|
+
// Serialize report data safely
|
|
67
|
+
let serializedData = JSON.stringify(reportData).replace(/</g, '\\u003c').replace(/>/g, '\\u003e').replace(/&/g, '\\u0026');
|
|
68
|
+
return `<!DOCTYPE html>
|
|
69
|
+
<html lang="en">
|
|
70
|
+
<head>
|
|
71
|
+
<meta charset="UTF-8">
|
|
72
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
73
|
+
<title>Vizzly Dev Report - ${new Date().toLocaleString()}</title>
|
|
74
|
+
<link rel="stylesheet" href="./reporter-bundle.css">
|
|
75
|
+
<style>
|
|
76
|
+
/* Loading spinner styles */
|
|
77
|
+
.reporter-loading {
|
|
78
|
+
display: flex;
|
|
79
|
+
align-items: center;
|
|
80
|
+
justify-content: center;
|
|
81
|
+
min-height: 100vh;
|
|
82
|
+
background: #0f172a;
|
|
83
|
+
color: #f59e0b;
|
|
84
|
+
}
|
|
85
|
+
.spinner {
|
|
86
|
+
width: 48px;
|
|
87
|
+
height: 48px;
|
|
88
|
+
border: 4px solid rgba(245, 158, 11, 0.2);
|
|
89
|
+
border-top-color: #f59e0b;
|
|
90
|
+
border-radius: 50%;
|
|
91
|
+
animation: spin 1s linear infinite;
|
|
92
|
+
margin-bottom: 1rem;
|
|
93
|
+
}
|
|
94
|
+
@keyframes spin {
|
|
95
|
+
to { transform: rotate(360deg); }
|
|
96
|
+
}
|
|
97
|
+
</style>
|
|
98
|
+
</head>
|
|
99
|
+
<body>
|
|
100
|
+
<div id="vizzly-reporter-root">
|
|
101
|
+
<div class="reporter-loading">
|
|
102
|
+
<div style="text-align: center;">
|
|
103
|
+
<div class="spinner"></div>
|
|
104
|
+
<p>Loading Vizzly Report...</p>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
|
|
109
|
+
<script>
|
|
110
|
+
// Embedded report data (static mode)
|
|
111
|
+
window.VIZZLY_REPORTER_DATA = ${serializedData};
|
|
112
|
+
window.VIZZLY_STATIC_MODE = true;
|
|
113
|
+
|
|
114
|
+
// Generate timestamp for "generated at" display
|
|
115
|
+
window.VIZZLY_REPORT_GENERATED_AT = "${new Date().toISOString()}";
|
|
116
|
+
|
|
117
|
+
console.log('Vizzly Static Report loaded');
|
|
118
|
+
console.log('Report data:', window.VIZZLY_REPORTER_DATA?.summary);
|
|
119
|
+
</script>
|
|
120
|
+
<script src="./reporter-bundle.js"></script>
|
|
121
|
+
</body>
|
|
122
|
+
</html>`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Generate a minimal HTML report when bundles are missing (fallback)
|
|
127
|
+
* @param {Object} reportData - Report data
|
|
128
|
+
* @returns {string} Minimal HTML content
|
|
129
|
+
*/
|
|
130
|
+
generateFallbackHtml(reportData) {
|
|
131
|
+
let summary = reportData.summary || {};
|
|
132
|
+
let comparisons = reportData.comparisons || [];
|
|
133
|
+
let failed = comparisons.filter(c => c.status === 'failed');
|
|
134
|
+
return `<!DOCTYPE html>
|
|
135
|
+
<html lang="en">
|
|
136
|
+
<head>
|
|
137
|
+
<meta charset="UTF-8">
|
|
138
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
139
|
+
<title>Vizzly Dev Report</title>
|
|
140
|
+
<style>
|
|
141
|
+
body {
|
|
142
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
143
|
+
background: #0f172a;
|
|
144
|
+
color: #e2e8f0;
|
|
145
|
+
padding: 2rem;
|
|
146
|
+
}
|
|
147
|
+
.container { max-width: 1200px; margin: 0 auto; }
|
|
148
|
+
.header { text-align: center; margin-bottom: 2rem; }
|
|
149
|
+
.summary {
|
|
150
|
+
display: flex;
|
|
151
|
+
gap: 2rem;
|
|
152
|
+
justify-content: center;
|
|
153
|
+
margin: 2rem 0;
|
|
154
|
+
}
|
|
155
|
+
.stat { text-align: center; }
|
|
156
|
+
.stat-number {
|
|
157
|
+
font-size: 3rem;
|
|
158
|
+
font-weight: bold;
|
|
159
|
+
display: block;
|
|
160
|
+
}
|
|
161
|
+
.warning {
|
|
162
|
+
background: #fef3c7;
|
|
163
|
+
color: #92400e;
|
|
164
|
+
padding: 1rem;
|
|
165
|
+
border-radius: 0.5rem;
|
|
166
|
+
margin: 2rem 0;
|
|
167
|
+
}
|
|
168
|
+
</style>
|
|
169
|
+
</head>
|
|
170
|
+
<body>
|
|
171
|
+
<div class="container">
|
|
172
|
+
<div class="header">
|
|
173
|
+
<h1>🐻 Vizzly Dev Report</h1>
|
|
174
|
+
<p>Generated: ${new Date().toLocaleString()}</p>
|
|
175
|
+
</div>
|
|
176
|
+
|
|
177
|
+
<div class="summary">
|
|
178
|
+
<div class="stat">
|
|
179
|
+
<span class="stat-number">${summary.total || 0}</span>
|
|
180
|
+
<span>Total</span>
|
|
181
|
+
</div>
|
|
182
|
+
<div class="stat">
|
|
183
|
+
<span class="stat-number" style="color: #10b981;">${summary.passed || 0}</span>
|
|
184
|
+
<span>Passed</span>
|
|
185
|
+
</div>
|
|
186
|
+
<div class="stat">
|
|
187
|
+
<span class="stat-number" style="color: #ef4444;">${summary.failed || 0}</span>
|
|
188
|
+
<span>Failed</span>
|
|
189
|
+
</div>
|
|
190
|
+
</div>
|
|
191
|
+
|
|
192
|
+
<div class="warning">
|
|
193
|
+
<strong>⚠️ Limited Report</strong>
|
|
194
|
+
<p>This is a fallback report. For the full interactive experience, ensure the reporter bundle is built:</p>
|
|
195
|
+
<code>npm run build:reporter</code>
|
|
196
|
+
</div>
|
|
197
|
+
|
|
198
|
+
${failed.length > 0 ? `
|
|
199
|
+
<h2>Failed Comparisons</h2>
|
|
200
|
+
<ul>
|
|
201
|
+
${failed.map(c => `<li>${c.name} - ${c.diffPercentage || 0}% difference</li>`).join('')}
|
|
202
|
+
</ul>
|
|
203
|
+
` : '<p style="text-align: center; font-size: 1.5rem;">✅ All tests passed!</p>'}
|
|
204
|
+
</div>
|
|
205
|
+
</body>
|
|
206
|
+
</html>`;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
@@ -1058,14 +1058,22 @@ export class TddService {
|
|
|
1058
1058
|
|
|
1059
1059
|
/**
|
|
1060
1060
|
* Accept a current screenshot as the new baseline
|
|
1061
|
-
* @param {string}
|
|
1061
|
+
* @param {string|Object} idOrComparison - Comparison ID or comparison object
|
|
1062
1062
|
* @returns {Object} Result object
|
|
1063
1063
|
*/
|
|
1064
|
-
async acceptBaseline(
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1064
|
+
async acceptBaseline(idOrComparison) {
|
|
1065
|
+
let comparison;
|
|
1066
|
+
|
|
1067
|
+
// Support both ID lookup and direct comparison object
|
|
1068
|
+
if (typeof idOrComparison === 'string') {
|
|
1069
|
+
// Find the comparison by ID in memory
|
|
1070
|
+
comparison = this.comparisons.find(c => c.id === idOrComparison);
|
|
1071
|
+
if (!comparison) {
|
|
1072
|
+
throw new Error(`No comparison found with ID: ${idOrComparison}`);
|
|
1073
|
+
}
|
|
1074
|
+
} else {
|
|
1075
|
+
// Use the provided comparison object directly
|
|
1076
|
+
comparison = idOrComparison;
|
|
1069
1077
|
}
|
|
1070
1078
|
const sanitizedName = comparison.name;
|
|
1071
1079
|
let properties = comparison.properties || {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function FormField({ label, name, type, value, onChange, error, help, disabled, required, placeholder, options, }: {
|
|
2
|
+
label: any;
|
|
3
|
+
name: any;
|
|
4
|
+
type?: string;
|
|
5
|
+
value: any;
|
|
6
|
+
onChange: any;
|
|
7
|
+
error: any;
|
|
8
|
+
help: any;
|
|
9
|
+
disabled: any;
|
|
10
|
+
required: any;
|
|
11
|
+
placeholder: any;
|
|
12
|
+
options: any;
|
|
13
|
+
}): any;
|
|
14
|
+
export function ConfigSourceBadge({ source }: {
|
|
15
|
+
source: any;
|
|
16
|
+
}): any;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function ProjectsView(): any;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function SettingsView(): any;
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if we're in static mode (data embedded in HTML)
|
|
3
|
+
*/
|
|
4
|
+
export function isStaticMode(): boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Fetch report data from server or return embedded static data
|
|
7
|
+
*/
|
|
1
8
|
export function fetchReportData(): Promise<any>;
|
|
2
9
|
export function acceptBaseline(comparisonId: any): Promise<any>;
|
|
3
10
|
export function acceptAllBaselines(): Promise<any>;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ConfigService for reading and writing configuration
|
|
3
|
+
* @extends BaseService
|
|
4
|
+
*/
|
|
5
|
+
export class ConfigService extends BaseService {
|
|
6
|
+
constructor(config: any, options?: {});
|
|
7
|
+
projectRoot: any;
|
|
8
|
+
explorer: import("cosmiconfig").PublicExplorerSync;
|
|
9
|
+
/**
|
|
10
|
+
* Get configuration with source information
|
|
11
|
+
* @param {string} scope - 'project', 'global', or 'merged'
|
|
12
|
+
* @returns {Promise<Object>} Config object with metadata
|
|
13
|
+
*/
|
|
14
|
+
getConfig(scope?: string): Promise<any>;
|
|
15
|
+
/**
|
|
16
|
+
* Get project-level config from vizzly.config.js or similar
|
|
17
|
+
* @private
|
|
18
|
+
* @returns {Promise<Object>}
|
|
19
|
+
*/
|
|
20
|
+
private _getProjectConfig;
|
|
21
|
+
/**
|
|
22
|
+
* Get global config from ~/.vizzly/config.json
|
|
23
|
+
* @private
|
|
24
|
+
* @returns {Promise<Object>}
|
|
25
|
+
*/
|
|
26
|
+
private _getGlobalConfig;
|
|
27
|
+
/**
|
|
28
|
+
* Get merged config showing source for each setting
|
|
29
|
+
* @private
|
|
30
|
+
* @returns {Promise<Object>}
|
|
31
|
+
*/
|
|
32
|
+
private _getMergedConfig;
|
|
33
|
+
/**
|
|
34
|
+
* Update configuration
|
|
35
|
+
* @param {string} scope - 'project' or 'global'
|
|
36
|
+
* @param {Object} updates - Configuration updates to apply
|
|
37
|
+
* @returns {Promise<Object>} Updated config
|
|
38
|
+
*/
|
|
39
|
+
updateConfig(scope: string, updates: any): Promise<any>;
|
|
40
|
+
/**
|
|
41
|
+
* Update project-level config
|
|
42
|
+
* @private
|
|
43
|
+
* @param {Object} updates - Config updates
|
|
44
|
+
* @returns {Promise<Object>} Updated config
|
|
45
|
+
*/
|
|
46
|
+
private _updateProjectConfig;
|
|
47
|
+
/**
|
|
48
|
+
* Update global config
|
|
49
|
+
* @private
|
|
50
|
+
* @param {Object} updates - Config updates
|
|
51
|
+
* @returns {Promise<Object>} Updated config
|
|
52
|
+
*/
|
|
53
|
+
private _updateGlobalConfig;
|
|
54
|
+
/**
|
|
55
|
+
* Write project config file (JavaScript format)
|
|
56
|
+
* @private
|
|
57
|
+
* @param {string} filepath - Path to write to
|
|
58
|
+
* @param {Object} config - Config object
|
|
59
|
+
* @returns {Promise<void>}
|
|
60
|
+
*/
|
|
61
|
+
private _writeProjectConfigFile;
|
|
62
|
+
/**
|
|
63
|
+
* Serialize config object to JavaScript module
|
|
64
|
+
* @private
|
|
65
|
+
* @param {Object} config - Config object
|
|
66
|
+
* @returns {string} JavaScript source code
|
|
67
|
+
*/
|
|
68
|
+
private _serializeToJavaScript;
|
|
69
|
+
/**
|
|
70
|
+
* Stringify object with proper indentation (2 spaces)
|
|
71
|
+
* @private
|
|
72
|
+
* @param {*} value - Value to stringify
|
|
73
|
+
* @param {number} depth - Current depth
|
|
74
|
+
* @returns {string}
|
|
75
|
+
*/
|
|
76
|
+
private _stringifyWithIndent;
|
|
77
|
+
/**
|
|
78
|
+
* Validate configuration object
|
|
79
|
+
* @param {Object} config - Config to validate
|
|
80
|
+
* @returns {Promise<Object>} Validation result
|
|
81
|
+
*/
|
|
82
|
+
validateConfig(config: any): Promise<any>;
|
|
83
|
+
/**
|
|
84
|
+
* Get the source of a specific config key
|
|
85
|
+
* @param {string} key - Config key
|
|
86
|
+
* @returns {Promise<string>} Source ('default', 'global', 'project', 'env', 'cli')
|
|
87
|
+
*/
|
|
88
|
+
getConfigSource(key: string): Promise<string>;
|
|
89
|
+
/**
|
|
90
|
+
* Deep merge two objects
|
|
91
|
+
* @private
|
|
92
|
+
* @param {Object} target - Target object
|
|
93
|
+
* @param {Object} source - Source object
|
|
94
|
+
* @returns {Object} Merged object
|
|
95
|
+
*/
|
|
96
|
+
private _deepMerge;
|
|
97
|
+
}
|
|
98
|
+
import { BaseService } from './base-service.js';
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProjectService for managing project mappings and operations
|
|
3
|
+
* @extends BaseService
|
|
4
|
+
*/
|
|
5
|
+
export class ProjectService extends BaseService {
|
|
6
|
+
constructor(config: any, options?: {});
|
|
7
|
+
apiService: any;
|
|
8
|
+
/**
|
|
9
|
+
* List all project mappings
|
|
10
|
+
* @returns {Promise<Array>} Array of project mappings
|
|
11
|
+
*/
|
|
12
|
+
listMappings(): Promise<any[]>;
|
|
13
|
+
/**
|
|
14
|
+
* Get project mapping for a specific directory
|
|
15
|
+
* @param {string} directory - Directory path
|
|
16
|
+
* @returns {Promise<Object|null>} Project mapping or null
|
|
17
|
+
*/
|
|
18
|
+
getMapping(directory: string): Promise<any | null>;
|
|
19
|
+
/**
|
|
20
|
+
* Create or update project mapping
|
|
21
|
+
* @param {string} directory - Directory path
|
|
22
|
+
* @param {Object} projectData - Project data
|
|
23
|
+
* @param {string} projectData.projectSlug - Project slug
|
|
24
|
+
* @param {string} projectData.organizationSlug - Organization slug
|
|
25
|
+
* @param {string} projectData.token - Project API token
|
|
26
|
+
* @param {string} [projectData.projectName] - Optional project name
|
|
27
|
+
* @returns {Promise<Object>} Created mapping
|
|
28
|
+
*/
|
|
29
|
+
createMapping(directory: string, projectData: {
|
|
30
|
+
projectSlug: string;
|
|
31
|
+
organizationSlug: string;
|
|
32
|
+
token: string;
|
|
33
|
+
projectName?: string;
|
|
34
|
+
}): Promise<any>;
|
|
35
|
+
/**
|
|
36
|
+
* Remove project mapping
|
|
37
|
+
* @param {string} directory - Directory path
|
|
38
|
+
* @returns {Promise<void>}
|
|
39
|
+
*/
|
|
40
|
+
removeMapping(directory: string): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Switch project for current directory
|
|
43
|
+
* @param {string} projectSlug - Project slug
|
|
44
|
+
* @param {string} organizationSlug - Organization slug
|
|
45
|
+
* @param {string} token - Project token
|
|
46
|
+
* @returns {Promise<Object>} Updated mapping
|
|
47
|
+
*/
|
|
48
|
+
switchProject(projectSlug: string, organizationSlug: string, token: string): Promise<any>;
|
|
49
|
+
/**
|
|
50
|
+
* List all projects from API
|
|
51
|
+
* @returns {Promise<Array>} Array of projects
|
|
52
|
+
*/
|
|
53
|
+
listProjects(): Promise<any[]>;
|
|
54
|
+
/**
|
|
55
|
+
* Get project details
|
|
56
|
+
* @param {string} projectSlug - Project slug
|
|
57
|
+
* @param {string} organizationSlug - Organization slug
|
|
58
|
+
* @returns {Promise<Object>} Project details
|
|
59
|
+
*/
|
|
60
|
+
getProject(projectSlug: string, organizationSlug: string): Promise<any>;
|
|
61
|
+
/**
|
|
62
|
+
* Get recent builds for a project
|
|
63
|
+
* @param {string} projectSlug - Project slug
|
|
64
|
+
* @param {string} organizationSlug - Organization slug
|
|
65
|
+
* @param {Object} options - Query options
|
|
66
|
+
* @param {number} [options.limit=10] - Number of builds to fetch
|
|
67
|
+
* @param {string} [options.branch] - Filter by branch
|
|
68
|
+
* @returns {Promise<Array>} Array of builds
|
|
69
|
+
*/
|
|
70
|
+
getRecentBuilds(projectSlug: string, organizationSlug: string, options?: {
|
|
71
|
+
limit?: number;
|
|
72
|
+
branch?: string;
|
|
73
|
+
}): Promise<any[]>;
|
|
74
|
+
/**
|
|
75
|
+
* Create a project token
|
|
76
|
+
* @param {string} projectSlug - Project slug
|
|
77
|
+
* @param {string} organizationSlug - Organization slug
|
|
78
|
+
* @param {Object} tokenData - Token data
|
|
79
|
+
* @param {string} tokenData.name - Token name
|
|
80
|
+
* @param {string} [tokenData.description] - Token description
|
|
81
|
+
* @returns {Promise<Object>} Created token
|
|
82
|
+
*/
|
|
83
|
+
createProjectToken(projectSlug: string, organizationSlug: string, tokenData: {
|
|
84
|
+
name: string;
|
|
85
|
+
description?: string;
|
|
86
|
+
}): Promise<any>;
|
|
87
|
+
/**
|
|
88
|
+
* List project tokens
|
|
89
|
+
* @param {string} projectSlug - Project slug
|
|
90
|
+
* @param {string} organizationSlug - Organization slug
|
|
91
|
+
* @returns {Promise<Array>} Array of tokens
|
|
92
|
+
*/
|
|
93
|
+
listProjectTokens(projectSlug: string, organizationSlug: string): Promise<any[]>;
|
|
94
|
+
/**
|
|
95
|
+
* Revoke a project token
|
|
96
|
+
* @param {string} projectSlug - Project slug
|
|
97
|
+
* @param {string} organizationSlug - Organization slug
|
|
98
|
+
* @param {string} tokenId - Token ID
|
|
99
|
+
* @returns {Promise<void>}
|
|
100
|
+
*/
|
|
101
|
+
revokeProjectToken(projectSlug: string, organizationSlug: string, tokenId: string): Promise<void>;
|
|
102
|
+
}
|
|
103
|
+
import { BaseService } from './base-service.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export class ServerManager extends BaseService {
|
|
2
|
-
constructor(config: any,
|
|
2
|
+
constructor(config: any, options?: {});
|
|
3
3
|
httpServer: {
|
|
4
4
|
start: () => Promise<any>;
|
|
5
5
|
stop: () => Promise<any>;
|
|
@@ -253,6 +253,7 @@ export class ServerManager extends BaseService {
|
|
|
253
253
|
}>;
|
|
254
254
|
cleanup: () => void;
|
|
255
255
|
};
|
|
256
|
+
services: any;
|
|
256
257
|
start(buildId?: any, tddMode?: boolean, setBaseline?: boolean): Promise<void>;
|
|
257
258
|
buildId: any;
|
|
258
259
|
tddMode: boolean;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export class StaticReportGenerator {
|
|
2
|
+
constructor(workingDir: any, config: any);
|
|
3
|
+
workingDir: any;
|
|
4
|
+
config: any;
|
|
5
|
+
reportDir: any;
|
|
6
|
+
reportPath: any;
|
|
7
|
+
/**
|
|
8
|
+
* Generate static HTML report with React reporter bundle
|
|
9
|
+
* @param {Object} reportData - Complete report data (same format as live dashboard)
|
|
10
|
+
* @returns {Promise<string>} Path to generated report
|
|
11
|
+
*/
|
|
12
|
+
generateReport(reportData: any): Promise<string>;
|
|
13
|
+
/**
|
|
14
|
+
* Generate HTML template with embedded React app
|
|
15
|
+
* @param {Object} reportData - Report data to embed
|
|
16
|
+
* @returns {string} HTML content
|
|
17
|
+
*/
|
|
18
|
+
generateHtmlTemplate(reportData: any): string;
|
|
19
|
+
/**
|
|
20
|
+
* Generate a minimal HTML report when bundles are missing (fallback)
|
|
21
|
+
* @param {Object} reportData - Report data
|
|
22
|
+
* @returns {string} Minimal HTML content
|
|
23
|
+
*/
|
|
24
|
+
generateFallbackHtml(reportData: any): string;
|
|
25
|
+
}
|
|
@@ -76,9 +76,9 @@ export class TddService {
|
|
|
76
76
|
private updateSingleBaseline;
|
|
77
77
|
/**
|
|
78
78
|
* Accept a current screenshot as the new baseline
|
|
79
|
-
* @param {string}
|
|
79
|
+
* @param {string|Object} idOrComparison - Comparison ID or comparison object
|
|
80
80
|
* @returns {Object} Result object
|
|
81
81
|
*/
|
|
82
|
-
acceptBaseline(
|
|
82
|
+
acceptBaseline(idOrComparison: string | any): any;
|
|
83
83
|
}
|
|
84
84
|
import { ApiService } from '../services/api-service.js';
|
package/dist/utils/console-ui.js
CHANGED
|
@@ -47,6 +47,7 @@ export class ConsoleUI {
|
|
|
47
47
|
errorData.error = {
|
|
48
48
|
name: error.name,
|
|
49
49
|
message: errorMessage,
|
|
50
|
+
code: error.code,
|
|
50
51
|
...(this.verbose && {
|
|
51
52
|
stack: error.stack
|
|
52
53
|
})
|
|
@@ -57,8 +58,31 @@ export class ConsoleUI {
|
|
|
57
58
|
console.error(JSON.stringify(errorData));
|
|
58
59
|
} else {
|
|
59
60
|
console.error(this.colors.red(`✖ ${message}`));
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
|
|
62
|
+
// Always show error details (not just in verbose mode)
|
|
63
|
+
if (error instanceof Error) {
|
|
64
|
+
// Use getUserMessage() if available (VizzlyError classes), otherwise use message
|
|
65
|
+
const errorMessage = error.getUserMessage ? error.getUserMessage() : error.message;
|
|
66
|
+
if (errorMessage && errorMessage !== message) {
|
|
67
|
+
console.error(this.colors.dim(errorMessage));
|
|
68
|
+
}
|
|
69
|
+
// Stack traces only in verbose mode
|
|
70
|
+
if (this.verbose && error.stack) {
|
|
71
|
+
console.error(this.colors.dim(error.stack));
|
|
72
|
+
}
|
|
73
|
+
} else if (typeof error === 'string' && error) {
|
|
74
|
+
console.error(this.colors.dim(error));
|
|
75
|
+
} else if (error && typeof error === 'object') {
|
|
76
|
+
// Show error object details if available
|
|
77
|
+
try {
|
|
78
|
+
const errorStr = JSON.stringify(error, null, 2);
|
|
79
|
+
if (errorStr !== '{}') {
|
|
80
|
+
console.error(this.colors.dim(errorStr));
|
|
81
|
+
}
|
|
82
|
+
} catch {
|
|
83
|
+
// Fallback for circular references or other JSON.stringify errors
|
|
84
|
+
console.error(this.colors.dim(String(error)));
|
|
85
|
+
}
|
|
62
86
|
}
|
|
63
87
|
}
|
|
64
88
|
if (exitCode > 0) {
|