JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 12
  • Score
    100M100P100Q71552F

Package Exports

  • ng-qcauto
  • ng-qcauto/package.json

Readme

πŸ“˜ ng-qcauto v2.0

Effortless, stable test IDs for Angular apps, controlled by testers β€” not code.


🌟 Overview

ng-qcauto is an Angular utility library that automatically injects stable data-qcauto attributes into DOM elements.

It empowers QA and test automation teams by providing deterministic, human-friendly selectors without requiring developers to clutter templates with data-testid.

        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚ qc_dashboard_button_xyz [πŸ“‹] β”‚  ← Overlay appears on hover
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                β”‚  Submit  β”‚  ← Your button (with dashed outline)
                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Features:

  • 🎯 Hover to Reveal: IDs only show when you hover over elements
  • πŸ“‹ Copy Button: Click to copy the ID to clipboard
  • βœ… Toast Notification: Confirms successful copy
  • πŸŽ›οΈ Toggle On/Off: Control visibility from the config modal
  • 🎨 Non-intrusive: Overlay doesn't disrupt your UI layout
  • πŸ” Visual Outline: Dashed green border helps identify tracked elementsIDs for Angular apps, controlled by testers β€” not code.**

-### 3. After Render

<!-- On /dashboard route -->
<button data-qcauto="qc_dashboard_button_1k9d2">Save</button>
<button class="btn-primary" data-qcauto="qc_dashboard_button_btn-primary">Submit</button>
<form id="loginForm" data-qcauto="qc_dashboard_form_loginForm"> ... </form>

<!-- With data-qc-key -->
<li data-qc-key="42" data-qcauto="qc_dashboard_li_42">John Doe</li>

Note: IDs now include the route path (e.g., qc_dashboard_*, qc_users_profile_*)


πŸ”Ž How IDs Are Generated (v2.0)

IDs follow this pattern: qc_{route}_{tag}_{identifier}

  1. Route Path: Current URL path (e.g., /users/profile β†’ users_profile)
  2. Tag: Element's tag name (e.g., button, input)
  3. Identifier:
    • If element has data-qc-key β†’ used directly (qc_home_li_42)
    • Else if element has id β†’ reused (qc_dashboard_form_loginForm)
    • Else β†’ deterministic hash (qc_users_button_1k9d2)

IDs remain stable across reloads as long as route and structure don't change.


πŸ‘οΈ Visual ID Indicators (NEW!)

When enabled, you'll see green badges above tracked elements showing their data-qcauto value:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ qc_dashboard_button_xyz [πŸ“‹] β”‚  ← Visual indicator with copy button
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚  Submit  β”‚  ← Your button
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Features:

  • πŸ“‹ Copy Button: Click to copy the ID to clipboard
  • βœ… Toast Notification: Confirms successful copy
  • �️ Toggle On/Off: Control visibility from the config modal
  • 🎨 Non-intrusive: Styled to not interfere with your UI

⌨️ Keyboard Shortcuts

  • Ctrl+Q+C (or Cmd+Q+C on Mac): Open configuration modaliew ng-qcauto is an Angular utility library that automatically injects stable data-qcauto attributes into DOM elements.

It empowers QA and test automation teams by providing deterministic, human-friendly selectors without requiring developers to clutter templates with data-testid.

✨ Key Features

  • πŸ”„ Automatic injection β€” works globally, no directives or template edits.
  • 🎯 Configurable β€” track elements by tag, class, or ID.
  • πŸ”‘ Stable IDs β€” deterministic hashes, with support for data-qc-key in lists.
  • πŸ›£οΈ Route-based IDs β€” IDs now include current route path for better stability.
  • ⌨️ Visual Configuration Modal β€” Press Ctrl+Q+C to open config modal (no DevTools needed!).
  • πŸ‘οΈ Visual ID Indicators β€” See IDs directly in the UI with copy functionality.
  • πŸ§‘β€πŸ€β€πŸ§‘ Tester-friendly β€” configuration lives in localStorage, editable via modal.
  • 🚦 Test-only mode β€” enable in dev/staging, disable in prod.
  • ⚑ Lightweight β€” observer-based, minimal performance impact.
  • πŸ— Angular v14 and below + v15+ support β€” works in both module-based and standalone bootstraps.

πŸ“ Angular Version Support

Angular Version Supported Setup Type
v15+ βœ… Yes Standalone bootstrap (bootstrapApplication)
v14 and below βœ… Yes Module bootstrap (bootstrapModule(AppModule))

πŸ“¦ Installation

npm install ng-qcauto

πŸš€ Usage

πŸ”Ή Angular v14 and Below (Modules)

For module-bootstrapped apps:

// main.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { initQcAutoGlobal } from 'ng-qcauto';

platformBrowserDynamic()
  .bootstrapModule(AppModule)
  .then(() => initQcAutoGlobal()) // init after Angular bootstraps
  .catch(err => console.error(err));

πŸ”Ή Angular v15+ (Standalone)

For standalone-bootstrapped apps:

// main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { initQcAutoGlobal } from 'ng-qcauto';

bootstrapApplication(AppComponent).then(() => {
  initQcAutoGlobal(); // init after bootstrap
});

πŸ§‘β€πŸ’» Tester Workflow

ng-qcauto reads its configuration from localStorage.

🎯 Method 1: Visual Config Modal (NEW in v2.0!)

  1. Press Ctrl+Q+C anywhere in the app
  2. The configuration modal will appear
  3. Enter your targets:
    • Tags: button, input, a
    • Classes: btn-primary, form-control
    • IDs: saveBtn, loginForm
  4. Toggle "Show Visual ID Indicators" to see IDs in the UI
  5. Click "Save & Reload"

πŸ› οΈ Method 2: Add Targets in DevTools (Classic)

