UNPKG

ng-qcauto

Version:

Effortless, stable test IDs for Angular apps. Automatically injects data-qcauto attributes for QA and test automation teams without cluttering templates.

1 lines 28.1 kB
{"version":3,"file":"ng-qcauto.mjs","sources":["../../../projects/ng-qcauto/src/lib/qc-hash.util.ts","../../../projects/ng-qcauto/src/lib/qc-dompath.util.ts","../../../projects/ng-qcauto/src/lib/qc-auto-global.ts","../../../projects/ng-qcauto/src/public-api.ts","../../../projects/ng-qcauto/src/ng-qcauto.ts"],"sourcesContent":["export function hashBase36(input: string): string {\r\n let h1 = 0x811c9dc5, h2 = 0x811c9dc5;\r\n for (let i = 0; i < input.length; i++) {\r\n const c = input.charCodeAt(i);\r\n h1 ^= c; h1 = Math.imul(h1, 0x01000193);\r\n h2 ^= (c << 1); h2 = Math.imul(h2, 0x01000193);\r\n }\r\n const mixed = (h1 ^ (h2 >>> 7)) >>> 0;\r\n return mixed.toString(36);\r\n}\r\n","// qc-dompath.util.ts\r\nexport function domPathWithinHost(el: Element, host: Element): string {\r\n const parts: string[] = [];\r\n let node: Element | null = el;\r\n\r\n while (node && node !== host && node.nodeType === Node.ELEMENT_NODE) {\r\n const tag = node.tagName.toLowerCase();\r\n // nth-of-type among element siblings with the same tag (more stable than nth-child)\r\n let index = 1;\r\n let sib = node.previousElementSibling;\r\n while (sib) {\r\n if (sib.tagName.toLowerCase() === tag) index++;\r\n sib = sib.previousElementSibling;\r\n }\r\n parts.push(`${tag}:${index}`);\r\n node = node.parentElement;\r\n }\r\n\r\n return parts.reverse().join('>');\r\n}\r\n","// qc-auto-global.ts\r\nimport { hashBase36 } from './qc-hash.util';\r\nimport { domPathWithinHost } from './qc-dompath.util';\r\n\r\n// Current version of the QC Auto configuration\r\nconst QC_AUTO_VERSION = '2.0.8';\r\nconst VERSION_KEY = 'qcAuto-version';\r\n\r\nexport interface QcAutoConfig {\r\n tags: string[];\r\n classes: string[];\r\n ids: string[];\r\n clickToCopy?: boolean;\r\n}\r\n\r\nfunction loadConfigFromStorage(): QcAutoConfig {\r\n const getArray = (key: string): string[] => {\r\n const raw = localStorage.getItem(key);\r\n try {\r\n return raw ? JSON.parse(raw) : [];\r\n } catch {\r\n return [];\r\n }\r\n };\r\n const clickToCopy = localStorage.getItem('qcAuto-clickToCopy');\r\n return {\r\n tags: getArray('qcAuto-tags'),\r\n classes: getArray('qcAuto-classes'),\r\n ids: getArray('qcAuto-ids'),\r\n clickToCopy: clickToCopy === 'true',\r\n };\r\n}\r\n\r\nfunction ensureDefaults() {\r\n const storedVersion = localStorage.getItem(VERSION_KEY);\r\n\r\n // If version doesn't match or doesn't exist, clear all old qcAuto data\r\n if (storedVersion !== QC_AUTO_VERSION) {\r\n console.log(`QC Auto: Version mismatch (stored: ${storedVersion}, current: ${QC_AUTO_VERSION}). Clearing old configuration...`);\r\n\r\n // Clear all qcAuto-related items from localStorage\r\n const keysToRemove: string[] = [];\r\n for (let i = 0; i < localStorage.length; i++) {\r\n const key = localStorage.key(i);\r\n if (key && key.startsWith('qcAuto-')) {\r\n keysToRemove.push(key);\r\n }\r\n }\r\n keysToRemove.forEach(key => localStorage.removeItem(key));\r\n\r\n // Set defaults for the new version\r\n const defaultTags = [\r\n 'a', 'button', 'input', 'textarea', 'select', 'form',\r\n 'label', 'option', 'img'\r\n ];\r\n localStorage.setItem('qcAuto-tags', JSON.stringify(defaultTags));\r\n localStorage.setItem('qcAuto-classes', JSON.stringify([]));\r\n localStorage.setItem('qcAuto-ids', JSON.stringify([]));\r\n localStorage.setItem('qcAuto-clickToCopy', 'false');\r\n\r\n // Store the current version\r\n localStorage.setItem(VERSION_KEY, QC_AUTO_VERSION);\r\n console.log(`QC Auto: Configuration initialized with version ${QC_AUTO_VERSION}`);\r\n }\r\n}\r\n\r\nlet CONFIG: QcAutoConfig = { tags: [], classes: [], ids: [], clickToCopy: false };\r\nlet mutationObserver: MutationObserver | null = null;\r\n\r\nfunction getCurrentRoutePath(): string {\r\n const path = window.location.pathname;\r\n // Clean up the path: remove leading/trailing slashes, replace slashes with underscores\r\n return path\r\n .replace(/^\\/+|\\/+$/g, '') // Remove leading/trailing slashes\r\n .replace(/\\//g, '_') // Replace slashes with underscores\r\n .replace(/[^a-zA-Z0-9_-]/g, '') || 'home'; // Remove special chars, default to 'home'\r\n}\r\n\r\nexport function initQcAutoGlobal() {\r\n ensureDefaults();\r\n CONFIG = loadConfigFromStorage();\r\n console.log('QC-Auto initialized with config:', CONFIG);\r\n\r\n // Inject styles for modal and toast\r\n injectModalStyles();\r\n\r\n // Setup keyboard shortcut listener (Ctrl+Q)\r\n setupKeyboardShortcut();\r\n\r\n // Setup click-to-copy if enabled\r\n if (CONFIG.clickToCopy) {\r\n setupClickToCopy();\r\n }\r\n\r\n // Initial scan\r\n document.querySelectorAll('*').forEach(el => {\r\n assignQcId(el);\r\n });\r\n\r\n // Watch DOM changes\r\n mutationObserver = new MutationObserver(muts => {\r\n muts.forEach(m => {\r\n m.addedNodes.forEach(node => {\r\n if (node instanceof Element) {\r\n if (matchesTarget(node)) {\r\n assignQcId(node);\r\n }\r\n node.querySelectorAll?.('*').forEach(el => {\r\n assignQcId(el);\r\n });\r\n }\r\n });\r\n });\r\n });\r\n mutationObserver.observe(document.body, { childList: true, subtree: true });\r\n}\r\n\r\nfunction matchesTarget(el: Element): boolean {\r\n const tag = el.tagName.toLowerCase();\r\n if (CONFIG.tags?.includes(tag)) return true;\r\n if (CONFIG.classes?.some(cls => el.classList.contains(cls))) return true;\r\n if (CONFIG.ids?.includes(el.id)) return true;\r\n return false;\r\n}\r\n\r\nfunction assignQcId(el: Element) {\r\n if (el.hasAttribute('data-qcauto')) return;\r\n if (!matchesTarget(el)) return;\r\n\r\n const routePath = getCurrentRoutePath();\r\n const key = el.getAttribute('data-qc-key');\r\n let basis: string;\r\n\r\n if (key) {\r\n basis = `${routePath}|${el.tagName}|${key}`;\r\n } else {\r\n const path = domPathWithinHost(el, document.body);\r\n basis = `${routePath}|${el.tagName}|${el.id}|${Array.from(el.classList).join('.') || ''}|${path}`;\r\n }\r\n\r\n const id = el.id\r\n ? `qc_${routePath}_${el.tagName.toLowerCase()}_${el.id}`\r\n : `qc_${routePath}_${el.tagName.toLowerCase()}_${hashBase36(basis)}`;\r\n\r\n el.setAttribute('data-qcauto', id);\r\n\r\n // Add cursor pointer if click-to-copy is enabled\r\n if (CONFIG.clickToCopy) {\r\n (el as HTMLElement).style.cursor = 'pointer';\r\n }\r\n}\r\n\r\n// Click-to-Copy System\r\nfunction setupClickToCopy() {\r\n document.body.addEventListener('contextmenu', (e: MouseEvent) => {\r\n const target = e.target as Element;\r\n\r\n // Don't copy if clicking on modal elements\r\n if (target.closest('.qc-config-modal')) return;\r\n\r\n // Find the closest element with data-qcauto attribute\r\n const qcElement = target.closest('[data-qcauto]');\r\n if (qcElement) {\r\n const qcId = qcElement.getAttribute('data-qcauto');\r\n if (qcId) {\r\n e.preventDefault(); // Prevent context menu from showing\r\n e.stopPropagation();\r\n copyToClipboard(qcId);\r\n }\r\n }\r\n }, true); // Use capture phase to catch events early\r\n}\r\n\r\nfunction copyToClipboard(text: string) {\r\n navigator.clipboard.writeText(text).then(() => {\r\n console.log('Copied to clipboard:', text);\r\n showToast(`✓ ${text}`);\r\n }).catch(err => {\r\n console.error('Failed to copy:', err);\r\n // Fallback method\r\n const textarea = document.createElement('textarea');\r\n textarea.value = text;\r\n textarea.style.position = 'fixed';\r\n textarea.style.opacity = '0';\r\n document.body.appendChild(textarea);\r\n textarea.select();\r\n document.execCommand('copy');\r\n document.body.removeChild(textarea);\r\n showToast(`✓ ${text}`);\r\n });\r\n}\r\n\r\nfunction showToast(message: string) {\r\n const toast = document.createElement('div');\r\n toast.className = 'qc-toast';\r\n toast.textContent = message;\r\n document.body.appendChild(toast);\r\n setTimeout(() => toast.remove(), 2000);\r\n}\r\n\r\n// Keyboard Shortcut System (Ctrl+Q)\r\nlet keySequence: string[] = [];\r\nlet keySequenceTimeout: any = null;\r\n\r\nfunction setupKeyboardShortcut() {\r\n document.addEventListener('keydown', (e: KeyboardEvent) => {\r\n if (e.ctrlKey || e.metaKey) {\r\n keySequence.push(e.key.toLowerCase());\r\n\r\n // Clear timeout if exists\r\n if (keySequenceTimeout) {\r\n clearTimeout(keySequenceTimeout);\r\n }\r\n\r\n // Reset sequence after 1 second\r\n keySequenceTimeout = setTimeout(() => {\r\n keySequence = [];\r\n }, 1000);\r\n\r\n // Check if sequence matches Ctrl+Q\r\n const sequenceStr = keySequence.join('');\r\n if (sequenceStr.includes('q')) {\r\n e.preventDefault();\r\n openConfigModal();\r\n keySequence = [];\r\n }\r\n }\r\n });\r\n}\r\n\r\n// Configuration Modal\r\nfunction openConfigModal() {\r\n // Remove existing modal if any\r\n const existing = document.querySelector('.qc-config-modal');\r\n if (existing) {\r\n existing.remove();\r\n return;\r\n }\r\n\r\n const modal = document.createElement('div');\r\n modal.className = 'qc-config-modal';\r\n\r\n const currentConfig = loadConfigFromStorage();\r\n\r\n modal.innerHTML = `\r\n <div class=\"qc-modal-content\">\r\n <div class=\"qc-modal-header\">\r\n <h2>QC Auto Configuration</h2>\r\n <button class=\"qc-modal-close\">&times;</button>\r\n </div>\r\n <div class=\"qc-modal-body\">\r\n <div class=\"qc-form-group\">\r\n <label for=\"qc-tags\">Tags (comma-separated):</label>\r\n <input\r\n type=\"text\"\r\n id=\"qc-tags\"\r\n placeholder=\"e.g., button, input, a\"\r\n value=\"${currentConfig.tags.join(', ')}\"\r\n />\r\n </div>\r\n <div class=\"qc-form-group\">\r\n <label for=\"qc-classes\">Classes (comma-separated):</label>\r\n <input\r\n type=\"text\"\r\n id=\"qc-classes\"\r\n placeholder=\"e.g., btn, form-control\"\r\n value=\"${currentConfig.classes.join(', ')}\"\r\n />\r\n </div>\r\n <div class=\"qc-form-group\">\r\n <label for=\"qc-ids\">IDs (comma-separated):</label>\r\n <input\r\n type=\"text\"\r\n id=\"qc-ids\"\r\n placeholder=\"e.g., submit-btn, user-form\"\r\n value=\"${currentConfig.ids.join(', ')}\"\r\n />\r\n </div>\r\n <div class=\"qc-form-group qc-checkbox-group\">\r\n <label>\r\n <input\r\n type=\"checkbox\"\r\n id=\"qc-click-to-copy\"\r\n ${currentConfig.clickToCopy ? 'checked' : ''}\r\n />\r\n Enable Click-to-Copy QC IDs\r\n </label>\r\n </div>\r\n </div>\r\n <div class=\"qc-modal-footer\">\r\n <button class=\"qc-btn qc-btn-primary\" id=\"qc-reload-btn\">Save & Reload</button>\r\n <button class=\"qc-btn qc-btn-secondary\" id=\"qc-cancel-btn\">Cancel</button>\r\n </div>\r\n </div>\r\n `;\r\n\r\n document.body.appendChild(modal);\r\n injectModalStyles();\r\n\r\n // Event listeners\r\n modal.querySelector('.qc-modal-close')?.addEventListener('click', () => modal.remove());\r\n modal.querySelector('#qc-cancel-btn')?.addEventListener('click', () => modal.remove());\r\n modal.querySelector('#qc-reload-btn')?.addEventListener('click', () => {\r\n saveConfigAndReload(modal);\r\n });\r\n\r\n // Close on outside click\r\n modal.addEventListener('click', (e) => {\r\n if (e.target === modal) {\r\n modal.remove();\r\n }\r\n });\r\n\r\n // Focus first input\r\n setTimeout(() => {\r\n (modal.querySelector('#qc-tags') as HTMLInputElement)?.focus();\r\n }, 100);\r\n}\r\n\r\nfunction saveConfigAndReload(modal: HTMLElement) {\r\n const tagsInput = (modal.querySelector('#qc-tags') as HTMLInputElement).value;\r\n const classesInput = (modal.querySelector('#qc-classes') as HTMLInputElement).value;\r\n const idsInput = (modal.querySelector('#qc-ids') as HTMLInputElement).value;\r\n const clickToCopy = (modal.querySelector('#qc-click-to-copy') as HTMLInputElement).checked;\r\n\r\n // Parse and save\r\n const tags = tagsInput.split(',').map(s => s.trim()).filter(s => s);\r\n const classes = classesInput.split(',').map(s => s.trim()).filter(s => s);\r\n const ids = idsInput.split(',').map(s => s.trim()).filter(s => s);\r\n\r\n localStorage.setItem('qcAuto-tags', JSON.stringify(tags));\r\n localStorage.setItem('qcAuto-classes', JSON.stringify(classes));\r\n localStorage.setItem('qcAuto-ids', JSON.stringify(ids));\r\n localStorage.setItem('qcAuto-clickToCopy', String(clickToCopy));\r\n\r\n console.log('Configuration saved:', { tags, classes, ids, clickToCopy });\r\n\r\n // Reload the page\r\n window.location.reload();\r\n}\r\n\r\nfunction injectModalStyles() {\r\n if (document.getElementById('qc-auto-styles')) return;\r\n\r\n const style = document.createElement('style');\r\n style.id = 'qc-auto-styles';\r\n style.textContent = `\r\n /* Force LTR direction and prevent color overrides */\r\n .qc-config-modal,\r\n .qc-config-modal * {\r\n direction: ltr !important;\r\n color: inherit !important;\r\n }\r\n\r\n .qc-config-modal {\r\n position: fixed;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n background: rgba(0, 0, 0, 0.5);\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n z-index: 999999;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\r\n }\r\n\r\n .qc-modal-content {\r\n background: white;\r\n border-radius: 8px;\r\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);\r\n width: 90%;\r\n max-width: 500px;\r\n max-height: 90vh;\r\n overflow-y: auto;\r\n }\r\n\r\n .qc-modal-header {\r\n padding: 20px;\r\n border-bottom: 1px solid #e0e0e0;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n }\r\n\r\n .qc-modal-header h2 {\r\n margin: 0;\r\n font-size: 20px;\r\n color: #333 !important;\r\n }\r\n\r\n .qc-modal-close {\r\n background: none;\r\n border: none;\r\n font-size: 28px;\r\n cursor: pointer;\r\n color: #999 !important;\r\n padding: 0;\r\n width: 30px;\r\n height: 30px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n line-height: 1;\r\n }\r\n\r\n .qc-modal-close:hover {\r\n color: #333 !important;\r\n }\r\n\r\n .qc-modal-body {\r\n padding: 20px;\r\n }\r\n\r\n .qc-form-group {\r\n margin-bottom: 20px;\r\n }\r\n\r\n .qc-form-group label {\r\n display: block;\r\n margin-bottom: 8px;\r\n font-weight: 600;\r\n color: #333 !important;\r\n font-size: 14px;\r\n }\r\n\r\n .qc-form-group input[type=\"text\"] {\r\n width: 100%;\r\n padding: 10px;\r\n border: 1px solid #ddd;\r\n border-radius: 4px;\r\n font-size: 14px;\r\n box-sizing: border-box;\r\n }\r\n\r\n .qc-form-group input[type=\"text\"]:focus {\r\n outline: none;\r\n border-color: #4CAF50 !important;\r\n }\r\n\r\n .qc-checkbox-group label {\r\n display: flex;\r\n align-items: center;\r\n cursor: pointer;\r\n font-weight: normal;\r\n }\r\n\r\n .qc-checkbox-group input[type=\"checkbox\"] {\r\n margin-right: 8px;\r\n width: 18px;\r\n height: 18px;\r\n cursor: pointer;\r\n }\r\n\r\n .qc-modal-footer {\r\n padding: 20px;\r\n border-top: 1px solid #e0e0e0;\r\n display: flex;\r\n gap: 10px;\r\n justify-content: flex-end;\r\n }\r\n\r\n .qc-btn {\r\n padding: 10px 20px;\r\n border: none;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n font-size: 14px;\r\n font-weight: 600;\r\n transition: all 0.2s;\r\n }\r\n\r\n .qc-btn-primary {\r\n background: #4CAF50 !important;\r\n color: white !important;\r\n }\r\n\r\n .qc-btn-primary:hover {\r\n background: #45a049 !important;\r\n }\r\n\r\n .qc-btn-secondary {\r\n background: #f0f0f0 !important;\r\n color: #333 !important;\r\n }\r\n\r\n .qc-btn-secondary:hover {\r\n background: #e0e0e0 !important;\r\n }\r\n\r\n /* Toast notification */\r\n .qc-toast {\r\n position: fixed;\r\n bottom: 20px;\r\n right: 20px;\r\n background: #323232 !important;\r\n color: white !important;\r\n padding: 12px 20px;\r\n border-radius: 4px;\r\n z-index: 1000000;\r\n animation: qc-toast-in 0.3s ease-out;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\r\n font-size: 14px;\r\n }\r\n\r\n @keyframes qc-toast-in {\r\n from {\r\n transform: translateY(100px);\r\n opacity: 0;\r\n }\r\n to {\r\n transform: translateY(0);\r\n opacity: 1;\r\n }\r\n }\r\n `;\r\n document.head.appendChild(style);\r\n}\r\n","/*\r\n * Public API Surface of ng-qcauto\r\n */\r\n\r\nexport * from './lib/qc-auto-global';\r\nexport * from './lib/qc-dompath.util';\r\nexport * from './lib/qc-hash.util';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}