semmet-angular 0.23.0 → 0.24.0

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.
Files changed (131) hide show
  1. package/README.md +2 -0
  2. package/package.json +1 -1
  3. package/src/accordion/files/__name@dasherize__/__name@dasherize__.spec.ts.template +124 -0
  4. package/src/accordion/index.js +1 -1
  5. package/src/accordion/index.js.map +1 -1
  6. package/src/accordion/index.ts +1 -1
  7. package/src/alert/files/__name@dasherize__/__name@dasherize__.spec.ts.template +27 -0
  8. package/src/alert/index.js +1 -1
  9. package/src/alert/index.js.map +1 -1
  10. package/src/alert/index.ts +1 -1
  11. package/src/alert-dialog/files/__name@dasherize__/__name@dasherize__.spec.ts.template +66 -0
  12. package/src/alert-dialog/index.js +1 -1
  13. package/src/alert-dialog/index.js.map +1 -1
  14. package/src/alert-dialog/index.ts +1 -1
  15. package/src/button/files/__name@dasherize__/__name@dasherize__.spec.ts.template +69 -0
  16. package/src/button/index.js +1 -1
  17. package/src/button/index.js.map +1 -1
  18. package/src/button/index.ts +1 -1
  19. package/src/button-group/files/__name@dasherize__/__name@dasherize__.spec.ts.template +70 -0
  20. package/src/button-group/index.js +1 -1
  21. package/src/button-group/index.js.map +1 -1
  22. package/src/button-group/index.ts +1 -1
  23. package/src/carousel/files/__name@dasherize__/__name@dasherize__.spec.ts.template +69 -0
  24. package/src/carousel/index.js +1 -1
  25. package/src/carousel/index.js.map +1 -1
  26. package/src/carousel/index.ts +1 -1
  27. package/src/checkbox/files/__name@dasherize__/__name@dasherize__.spec.ts.template +41 -0
  28. package/src/checkbox/index.js +1 -1
  29. package/src/checkbox/index.js.map +1 -1
  30. package/src/checkbox/index.ts +1 -1
  31. package/src/close-button/files/__name@dasherize__/__name@dasherize__.spec.ts.template +64 -0
  32. package/src/close-button/index.js +1 -1
  33. package/src/close-button/index.js.map +1 -1
  34. package/src/close-button/index.ts +1 -1
  35. package/src/combobox/files/__name@dasherize__/__name@dasherize__.spec.ts.template +79 -0
  36. package/src/combobox/index.js +1 -1
  37. package/src/combobox/index.js.map +1 -1
  38. package/src/combobox/index.ts +1 -1
  39. package/src/dialog/files/__name@dasherize__/__name@dasherize__.spec.ts.template +68 -0
  40. package/src/dialog/index.js +1 -1
  41. package/src/dialog/index.js.map +1 -1
  42. package/src/dialog/index.ts +1 -1
  43. package/src/disclosure/files/__name@dasherize__/__name@dasherize__.spec.ts.template +67 -0
  44. package/src/disclosure/index.js +1 -1
  45. package/src/disclosure/index.js.map +1 -1
  46. package/src/disclosure/index.ts +1 -1
  47. package/src/input/files/__name@dasherize__/__name@dasherize__.spec.ts.template +56 -0
  48. package/src/input/index.js +1 -1
  49. package/src/input/index.js.map +1 -1
  50. package/src/input/index.ts +1 -1
  51. package/src/list-group/files/__name@dasherize__/__name@dasherize__.spec.ts.template +66 -0
  52. package/src/list-group/index.js +1 -1
  53. package/src/list-group/index.js.map +1 -1
  54. package/src/list-group/index.ts +1 -1
  55. package/src/listbox/files/__name@dasherize__/__name@dasherize__.spec.ts.template +50 -0
  56. package/src/listbox/index.js +1 -1
  57. package/src/listbox/index.js.map +1 -1
  58. package/src/listbox/index.ts +1 -1
  59. package/src/menu-button/files/__name@dasherize__/__name@dasherize__.spec.ts.template +64 -0
  60. package/src/menu-button/index.js +1 -1
  61. package/src/menu-button/index.js.map +1 -1
  62. package/src/menu-button/index.ts +1 -1
  63. package/src/navbar/files/__name@dasherize__/__name@dasherize__.spec.ts.template +74 -0
  64. package/src/navbar/index.js +1 -1
  65. package/src/navbar/index.js.map +1 -1
  66. package/src/navbar/index.ts +1 -1
  67. package/src/navigation-menu/files/__name@dasherize__/__name@dasherize__.spec.ts.template +51 -0
  68. package/src/navigation-menu/index.js +1 -1
  69. package/src/navigation-menu/index.js.map +1 -1
  70. package/src/navigation-menu/index.ts +1 -1
  71. package/src/offcanvas/files/__name@dasherize__/__name@dasherize__.spec.ts.template +70 -0
  72. package/src/offcanvas/index.js +1 -1
  73. package/src/offcanvas/index.js.map +1 -1
  74. package/src/offcanvas/index.ts +1 -1
  75. package/src/pagination/files/__name@dasherize__/__name@dasherize__.spec.ts.template +41 -0
  76. package/src/pagination/index.js +1 -1
  77. package/src/pagination/index.js.map +1 -1
  78. package/src/pagination/index.ts +1 -1
  79. package/src/popover/files/__name@dasherize__/__name@dasherize__.spec.ts.template +69 -0
  80. package/src/popover/index.js +1 -1
  81. package/src/popover/index.js.map +1 -1
  82. package/src/popover/index.ts +1 -1
  83. package/src/radio-group/files/__name@dasherize__/__name@dasherize__.spec.ts.template +47 -0
  84. package/src/radio-group/index.js +1 -1
  85. package/src/radio-group/index.js.map +1 -1
  86. package/src/radio-group/index.ts +1 -1
  87. package/src/select/files/__name@dasherize__/__name@dasherize__.spec.ts.template +54 -0
  88. package/src/select/index.js +1 -1
  89. package/src/select/index.js.map +1 -1
  90. package/src/select/index.ts +1 -1
  91. package/src/slider/files/__name@dasherize__/__name@dasherize__.spec.ts.template +61 -0
  92. package/src/slider/index.js +1 -1
  93. package/src/slider/index.js.map +1 -1
  94. package/src/slider/index.ts +1 -1
  95. package/src/spinbutton/files/__name@dasherize__/__name@dasherize__.spec.ts.template +74 -0
  96. package/src/spinbutton/index.js +1 -1
  97. package/src/spinbutton/index.js.map +1 -1
  98. package/src/spinbutton/index.ts +1 -1
  99. package/src/switch/files/__name@dasherize__/__name@dasherize__.spec.ts.template +35 -0
  100. package/src/switch/index.js +1 -1
  101. package/src/switch/index.js.map +1 -1
  102. package/src/switch/index.ts +1 -1
  103. package/src/tabs/files/__name@dasherize__/__name@dasherize__.spec.ts.template +113 -0
  104. package/src/tabs/index.js +1 -1
  105. package/src/tabs/index.js.map +1 -1
  106. package/src/tabs/index.ts +1 -1
  107. package/src/textarea/files/__name@dasherize__/__name@dasherize__.spec.ts.template +59 -0
  108. package/src/textarea/index.js +1 -1
  109. package/src/textarea/index.js.map +1 -1
  110. package/src/textarea/index.ts +1 -1
  111. package/src/toast/files/__name@dasherize__/__name@dasherize__.spec.ts.template +48 -0
  112. package/src/toast/index.js +1 -1
  113. package/src/toast/index.js.map +1 -1
  114. package/src/toast/index.ts +1 -1
  115. package/src/toolbar/files/__name@dasherize__/__name@dasherize__.spec.ts.template +45 -0
  116. package/src/toolbar/index.js +1 -1
  117. package/src/toolbar/index.js.map +1 -1
  118. package/src/toolbar/index.ts +1 -1
  119. package/src/tooltip/files/__name@dasherize__/__name@dasherize__.spec.ts.template +56 -0
  120. package/src/tooltip/index.js +1 -1
  121. package/src/tooltip/index.js.map +1 -1
  122. package/src/tooltip/index.ts +1 -1
  123. package/src/tree-view/files/__name@dasherize__/__name@dasherize__.spec.ts.template +84 -0
  124. package/src/tree-view/index.js +1 -1
  125. package/src/tree-view/index.js.map +1 -1
  126. package/src/tree-view/index.ts +1 -1
  127. package/src/utils/component-test-files/__name@dasherize__/__name@dasherize__.spec.ts.template +15 -1
  128. package/src/utils/generate-component.d.ts +6 -1
  129. package/src/utils/generate-component.js +21 -6
  130. package/src/utils/generate-component.js.map +1 -1
  131. package/src/utils/generate-component.ts +28 -7
