feat: dead-config sweep, test suite foundation, widget settingsSchema validation
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
Sprint G: audited every BootstrapConfig field for a real runtime consumer (docs/DEAD-CONFIG-AUDIT.md). Wired 3 previously-dead editable fields: footer.logoUrl, company.address.street/contacts.phone, catalog.suggestionsEnabled. Remaining dead fields needing a business/design decision tracked in PRODUCT_BACKLOG.md/KNOWN-ISSUES.md, not silently left. Sprint H: 6 new spec files (test count 57 -> 83), covering ProjectEditorFacade (undo/redo, draft persistence, publish gating), AdminAnalyticsFacade (never-fabricate-a-number contract), and regression coverage for this session's carousel/hero/profile-toggle fixes. Sprint I: widget settingsSchema (declared in widget-manifest.json, never validated) now enforced via a new lightweight schema check in ProjectValidator, surfaced through the existing issuesByField pipeline. Same check reused in diagnostics so editor and diagnostics can't disagree. Verification: tsc clean, ng build clean, 83/83 tests pass, barry-cache validate clean (2 pre-existing unrelated warnings only). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { TranslateService } from '../../../i18n/translate.service';
|
||||
import { BootstrapConfig } from '../../../shared/models/config';
|
||||
import { WidgetManifestFile } from '../../../widgets/contracts/widget-manifest.contract';
|
||||
import { validateAgainstSchemaLite } from '../../project-editor/schema/validators/primitives';
|
||||
import { DiagnosticEntry } from '../models/diagnostics.model';
|
||||
|
||||
const KNOWN_LAYOUTS = new Set(['default', 'sidebar-left', 'carousel-home', 'minimal']);
|
||||
@@ -28,6 +29,7 @@ export class BootstrapDiagnosticsValidator {
|
||||
|
||||
this.validateRequiredProperties(bootstrap, entries);
|
||||
this.validateUnknownWidgetTypes(bootstrap, manifest, entries);
|
||||
this.validateWidgetSettingsSchema(bootstrap, manifest, entries);
|
||||
this.validateDuplicateIds(bootstrap, entries);
|
||||
this.validateLayouts(bootstrap, entries);
|
||||
this.validateFeatureFlags(bootstrap, entries);
|
||||
@@ -85,6 +87,36 @@ export class BootstrapDiagnosticsValidator {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reuses the same shallow schema check as ProjectValidator.widgetSettingsSchemaIssues
|
||||
* (`validateAgainstSchemaLite`) so the editor and the diagnostics page never
|
||||
* disagree about what "valid widget settings" means - one check, two surfaces.
|
||||
*/
|
||||
private validateWidgetSettingsSchema(bootstrap: BootstrapConfig, manifest: WidgetManifestFile | null, entries: DiagnosticEntry[]): void {
|
||||
const manifestByType = new Map((manifest?.widgets ?? []).map(widget => [widget.type, widget]));
|
||||
for (const page of bootstrap.pages ?? []) {
|
||||
for (const section of page.sections ?? []) {
|
||||
for (const widget of section.widgets ?? []) {
|
||||
const entry = manifestByType.get(widget.type);
|
||||
if (!entry?.settingsSchema || !widget.props || typeof widget.props !== 'object') {
|
||||
continue;
|
||||
}
|
||||
const errors = validateAgainstSchemaLite(widget.props, entry.settingsSchema);
|
||||
if (errors.length > 0) {
|
||||
entries.push({
|
||||
code: 'BOOTSTRAP_WIDGET_SETTINGS_SCHEMA_MISMATCH',
|
||||
severity: 'warning',
|
||||
title: 'diagnostics.widgetSettingsSchemaMismatchTitle',
|
||||
description: `diagnostics.widgetSettingsSchemaMismatchDescription:${widget.type}(${errors.join(', ')})`,
|
||||
affectedComponent: `page:${page.key}/section:${section.id}/widget:${widget.id}`,
|
||||
suggestedResolution: 'diagnostics.widgetSettingsSchemaMismatchResolution'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private validateDuplicateIds(bootstrap: BootstrapConfig, entries: DiagnosticEntry[]): void {
|
||||
const pageIds = new Set<string>();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user