localStorage.setItem('qcAuto-tags', JSON.stringify(['button','input','a']));
localStorage.setItem('qcAuto-classes', JSON.stringify(['btn-primary']));
localStorage.setItem('qcAuto-ids', JSON.stringify(['saveBtn']));
localStorage.setItem('qcAuto-showVisualIds', 'true'); // NEW: Show visual indicators
location.reload();

2. Example Template

<button>Save</button>
<button class="btn-primary">Submit</button>
<form id="loginForm"> ... </form>

<ul>
  <li *ngFor="let user of users" [attr.data-qc-key]="user.id">
    {{ user.name }}
  </li>
</ul>

3. After Render

<button data-qcauto="qc_button_1k9d2">Save</button>
<button class="btn-primary" data-qcauto="qc_button_btn-primary">Submit</button>
<form id="loginForm" data-qcauto="qc_form_loginForm"> ... </form>

<li data-qc-key="42" data-qcauto="qc_li_42">John Doe</li>

πŸ”Ž How IDs Are Generated

  • If element has data-qc-key β†’ used directly (qc_li_42).
  • Else if element has id β†’ reused (qc_form_loginForm).
  • Else β†’ deterministic hash (qc_button_1k9d2).

IDs remain stable across reloads as long as structure doesn’t change.


βš™οΈ Configuration Reference

LocalStorage Keys

  • qcAuto-tags β†’ Array of tag names (e.g. ['button','input'])
  • qcAuto-classes β†’ Array of class names (e.g. ['btn-primary'])
  • qcAuto-ids β†’ Array of element IDs (e.g. ['loginForm'])
  • qcAuto-showVisualIds β†’ Boolean string ('true' or 'false') for visual indicators (NEW!)

Reset Config

localStorage.setItem('qcAuto-tags', JSON.stringify([]));
localStorage.setItem('qcAuto-classes', JSON.stringify([]));
localStorage.setItem('qcAuto-ids', JSON.stringify([]));
localStorage.setItem('qcAuto-showVisualIds', 'false');
location.reload();

πŸ§ͺ Testing Examples

Cypress

// Using full ID with route
cy.get('[data-qcauto="qc_dashboard_form_loginForm"]').should('be.visible');

// Using partial match for route independence
cy.get('[data-qcauto$="form_loginForm"]').click();

// Find all buttons on a specific route
cy.get('[data-qcauto^="qc_dashboard_button"]').should('have.length', 3);

Custom command:

Cypress.Commands.add('qc', (selector, matchType = 'exact') => {
  if (matchType === 'exact') {
    return cy.get(`[data-qcauto="${selector}"]`);
  } else if (matchType === 'ends') {
    return cy.get(`[data-qcauto$="${selector}"]`);
  } else if (matchType === 'contains') {
    return cy.get(`[data-qcauto*="${selector}"]`);
  }
});

// Usage
cy.qc('qc_dashboard_form_loginForm').submit();
cy.qc('form_loginForm', 'ends').submit(); // Route-independent

Playwright

// Full ID
await page.locator('[data-qcauto="qc_users_li_42"]').click();

// Partial match (route-independent)
await page.locator('[data-qcauto$="li_42"]').click();

// Find by route prefix
const dashboardButtons = await page.locator('[data-qcauto^="qc_dashboard_"]').all();

Selenium

// Java example
WebElement loginForm = driver.findElement(
    By.cssSelector("[data-qcauto='qc_home_form_loginForm']")
);

// Route-independent
WebElement loginForm = driver.findElement(
    By.cssSelector("[data-qcauto$='form_loginForm']")
);

πŸ›‘ Test-Only Mode

To disable in production, guard init with environment flags:

import { environment } from './environments/environment';
import { initQcAutoGlobal } from 'ng-qcauto';

bootstrapApplication(AppComponent).then(() => {
  if (!environment.production) {
    initQcAutoGlobal();
  }
});

⚑ Performance Notes

  • Startup: one-time DOM scan (few ms even for large apps).
  • Runtime: MutationObserver handles only new nodes.
  • Optimized:
    • Skips already tagged nodes.
    • Filters by config before hashing.
    • Uses data-qc-key for list stability.

Overhead is negligible compared to Angular rendering.


οΏ½ Migration from v1.x to v2.0

Breaking Changes

ID Format Change: IDs now include route path prefix.

Before (v1.x):

<button data-qcauto="qc_button_1k9d2">Submit</button>

After (v2.0):

<button data-qcauto="qc_dashboard_button_1k9d2">Submit</button>

Migration Strategy

Update your test selectors to use the new format:

// Old
cy.get('[data-qcauto="qc_button_xyz"]')

// New
cy.get('[data-qcauto="qc_dashboard_button_xyz"]')

Option 2: Use Partial Matching (Quick Fix)

Use suffix matching to ignore route prefix:

// Works with both v1.x and v2.0
cy.get('[data-qcauto$="button_xyz"]')

New Features to Adopt

  1. Visual Config Modal: Use Ctrl+Q+C instead of DevTools
  2. Visual ID Indicators: Enable to easily discover IDs
  3. Route-based Stability: IDs are now more stable per route

πŸ› Troubleshooting

  • Make sure the page has loaded completely
  • Check browser console for errors
  • Try Cmd+Q+C on Mac

Visual indicators not showing

  • Open config modal (Ctrl+Q+C)
  • Check "Show Visual ID Indicators"
  • Click "Save & Reload"

IDs changing unexpectedly

  • IDs now include route path
  • Ensure you're on the same route when testing
  • Use data-qc-key for dynamic list items

Elements not getting IDs

  • Check your configuration (tags, classes, ids)
  • Open config modal to verify settings
  • Check browser console for initialization logs

οΏ½πŸ“œ License

MIT Β© 2025 – Kareem Mostafa