@@ -0,0 +1,64 @@
1
+ import { Component } from '@angular/core';
2
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
3
+
4
+ import { <%= classify(name) %> } from './<%= dasherize(name) %>';
5
+
6
+ @Component({
7
+ imports: [<%= classify(name) %>],
8
+ template: `
9
+ <<%= selector %>
10
+ label="Close dialog"
11
+ variant="inverse"
12
+ size="lg"
13
+ [disabled]="disabled"
14
+ (buttonClick)="clickCount = clickCount + 1"
15
+ />
16
+ `,
17
+ })
18
+ class HostComponent {
19
+ disabled = false;
20
+ clickCount = 0;
21
+ }
22
+
23
+ describe('<%= classify(name) %>', () => {
24
+ let fixture: ComponentFixture<HostComponent>;
25
+ let host: HTMLElement;
26
+
27
+ beforeEach(async () => {
28
+ await TestBed.configureTestingModule({
29
+ imports: [HostComponent],
30
+ }).compileComponents();
31
+
32
+ fixture = TestBed.createComponent(HostComponent);
33
+ fixture.detectChanges();
34
+ host = fixture.nativeElement as HTMLElement;
35
+ });
36
+
37
+ it('renders a native close button with accessible name and visual variants', () => {
38
+ const button = host.querySelector<HTMLButtonElement>('button');
39
+ const icon = host.querySelector<HTMLElement>('.semmet-close-button__icon');
40
+
41
+ expect(button?.type).toBe('button');
42
+ expect(button?.getAttribute('aria-label')).toBe('Close dialog');
43
+ expect(button?.classList.contains('semmet-close-button--inverse')).toBe(true);
44
+ expect(button?.classList.contains('semmet-close-button--lg')).toBe(true);
45
+ expect(icon?.getAttribute('aria-hidden')).toBe('true');
46
+ });
47
+
48
+ it('emits buttonClick only when enabled', () => {
49
+ const component = fixture.componentInstance;
50
+ const button = host.querySelector<HTMLButtonElement>('button');
51
+
52
+ button?.click();
53
+ fixture.detectChanges();
54
+ expect(component.clickCount).toBe(1);
55
+
56
+ component.disabled = true;
57
+ fixture.detectChanges();
58
+
59
+ button?.click();
60
+ fixture.detectChanges();
61
+ expect(component.clickCount).toBe(1);
62
+ expect(button?.disabled).toBe(true);
63
+ });
64
+ });
@@ -2,5 +2,5 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.closeButton = void 0;
4
4
  const generate_component_1 = require("../utils/generate-component");
