Skip to content

KareemMostafa77/qc-auto-package

Repository files navigation

๐Ÿ“˜ ng-qcauto v2.0

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


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

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

Examples:

  • /dashboard route โ†’ qc_dashboard_button_abc123
  • /users/profile route โ†’ qc_users_profile_input_xyz789
  • Root / route โ†’ qc_home_form_loginForm

Identifier Logic:

  1. If element has data-qc-key โ†’ used directly (qc_dashboard_li_42)
  2. Else if element has id โ†’ reused (qc_dashboard_form_loginForm)
  3. Else โ†’ deterministic hash (qc_dashboard_button_1k9d2)

IDs remain stable across reloads as long as route and structure don't change. 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.

โœจ Key Features

  • ๐Ÿ”„ Automatic injection โ€” works globally, no directives or template edits.
  • ๐ŸŽฏ Configurable โ€” track elements by tag, class, or ID.
  • ๐Ÿ”‘ Route-based stable IDs โ€” IDs include route path for better organization.
  • โŒจ๏ธ Ctrl+Q Modal โ€” Easy configuration interface without DevTools.
  • ๐Ÿ–ฑ๏ธ Right-click to Copy โ€” Quickly copy QC IDs during testing.
  • ๐Ÿง‘โ€๐Ÿคโ€๐Ÿง‘ Tester-friendly โ€” configuration lives in localStorage, manageable 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 VersionSupportedSetup Type
v15+โœ… YesStandalone bootstrap (bootstrapApplication)
v14 and belowโœ… YesModule bootstrap (bootstrapModule(AppModule))

๐Ÿ“ฆ Installation

npm install ng-qcauto

๐Ÿš€ Usage

๐Ÿ”น Angular v14 and Below (Modules)

For module-bootstrapped apps:

// main.tsimport{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.tsimport{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.

1๏ธโƒฃ Open Configuration Modal

Press Ctrl+Q (or Cmd+Q on Mac) anywhere in the app to open the configuration modal:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ QC Auto Configuration โœ• โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ Tags: button, input, a โ”‚ โ”‚ Classes: btn-primary โ”‚ โ”‚ IDs: saveBtn โ”‚ โ”‚ โ˜‘ Enable Click-to-Copy QC IDs โ”‚ โ”‚ โ”‚ โ”‚ [Save & Reload] [Cancel] โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ 

OR use DevTools Console:

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-clickToCopy','true');location.reload();

2๏ธโƒฃ Example Template

<!-- On /dashboard route --><button>Save</button><buttonclass="btn-primary">Submit</button><formid="loginForm"> ... </form><ul><li*ngFor="let user of users" [attr.data-qc-key]="user.id">{{user.name }} </li></ul>

3๏ธโƒฃ After Render

<!-- On /dashboard route --><buttondata-qcauto="qc_dashboard_button_1k9d2">Save</button><buttonclass="btn-primary" data-qcauto="qc_dashboard_button_btn-primary">Submit</button><formid="loginForm" data-qcauto="qc_dashboard_form_loginForm"> ... </form><lidata-qc-key="42" data-qcauto="qc_dashboard_li_42">John Doe</li>

4๏ธโƒฃ Copy QC IDs (NEW!)

When Click-to-Copy is enabled:

  1. Elements with QC IDs show a pointer cursor ๐Ÿ‘†
  2. Right-click any element to copy its QC ID
  3. A toast notification appears: โœ“ qc_dashboard_button_1k9d2
  4. Paste anywhere: Ctrl+V

๐Ÿ”Ž 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-clickToCopy โ†’ Boolean string ('true' or 'false') for right-click copy mode

โŒจ๏ธ Keyboard Shortcut

  • Ctrl+Q (Windows/Linux) or Cmd+Q (Mac) โ†’ Opens configuration modal
  • Press again to close modal

Reset Config

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

๐Ÿงช Testing Examples

Cypress

// Full IDcy.get('[data-qcauto="qc_dashboard_form_loginForm"]').should('be.visible');// Pattern matching (all buttons on dashboard)cy.get('[data-qcauto^="qc_dashboard_button"]').click();// By route prefixcy.get('[data-qcauto^="qc_users_profile"]').should('exist');

Custom command:

Cypress.Commands.add('qc',selector=>cy.get(`[data-qcauto="${selector}"]`));// Usagecy.qc('qc_dashboard_form_loginForm').submit();cy.qc('qc_users_profile_button_save').click();

Playwright

// Direct selectorawaitpage.locator('[data-qcauto="qc_dashboard_li_42"]').click();// Route-based patternawaitpage.locator('[data-qcauto^="qc_checkout"]').count();

Selenium

// JavaWebElementelement = driver.findElement( By.cssSelector("[data-qcauto='qc_dashboard_button_submit']")); element.click();

๐Ÿ›ก 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.


๐Ÿ“œ License

MIT ยฉ 2025 โ€“ Kareem Mostafa

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published