@qontinui/ui-bridge 0.3.0 → 0.3.1
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/dist/ai/index.d.mts +312 -155
- package/dist/ai/index.d.ts +312 -155
- package/dist/ai/index.js +2363 -67
- package/dist/ai/index.js.map +1 -1
- package/dist/ai/index.mjs +2328 -68
- package/dist/ai/index.mjs.map +1 -1
- package/dist/annotations/index.d.mts +218 -0
- package/dist/annotations/index.d.ts +218 -0
- package/dist/annotations/index.js +246 -0
- package/dist/annotations/index.js.map +1 -0
- package/dist/annotations/index.mjs +241 -0
- package/dist/annotations/index.mjs.map +1 -0
- package/dist/assertions-BSR3afVr.d.ts +161 -0
- package/dist/assertions-CTw1hfOx.d.mts +161 -0
- package/dist/babel-plugin/index.js +23 -34
- package/dist/babel-plugin/index.js.map +1 -1
- package/dist/babel-plugin/index.mjs +23 -34
- package/dist/babel-plugin/index.mjs.map +1 -1
- package/dist/browser-capture-Bms60T6f.d.mts +47 -0
- package/dist/browser-capture-CsTU29mb.d.ts +47 -0
- package/dist/control/index.d.mts +26 -7
- package/dist/control/index.d.ts +26 -7
- package/dist/control/index.js +276 -48
- package/dist/control/index.js.map +1 -1
- package/dist/control/index.mjs +276 -48
- package/dist/control/index.mjs.map +1 -1
- package/dist/core/index.d.mts +2 -2
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs.map +1 -1
- package/dist/debug/index.d.mts +5 -3
- package/dist/debug/index.d.ts +5 -3
- package/dist/debug/index.js +925 -1
- package/dist/debug/index.js.map +1 -1
- package/dist/debug/index.mjs +924 -2
- package/dist/debug/index.mjs.map +1 -1
- package/dist/index.d.mts +12 -7
- package/dist/index.d.ts +12 -7
- package/dist/index.js +4720 -173
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4656 -174
- package/dist/index.mjs.map +1 -1
- package/dist/{metrics-DTA2bwG7.d.mts → metrics-DuA2qIIz.d.mts} +2 -2
- package/dist/{metrics-BfiT_rhZ.d.ts → metrics-KFAAKNEB.d.ts} +2 -2
- package/dist/native/control/index.js +2 -7
- package/dist/native/control/index.js.map +1 -1
- package/dist/native/control/index.mjs +2 -7
- package/dist/native/control/index.mjs.map +1 -1
- package/dist/native/core/index.js.map +1 -1
- package/dist/native/core/index.mjs.map +1 -1
- package/dist/native/debug/index.js +23 -66
- package/dist/native/debug/index.js.map +1 -1
- package/dist/native/debug/index.mjs +23 -66
- package/dist/native/debug/index.mjs.map +1 -1
- package/dist/native/index.js +89 -131
- package/dist/native/index.js.map +1 -1
- package/dist/native/index.mjs +89 -131
- package/dist/native/index.mjs.map +1 -1
- package/dist/native/react/index.js +28 -52
- package/dist/native/react/index.js.map +1 -1
- package/dist/native/react/index.mjs +28 -52
- package/dist/native/react/index.mjs.map +1 -1
- package/dist/native/server/index.js +38 -13
- package/dist/native/server/index.js.map +1 -1
- package/dist/native/server/index.mjs +38 -13
- package/dist/native/server/index.mjs.map +1 -1
- package/dist/react/index.d.mts +107 -8
- package/dist/react/index.d.ts +107 -8
- package/dist/react/index.js +2194 -84
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +2194 -85
- package/dist/react/index.mjs.map +1 -1
- package/dist/{registry-BKLEm-yk.d.ts → registry-C6dDtn1v.d.ts} +27 -2
- package/dist/{registry-BmZgyCz8.d.mts → registry-POtcxnal.d.mts} +27 -2
- package/dist/render-log/index.d.mts +1 -1
- package/dist/render-log/index.d.ts +1 -1
- package/dist/server/express.d.mts +5 -4
- package/dist/server/express.d.ts +5 -4
- package/dist/server/express.js +104 -2
- package/dist/server/express.js.map +1 -1
- package/dist/server/express.mjs +104 -2
- package/dist/server/express.mjs.map +1 -1
- package/dist/server/handlers.d.mts +36 -5
- package/dist/server/handlers.d.ts +36 -5
- package/dist/server/handlers.js +3129 -224
- package/dist/server/handlers.js.map +1 -1
- package/dist/server/handlers.mjs +3129 -224
- package/dist/server/handlers.mjs.map +1 -1
- package/dist/server/index.d.mts +7 -5
- package/dist/server/index.d.ts +7 -5
- package/dist/server/index.js +3215 -183
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +3215 -183
- package/dist/server/index.mjs.map +1 -1
- package/dist/server/nextjs.d.mts +6 -4
- package/dist/server/nextjs.d.ts +6 -4
- package/dist/server/nextjs.js +106 -3
- package/dist/server/nextjs.js.map +1 -1
- package/dist/server/nextjs.mjs +106 -3
- package/dist/server/nextjs.mjs.map +1 -1
- package/dist/server/standalone.d.mts +6 -5
- package/dist/server/standalone.d.ts +6 -5
- package/dist/server/standalone.js +131 -5
- package/dist/server/standalone.js.map +1 -1
- package/dist/server/standalone.mjs +131 -5
- package/dist/server/standalone.mjs.map +1 -1
- package/dist/specs/index.d.mts +365 -0
- package/dist/specs/index.d.ts +365 -0
- package/dist/specs/index.js +2809 -0
- package/dist/specs/index.js.map +1 -0
- package/dist/specs/index.mjs +2786 -0
- package/dist/specs/index.mjs.map +1 -0
- package/dist/{standalone-BURj8J3G.d.ts → standalone-B6GLIEmR.d.ts} +6 -2
- package/dist/{standalone-Dwmel29d.d.mts → standalone-CjdYqj3P.d.mts} +6 -2
- package/dist/{types-CHnlwiTK.d.ts → types-B2EfvEaq.d.ts} +83 -3
- package/dist/{types-B7J7noLK.d.mts → types-C7gVYRnF.d.ts} +72 -2
- package/dist/{types-BkNRILUa.d.ts → types-CJGrBEhC.d.mts} +72 -2
- package/dist/types-CebMQj76.d.ts +1275 -0
- package/dist/types-D_ypYl3T.d.mts +1275 -0
- package/dist/types-UBtp7R0u.d.mts +132 -0
- package/dist/types-UBtp7R0u.d.ts +132 -0
- package/dist/{types-CEQLnFMv.d.mts → types-gO696T_t.d.mts} +83 -3
- package/dist/{types-jKVgTI6_.d.mts → types-suaYwWWg.d.mts} +173 -2
- package/dist/{types-jKVgTI6_.d.ts → types-suaYwWWg.d.ts} +173 -2
- package/package.json +18 -2
- package/dist/types-B5Q0GVo0.d.mts +0 -646
- package/dist/types-DfPqwU-i.d.ts +0 -646
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/annotations/types.ts","../../src/annotations/store.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Annotation Types\n *\n * Types for the semantic annotation system that allows developers\n * to attach rich human-authored context to UI elements.\n */\n\n/**\n * Annotation for a single UI element.\n *\n * All fields are optional - annotate only what's useful.\n * Annotations provide human-authored semantic context that enriches\n * the UI Bridge's understanding of elements beyond what can be\n * inferred from the DOM alone.\n *\n * @example Basic annotation for a button\n * ```ts\n * const annotation: ElementAnnotation = {\n * description: 'Primary login button',\n * purpose: 'Submits the login form and authenticates the user',\n * tags: ['auth', 'primary-action'],\n * };\n * store.set('login-btn', annotation);\n * ```\n *\n * @example Detailed annotation with relationships and metadata\n * ```ts\n * const annotation: ElementAnnotation = {\n * description: 'Email input field',\n * purpose: 'Collects the user email for authentication',\n * notes: 'Validates email format on blur. Shows inline error below the field.',\n * tags: ['auth', 'form-input', 'required'],\n * relatedElements: ['email-label', 'email-error', 'login-btn'],\n * metadata: { validationPattern: '^[^@]+@[^@]+\\\\.[^@]+$' },\n * author: 'design-team',\n * };\n * ```\n */\nexport interface ElementAnnotation {\n /** Human-readable description of what this element is */\n description?: string;\n /** Why this element exists / what it's for */\n purpose?: string;\n /** Behavioral notes, edge cases, or caveats */\n notes?: string;\n /** Searchable tags for categorization */\n tags?: string[];\n /** IDs of related elements (e.g., a label and its input) */\n relatedElements?: string[];\n /** Arbitrary key-value metadata */\n metadata?: Record<string, unknown>;\n /** Timestamp of last update (auto-set by store) */\n updatedAt?: number;\n /** Author of this annotation */\n author?: string;\n}\n\n/**\n * Annotation configuration file format.\n *\n * This is the import/export format - a JSON file with version and annotations map.\n * Use `AnnotationStore.exportConfig()` to generate this object, and\n * `AnnotationStore.importConfig()` to load it back.\n *\n * @example JSON file format (`annotations.json`)\n * ```json\n * {\n * \"version\": \"1.0.0\",\n * \"annotations\": {\n * \"login-btn\": {\n * \"description\": \"Primary login button\",\n * \"purpose\": \"Submits the login form\",\n * \"tags\": [\"auth\", \"primary-action\"]\n * },\n * \"email-input\": {\n * \"description\": \"Email address input\",\n * \"purpose\": \"Collects user email for authentication\",\n * \"relatedElements\": [\"email-label\", \"email-error\"]\n * }\n * },\n * \"metadata\": {\n * \"appName\": \"MyApp\",\n * \"description\": \"Annotations for the login page\"\n * }\n * }\n * ```\n */\nexport interface AnnotationConfig {\n /** Config format version */\n version: string;\n /** Map of element ID to annotation */\n annotations: Record<string, ElementAnnotation>;\n /** Optional file-level metadata */\n metadata?: {\n appName?: string;\n exportedAt?: number;\n description?: string;\n };\n}\n\n/**\n * Annotation coverage statistics.\n */\nexport interface AnnotationCoverage {\n /** Total elements known to the system */\n totalElements: number;\n /** Elements that have annotations */\n annotatedElements: number;\n /** Coverage as a percentage (0-100) */\n coveragePercent: number;\n /** IDs of annotated elements */\n annotatedIds: string[];\n /** IDs of unannotated elements */\n unannotatedIds: string[];\n /** When this coverage was computed */\n timestamp: number;\n}\n\n/**\n * Event types emitted by the annotation store.\n */\nexport type AnnotationEventType =\n | 'annotation:set'\n | 'annotation:deleted'\n | 'annotation:imported'\n | 'annotation:cleared';\n\n/**\n * Event payload for annotation store events.\n */\nexport interface AnnotationEvent {\n type: AnnotationEventType;\n elementId?: string;\n annotation?: ElementAnnotation;\n count?: number;\n timestamp: number;\n}\n\n/** Current annotation config version */\nexport const ANNOTATION_CONFIG_VERSION = '1.0.0';\n","/**\n * Annotation Store\n *\n * In-memory store for element annotations with CRUD operations,\n * import/export, coverage tracking, and event emission.\n */\n\nimport type {\n ElementAnnotation,\n AnnotationConfig,\n AnnotationCoverage,\n AnnotationEvent,\n} from './types';\nimport { ANNOTATION_CONFIG_VERSION } from './types';\n\n/**\n * Listener function for annotation events.\n */\nexport type AnnotationListener = (event: AnnotationEvent) => void;\n\n/**\n * Annotation Store\n *\n * Stores element annotations in memory with event-driven updates.\n * Provides CRUD operations, import/export, coverage tracking, and\n * an event system for reacting to annotation changes.\n *\n * @example Basic CRUD usage\n * ```ts\n * const store = new AnnotationStore();\n *\n * // Set an annotation\n * store.set('login-btn', {\n * description: 'Primary login button',\n * purpose: 'Submits the login form',\n * tags: ['auth', 'primary-action'],\n * });\n *\n * // Read it back\n * const annotation = store.get('login-btn');\n * console.log(annotation?.description); // 'Primary login button'\n *\n * // Check existence\n * store.has('login-btn'); // true\n *\n * // Delete it\n * store.delete('login-btn'); // true\n * ```\n *\n * @example Import/export workflow\n * ```ts\n * const store = new AnnotationStore();\n *\n * // Import from a config file\n * const config = JSON.parse(fs.readFileSync('annotations.json', 'utf-8'));\n * const count = store.importConfig(config);\n * console.log(`Imported ${count} annotations`);\n *\n * // Export current state\n * const exported = store.exportConfig({ appName: 'MyApp' });\n * fs.writeFileSync('annotations.json', JSON.stringify(exported, null, 2));\n * ```\n *\n * @example Listening for changes\n * ```ts\n * const store = new AnnotationStore();\n *\n * const unsubscribe = store.on((event) => {\n * switch (event.type) {\n * case 'annotation:set':\n * console.log(`Updated: ${event.elementId}`);\n * break;\n * case 'annotation:deleted':\n * console.log(`Deleted: ${event.elementId}`);\n * break;\n * case 'annotation:imported':\n * console.log(`Imported ${event.count} annotations`);\n * break;\n * case 'annotation:cleared':\n * console.log('All annotations cleared');\n * break;\n * }\n * });\n *\n * // Later, stop listening\n * unsubscribe();\n * ```\n */\nexport class AnnotationStore {\n private store = new Map<string, ElementAnnotation>();\n private listeners = new Set<AnnotationListener>();\n\n /**\n * Get an annotation by element ID.\n */\n get(elementId: string): ElementAnnotation | undefined {\n return this.store.get(elementId);\n }\n\n /**\n * Get all annotations as a record.\n */\n getAll(): Record<string, ElementAnnotation> {\n const result: Record<string, ElementAnnotation> = {};\n for (const [id, annotation] of this.store) {\n result[id] = annotation;\n }\n return result;\n }\n\n /**\n * Set an annotation for an element. Auto-sets `updatedAt`.\n */\n set(elementId: string, annotation: ElementAnnotation): void {\n const updated: ElementAnnotation = {\n ...annotation,\n updatedAt: Date.now(),\n };\n this.store.set(elementId, updated);\n this.emit({\n type: 'annotation:set',\n elementId,\n annotation: updated,\n timestamp: Date.now(),\n });\n }\n\n /**\n * Delete an annotation by element ID.\n *\n * @returns true if the annotation existed and was deleted\n */\n delete(elementId: string): boolean {\n const existed = this.store.delete(elementId);\n if (existed) {\n this.emit({\n type: 'annotation:deleted',\n elementId,\n timestamp: Date.now(),\n });\n }\n return existed;\n }\n\n /**\n * Check if an annotation exists for an element.\n */\n has(elementId: string): boolean {\n return this.store.has(elementId);\n }\n\n /**\n * Get the number of stored annotations.\n */\n get count(): number {\n return this.store.size;\n }\n\n /**\n * Clear all annotations.\n */\n clear(): void {\n this.store.clear();\n this.emit({\n type: 'annotation:cleared',\n timestamp: Date.now(),\n });\n }\n\n /**\n * Import annotations from a config object.\n *\n * Merges with existing annotations (new values overwrite per element ID).\n *\n * @returns Number of annotations imported\n *\n * @example\n * ```ts\n * const config: AnnotationConfig = {\n * version: '1.0.0',\n * annotations: {\n * 'btn-1': { description: 'Submit button', tags: ['form'] },\n * 'input-1': { description: 'Name field' },\n * },\n * };\n * const count = store.importConfig(config); // 2\n * ```\n */\n importConfig(config: AnnotationConfig): number {\n let count = 0;\n for (const [id, annotation] of Object.entries(config.annotations)) {\n this.store.set(id, {\n ...annotation,\n updatedAt: annotation.updatedAt ?? Date.now(),\n });\n count++;\n }\n this.emit({\n type: 'annotation:imported',\n count,\n timestamp: Date.now(),\n });\n return count;\n }\n\n /**\n * Export all annotations as a config object.\n *\n * The returned object can be serialized to JSON and saved to a file,\n * then later re-imported with {@link importConfig}.\n *\n * @param metadata - Optional metadata to include (appName, description, etc.)\n * @returns AnnotationConfig with all current annotations\n *\n * @example\n * ```ts\n * const config = store.exportConfig({ appName: 'MyApp' });\n * // config.version === '1.0.0'\n * // config.annotations === { 'btn-1': { ... }, 'input-1': { ... } }\n * // config.metadata === { appName: 'MyApp', exportedAt: 1706900000000 }\n *\n * // Save to file\n * fs.writeFileSync('annotations.json', JSON.stringify(config, null, 2));\n * ```\n */\n exportConfig(metadata?: AnnotationConfig['metadata']): AnnotationConfig {\n return {\n version: ANNOTATION_CONFIG_VERSION,\n annotations: this.getAll(),\n metadata: {\n ...metadata,\n exportedAt: Date.now(),\n },\n };\n }\n\n /**\n * Compute annotation coverage against a set of known element IDs.\n *\n * Compares the store's annotations against the provided list of element IDs\n * to determine what percentage of elements have been annotated.\n *\n * @param allElementIds - Array of all known element IDs in the UI\n * @returns Coverage statistics including percentages and lists of annotated/unannotated IDs\n *\n * @example\n * ```ts\n * store.set('btn-1', { description: 'Submit' });\n * store.set('input-1', { description: 'Name' });\n *\n * const coverage = store.getCoverage(['btn-1', 'input-1', 'input-2', 'link-1']);\n * // coverage.totalElements === 4\n * // coverage.annotatedElements === 2\n * // coverage.coveragePercent === 50\n * // coverage.annotatedIds === ['btn-1', 'input-1']\n * // coverage.unannotatedIds === ['input-2', 'link-1']\n * ```\n */\n getCoverage(allElementIds: string[]): AnnotationCoverage {\n const annotatedIds: string[] = [];\n const unannotatedIds: string[] = [];\n\n for (const id of allElementIds) {\n if (this.store.has(id)) {\n annotatedIds.push(id);\n } else {\n unannotatedIds.push(id);\n }\n }\n\n const total = allElementIds.length;\n return {\n totalElements: total,\n annotatedElements: annotatedIds.length,\n coveragePercent: total > 0 ? (annotatedIds.length / total) * 100 : 0,\n annotatedIds,\n unannotatedIds,\n timestamp: Date.now(),\n };\n }\n\n /**\n * Subscribe to annotation events.\n *\n * The listener is called whenever annotations are set, deleted, imported,\n * or cleared. Returns an unsubscribe function to stop listening.\n *\n * @param listener - Callback function receiving {@link AnnotationEvent} objects\n * @returns Unsubscribe function - call it to remove the listener\n *\n * @example\n * ```ts\n * const unsubscribe = store.on((event) => {\n * if (event.type === 'annotation:set') {\n * console.log(`Element ${event.elementId} annotated:`, event.annotation);\n * }\n * });\n *\n * store.set('btn-1', { description: 'Submit' });\n * // Logs: \"Element btn-1 annotated: { description: 'Submit', updatedAt: ... }\"\n *\n * unsubscribe(); // Stop listening\n * ```\n */\n on(listener: AnnotationListener): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n /**\n * Emit an event to all listeners.\n */\n private emit(event: AnnotationEvent): void {\n for (const listener of this.listeners) {\n try {\n listener(event);\n } catch {\n // Don't let listener errors break the store\n }\n }\n }\n}\n\n// Global singleton\nlet globalStore: AnnotationStore | null = null;\n\n/**\n * Get the global annotation store singleton.\n */\nexport function getGlobalAnnotationStore(): AnnotationStore {\n if (!globalStore) {\n globalStore = new AnnotationStore();\n }\n return globalStore;\n}\n\n/**\n * Reset the global annotation store (primarily for testing).\n */\nexport function resetGlobalAnnotationStore(): void {\n globalStore = null;\n}\n"]}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
// src/annotations/types.ts
|
|
2
|
+
var ANNOTATION_CONFIG_VERSION = "1.0.0";
|
|
3
|
+
|
|
4
|
+
// src/annotations/store.ts
|
|
5
|
+
var AnnotationStore = class {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.store = /* @__PURE__ */ new Map();
|
|
8
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Get an annotation by element ID.
|
|
12
|
+
*/
|
|
13
|
+
get(elementId) {
|
|
14
|
+
return this.store.get(elementId);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Get all annotations as a record.
|
|
18
|
+
*/
|
|
19
|
+
getAll() {
|
|
20
|
+
const result = {};
|
|
21
|
+
for (const [id, annotation] of this.store) {
|
|
22
|
+
result[id] = annotation;
|
|
23
|
+
}
|
|
24
|
+
return result;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Set an annotation for an element. Auto-sets `updatedAt`.
|
|
28
|
+
*/
|
|
29
|
+
set(elementId, annotation) {
|
|
30
|
+
const updated = {
|
|
31
|
+
...annotation,
|
|
32
|
+
updatedAt: Date.now()
|
|
33
|
+
};
|
|
34
|
+
this.store.set(elementId, updated);
|
|
35
|
+
this.emit({
|
|
36
|
+
type: "annotation:set",
|
|
37
|
+
elementId,
|
|
38
|
+
annotation: updated,
|
|
39
|
+
timestamp: Date.now()
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Delete an annotation by element ID.
|
|
44
|
+
*
|
|
45
|
+
* @returns true if the annotation existed and was deleted
|
|
46
|
+
*/
|
|
47
|
+
delete(elementId) {
|
|
48
|
+
const existed = this.store.delete(elementId);
|
|
49
|
+
if (existed) {
|
|
50
|
+
this.emit({
|
|
51
|
+
type: "annotation:deleted",
|
|
52
|
+
elementId,
|
|
53
|
+
timestamp: Date.now()
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return existed;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Check if an annotation exists for an element.
|
|
60
|
+
*/
|
|
61
|
+
has(elementId) {
|
|
62
|
+
return this.store.has(elementId);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get the number of stored annotations.
|
|
66
|
+
*/
|
|
67
|
+
get count() {
|
|
68
|
+
return this.store.size;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Clear all annotations.
|
|
72
|
+
*/
|
|
73
|
+
clear() {
|
|
74
|
+
this.store.clear();
|
|
75
|
+
this.emit({
|
|
76
|
+
type: "annotation:cleared",
|
|
77
|
+
timestamp: Date.now()
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Import annotations from a config object.
|
|
82
|
+
*
|
|
83
|
+
* Merges with existing annotations (new values overwrite per element ID).
|
|
84
|
+
*
|
|
85
|
+
* @returns Number of annotations imported
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* const config: AnnotationConfig = {
|
|
90
|
+
* version: '1.0.0',
|
|
91
|
+
* annotations: {
|
|
92
|
+
* 'btn-1': { description: 'Submit button', tags: ['form'] },
|
|
93
|
+
* 'input-1': { description: 'Name field' },
|
|
94
|
+
* },
|
|
95
|
+
* };
|
|
96
|
+
* const count = store.importConfig(config); // 2
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
importConfig(config) {
|
|
100
|
+
let count = 0;
|
|
101
|
+
for (const [id, annotation] of Object.entries(config.annotations)) {
|
|
102
|
+
this.store.set(id, {
|
|
103
|
+
...annotation,
|
|
104
|
+
updatedAt: annotation.updatedAt ?? Date.now()
|
|
105
|
+
});
|
|
106
|
+
count++;
|
|
107
|
+
}
|
|
108
|
+
this.emit({
|
|
109
|
+
type: "annotation:imported",
|
|
110
|
+
count,
|
|
111
|
+
timestamp: Date.now()
|
|
112
|
+
});
|
|
113
|
+
return count;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Export all annotations as a config object.
|
|
117
|
+
*
|
|
118
|
+
* The returned object can be serialized to JSON and saved to a file,
|
|
119
|
+
* then later re-imported with {@link importConfig}.
|
|
120
|
+
*
|
|
121
|
+
* @param metadata - Optional metadata to include (appName, description, etc.)
|
|
122
|
+
* @returns AnnotationConfig with all current annotations
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```ts
|
|
126
|
+
* const config = store.exportConfig({ appName: 'MyApp' });
|
|
127
|
+
* // config.version === '1.0.0'
|
|
128
|
+
* // config.annotations === { 'btn-1': { ... }, 'input-1': { ... } }
|
|
129
|
+
* // config.metadata === { appName: 'MyApp', exportedAt: 1706900000000 }
|
|
130
|
+
*
|
|
131
|
+
* // Save to file
|
|
132
|
+
* fs.writeFileSync('annotations.json', JSON.stringify(config, null, 2));
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
exportConfig(metadata) {
|
|
136
|
+
return {
|
|
137
|
+
version: ANNOTATION_CONFIG_VERSION,
|
|
138
|
+
annotations: this.getAll(),
|
|
139
|
+
metadata: {
|
|
140
|
+
...metadata,
|
|
141
|
+
exportedAt: Date.now()
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Compute annotation coverage against a set of known element IDs.
|
|
147
|
+
*
|
|
148
|
+
* Compares the store's annotations against the provided list of element IDs
|
|
149
|
+
* to determine what percentage of elements have been annotated.
|
|
150
|
+
*
|
|
151
|
+
* @param allElementIds - Array of all known element IDs in the UI
|
|
152
|
+
* @returns Coverage statistics including percentages and lists of annotated/unannotated IDs
|
|
153
|
+
*
|
|
154
|
+
* @example
|
|
155
|
+
* ```ts
|
|
156
|
+
* store.set('btn-1', { description: 'Submit' });
|
|
157
|
+
* store.set('input-1', { description: 'Name' });
|
|
158
|
+
*
|
|
159
|
+
* const coverage = store.getCoverage(['btn-1', 'input-1', 'input-2', 'link-1']);
|
|
160
|
+
* // coverage.totalElements === 4
|
|
161
|
+
* // coverage.annotatedElements === 2
|
|
162
|
+
* // coverage.coveragePercent === 50
|
|
163
|
+
* // coverage.annotatedIds === ['btn-1', 'input-1']
|
|
164
|
+
* // coverage.unannotatedIds === ['input-2', 'link-1']
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
getCoverage(allElementIds) {
|
|
168
|
+
const annotatedIds = [];
|
|
169
|
+
const unannotatedIds = [];
|
|
170
|
+
for (const id of allElementIds) {
|
|
171
|
+
if (this.store.has(id)) {
|
|
172
|
+
annotatedIds.push(id);
|
|
173
|
+
} else {
|
|
174
|
+
unannotatedIds.push(id);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
const total = allElementIds.length;
|
|
178
|
+
return {
|
|
179
|
+
totalElements: total,
|
|
180
|
+
annotatedElements: annotatedIds.length,
|
|
181
|
+
coveragePercent: total > 0 ? annotatedIds.length / total * 100 : 0,
|
|
182
|
+
annotatedIds,
|
|
183
|
+
unannotatedIds,
|
|
184
|
+
timestamp: Date.now()
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Subscribe to annotation events.
|
|
189
|
+
*
|
|
190
|
+
* The listener is called whenever annotations are set, deleted, imported,
|
|
191
|
+
* or cleared. Returns an unsubscribe function to stop listening.
|
|
192
|
+
*
|
|
193
|
+
* @param listener - Callback function receiving {@link AnnotationEvent} objects
|
|
194
|
+
* @returns Unsubscribe function - call it to remove the listener
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* ```ts
|
|
198
|
+
* const unsubscribe = store.on((event) => {
|
|
199
|
+
* if (event.type === 'annotation:set') {
|
|
200
|
+
* console.log(`Element ${event.elementId} annotated:`, event.annotation);
|
|
201
|
+
* }
|
|
202
|
+
* });
|
|
203
|
+
*
|
|
204
|
+
* store.set('btn-1', { description: 'Submit' });
|
|
205
|
+
* // Logs: "Element btn-1 annotated: { description: 'Submit', updatedAt: ... }"
|
|
206
|
+
*
|
|
207
|
+
* unsubscribe(); // Stop listening
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
on(listener) {
|
|
211
|
+
this.listeners.add(listener);
|
|
212
|
+
return () => {
|
|
213
|
+
this.listeners.delete(listener);
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Emit an event to all listeners.
|
|
218
|
+
*/
|
|
219
|
+
emit(event) {
|
|
220
|
+
for (const listener of this.listeners) {
|
|
221
|
+
try {
|
|
222
|
+
listener(event);
|
|
223
|
+
} catch {
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
var globalStore = null;
|
|
229
|
+
function getGlobalAnnotationStore() {
|
|
230
|
+
if (!globalStore) {
|
|
231
|
+
globalStore = new AnnotationStore();
|
|
232
|
+
}
|
|
233
|
+
return globalStore;
|
|
234
|
+
}
|
|
235
|
+
function resetGlobalAnnotationStore() {
|
|
236
|
+
globalStore = null;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export { ANNOTATION_CONFIG_VERSION, AnnotationStore, getGlobalAnnotationStore, resetGlobalAnnotationStore };
|
|
240
|
+
//# sourceMappingURL=index.mjs.map
|
|
241
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/annotations/types.ts","../../src/annotations/store.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Annotation Types\n *\n * Types for the semantic annotation system that allows developers\n * to attach rich human-authored context to UI elements.\n */\n\n/**\n * Annotation for a single UI element.\n *\n * All fields are optional - annotate only what's useful.\n * Annotations provide human-authored semantic context that enriches\n * the UI Bridge's understanding of elements beyond what can be\n * inferred from the DOM alone.\n *\n * @example Basic annotation for a button\n * ```ts\n * const annotation: ElementAnnotation = {\n * description: 'Primary login button',\n * purpose: 'Submits the login form and authenticates the user',\n * tags: ['auth', 'primary-action'],\n * };\n * store.set('login-btn', annotation);\n * ```\n *\n * @example Detailed annotation with relationships and metadata\n * ```ts\n * const annotation: ElementAnnotation = {\n * description: 'Email input field',\n * purpose: 'Collects the user email for authentication',\n * notes: 'Validates email format on blur. Shows inline error below the field.',\n * tags: ['auth', 'form-input', 'required'],\n * relatedElements: ['email-label', 'email-error', 'login-btn'],\n * metadata: { validationPattern: '^[^@]+@[^@]+\\\\.[^@]+$' },\n * author: 'design-team',\n * };\n * ```\n */\nexport interface ElementAnnotation {\n /** Human-readable description of what this element is */\n description?: string;\n /** Why this element exists / what it's for */\n purpose?: string;\n /** Behavioral notes, edge cases, or caveats */\n notes?: string;\n /** Searchable tags for categorization */\n tags?: string[];\n /** IDs of related elements (e.g., a label and its input) */\n relatedElements?: string[];\n /** Arbitrary key-value metadata */\n metadata?: Record<string, unknown>;\n /** Timestamp of last update (auto-set by store) */\n updatedAt?: number;\n /** Author of this annotation */\n author?: string;\n}\n\n/**\n * Annotation configuration file format.\n *\n * This is the import/export format - a JSON file with version and annotations map.\n * Use `AnnotationStore.exportConfig()` to generate this object, and\n * `AnnotationStore.importConfig()` to load it back.\n *\n * @example JSON file format (`annotations.json`)\n * ```json\n * {\n * \"version\": \"1.0.0\",\n * \"annotations\": {\n * \"login-btn\": {\n * \"description\": \"Primary login button\",\n * \"purpose\": \"Submits the login form\",\n * \"tags\": [\"auth\", \"primary-action\"]\n * },\n * \"email-input\": {\n * \"description\": \"Email address input\",\n * \"purpose\": \"Collects user email for authentication\",\n * \"relatedElements\": [\"email-label\", \"email-error\"]\n * }\n * },\n * \"metadata\": {\n * \"appName\": \"MyApp\",\n * \"description\": \"Annotations for the login page\"\n * }\n * }\n * ```\n */\nexport interface AnnotationConfig {\n /** Config format version */\n version: string;\n /** Map of element ID to annotation */\n annotations: Record<string, ElementAnnotation>;\n /** Optional file-level metadata */\n metadata?: {\n appName?: string;\n exportedAt?: number;\n description?: string;\n };\n}\n\n/**\n * Annotation coverage statistics.\n */\nexport interface AnnotationCoverage {\n /** Total elements known to the system */\n totalElements: number;\n /** Elements that have annotations */\n annotatedElements: number;\n /** Coverage as a percentage (0-100) */\n coveragePercent: number;\n /** IDs of annotated elements */\n annotatedIds: string[];\n /** IDs of unannotated elements */\n unannotatedIds: string[];\n /** When this coverage was computed */\n timestamp: number;\n}\n\n/**\n * Event types emitted by the annotation store.\n */\nexport type AnnotationEventType =\n | 'annotation:set'\n | 'annotation:deleted'\n | 'annotation:imported'\n | 'annotation:cleared';\n\n/**\n * Event payload for annotation store events.\n */\nexport interface AnnotationEvent {\n type: AnnotationEventType;\n elementId?: string;\n annotation?: ElementAnnotation;\n count?: number;\n timestamp: number;\n}\n\n/** Current annotation config version */\nexport const ANNOTATION_CONFIG_VERSION = '1.0.0';\n","/**\n * Annotation Store\n *\n * In-memory store for element annotations with CRUD operations,\n * import/export, coverage tracking, and event emission.\n */\n\nimport type {\n ElementAnnotation,\n AnnotationConfig,\n AnnotationCoverage,\n AnnotationEvent,\n} from './types';\nimport { ANNOTATION_CONFIG_VERSION } from './types';\n\n/**\n * Listener function for annotation events.\n */\nexport type AnnotationListener = (event: AnnotationEvent) => void;\n\n/**\n * Annotation Store\n *\n * Stores element annotations in memory with event-driven updates.\n * Provides CRUD operations, import/export, coverage tracking, and\n * an event system for reacting to annotation changes.\n *\n * @example Basic CRUD usage\n * ```ts\n * const store = new AnnotationStore();\n *\n * // Set an annotation\n * store.set('login-btn', {\n * description: 'Primary login button',\n * purpose: 'Submits the login form',\n * tags: ['auth', 'primary-action'],\n * });\n *\n * // Read it back\n * const annotation = store.get('login-btn');\n * console.log(annotation?.description); // 'Primary login button'\n *\n * // Check existence\n * store.has('login-btn'); // true\n *\n * // Delete it\n * store.delete('login-btn'); // true\n * ```\n *\n * @example Import/export workflow\n * ```ts\n * const store = new AnnotationStore();\n *\n * // Import from a config file\n * const config = JSON.parse(fs.readFileSync('annotations.json', 'utf-8'));\n * const count = store.importConfig(config);\n * console.log(`Imported ${count} annotations`);\n *\n * // Export current state\n * const exported = store.exportConfig({ appName: 'MyApp' });\n * fs.writeFileSync('annotations.json', JSON.stringify(exported, null, 2));\n * ```\n *\n * @example Listening for changes\n * ```ts\n * const store = new AnnotationStore();\n *\n * const unsubscribe = store.on((event) => {\n * switch (event.type) {\n * case 'annotation:set':\n * console.log(`Updated: ${event.elementId}`);\n * break;\n * case 'annotation:deleted':\n * console.log(`Deleted: ${event.elementId}`);\n * break;\n * case 'annotation:imported':\n * console.log(`Imported ${event.count} annotations`);\n * break;\n * case 'annotation:cleared':\n * console.log('All annotations cleared');\n * break;\n * }\n * });\n *\n * // Later, stop listening\n * unsubscribe();\n * ```\n */\nexport class AnnotationStore {\n private store = new Map<string, ElementAnnotation>();\n private listeners = new Set<AnnotationListener>();\n\n /**\n * Get an annotation by element ID.\n */\n get(elementId: string): ElementAnnotation | undefined {\n return this.store.get(elementId);\n }\n\n /**\n * Get all annotations as a record.\n */\n getAll(): Record<string, ElementAnnotation> {\n const result: Record<string, ElementAnnotation> = {};\n for (const [id, annotation] of this.store) {\n result[id] = annotation;\n }\n return result;\n }\n\n /**\n * Set an annotation for an element. Auto-sets `updatedAt`.\n */\n set(elementId: string, annotation: ElementAnnotation): void {\n const updated: ElementAnnotation = {\n ...annotation,\n updatedAt: Date.now(),\n };\n this.store.set(elementId, updated);\n this.emit({\n type: 'annotation:set',\n elementId,\n annotation: updated,\n timestamp: Date.now(),\n });\n }\n\n /**\n * Delete an annotation by element ID.\n *\n * @returns true if the annotation existed and was deleted\n */\n delete(elementId: string): boolean {\n const existed = this.store.delete(elementId);\n if (existed) {\n this.emit({\n type: 'annotation:deleted',\n elementId,\n timestamp: Date.now(),\n });\n }\n return existed;\n }\n\n /**\n * Check if an annotation exists for an element.\n */\n has(elementId: string): boolean {\n return this.store.has(elementId);\n }\n\n /**\n * Get the number of stored annotations.\n */\n get count(): number {\n return this.store.size;\n }\n\n /**\n * Clear all annotations.\n */\n clear(): void {\n this.store.clear();\n this.emit({\n type: 'annotation:cleared',\n timestamp: Date.now(),\n });\n }\n\n /**\n * Import annotations from a config object.\n *\n * Merges with existing annotations (new values overwrite per element ID).\n *\n * @returns Number of annotations imported\n *\n * @example\n * ```ts\n * const config: AnnotationConfig = {\n * version: '1.0.0',\n * annotations: {\n * 'btn-1': { description: 'Submit button', tags: ['form'] },\n * 'input-1': { description: 'Name field' },\n * },\n * };\n * const count = store.importConfig(config); // 2\n * ```\n */\n importConfig(config: AnnotationConfig): number {\n let count = 0;\n for (const [id, annotation] of Object.entries(config.annotations)) {\n this.store.set(id, {\n ...annotation,\n updatedAt: annotation.updatedAt ?? Date.now(),\n });\n count++;\n }\n this.emit({\n type: 'annotation:imported',\n count,\n timestamp: Date.now(),\n });\n return count;\n }\n\n /**\n * Export all annotations as a config object.\n *\n * The returned object can be serialized to JSON and saved to a file,\n * then later re-imported with {@link importConfig}.\n *\n * @param metadata - Optional metadata to include (appName, description, etc.)\n * @returns AnnotationConfig with all current annotations\n *\n * @example\n * ```ts\n * const config = store.exportConfig({ appName: 'MyApp' });\n * // config.version === '1.0.0'\n * // config.annotations === { 'btn-1': { ... }, 'input-1': { ... } }\n * // config.metadata === { appName: 'MyApp', exportedAt: 1706900000000 }\n *\n * // Save to file\n * fs.writeFileSync('annotations.json', JSON.stringify(config, null, 2));\n * ```\n */\n exportConfig(metadata?: AnnotationConfig['metadata']): AnnotationConfig {\n return {\n version: ANNOTATION_CONFIG_VERSION,\n annotations: this.getAll(),\n metadata: {\n ...metadata,\n exportedAt: Date.now(),\n },\n };\n }\n\n /**\n * Compute annotation coverage against a set of known element IDs.\n *\n * Compares the store's annotations against the provided list of element IDs\n * to determine what percentage of elements have been annotated.\n *\n * @param allElementIds - Array of all known element IDs in the UI\n * @returns Coverage statistics including percentages and lists of annotated/unannotated IDs\n *\n * @example\n * ```ts\n * store.set('btn-1', { description: 'Submit' });\n * store.set('input-1', { description: 'Name' });\n *\n * const coverage = store.getCoverage(['btn-1', 'input-1', 'input-2', 'link-1']);\n * // coverage.totalElements === 4\n * // coverage.annotatedElements === 2\n * // coverage.coveragePercent === 50\n * // coverage.annotatedIds === ['btn-1', 'input-1']\n * // coverage.unannotatedIds === ['input-2', 'link-1']\n * ```\n */\n getCoverage(allElementIds: string[]): AnnotationCoverage {\n const annotatedIds: string[] = [];\n const unannotatedIds: string[] = [];\n\n for (const id of allElementIds) {\n if (this.store.has(id)) {\n annotatedIds.push(id);\n } else {\n unannotatedIds.push(id);\n }\n }\n\n const total = allElementIds.length;\n return {\n totalElements: total,\n annotatedElements: annotatedIds.length,\n coveragePercent: total > 0 ? (annotatedIds.length / total) * 100 : 0,\n annotatedIds,\n unannotatedIds,\n timestamp: Date.now(),\n };\n }\n\n /**\n * Subscribe to annotation events.\n *\n * The listener is called whenever annotations are set, deleted, imported,\n * or cleared. Returns an unsubscribe function to stop listening.\n *\n * @param listener - Callback function receiving {@link AnnotationEvent} objects\n * @returns Unsubscribe function - call it to remove the listener\n *\n * @example\n * ```ts\n * const unsubscribe = store.on((event) => {\n * if (event.type === 'annotation:set') {\n * console.log(`Element ${event.elementId} annotated:`, event.annotation);\n * }\n * });\n *\n * store.set('btn-1', { description: 'Submit' });\n * // Logs: \"Element btn-1 annotated: { description: 'Submit', updatedAt: ... }\"\n *\n * unsubscribe(); // Stop listening\n * ```\n */\n on(listener: AnnotationListener): () => void {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n /**\n * Emit an event to all listeners.\n */\n private emit(event: AnnotationEvent): void {\n for (const listener of this.listeners) {\n try {\n listener(event);\n } catch {\n // Don't let listener errors break the store\n }\n }\n }\n}\n\n// Global singleton\nlet globalStore: AnnotationStore | null = null;\n\n/**\n * Get the global annotation store singleton.\n */\nexport function getGlobalAnnotationStore(): AnnotationStore {\n if (!globalStore) {\n globalStore = new AnnotationStore();\n }\n return globalStore;\n}\n\n/**\n * Reset the global annotation store (primarily for testing).\n */\nexport function resetGlobalAnnotationStore(): void {\n globalStore = null;\n}\n"]}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { D as DiscoveredElement } from './types-C7gVYRnF.js';
|
|
2
|
+
import { A as AIDiscoveredElement, d as AssertionRequest, e as AssertionResult, B as BatchAssertionRequest, g as BatchAssertionResult, a8 as SearchCriteria } from './types-CebMQj76.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Assertions Module
|
|
6
|
+
*
|
|
7
|
+
* Provides verification/assertion API for AI agents to validate
|
|
8
|
+
* page state without writing Playwright tests.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Configuration for assertions
|
|
13
|
+
*/
|
|
14
|
+
interface AssertionConfig {
|
|
15
|
+
/** Default timeout for wait-based assertions */
|
|
16
|
+
defaultTimeout: number;
|
|
17
|
+
/** Polling interval for wait-based assertions */
|
|
18
|
+
pollInterval: number;
|
|
19
|
+
/** Default fuzzy threshold for element search */
|
|
20
|
+
fuzzyThreshold: number;
|
|
21
|
+
/** Include suggestions in failure messages */
|
|
22
|
+
includeSuggestions: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Default assertion configuration
|
|
26
|
+
*/
|
|
27
|
+
declare const DEFAULT_ASSERTION_CONFIG: AssertionConfig;
|
|
28
|
+
/**
|
|
29
|
+
* Assertion executor class
|
|
30
|
+
*/
|
|
31
|
+
declare class AssertionExecutor {
|
|
32
|
+
private config;
|
|
33
|
+
private searchEngine;
|
|
34
|
+
private elements;
|
|
35
|
+
constructor(config?: Partial<AssertionConfig>);
|
|
36
|
+
/**
|
|
37
|
+
* Update available elements for assertions
|
|
38
|
+
*/
|
|
39
|
+
updateElements(elements: Array<DiscoveredElement | AIDiscoveredElement>): void;
|
|
40
|
+
/**
|
|
41
|
+
* Execute a single assertion
|
|
42
|
+
*/
|
|
43
|
+
assert(request: AssertionRequest): Promise<AssertionResult>;
|
|
44
|
+
/**
|
|
45
|
+
* Execute multiple assertions
|
|
46
|
+
*/
|
|
47
|
+
assertBatch(request: BatchAssertionRequest): Promise<BatchAssertionResult>;
|
|
48
|
+
/**
|
|
49
|
+
* Convenience method: assert element is visible
|
|
50
|
+
*/
|
|
51
|
+
assertVisible(target: string | SearchCriteria, timeout?: number): Promise<AssertionResult>;
|
|
52
|
+
/**
|
|
53
|
+
* Convenience method: assert element is hidden
|
|
54
|
+
*/
|
|
55
|
+
assertHidden(target: string | SearchCriteria, timeout?: number): Promise<AssertionResult>;
|
|
56
|
+
/**
|
|
57
|
+
* Convenience method: assert element is enabled
|
|
58
|
+
*/
|
|
59
|
+
assertEnabled(target: string | SearchCriteria, timeout?: number): Promise<AssertionResult>;
|
|
60
|
+
/**
|
|
61
|
+
* Convenience method: assert element is disabled
|
|
62
|
+
*/
|
|
63
|
+
assertDisabled(target: string | SearchCriteria, timeout?: number): Promise<AssertionResult>;
|
|
64
|
+
/**
|
|
65
|
+
* Convenience method: assert element has text
|
|
66
|
+
*/
|
|
67
|
+
assertHasText(target: string | SearchCriteria, text: string, timeout?: number): Promise<AssertionResult>;
|
|
68
|
+
/**
|
|
69
|
+
* Convenience method: assert element contains text
|
|
70
|
+
*/
|
|
71
|
+
assertContainsText(target: string | SearchCriteria, text: string, timeout?: number): Promise<AssertionResult>;
|
|
72
|
+
/**
|
|
73
|
+
* Convenience method: assert element has value
|
|
74
|
+
*/
|
|
75
|
+
assertHasValue(target: string | SearchCriteria, value: string, timeout?: number): Promise<AssertionResult>;
|
|
76
|
+
/**
|
|
77
|
+
* Convenience method: assert element exists
|
|
78
|
+
*/
|
|
79
|
+
assertExists(target: string | SearchCriteria, timeout?: number): Promise<AssertionResult>;
|
|
80
|
+
/**
|
|
81
|
+
* Convenience method: assert element does not exist
|
|
82
|
+
*/
|
|
83
|
+
assertNotExists(target: string | SearchCriteria, timeout?: number): Promise<AssertionResult>;
|
|
84
|
+
/**
|
|
85
|
+
* Convenience method: assert checkbox is checked
|
|
86
|
+
*/
|
|
87
|
+
assertChecked(target: string | SearchCriteria, timeout?: number): Promise<AssertionResult>;
|
|
88
|
+
/**
|
|
89
|
+
* Convenience method: assert checkbox is unchecked
|
|
90
|
+
*/
|
|
91
|
+
assertUnchecked(target: string | SearchCriteria, timeout?: number): Promise<AssertionResult>;
|
|
92
|
+
/**
|
|
93
|
+
* Convenience method: assert element count
|
|
94
|
+
*/
|
|
95
|
+
assertCount(target: SearchCriteria, expectedCount: number, timeout?: number): Promise<AssertionResult>;
|
|
96
|
+
/**
|
|
97
|
+
* Find element by target with full search metadata.
|
|
98
|
+
* Returns the SearchResult (including confidence, matchReasons, scores)
|
|
99
|
+
* or null if no match above the fuzzy threshold.
|
|
100
|
+
*/
|
|
101
|
+
private findElementDetailed;
|
|
102
|
+
/**
|
|
103
|
+
* Find element by target (string or criteria).
|
|
104
|
+
* Public for use by condition evaluation in SpecExecutor.
|
|
105
|
+
*/
|
|
106
|
+
findElement(target: string | SearchCriteria, fuzzy?: boolean): Promise<AIDiscoveredElement | null>;
|
|
107
|
+
/**
|
|
108
|
+
* Execute the actual assertion
|
|
109
|
+
*/
|
|
110
|
+
private executeAssertion;
|
|
111
|
+
/**
|
|
112
|
+
* Assert visibility state
|
|
113
|
+
*/
|
|
114
|
+
private assertVisibility;
|
|
115
|
+
/**
|
|
116
|
+
* Assert enabled state
|
|
117
|
+
*/
|
|
118
|
+
private assertEnabledState;
|
|
119
|
+
/**
|
|
120
|
+
* Assert focused state
|
|
121
|
+
*/
|
|
122
|
+
private assertFocused;
|
|
123
|
+
/**
|
|
124
|
+
* Assert checked state
|
|
125
|
+
*/
|
|
126
|
+
private assertCheckedState;
|
|
127
|
+
/**
|
|
128
|
+
* Assert text content
|
|
129
|
+
*/
|
|
130
|
+
private assertTextMatch;
|
|
131
|
+
/**
|
|
132
|
+
* Assert input value
|
|
133
|
+
*/
|
|
134
|
+
private assertValue;
|
|
135
|
+
/**
|
|
136
|
+
* Assert element count
|
|
137
|
+
*/
|
|
138
|
+
private assertElementCount;
|
|
139
|
+
/**
|
|
140
|
+
* Assert attribute value (placeholder for DOM attribute assertions)
|
|
141
|
+
*/
|
|
142
|
+
private assertAttribute;
|
|
143
|
+
/**
|
|
144
|
+
* Assert element has CSS class
|
|
145
|
+
*/
|
|
146
|
+
private assertHasClass;
|
|
147
|
+
/**
|
|
148
|
+
* Assert CSS property value
|
|
149
|
+
*/
|
|
150
|
+
private assertCssProperty;
|
|
151
|
+
/**
|
|
152
|
+
* Create an assertion result
|
|
153
|
+
*/
|
|
154
|
+
private createResult;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Create a default assertion executor
|
|
158
|
+
*/
|
|
159
|
+
declare function createAssertionExecutor(config?: Partial<AssertionConfig>): AssertionExecutor;
|
|
160
|
+
|
|
161
|
+
export { type AssertionConfig as A, DEFAULT_ASSERTION_CONFIG as D, AssertionExecutor as a, createAssertionExecutor as c };
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { D as DiscoveredElement } from './types-CJGrBEhC.mjs';
|
|
2
|
+
import { A as AIDiscoveredElement, d as AssertionRequest, e as AssertionResult, B as BatchAssertionRequest, g as BatchAssertionResult, a8 as SearchCriteria } from './types-D_ypYl3T.mjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Assertions Module
|
|
6
|
+
*
|
|
7
|
+
* Provides verification/assertion API for AI agents to validate
|
|
8
|
+
* page state without writing Playwright tests.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Configuration for assertions
|
|
13
|
+
*/
|
|
14
|
+
interface AssertionConfig {
|
|
15
|
+
/** Default timeout for wait-based assertions */
|
|
16
|
+
defaultTimeout: number;
|
|
17
|
+
/** Polling interval for wait-based assertions */
|
|
18
|
+
pollInterval: number;
|
|
19
|
+
/** Default fuzzy threshold for element search */
|
|
20
|
+
fuzzyThreshold: number;
|
|
21
|
+
/** Include suggestions in failure messages */
|
|
22
|
+
includeSuggestions: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Default assertion configuration
|
|
26
|
+
*/
|
|
27
|
+
declare const DEFAULT_ASSERTION_CONFIG: AssertionConfig;
|
|
28
|
+
/**
|
|
29
|
+
* Assertion executor class
|
|
30
|
+
*/
|
|
31
|
+
declare class AssertionExecutor {
|
|
32
|
+
private config;
|
|
33
|
+
private searchEngine;
|
|
34
|
+
private elements;
|
|
35
|
+
constructor(config?: Partial<AssertionConfig>);
|
|
36
|
+
/**
|
|
37
|
+
* Update available elements for assertions
|
|
38
|
+
*/
|
|
39
|
+
updateElements(elements: Array<DiscoveredElement | AIDiscoveredElement>): void;
|
|
40
|
+
/**
|
|
41
|
+
* Execute a single assertion
|
|
42
|
+
*/
|
|
43
|
+
assert(request: AssertionRequest): Promise<AssertionResult>;
|
|
44
|
+
/**
|
|
45
|
+
* Execute multiple assertions
|
|
46
|
+
*/
|
|
47
|
+
assertBatch(request: BatchAssertionRequest): Promise<BatchAssertionResult>;
|
|
48
|
+
/**
|
|
49
|
+
* Convenience method: assert element is visible
|
|
50
|
+
*/
|
|
51
|
+
assertVisible(target: string | SearchCriteria, timeout?: number): Promise<AssertionResult>;
|
|
52
|
+
/**
|
|
53
|
+
* Convenience method: assert element is hidden
|
|
54
|
+
*/
|
|
55
|
+
assertHidden(target: string | SearchCriteria, timeout?: number): Promise<AssertionResult>;
|
|
56
|
+
/**
|
|
57
|
+
* Convenience method: assert element is enabled
|
|
58
|
+
*/
|
|
59
|
+
assertEnabled(target: string | SearchCriteria, timeout?: number): Promise<AssertionResult>;
|
|
60
|
+
/**
|
|
61
|
+
* Convenience method: assert element is disabled
|
|
62
|
+
*/
|
|
63
|
+
assertDisabled(target: string | SearchCriteria, timeout?: number): Promise<AssertionResult>;
|
|
64
|
+
/**
|
|
65
|
+
* Convenience method: assert element has text
|
|
66
|
+
*/
|
|
67
|
+
assertHasText(target: string | SearchCriteria, text: string, timeout?: number): Promise<AssertionResult>;
|
|
68
|
+
/**
|
|
69
|
+
* Convenience method: assert element contains text
|
|
70
|
+
*/
|
|
71
|
+
assertContainsText(target: string | SearchCriteria, text: string, timeout?: number): Promise<AssertionResult>;
|
|
72
|
+
/**
|
|
73
|
+
* Convenience method: assert element has value
|
|
74
|
+
*/
|
|
75
|
+
assertHasValue(target: string | SearchCriteria, value: string, timeout?: number): Promise<AssertionResult>;
|
|
76
|
+
/**
|
|
77
|
+
* Convenience method: assert element exists
|
|
78
|
+
*/
|
|
79
|
+
assertExists(target: string | SearchCriteria, timeout?: number): Promise<AssertionResult>;
|
|
80
|
+
/**
|
|
81
|
+
* Convenience method: assert element does not exist
|
|
82
|
+
*/
|
|
83
|
+
assertNotExists(target: string | SearchCriteria, timeout?: number): Promise<AssertionResult>;
|
|
84
|
+
/**
|
|
85
|
+
* Convenience method: assert checkbox is checked
|
|
86
|
+
*/
|
|
87
|
+
assertChecked(target: string | SearchCriteria, timeout?: number): Promise<AssertionResult>;
|
|
88
|
+
/**
|
|
89
|
+
* Convenience method: assert checkbox is unchecked
|
|
90
|
+
*/
|
|
91
|
+
assertUnchecked(target: string | SearchCriteria, timeout?: number): Promise<AssertionResult>;
|
|
92
|
+
/**
|
|
93
|
+
* Convenience method: assert element count
|
|
94
|
+
*/
|
|
95
|
+
assertCount(target: SearchCriteria, expectedCount: number, timeout?: number): Promise<AssertionResult>;
|
|
96
|
+
/**
|
|
97
|
+
* Find element by target with full search metadata.
|
|
98
|
+
* Returns the SearchResult (including confidence, matchReasons, scores)
|
|
99
|
+
* or null if no match above the fuzzy threshold.
|
|
100
|
+
*/
|
|
101
|
+
private findElementDetailed;
|
|
102
|
+
/**
|
|
103
|
+
* Find element by target (string or criteria).
|
|
104
|
+
* Public for use by condition evaluation in SpecExecutor.
|
|
105
|
+
*/
|
|
106
|
+
findElement(target: string | SearchCriteria, fuzzy?: boolean): Promise<AIDiscoveredElement | null>;
|
|
107
|
+
/**
|
|
108
|
+
* Execute the actual assertion
|
|
109
|
+
*/
|
|
110
|
+
private executeAssertion;
|
|
111
|
+
/**
|
|
112
|
+
* Assert visibility state
|
|
113
|
+
*/
|
|
114
|
+
private assertVisibility;
|
|
115
|
+
/**
|
|
116
|
+
* Assert enabled state
|
|
117
|
+
*/
|
|
118
|
+
private assertEnabledState;
|
|
119
|
+
/**
|
|
120
|
+
* Assert focused state
|
|
121
|
+
*/
|
|
122
|
+
private assertFocused;
|
|
123
|
+
/**
|
|
124
|
+
* Assert checked state
|
|
125
|
+
*/
|
|
126
|
+
private assertCheckedState;
|
|
127
|
+
/**
|
|
128
|
+
* Assert text content
|
|
129
|
+
*/
|
|
130
|
+
private assertTextMatch;
|
|
131
|
+
/**
|
|
132
|
+
* Assert input value
|
|
133
|
+
*/
|
|
134
|
+
private assertValue;
|
|
135
|
+
/**
|
|
136
|
+
* Assert element count
|
|
137
|
+
*/
|
|
138
|
+
private assertElementCount;
|
|
139
|
+
/**
|
|
140
|
+
* Assert attribute value (placeholder for DOM attribute assertions)
|
|
141
|
+
*/
|
|
142
|
+
private assertAttribute;
|
|
143
|
+
/**
|
|
144
|
+
* Assert element has CSS class
|
|
145
|
+
*/
|
|
146
|
+
private assertHasClass;
|
|
147
|
+
/**
|
|
148
|
+
* Assert CSS property value
|
|
149
|
+
*/
|
|
150
|
+
private assertCssProperty;
|
|
151
|
+
/**
|
|
152
|
+
* Create an assertion result
|
|
153
|
+
*/
|
|
154
|
+
private createResult;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Create a default assertion executor
|
|
158
|
+
*/
|
|
159
|
+
declare function createAssertionExecutor(config?: Partial<AssertionConfig>): AssertionExecutor;
|
|
160
|
+
|
|
161
|
+
export { type AssertionConfig as A, DEFAULT_ASSERTION_CONFIG as D, AssertionExecutor as a, createAssertionExecutor as c };
|