5
- exports.closeButton = (0, generate_component_1.createAriaComponentSchematic)();
5
+ exports.closeButton = (0, generate_component_1.createAriaComponentSchematic)({ includeSharedUnitTest: false });
6
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;AAAA,oEAA2E;AAE9D,QAAA,WAAW,GAAG,IAAA,iDAA4B,GAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;AAAA,oEAA2E;AAE9D,QAAA,WAAW,GAAG,IAAA,iDAA4B,EAAC,EAAE,qBAAqB,EAAE,KAAK,EAAE,CAAC,CAAC"}
@@ -1,3 +1,3 @@
1
1
  import { createAriaComponentSchematic } from '../utils/generate-component';
2
2
 
3
- export const closeButton = createAriaComponentSchematic();
3
+ export const closeButton = createAriaComponentSchematic({ includeSharedUnitTest: false });
@@ -0,0 +1,79 @@
1
+ import { Component } from '@angular/core';
2
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
3
+ import { By } from '@angular/platform-browser';
4
+
5
+ import { <%= classify(name) %> } from './<%= dasherize(name) %>';
6
+
7
+ @Component({
8
+ imports: [<%= classify(name) %>],
9
+ template: `<<%= selector %> />`,
10
+ })
11
+ class HostComponent {}
12
+
13
+ describe('<%= classify(name) %>', () => {
14
+ let fixture: ComponentFixture<HostComponent>;
15
+ let host: HTMLElement;
16
+
17
+ beforeEach(async () => {
18
+ await TestBed.configureTestingModule({
19
+ imports: [HostComponent],
20
+ }).compileComponents();
21
+
22
+ fixture = TestBed.createComponent(HostComponent);
23
+ fixture.detectChanges();
24
+ host = fixture.nativeElement as HTMLElement;
25
+ });
26
+
27
+ it('renders the combobox with label and collapsed popup wiring', () => {
28
+ const input = host.querySelector<HTMLInputElement>('[role="combobox"]');
29
+ const listbox = host.querySelector<HTMLElement>('[role="listbox"]');
30
+
31
+ expect(input).toBeTruthy();
32
+ expect(input?.getAttribute('aria-autocomplete')).toBe('list');
33
+ expect(input?.getAttribute('aria-expanded')).toBe('false');
34
+ expect(input?.getAttribute('aria-controls')).toBe(listbox?.id);
35
+ expect(input?.getAttribute('aria-labelledby')).toBeTruthy();
36
+ expect(listbox?.hidden).toBe(true);
37
+ });
38
+
39
+ it('filters options from user input and opens the listbox', () => {
40
+ const inputDebug = fixture.debugElement.query(By.css('[role="combobox"]'));
41
+ const input = inputDebug.nativeElement as HTMLInputElement;
42
+
43
+ input.value = 'ba';
44
+ inputDebug.triggerEventHandler('input', { target: input });
45
+ fixture.detectChanges();
46
+
47
+ const options = Array.from(host.querySelectorAll<HTMLElement>('[role="option"]'));
48
+ const listbox = host.querySelector<HTMLElement>('[role="listbox"]');
49
+
50
+ expect(input.value).toBe('ba');
51
+ expect(listbox?.hidden).toBe(false);
52
+ expect(options.map((option) => option.textContent?.trim())).toEqual(['Banana']);
53
+ });
54
+
55
+ it('moves active option with the keyboard and selects it with Enter', () => {
56
+ const inputDebug = fixture.debugElement.query(By.css('[role="combobox"]'));
57
+ const input = inputDebug.nativeElement as HTMLInputElement;
58
+
59
+ inputDebug.triggerEventHandler('keydown', new KeyboardEvent('keydown', { key: 'ArrowDown' }));
60
+ fixture.detectChanges();
61
+
62
+ let activeOption = host.querySelector<HTMLElement>('[role="option"][aria-selected="true"]');
63
+ expect(input.getAttribute('aria-activedescendant')).toBe(activeOption?.id);
64
+ expect(activeOption?.textContent?.trim()).toBe('Apple');
65
+
66
+ inputDebug.triggerEventHandler('keydown', new KeyboardEvent('keydown', { key: 'ArrowDown' }));
67
+ fixture.detectChanges();
68
+
69
+ activeOption = host.querySelector<HTMLElement>('[role="option"][aria-selected="true"]');
70
+ expect(activeOption?.textContent?.trim()).toBe('Banana');
71
+
72
+ inputDebug.triggerEventHandler('keydown', new KeyboardEvent('keydown', { key: 'Enter' }));
73
+ fixture.detectChanges();
74
+
75
+ const listbox = host.querySelector<HTMLElement>('[role="listbox"]');
76
+ expect(input.value).toBe('Banana');
77
+ expect(listbox?.hidden).toBe(true);
78
+ });
79
+ });
@@ -2,5 +2,5 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.combobox = void 0;
4
4
  const generate_component_1 = require("../utils/generate-component");
5
- exports.combobox = (0, generate_component_1.createAriaComponentSchematic)();
5
+ exports.combobox = (0, generate_component_1.createAriaComponentSchematic)({ includeSharedUnitTest: false });
6
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;AAAA,oEAA2E;AAE9D,QAAA,QAAQ,GAAG,IAAA,iDAA4B,GAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;AAAA,oEAA2E;AAE9D,QAAA,QAAQ,GAAG,IAAA,iDAA4B,EAAC,EAAE,qBAAqB,EAAE,KAAK,EAAE,CAAC,CAAC"}
@@ -1,3 +1,3 @@
1
1
  import { createAriaComponentSchematic } from '../utils/generate-component';
2
2
 
3
- export const combobox = createAriaComponentSchematic();
3
+ export const combobox = createAriaComponentSchematic({ includeSharedUnitTest: false });
@@ -0,0 +1,68 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { <%= classify(name) %> } from './<%= dasherize(name) %>';
3
+
4
+ describe('<%= classify(name) %>', () => {
5
+ let fixture: ComponentFixture<<%= classify(name) %>>;
6
+
7
+ beforeEach(async () => {
8
+ await TestBed.configureTestingModule({
9
+ imports: [<%= classify(name) %>],
10
+ }).compileComponents();
11
+
12
+ fixture = TestBed.createComponent(<%= classify(name) %>);
13
+ fixture.detectChanges();
14
+ });
15
+
16
+ function openButton(): HTMLButtonElement {
17
+ return fixture.nativeElement.querySelector('button');
18
+ }
19
+
20
+ function dialog(): HTMLElement | null {
21
+ return fixture.nativeElement.querySelector('[role="dialog"]');
22
+ }
23
+
24
+ it('starts closed with an opening trigger', () => {
25
+ expect(openButton().textContent?.trim()).toBe('Open dialog');
26
+ expect(dialog()).toBeNull();
27
+ });
28
+
29
+ it('opens a modal dialog with labelled title', () => {
30
+ openButton().click();
31
+ fixture.detectChanges();
32
+
33
+ const element = dialog();
34
+ const title = fixture.nativeElement.querySelector('h2');
35
+
36
+ expect(element).toBeTruthy();
37
+ expect(element?.getAttribute('aria-modal')).toBe('true');
38
+ expect(element?.getAttribute('aria-labelledby')).toBe(title.id);
39
+ expect(element?.getAttribute('tabindex')).toBe('-1');
40
+ expect(title.textContent?.trim()).toBe('Dialog title');
41
+ });
42
+
43
+ it('closes with the close button and restores focus to the trigger', () => {
44
+ const trigger = openButton();
45
+ trigger.focus();
46
+ trigger.click();
47
+ fixture.detectChanges();
48
+
49
+ const closeButton = Array.from(fixture.nativeElement.querySelectorAll('button')).at(-1) as HTMLButtonElement;
50
+ closeButton.click();
51
+ fixture.detectChanges();
52
+
53
+ expect(dialog()).toBeNull();
54
+ expect(document.activeElement).toBe(trigger);
55
+ });
56
+
57
+ it('closes with Escape from inside the dialog', () => {
58
+ const trigger = openButton();
59
+ trigger.click();
60
+ fixture.detectChanges();
61
+
62
+ dialog()?.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
63
+ fixture.detectChanges();
64
+
65
+ expect(dialog()).toBeNull();
66
+ expect(document.activeElement).toBe(trigger);
67
+ });
68
+ });
@@ -2,5 +2,5 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.dialog = void 0;
4
4
  const generate_component_1 = require("../utils/generate-component");
5
- exports.dialog = (0, generate_component_1.createAriaComponentSchematic)();
5
+ exports.dialog = (0, generate_component_1.createAriaComponentSchematic)({ includeSharedUnitTest: false });
6
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;AAAA,oEAA2E;AAE9D,QAAA,MAAM,GAAG,IAAA,iDAA4B,GAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;AAAA,oEAA2E;AAE9D,QAAA,MAAM,GAAG,IAAA,iDAA4B,EAAC,EAAE,qBAAqB,EAAE,KAAK,EAAE,CAAC,CAAC"}
@@ -1,3 +1,3 @@
1
1
  import { createAriaComponentSchematic } from '../utils/generate-component';
2
2
 
3
- export const dialog = createAriaComponentSchematic();
3
+ export const dialog = createAriaComponentSchematic({ includeSharedUnitTest: false });
@@ -0,0 +1,67 @@
1
+ import { Component } from '@angular/core';
2
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
3
+ import { <%= classify(name) %>, <%= classify(name) %>Content } from './<%= dasherize(name) %>';
4
+
5
+ @Component({
6
+ imports: [<%= classify(name) %>, <%= classify(name) %>Content],
7
+ template: `
8
+ <<%= selector %> label="Show profile details" [(expanded)]="expanded" [preserveContent]="preserveContent">
9
+ <ng-template <%= camelize(name) %>Content>
10
+ <p>Profile details</p>
11
+ </ng-template>
12
+ </<%= selector %>>
13
+ `,
14
+ })
15
+ class HostComponent {
16
+ expanded = false;
17
+ preserveContent = true;
18
+ }
19
+
20
+ describe('<%= classify(name) %>', () => {
21
+ let fixture: ComponentFixture<HostComponent>;
22
+
23
+ beforeEach(async () => {
24
+ await TestBed.configureTestingModule({
25
+ imports: [HostComponent],
26
+ }).compileComponents();
27
+
28
+ fixture = TestBed.createComponent(HostComponent);
29
+ fixture.detectChanges();
30
+ });
31
+
32
+ function button(): HTMLButtonElement {
33
+ return fixture.nativeElement.querySelector('button');
34
+ }
35
+
36
+ function panel(): HTMLElement {
37
+ return fixture.nativeElement.querySelector('div');
38
+ }
39
+
40
+ it('renders button and panel with ARIA relationships', () => {
41
+ expect(button().textContent?.trim()).toBe('Show profile details');
42
+ expect(button().getAttribute('aria-expanded')).toBe('false');
43
+ expect(button().getAttribute('aria-controls')).toBe(panel().id);
44
+ expect(panel().getAttribute('aria-labelledby')).toBe(button().id);
45
+ expect(panel().hidden).toBe(true);
46
+ });
47
+
48
+ it('toggles expanded state from the trigger button', () => {
49
+ button().click();
50
+ fixture.detectChanges();
51
+
52
+ expect(fixture.componentInstance.expanded).toBe(true);
53
+ expect(button().getAttribute('aria-expanded')).toBe('true');
54
+ expect(panel().hidden).toBe(false);
55
+ expect(panel().textContent).toContain('Profile details');
56
+ });
57
+
58
+ it('preserves content after first render when preserveContent is enabled', () => {
59
+ button().click();
60
+ fixture.detectChanges();
61
+ button().click();
62
+ fixture.detectChanges();
63
+
64
+ expect(panel().hidden).toBe(true);
65
+ expect(panel().textContent).toContain('Profile details');
66
+ });
67
+ });
@@ -2,5 +2,5 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.disclosure = void 0;
4
4
  const generate_component_1 = require("../utils/generate-component");
5
- exports.disclosure = (0, generate_component_1.createAriaComponentSchematic)();
5
+ exports.disclosure = (0, generate_component_1.createAriaComponentSchematic)({ includeSharedUnitTest: false });
6
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;AAAA,oEAA2E;AAE9D,QAAA,UAAU,GAAG,IAAA,iDAA4B,GAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;AAAA,oEAA2E;AAE9D,QAAA,UAAU,GAAG,IAAA,iDAA4B,EAAC,EAAE,qBAAqB,EAAE,KAAK,EAAE,CAAC,CAAC"}
@@ -1,3 +1,3 @@
1
1
  import { createAriaComponentSchematic } from '../utils/generate-component';
2
2
 
3
- export const disclosure = createAriaComponentSchematic();
3
+ export const disclosure = createAriaComponentSchematic({ includeSharedUnitTest: false });
@@ -0,0 +1,56 @@
1
+ import { Component } from '@angular/core';
2
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
3
+ import { <%= classify(name) %> } from './<%= dasherize(name) %>';
4
+
5
+ @Component({
6
+ imports: [<%= classify(name) %>],
7
+ template: `
8
+ <<%= selector %>
9
+ label="Work email"
10
+ hint="Use your company address."
11
+ error="Email is required."
12
+ [required]="true"
13
+ [(value)]="email"
14
+ />
15
+ `,
16
+ })
17
+ class HostComponent {
18
+ email = '';
19
+ }
20
+
21
+ describe('<%= classify(name) %>', () => {
22
+ let fixture: ComponentFixture<HostComponent>;
23
+
24
+ beforeEach(async () => {
25
+ await TestBed.configureTestingModule({ imports: [HostComponent] }).compileComponents();
26
+ fixture = TestBed.createComponent(HostComponent);
27
+ fixture.detectChanges();
28
+ });
29
+
30
+ function input(): HTMLInputElement {
31
+ return fixture.nativeElement.querySelector('input');
32
+ }
33
+
34
+ it('wires label, required state, hint, and error message', () => {
35
+ const label = fixture.nativeElement.querySelector('label');
36
+ const hint = fixture.nativeElement.querySelector('.semmet-field__hint');
37
+ const error = fixture.nativeElement.querySelector('.semmet-field__error');
38
+
39
+ expect(label.textContent).toContain('Work email');
40
+ expect(label.getAttribute('for')).toBe(input().id);
41
+ expect(input().required).toBe(true);
42
+ expect(input().getAttribute('aria-required')).toBe('true');
43
+ expect(input().getAttribute('aria-invalid')).toBe('true');
44
+ expect(input().getAttribute('aria-describedby')).toContain(hint.id);
45
+ expect(input().getAttribute('aria-describedby')).toContain(error.id);
46
+ expect(error.getAttribute('role')).toBe('alert');
47
+ });
48
+
49
+ it('updates the bound value on input', () => {
50
+ input().value = 'team@example.com';
51
+ input().dispatchEvent(new Event('input', { bubbles: true }));
52
+ fixture.detectChanges();
53
+
54
+ expect(fixture.componentInstance.email).toBe('team@example.com');
55
+ });
56
+ });
@@ -2,5 +2,5 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.input = void 0;
4
4
  const generate_component_1 = require("../utils/generate-component");
5
- exports.input = (0, generate_component_1.createAriaComponentSchematic)();
5
+ exports.input = (0, generate_component_1.createAriaComponentSchematic)({ includeSharedUnitTest: false });
6
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;AAAA,oEAA2E;AAE9D,QAAA,KAAK,GAAG,IAAA,iDAA4B,GAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;AAAA,oEAA2E;AAE9D,QAAA,KAAK,GAAG,IAAA,iDAA4B,EAAC,EAAE,qBAAqB,EAAE,KAAK,EAAE,CAAC,CAAC"}
@@ -1,3 +1,3 @@
1
1
  import { createAriaComponentSchematic } from '../utils/generate-component';
2
2
 
3
- export const input = createAriaComponentSchematic();
3
+ export const input = createAriaComponentSchematic({ includeSharedUnitTest: false });
@@ -0,0 +1,66 @@
1
+ import { Component } from '@angular/core';
2
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
3
+
4
+ import { <%= classify(name) %> } from './<%= dasherize(name) %>';
5
+
6
+ @Component({
7
+ imports: [<%= classify(name) %>],
8
+ template: `
9
+ <<%= selector %>
10
+ label="Account sections"
11
+ [items]="items"
12
+ />
13
+ `,
14
+ })
15
+ class HostComponent {
16
+ readonly items = [
17
+ { id: 'profile', title: 'Profile', description: 'Public identity', active: true },
18
+ { id: 'security', title: 'Security', description: 'Password settings', badge: '2' },
19
+ { id: 'billing', title: 'Billing', description: 'Invoices', disabled: true },
20
+ ];
21
+ }
22
+
23
+ describe('<%= classify(name) %>', () => {
24
+ let fixture: ComponentFixture<HostComponent>;
25
+ let host: HTMLElement;
26
+
27
+ beforeEach(async () => {
28
+ await TestBed.configureTestingModule({
29
+ imports: [HostComponent],
30
+ }).compileComponents();
31
+
32
+ fixture = TestBed.createComponent(HostComponent);
33
+ fixture.detectChanges();
34
+ host = fixture.nativeElement as HTMLElement;
35
+ });
36
+
37
+ it('renders a labeled semantic list with active and disabled states', () => {
38
+ const list = host.querySelector<HTMLUListElement>('ul');
39
+ const buttons = Array.from(host.querySelectorAll<HTMLButtonElement>('button'));
40
+
41
+ expect(list?.getAttribute('aria-label')).toBe('Account sections');
42
+ expect(buttons.map((button) => button.textContent?.replace(/\s+/g, ' ').trim())).toEqual([
43
+ 'Profile Public identity',
44
+ 'Security Password settings 2',
45
+ 'Billing Invoices',
46
+ ]);
47
+ expect(buttons[0].getAttribute('aria-current')).toBe('true');
48
+ expect(buttons[2].disabled).toBe(true);
49
+ });
50
+
51
+ it('updates selected item when an enabled item is activated', () => {
52
+ const buttons = Array.from(host.querySelectorAll<HTMLButtonElement>('button'));
53
+
54
+ buttons[1].click();
55
+ fixture.detectChanges();
56
+
57
+ expect(buttons[0].getAttribute('aria-current')).toBeNull();
58
+ expect(buttons[1].getAttribute('aria-current')).toBe('true');
59
+
60
+ buttons[2].click();
61
+ fixture.detectChanges();
62
+
63
+ expect(buttons[1].getAttribute('aria-current')).toBe('true');
64
+ expect(buttons[2].getAttribute('aria-current')).toBeNull();
65
+ });
66
+ });
@@ -2,5 +2,5 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.listGroup = void 0;
4
4
  const generate_component_1 = require("../utils/generate-component");
5
- exports.listGroup = (0, generate_component_1.createAriaComponentSchematic)();
5
+ exports.listGroup = (0, generate_component_1.createAriaComponentSchematic)({ includeSharedUnitTest: false });
6
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;AAAA,oEAA2E;AAE9D,QAAA,SAAS,GAAG,IAAA,iDAA4B,GAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;AAAA,oEAA2E;AAE9D,QAAA,SAAS,GAAG,IAAA,iDAA4B,EAAC,EAAE,qBAAqB,EAAE,KAAK,EAAE,CAAC,CAAC"}
@@ -1,3 +1,3 @@
1
1
  import { createAriaComponentSchematic } from '../utils/generate-component';
2
2
 
3
- export const listGroup = createAriaComponentSchematic();
3
+ export const listGroup = createAriaComponentSchematic({ includeSharedUnitTest: false });
@@ -0,0 +1,50 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { <%= classify(name) %> } from './<%= dasherize(name) %>';
3
+
4
+ describe('<%= classify(name) %>', () => {
5
+ let fixture: ComponentFixture<<%= classify(name) %>>;
6
+
7
+ beforeEach(async () => {
8
+ await TestBed.configureTestingModule({ imports: [<%= classify(name) %>] }).compileComponents();
9
+ fixture = TestBed.createComponent(<%= classify(name) %>);
10
+ fixture.detectChanges();
11
+ });
12
+
13
+ function listbox(): HTMLElement {
14
+ return fixture.nativeElement.querySelector('[role="listbox"]');
15
+ }
16
+
17
+ function options(): HTMLElement[] {
18
+ return Array.from(fixture.nativeElement.querySelectorAll('[role="option"]'));
19
+ }
20
+
21
+ it('renders listbox semantics with active descendant', () => {
22
+ const [first, second] = options();
23
+
24
+ expect(listbox().getAttribute('aria-labelledby')).toBeTruthy();
25
+ expect(listbox().getAttribute('aria-activedescendant')).toBe(first.id);
26
+ expect(first.getAttribute('aria-selected')).toBe('true');
27
+ expect(second.getAttribute('aria-selected')).toBe('false');
28
+ });
29
+
30
+ it('selects an option on click', () => {
31
+ const [, second] = options();
32
+ second.click();
33
+ fixture.detectChanges();
34
+
35
+ expect(listbox().getAttribute('aria-activedescendant')).toBe(second.id);
36
+ expect(second.getAttribute('aria-selected')).toBe('true');
37
+ });
38
+
39
+ it('moves active option with keyboard', () => {
40
+ listbox().dispatchEvent(new KeyboardEvent('keydown', { key: 'End', bubbles: true }));
41
+ fixture.detectChanges();
42
+
43
+ expect(listbox().getAttribute('aria-activedescendant')).toBe(options()[1].id);
44
+
45
+ listbox().dispatchEvent(new KeyboardEvent('keydown', { key: 'Home', bubbles: true }));
46
+ fixture.detectChanges();
47
+
48
+ expect(listbox().getAttribute('aria-activedescendant')).toBe(options()[0].id);
49
+ });
50
+ });
@@ -2,5 +2,5 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.listbox = void 0;
4
4
  const generate_component_1 = require("../utils/generate-component");
5
- exports.listbox = (0, generate_component_1.createAriaComponentSchematic)();
5
+ exports.listbox = (0, generate_component_1.createAriaComponentSchematic)({ includeSharedUnitTest: false });
6
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;AAAA,oEAA2E;AAE9D,QAAA,OAAO,GAAG,IAAA,iDAA4B,GAAE,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;AAAA,oEAA2E;AAE9D,QAAA,OAAO,GAAG,IAAA,iDAA4B,EAAC,EAAE,qBAAqB,EAAE,KAAK,EAAE,CAAC,CAAC"}
@@ -1,3 +1,3 @@
1
1
  import { createAriaComponentSchematic } from '../utils/generate-component';
2
2
 
3
- export const listbox = createAriaComponentSchematic();
3
+ export const listbox = createAriaComponentSchematic({ includeSharedUnitTest: false });
@@ -0,0 +1,64 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { <%= classify(name) %> } from './<%= dasherize(name) %>';
3
+
4
+ describe('<%= classify(name) %>', () => {
5
+ let fixture: ComponentFixture<<%= classify(name) %>>;
6
+
7
+ beforeEach(async () => {
8
+ await TestBed.configureTestingModule({ imports: [<%= classify(name) %>] }).compileComponents();
9
+ fixture = TestBed.createComponent(<%= classify(name) %>);
10
+ fixture.detectChanges();
11
+ });
12
+
13
+ function trigger(): HTMLButtonElement {
14
+ return fixture.nativeElement.querySelector('button');
15
+ }
16
+
17
+ function menu(): HTMLElement {
18
+ return fixture.nativeElement.querySelector('[role="menu"]');
19
+ }
20
+
21
+ function menuItems(): HTMLElement[] {
22
+ return Array.from(fixture.nativeElement.querySelectorAll('[role="menuitem"]'));
23
+ }
24
+
25
+ it('starts closed with menu button semantics', () => {
26
+ expect(trigger().getAttribute('aria-haspopup')).toBe('true');
27
+ expect(trigger().getAttribute('aria-expanded')).toBe('false');
28
+ expect(trigger().getAttribute('aria-controls')).toBe(menu().id);
29
+ expect(menu().hidden).toBe(true);
30
+ });
31
+
32
+ it('opens from click and wires menu labelling', () => {
33
+ trigger().click();
34
+ fixture.detectChanges();
35
+
36
+ expect(trigger().getAttribute('aria-expanded')).toBe('true');
37
+ expect(menu().hidden).toBe(false);
38
+ expect(menu().getAttribute('aria-labelledby')).toBe(trigger().id);
39
+ expect(menuItems()[0].textContent?.trim()).toBe('First option');
40
+ });
41
+
42
+ it('opens with keyboard and closes with Escape', () => {
43
+ trigger().dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }));
44
+ fixture.detectChanges();
45
+ expect(menu().hidden).toBe(false);
46
+
47
+ menuItems()[0].dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
48
+ fixture.detectChanges();
49
+
50
+ expect(menu().hidden).toBe(true);
51
+ expect(document.activeElement).toBe(trigger());
52
+ });
53
+
54
+ it('moves focus between menu items', () => {
55
+ trigger().click();
56
+ fixture.detectChanges();
57
+
58
+ menuItems()[0].focus();
59
+ menuItems()[0].dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }));
60
+ fixture.detectChanges();
61
+
62
+ expect(document.activeElement).toBe(menuItems()[1]);
63
+ });
64
+ });