From 60d3317d4a2c4564c16e932fa426d224fe80bcca Mon Sep 17 00:00:00 2001 From: Miles Malerba Date: Thu, 13 Jun 2024 08:08:58 -0700 Subject: [PATCH] test: Convert material chips tests to zoneless (#29238) (cherry picked from commit 799d95269eaae15e0b6c602c4735edd03758cc3f) --- src/material/chips/chip-grid.spec.ts | 34 ++++++++++++++++--- src/material/chips/chip-grid.ts | 20 ++++++++--- src/material/chips/chip-input.spec.ts | 16 ++++----- src/material/chips/chip-listbox.spec.ts | 28 +++++++++++---- src/material/chips/chip-option.spec.ts | 29 ++++++++++------ src/material/chips/chip-remove.spec.ts | 14 ++++---- src/material/chips/chip-row.spec.ts | 30 ++++++++-------- src/material/chips/chip-row.ts | 30 ++++++++-------- src/material/chips/chip-set.spec.ts | 15 ++++---- src/material/chips/chip-set.ts | 8 +++-- src/material/chips/chip.spec.ts | 18 +++++----- src/material/chips/chip.ts | 2 +- .../chips/testing/chip-grid-harness.spec.ts | 14 ++++---- .../chips/testing/chip-input-harness.spec.ts | 11 ++---- .../testing/chip-listbox-harness.spec.ts | 14 ++++---- .../chips/testing/chip-row-harness.spec.ts | 3 +- tools/public_api_guard/material/chips.md | 7 +++- 17 files changed, 175 insertions(+), 118 deletions(-) diff --git a/src/material/chips/chip-grid.spec.ts b/src/material/chips/chip-grid.spec.ts index 85edeebe8781..cb18d49372f9 100644 --- a/src/material/chips/chip-grid.spec.ts +++ b/src/material/chips/chip-grid.spec.ts @@ -20,6 +20,7 @@ import { typeInElement, } from '@angular/cdk/testing/private'; import { + ChangeDetectorRef, Component, DebugElement, EventEmitter, @@ -27,8 +28,9 @@ import { Type, ViewChild, ViewChildren, - provideZoneChangeDetection, + inject, } from '@angular/core'; +import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; import {ComponentFixture, TestBed, fakeAsync, flush, tick} from '@angular/core/testing'; import {FormControl, FormsModule, NgForm, ReactiveFormsModule, Validators} from '@angular/forms'; import {MatFormFieldModule} from '@angular/material/form-field'; @@ -70,11 +72,13 @@ describe('MDC-based MatChipGrid', () => { expect(chips.toArray().every(chip => chip.disabled)).toBe(false); chipGridInstance.disabled = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chips.toArray().every(chip => chip.disabled)).toBe(true); chipGridInstance.disabled = false; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chips.toArray().every(chip => chip.disabled)).toBe(false); @@ -84,11 +88,13 @@ describe('MDC-based MatChipGrid', () => { expect(chips.toArray().every(chip => chip.disabled)).toBe(false); chipGridInstance.disabled = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chips.toArray().every(chip => chip.disabled)).toBe(true); fixture.componentInstance.chips.push(5, 6); + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); tick(); fixture.detectChanges(); @@ -98,6 +104,7 @@ describe('MDC-based MatChipGrid', () => { it('should not set a role on the grid when the list is empty', () => { testComponent.chips = []; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chipGridNativeElement.hasAttribute('role')).toBe(false); @@ -105,6 +112,7 @@ describe('MDC-based MatChipGrid', () => { it('should be able to set a custom role', () => { testComponent.role = 'listbox'; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chipGridNativeElement.getAttribute('role')).toBe('listbox'); @@ -140,6 +148,7 @@ describe('MDC-based MatChipGrid', () => { .toBe(false); chipGridInstance.disabled = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); chipGridInstance.focus(); @@ -154,6 +163,7 @@ describe('MDC-based MatChipGrid', () => { expect(chipGridNativeElement.getAttribute('tabindex')).toBe('0'); chipGridInstance.disabled = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chipGridNativeElement.getAttribute('tabindex')).toBe('-1'); @@ -168,6 +178,7 @@ describe('MDC-based MatChipGrid', () => { // Destroy the middle item testComponent.chips.splice(2, 1); + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); // It focuses the 4th item @@ -180,6 +191,7 @@ describe('MDC-based MatChipGrid', () => { // Destroy the last item testComponent.chips.pop(); + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); // It focuses the next-to-last item @@ -196,6 +208,7 @@ describe('MDC-based MatChipGrid', () => { // Destroy the middle item testComponent.chips.splice(2, 1); + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); flush(); @@ -205,12 +218,14 @@ describe('MDC-based MatChipGrid', () => { it('should focus the grid if the last focused item is removed', () => { testComponent.chips = [0]; + fixture.changeDetectorRef.markForCheck(); spyOn(chipGridInstance, 'focus'); patchElementFocus(chips.last.primaryAction!._elementRef.nativeElement); chips.last.focus(); testComponent.chips.pop(); + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chipGridInstance.focus).toHaveBeenCalled(); @@ -350,6 +365,7 @@ describe('MDC-based MatChipGrid', () => { it(`should use user defined tabIndex`, fakeAsync(() => { chipGridInstance.tabIndex = 4; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chipGridInstance.tabIndex) @@ -422,6 +438,7 @@ describe('MDC-based MatChipGrid', () => { it('should ignore all non-tab navigation keyboard events from an editing chip', fakeAsync(() => { testComponent.editable = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); chips.first.focus(); @@ -572,6 +589,7 @@ describe('MDC-based MatChipGrid', () => { it('should take an initial view value with reactive forms', () => { fixture.componentInstance.control = new FormControl('[pizza-1]'); + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(fixture.componentInstance.chipGrid.value).toEqual('[pizza-1]'); @@ -756,6 +774,7 @@ describe('MDC-based MatChipGrid', () => { it('should set aria-invalid if the form field is invalid', fakeAsync(() => { fixture.componentInstance.control = new FormControl('', [Validators.required]); + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); const input: HTMLInputElement = fixture.nativeElement.querySelector('input'); @@ -991,10 +1010,7 @@ describe('MDC-based MatChipGrid', () => { MatInputModule, animationsModule, ], - providers: [ - {provide: Directionality, useValue: directionality}, - provideZoneChangeDetection(), - ], + providers: [{provide: Directionality, useValue: directionality}], declarations: [component], }).compileComponents(); @@ -1149,6 +1165,14 @@ class ChipGridWithFormErrorMessages { @ViewChild('form') form: NgForm; formControl = new FormControl('', Validators.required); + + private readonly _changeDetectorRef = inject(ChangeDetectorRef); + + constructor() { + this.formControl.events.pipe(takeUntilDestroyed()).subscribe(() => { + this._changeDetectorRef.markForCheck(); + }); + } } @Component({ diff --git a/src/material/chips/chip-grid.ts b/src/material/chips/chip-grid.ts index c75db9aeaeea..32e9cb47d8e8 100644 --- a/src/material/chips/chip-grid.ts +++ b/src/material/chips/chip-grid.ts @@ -6,6 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ +import {Directionality} from '@angular/cdk/bidi'; import {hasModifierKey, TAB} from '@angular/cdk/keycodes'; import { AfterContentInit, @@ -20,6 +21,7 @@ import { EventEmitter, Input, OnDestroy, + OnInit, Optional, Output, QueryList, @@ -33,15 +35,14 @@ import { NgForm, Validators, } from '@angular/forms'; -import {ErrorStateMatcher, _ErrorStateTracker} from '@angular/material/core'; +import {_ErrorStateTracker, ErrorStateMatcher} from '@angular/material/core'; import {MatFormFieldControl} from '@angular/material/form-field'; -import {MatChipTextControl} from './chip-text-control'; -import {Observable, Subject, merge} from 'rxjs'; +import {merge, Observable, Subject} from 'rxjs'; import {takeUntil} from 'rxjs/operators'; import {MatChipEvent} from './chip'; import {MatChipRow} from './chip-row'; import {MatChipSet} from './chip-set'; -import {Directionality} from '@angular/cdk/bidi'; +import {MatChipTextControl} from './chip-text-control'; /** Change event object that is emitted when the chip grid value has changed. */ export class MatChipGridChange { @@ -90,7 +91,8 @@ export class MatChipGrid ControlValueAccessor, DoCheck, MatFormFieldControl, - OnDestroy + OnDestroy, + OnInit { /** * Implemented as part of MatFormFieldControl. @@ -278,6 +280,14 @@ export class MatChipGrid ); } + ngOnInit() { + if (this.ngControl) { + this.ngControl.control?.events.pipe(takeUntil(this._destroyed)).subscribe(() => { + this._changeDetectorRef.markForCheck(); + }); + } + } + ngAfterContentInit() { this.chipBlurChanges.pipe(takeUntil(this._destroyed)).subscribe(() => { this._blur(); diff --git a/src/material/chips/chip-input.spec.ts b/src/material/chips/chip-input.spec.ts index ca0a6fcb416a..32e5d203743e 100644 --- a/src/material/chips/chip-input.spec.ts +++ b/src/material/chips/chip-input.spec.ts @@ -2,8 +2,8 @@ import {Directionality} from '@angular/cdk/bidi'; import {COMMA, ENTER, TAB} from '@angular/cdk/keycodes'; import {PlatformModule} from '@angular/cdk/platform'; import {dispatchKeyboardEvent} from '@angular/cdk/testing/private'; -import {Component, DebugElement, ViewChild, provideZoneChangeDetection} from '@angular/core'; -import {waitForAsync, ComponentFixture, fakeAsync, TestBed, flush} from '@angular/core/testing'; +import {Component, DebugElement, ViewChild} from '@angular/core'; +import {ComponentFixture, TestBed, fakeAsync, flush, waitForAsync} from '@angular/core/testing'; import {MatFormFieldModule} from '@angular/material/form-field'; import {By} from '@angular/platform-browser'; import {NoopAnimationsModule} from '@angular/platform-browser/animations'; @@ -25,12 +25,6 @@ describe('MDC-based MatChipInput', () => { let chipInputDirective: MatChipInput; let dir = 'ltr'; - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [provideZoneChangeDetection()], - }); - }); - beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [PlatformModule, MatChipsModule, MatFormFieldModule, NoopAnimationsModule], @@ -77,6 +71,7 @@ describe('MDC-based MatChipInput', () => { expect(inputNativeElement.hasAttribute('placeholder')).toBe(false); testChipInput.placeholder = 'bound placeholder'; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(inputNativeElement.getAttribute('placeholder')).toBe('bound placeholder'); @@ -87,6 +82,7 @@ describe('MDC-based MatChipInput', () => { expect(chipInputDirective.disabled).toBe(false); fixture.componentInstance.chipGridInstance.disabled = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(inputNativeElement.getAttribute('disabled')).toBe('true'); @@ -97,6 +93,7 @@ describe('MDC-based MatChipInput', () => { expect(inputNativeElement.hasAttribute('aria-required')).toBe(false); fixture.componentInstance.required = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(inputNativeElement.getAttribute('aria-required')).toBe('true'); @@ -106,6 +103,7 @@ describe('MDC-based MatChipInput', () => { expect(inputNativeElement.hasAttribute('required')).toBe(false); fixture.componentInstance.required = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(inputNativeElement.getAttribute('required')).toBe('true'); @@ -144,6 +142,7 @@ describe('MDC-based MatChipInput', () => { spyOn(testChipInput, 'add'); testChipInput.addOnBlur = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); chipInputDirective._blur(); @@ -154,6 +153,7 @@ describe('MDC-based MatChipInput', () => { spyOn(testChipInput, 'add'); testChipInput.addOnBlur = false; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); chipInputDirective._blur(); diff --git a/src/material/chips/chip-listbox.spec.ts b/src/material/chips/chip-listbox.spec.ts index 4ebf4093d7f8..34159fd46cde 100644 --- a/src/material/chips/chip-listbox.spec.ts +++ b/src/material/chips/chip-listbox.spec.ts @@ -13,7 +13,6 @@ import { Type, ViewChild, ViewChildren, - provideZoneChangeDetection, } from '@angular/core'; import {ComponentFixture, TestBed, fakeAsync, flush, tick} from '@angular/core/testing'; import {FormControl, FormsModule, ReactiveFormsModule} from '@angular/forms'; @@ -29,11 +28,6 @@ describe('MDC-based MatChipListbox', () => { let chips: QueryList; let directionality: {value: Direction; change: EventEmitter}; let primaryActions: NodeListOf; - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [provideZoneChangeDetection()], - }); - }); describe('StandardChipList', () => { describe('basic behaviors', () => { @@ -47,6 +41,7 @@ describe('MDC-based MatChipListbox', () => { it('should not have the aria-selected attribute when it is not selectable', fakeAsync(() => { testComponent.selectable = false; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); tick(); @@ -64,11 +59,13 @@ describe('MDC-based MatChipListbox', () => { expect(chips.toArray().every(chip => chip.disabled)).toBe(false); chipListboxInstance.disabled = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chips.toArray().every(chip => chip.disabled)).toBe(true); chipListboxInstance.disabled = false; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chips.toArray().every(chip => chip.disabled)).toBe(false); @@ -78,11 +75,13 @@ describe('MDC-based MatChipListbox', () => { expect(chips.toArray().every(chip => chip.disabled)).toBe(false); chipListboxInstance.disabled = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chips.toArray().every(chip => chip.disabled)).toBe(true); fixture.componentInstance.chips.push(5, 6); + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); tick(); fixture.detectChanges(); @@ -92,6 +91,7 @@ describe('MDC-based MatChipListbox', () => { it('should not set a role on the grid when the list is empty', () => { testComponent.chips = []; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chipListboxNativeElement.hasAttribute('role')).toBe(false); @@ -99,6 +99,7 @@ describe('MDC-based MatChipListbox', () => { it('should be able to set a custom role', () => { testComponent.role = 'grid'; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chipListboxNativeElement.getAttribute('role')).toBe('grid'); @@ -106,6 +107,7 @@ describe('MDC-based MatChipListbox', () => { it('should not set aria-required when it does not have a role', () => { testComponent.chips = []; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chipListboxNativeElement.hasAttribute('role')).toBe(false); @@ -138,6 +140,7 @@ describe('MDC-based MatChipListbox', () => { it('should not have role when empty', () => { fixture.componentInstance.foods = []; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chipListboxNativeElement.getAttribute('role')) @@ -171,6 +174,7 @@ describe('MDC-based MatChipListbox', () => { .toBe(false); chipListboxInstance.disabled = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); chipListboxInstance.focus(); @@ -185,6 +189,7 @@ describe('MDC-based MatChipListbox', () => { expect(chipListboxNativeElement.getAttribute('tabindex')).toBe('0'); chipListboxInstance.disabled = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chipListboxNativeElement.getAttribute('tabindex')).toBe('-1'); @@ -200,6 +205,7 @@ describe('MDC-based MatChipListbox', () => { // Destroy the middle item testComponent.chips.splice(2, 1); + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); // It focuses the 4th item @@ -213,6 +219,7 @@ describe('MDC-based MatChipListbox', () => { // Destroy the last item testComponent.chips.pop(); + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); // It focuses the next-to-last item @@ -229,6 +236,7 @@ describe('MDC-based MatChipListbox', () => { // Destroy the middle item testComponent.chips.splice(2, 1); + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); tick(); @@ -238,6 +246,7 @@ describe('MDC-based MatChipListbox', () => { it('should focus the listbox if the last focused item is removed', fakeAsync(() => { testComponent.chips = [0]; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); spyOn(chipListboxInstance, 'focus'); @@ -245,6 +254,7 @@ describe('MDC-based MatChipListbox', () => { chips.last.focus(); testComponent.chips.pop(); + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chipListboxInstance.focus).toHaveBeenCalled(); @@ -370,6 +380,7 @@ describe('MDC-based MatChipListbox', () => { it('should use user defined tabIndex', fakeAsync(() => { chipListboxInstance.tabIndex = 4; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); @@ -429,6 +440,7 @@ describe('MDC-based MatChipListbox', () => { .toBe(chips.first); fixture.componentInstance.foods = []; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); tick(); @@ -440,6 +452,7 @@ describe('MDC-based MatChipListbox', () => { it('should select an option that was added after initialization', () => { fixture = createComponent(BasicChipListbox); fixture.componentInstance.foods.push({viewValue: 'Potatoes', value: 'potatoes-8'}); + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); primaryActions = chipListboxNativeElement.querySelectorAll( @@ -509,6 +522,7 @@ describe('MDC-based MatChipListbox', () => { {value: 'tacos-2', viewValue: 'Tacos'}, ]; fixture.componentInstance.selectable = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); primaryActions = chipListboxNativeElement.querySelectorAll( @@ -547,6 +561,7 @@ describe('MDC-based MatChipListbox', () => { {value: 'tacos-2', viewValue: 'Tacos'}, ]; fixture.componentInstance.selectable = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); primaryActions = chipListboxNativeElement.querySelectorAll( @@ -585,6 +600,7 @@ describe('MDC-based MatChipListbox', () => { it('should take an initial view value with reactive forms', fakeAsync(() => { fixture.componentInstance.control = new FormControl('pizza-1'); + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); tick(); const array = chips.toArray(); diff --git a/src/material/chips/chip-option.spec.ts b/src/material/chips/chip-option.spec.ts index e7295766a14d..f2a29a30ff9f 100644 --- a/src/material/chips/chip-option.spec.ts +++ b/src/material/chips/chip-option.spec.ts @@ -1,20 +1,20 @@ import {Directionality} from '@angular/cdk/bidi'; +import {ENTER, SPACE} from '@angular/cdk/keycodes'; import {dispatchFakeEvent, dispatchKeyboardEvent} from '@angular/cdk/testing/private'; -import {Component, DebugElement, ViewChild, provideZoneChangeDetection} from '@angular/core'; -import {waitForAsync, ComponentFixture, fakeAsync, flush, TestBed} from '@angular/core/testing'; +import {Component, DebugElement, ViewChild} from '@angular/core'; +import {ComponentFixture, TestBed, fakeAsync, flush, waitForAsync} from '@angular/core/testing'; import {MAT_RIPPLE_GLOBAL_OPTIONS, RippleGlobalOptions} from '@angular/material/core'; import {By} from '@angular/platform-browser'; import {Subject} from 'rxjs'; import { + MAT_CHIPS_DEFAULT_OPTIONS, MatChipEvent, MatChipListbox, MatChipOption, - MatChipsDefaultOptions, MatChipSelectionChange, + MatChipsDefaultOptions, MatChipsModule, - MAT_CHIPS_DEFAULT_OPTIONS, } from './index'; -import {ENTER, SPACE} from '@angular/cdk/keycodes'; describe('MDC-based Option Chips', () => { let fixture: ComponentFixture; @@ -27,12 +27,6 @@ describe('MDC-based Option Chips', () => { let hideSingleSelectionIndicator: boolean | undefined; - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [provideZoneChangeDetection()], - }); - }); - beforeEach(waitForAsync(() => { globalRippleOptions = {}; const defaultOptions: MatChipsDefaultOptions = { @@ -96,6 +90,7 @@ describe('MDC-based Option Chips', () => { // Force a destroy callback testComponent.shouldShow = false; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(testComponent.chipDestroy).toHaveBeenCalledTimes(1); @@ -105,6 +100,7 @@ describe('MDC-based Option Chips', () => { expect(chipNativeElement.classList).toContain('mat-primary'); testComponent.color = 'warn'; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chipNativeElement.classList).not.toContain('mat-primary'); @@ -116,6 +112,7 @@ describe('MDC-based Option Chips', () => { expect(chipNativeElement.classList).not.toContain('mat-mdc-chip-selected'); testComponent.selected = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chipNativeElement.classList).toContain('mat-mdc-chip-selected'); @@ -203,6 +200,7 @@ describe('MDC-based Option Chips', () => { it('should be able to set a custom role', () => { chipInstance.role = 'button'; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chipNativeElement.getAttribute('role')).toBe('button'); @@ -213,6 +211,7 @@ describe('MDC-based Option Chips', () => { describe('when selectable is true', () => { beforeEach(() => { testComponent.selectable = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); }); @@ -252,6 +251,7 @@ describe('MDC-based Option Chips', () => { expect(primaryAction.getAttribute('aria-selected')).toBe('false'); testComponent.selected = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(primaryAction.getAttribute('aria-selected')).toBe('true'); @@ -259,11 +259,13 @@ describe('MDC-based Option Chips', () => { it('should have the correct aria-selected in multi-selection mode', fakeAsync(() => { testComponent.chipList.multiple = true; + fixture.changeDetectorRef.markForCheck(); flush(); fixture.detectChanges(); expect(primaryAction.getAttribute('aria-selected')).toBe('false'); testComponent.selected = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(primaryAction.getAttribute('aria-selected')).toBe('true'); @@ -272,6 +274,7 @@ describe('MDC-based Option Chips', () => { it('should disable focus on the checkmark', fakeAsync(() => { // The checkmark is only shown in multi selection mode. testComponent.chipList.multiple = true; + fixture.changeDetectorRef.markForCheck(); flush(); fixture.detectChanges(); @@ -283,6 +286,7 @@ describe('MDC-based Option Chips', () => { describe('when selectable is false', () => { beforeEach(() => { testComponent.selectable = false; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); }); @@ -306,6 +310,7 @@ describe('MDC-based Option Chips', () => { expect(primaryAction.getAttribute('aria-disabled')).toBe('false'); testComponent.disabled = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(primaryAction.getAttribute('aria-disabled')).toBe('true'); @@ -330,6 +335,7 @@ describe('MDC-based Option Chips', () => { it('should apply `ariaLabel` and `ariaDesciption` to the element with option role', () => { testComponent.ariaLabel = 'option name'; testComponent.ariaDescription = 'option description'; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); @@ -387,6 +393,7 @@ describe('MDC-based Option Chips', () => { it('displays checkmark graphic when avatar is provided', () => { testComponent.selected = true; testComponent.avatarLabel = 'A'; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chipNativeElement.querySelector('.mat-mdc-chip-graphic')).toBeTruthy(); diff --git a/src/material/chips/chip-remove.spec.ts b/src/material/chips/chip-remove.spec.ts index 1bffa65230b2..1393c84b078a 100644 --- a/src/material/chips/chip-remove.spec.ts +++ b/src/material/chips/chip-remove.spec.ts @@ -1,19 +1,14 @@ -import {Component, provideZoneChangeDetection} from '@angular/core'; -import {waitForAsync, ComponentFixture, TestBed, fakeAsync, flush} from '@angular/core/testing'; +import {ENTER, SPACE} from '@angular/cdk/keycodes'; import {dispatchKeyboardEvent, dispatchMouseEvent} from '@angular/cdk/testing/private'; +import {Component} from '@angular/core'; +import {ComponentFixture, TestBed, fakeAsync, flush, waitForAsync} from '@angular/core/testing'; import {By} from '@angular/platform-browser'; -import {SPACE, ENTER} from '@angular/cdk/keycodes'; import {MatChip, MatChipsModule} from './index'; describe('MDC-based Chip Remove', () => { let fixture: ComponentFixture; let testChip: TestChip; let chipNativeElement: HTMLElement; - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [provideZoneChangeDetection()], - }); - }); beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ @@ -50,6 +45,7 @@ describe('MDC-based Chip Remove', () => { it('should emit (removed) event when exit animation is complete', fakeAsync(() => { testChip.removable = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); chipNativeElement.querySelector('button')!.click(); @@ -70,6 +66,7 @@ describe('MDC-based Chip Remove', () => { const buttonElement = chipNativeElement.querySelector('button')!; testChip.removable = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); const event = dispatchKeyboardEvent(buttonElement, 'keydown', SPACE); @@ -83,6 +80,7 @@ describe('MDC-based Chip Remove', () => { const buttonElement = chipNativeElement.querySelector('button')!; testChip.removable = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); const event = dispatchKeyboardEvent(buttonElement, 'keydown', ENTER); diff --git a/src/material/chips/chip-row.spec.ts b/src/material/chips/chip-row.spec.ts index 8807a1046d0d..2c139c17cb95 100644 --- a/src/material/chips/chip-row.spec.ts +++ b/src/material/chips/chip-row.spec.ts @@ -6,19 +6,13 @@ import { dispatchFakeEvent, dispatchKeyboardEvent, } from '@angular/cdk/testing/private'; -import { - Component, - DebugElement, - ElementRef, - ViewChild, - provideZoneChangeDetection, -} from '@angular/core'; -import {waitForAsync, ComponentFixture, TestBed, flush, fakeAsync} from '@angular/core/testing'; +import {Component, DebugElement, ElementRef, ViewChild} from '@angular/core'; +import {ComponentFixture, TestBed, fakeAsync, flush, waitForAsync} from '@angular/core/testing'; import {By} from '@angular/platform-browser'; import {Subject} from 'rxjs'; import { - MatChipEditedEvent, MatChipEditInput, + MatChipEditedEvent, MatChipEvent, MatChipGrid, MatChipRow, @@ -33,12 +27,6 @@ describe('MDC-based Row Chips', () => { let dir = 'ltr'; - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [provideZoneChangeDetection()], - }); - }); - beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [MatChipsModule, SingleChip], @@ -83,6 +71,7 @@ describe('MDC-based Row Chips', () => { // Force a destroy callback testComponent.shouldShow = false; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(testComponent.chipDestroy).toHaveBeenCalledTimes(1); @@ -92,6 +81,7 @@ describe('MDC-based Row Chips', () => { expect(chipNativeElement.classList).toContain('mat-primary'); testComponent.color = 'warn'; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chipNativeElement.classList).not.toContain('mat-primary'); @@ -117,6 +107,7 @@ describe('MDC-based Row Chips', () => { it('should be able to set a custom role', () => { chipInstance.role = 'button'; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chipNativeElement.getAttribute('role')).toBe('button'); @@ -127,6 +118,7 @@ describe('MDC-based Row Chips', () => { describe('when removable is true', () => { beforeEach(() => { testComponent.removable = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); }); @@ -170,6 +162,7 @@ describe('MDC-based Row Chips', () => { describe('when removable is false', () => { beforeEach(() => { testComponent.removable = false; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); }); @@ -205,6 +198,7 @@ describe('MDC-based Row Chips', () => { expect(primaryActionElement.getAttribute('aria-disabled')).toBe('false'); testComponent.disabled = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(primaryActionElement.getAttribute('aria-disabled')).toBe('true'); @@ -236,6 +230,7 @@ describe('MDC-based Row Chips', () => { describe('editable behavior', () => { beforeEach(() => { testComponent.editable = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); }); @@ -260,6 +255,7 @@ describe('MDC-based Row Chips', () => { beforeEach(fakeAsync(() => { testComponent.editable = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); dispatchFakeEvent(chipNativeElement, 'dblclick'); fixture.detectChanges(); @@ -283,10 +279,12 @@ describe('MDC-based Row Chips', () => { it('should set the role of the primary action to gridcell', () => { testComponent.editable = false; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(primaryAction.getAttribute('role')).toBe('gridcell'); testComponent.editable = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); // Test regression of bug where element is mislabeled as a button role. Element that does not perform its // action on click event is not a button by ARIA spec (#27106). @@ -329,6 +327,7 @@ describe('MDC-based Row Chips', () => { it('should use the default edit input if none is projected', () => { keyDownOnPrimaryAction(ENTER, 'Enter'); testComponent.useCustomEditInput = false; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); dispatchFakeEvent(chipNativeElement, 'dblclick'); fixture.detectChanges(); @@ -369,6 +368,7 @@ describe('MDC-based Row Chips', () => { it('should apply `ariaLabel` and `ariaDesciption` to the primary gridcell', () => { fixture.componentInstance.ariaLabel = 'chip name'; fixture.componentInstance.ariaDescription = 'chip description'; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); diff --git a/src/material/chips/chip-row.ts b/src/material/chips/chip-row.ts index f790eb8e73fc..bee7f55e087d 100644 --- a/src/material/chips/chip-row.ts +++ b/src/material/chips/chip-row.ts @@ -6,8 +6,11 @@ * found in the LICENSE file at https://angular.io/license */ +import {FocusMonitor} from '@angular/cdk/a11y'; import {ENTER} from '@angular/cdk/keycodes'; +import {DOCUMENT} from '@angular/common'; import { + ANIMATION_MODULE_TYPE, AfterViewInit, Attribute, ChangeDetectionStrategy, @@ -23,16 +26,14 @@ import { Output, ViewChild, ViewEncapsulation, - ANIMATION_MODULE_TYPE, + afterNextRender, } from '@angular/core'; -import {DOCUMENT} from '@angular/common'; import {MAT_RIPPLE_GLOBAL_OPTIONS, RippleGlobalOptions} from '@angular/material/core'; -import {FocusMonitor} from '@angular/cdk/a11y'; +import {takeUntil} from 'rxjs/operators'; import {MatChip, MatChipEvent} from './chip'; +import {MatChipAction} from './chip-action'; import {MatChipEditInput} from './chip-edit-input'; -import {takeUntil} from 'rxjs/operators'; import {MAT_CHIP} from './tokens'; -import {MatChipAction} from './chip-action'; /** Represents an event fired on an individual `mat-chip` when it is edited. */ export interface MatChipEditedEvent extends MatChipEvent { @@ -182,17 +183,14 @@ export class MatChipRow extends MatChip implements AfterViewInit { this._isEditing = this._editStartPending = true; - // Starting the editing sequence below depends on the edit input - // query resolving on time. Trigger a synchronous change detection to - // ensure that it happens by the time we hit the timeout below. - this._changeDetectorRef.detectChanges(); - - // TODO(crisbeto): this timeout shouldn't be necessary given the `detectChange` call above. - // Defer initializing the input so it has time to be added to the DOM. - setTimeout(() => { - this._getEditInput().initialize(value); - this._editStartPending = false; - }); + // Defer initializing the input until after it has been added to the DOM. + afterNextRender( + () => { + this._getEditInput().initialize(value); + this._editStartPending = false; + }, + {injector: this._injector}, + ); } private _onEditFinish() { diff --git a/src/material/chips/chip-set.spec.ts b/src/material/chips/chip-set.spec.ts index 7b2d5a5690b4..bf556874b336 100644 --- a/src/material/chips/chip-set.spec.ts +++ b/src/material/chips/chip-set.spec.ts @@ -1,6 +1,6 @@ -import {Component, DebugElement, QueryList, provideZoneChangeDetection} from '@angular/core'; -import {waitForAsync, ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing'; import {CommonModule} from '@angular/common'; +import {Component, DebugElement, QueryList} from '@angular/core'; +import {ComponentFixture, TestBed, fakeAsync, tick, waitForAsync} from '@angular/core/testing'; import {By} from '@angular/platform-browser'; import {MatChip, MatChipSet, MatChipsModule} from './index'; @@ -20,12 +20,6 @@ describe('MDC-based MatChipSet', () => { let chipSetInstance: MatChipSet; let chips: QueryList; - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [provideZoneChangeDetection()], - }); - }); - describe('basic behaviors', () => { beforeEach(() => { fixture = TestBed.createComponent(BasicChipSet); @@ -45,11 +39,13 @@ describe('MDC-based MatChipSet', () => { expect(chips.toArray().every(chip => chip.disabled)).toBe(false); chipSetInstance.disabled = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chips.toArray().every(chip => chip.disabled)).toBe(true); chipSetInstance.disabled = false; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chips.toArray().every(chip => chip.disabled)).toBe(false); @@ -59,11 +55,13 @@ describe('MDC-based MatChipSet', () => { expect(chips.toArray().every(chip => chip.disabled)).toBe(false); chipSetInstance.disabled = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chips.toArray().every(chip => chip.disabled)).toBe(true); fixture.componentInstance.chips.push(5, 6); + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); tick(); fixture.detectChanges(); @@ -77,6 +75,7 @@ describe('MDC-based MatChipSet', () => { it('should allow a custom role to be specified', () => { chipSetInstance.role = 'list'; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chipSetNativeElement.getAttribute('role')).toBe('list'); }); diff --git a/src/material/chips/chip-set.ts b/src/material/chips/chip-set.ts index 5495059a49ee..d38d1ff9a57b 100644 --- a/src/material/chips/chip-set.ts +++ b/src/material/chips/chip-set.ts @@ -23,7 +23,7 @@ import { booleanAttribute, numberAttribute, } from '@angular/core'; -import {merge, Observable, Subject} from 'rxjs'; +import {Observable, Subject, merge} from 'rxjs'; import {startWith, switchMap, takeUntil} from 'rxjs/operators'; import {MatChip, MatChipEvent} from './chip'; import {MatChipAction} from './chip-action'; @@ -194,10 +194,14 @@ export class MatChipSet implements AfterViewInit, OnDestroy { if (this.tabIndex !== -1) { const previousTabIndex = this.tabIndex; this.tabIndex = -1; + this._changeDetectorRef.markForCheck(); // Note that this needs to be a `setTimeout`, because a `Promise.resolve` // doesn't allow enough time for the focus to escape. - setTimeout(() => (this.tabIndex = previousTabIndex)); + setTimeout(() => { + this.tabIndex = previousTabIndex; + this._changeDetectorRef.markForCheck(); + }); } } diff --git a/src/material/chips/chip.spec.ts b/src/material/chips/chip.spec.ts index 475a21ccd5d1..9d4037038bdd 100644 --- a/src/material/chips/chip.spec.ts +++ b/src/material/chips/chip.spec.ts @@ -1,6 +1,6 @@ import {Directionality} from '@angular/cdk/bidi'; -import {Component, DebugElement, ViewChild, provideZoneChangeDetection} from '@angular/core'; -import {waitForAsync, ComponentFixture, TestBed} from '@angular/core/testing'; +import {Component, DebugElement, ViewChild} from '@angular/core'; +import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing'; import {By} from '@angular/platform-browser'; import {Subject} from 'rxjs'; import {MatChip, MatChipEvent, MatChipSet, MatChipsModule} from './index'; @@ -13,12 +13,6 @@ describe('MDC-based MatChip', () => { let dir = 'ltr'; - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [provideZoneChangeDetection()], - }); - }); - beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [ @@ -68,6 +62,7 @@ describe('MDC-based MatChip', () => { expect(chip.getAttribute('tabindex')).toBe('12'); fixture.componentInstance.tabindex = 15; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chip.getAttribute('tabindex')).toBe('15'); @@ -112,6 +107,7 @@ describe('MDC-based MatChip', () => { // Force a destroy callback testComponent.shouldShow = false; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(testComponent.chipDestroy).toHaveBeenCalledTimes(1); @@ -121,6 +117,7 @@ describe('MDC-based MatChip', () => { expect(chipNativeElement.classList).toContain('mat-primary'); testComponent.color = 'warn'; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chipNativeElement.classList).not.toContain('mat-primary'); @@ -142,6 +139,7 @@ describe('MDC-based MatChip', () => { .toBe(false); testComponent.rippleDisabled = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chipInstance.ripple.disabled) @@ -155,6 +153,7 @@ describe('MDC-based MatChip', () => { .toBe(false); testComponent.disabled = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chipInstance.ripple.disabled) @@ -164,6 +163,7 @@ describe('MDC-based MatChip', () => { it('should make disabled chips non-focusable', () => { testComponent.disabled = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(primaryAction.hasAttribute('tabindex')).toBe(false); }); @@ -174,6 +174,7 @@ describe('MDC-based MatChip', () => { it('should return the chip value if defined', () => { fixture.componentInstance.value = 123; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chipInstance.value).toBe(123); @@ -181,6 +182,7 @@ describe('MDC-based MatChip', () => { it('should return the chip value if set to null', () => { fixture.componentInstance.value = null; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); expect(chipInstance.value).toBeNull(); diff --git a/src/material/chips/chip.ts b/src/material/chips/chip.ts index 71a677c59e91..57f6a1899241 100644 --- a/src/material/chips/chip.ts +++ b/src/material/chips/chip.ts @@ -244,7 +244,7 @@ export class MatChip implements OnInit, AfterViewInit, AfterContentInit, DoCheck */ _rippleLoader: MatRippleLoader = inject(MatRippleLoader); - private _injector = inject(Injector); + protected _injector = inject(Injector); constructor( public _changeDetectorRef: ChangeDetectorRef, diff --git a/src/material/chips/testing/chip-grid-harness.spec.ts b/src/material/chips/testing/chip-grid-harness.spec.ts index e99aad58915f..7751683e33b0 100644 --- a/src/material/chips/testing/chip-grid-harness.spec.ts +++ b/src/material/chips/testing/chip-grid-harness.spec.ts @@ -1,8 +1,8 @@ import {HarnessLoader, parallel} from '@angular/cdk/testing'; import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed'; -import {FormControl, ReactiveFormsModule, Validators} from '@angular/forms'; -import {Component, provideZoneChangeDetection} from '@angular/core'; +import {Component} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; +import {FormControl, ReactiveFormsModule, Validators} from '@angular/forms'; import {MatChipsModule} from '../index'; import {MatChipGridHarness} from './chip-grid-harness'; @@ -10,12 +10,6 @@ describe('MatChipGridHarness', () => { let fixture: ComponentFixture; let loader: HarnessLoader; - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [provideZoneChangeDetection()], - }); - }); - beforeEach(async () => { await TestBed.configureTestingModule({ imports: [MatChipsModule, ReactiveFormsModule, ChipGridHarnessTest], @@ -69,6 +63,7 @@ describe('MatChipGridHarness', () => { expect(await harness.isRequired()).toBe(false); fixture.componentInstance.required = true; + fixture.changeDetectorRef.markForCheck(); expect(await harness.isRequired()).toBe(true); }); @@ -88,6 +83,7 @@ describe('MatChipGridHarness', () => { const grid = await loader.getHarness(MatChipGridHarness); const chips = await grid.getRows(); fixture.componentInstance.firstChipEditable = true; + fixture.changeDetectorRef.markForCheck(); expect(await parallel(() => chips.map(chip => chip.isEditable()))).toEqual([ true, @@ -101,6 +97,7 @@ describe('MatChipGridHarness', () => { const chip = (await grid.getRows())[0]; let error: string | null = null; fixture.componentInstance.firstChipEditable = false; + fixture.changeDetectorRef.markForCheck(); try { await chip.startEditing(); @@ -115,6 +112,7 @@ describe('MatChipGridHarness', () => { const grid = await loader.getHarness(MatChipGridHarness); const chip = (await grid.getRows())[0]; fixture.componentInstance.firstChipEditable = true; + fixture.changeDetectorRef.markForCheck(); await chip.startEditing(); await (await chip.getEditInput()).setValue('new value'); diff --git a/src/material/chips/testing/chip-input-harness.spec.ts b/src/material/chips/testing/chip-input-harness.spec.ts index 41305dacda92..9b0e60d6e44d 100644 --- a/src/material/chips/testing/chip-input-harness.spec.ts +++ b/src/material/chips/testing/chip-input-harness.spec.ts @@ -1,7 +1,7 @@ -import {HarnessLoader, TestKey} from '@angular/cdk/testing'; import {COMMA} from '@angular/cdk/keycodes'; +import {HarnessLoader, TestKey} from '@angular/cdk/testing'; import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed'; -import {Component, provideZoneChangeDetection} from '@angular/core'; +import {Component} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {MatChipsModule} from '../index'; import {MatChipInputHarness} from './chip-input-harness'; @@ -10,12 +10,6 @@ describe('MatChipInputHarness', () => { let fixture: ComponentFixture; let loader: HarnessLoader; - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [provideZoneChangeDetection()], - }); - }); - beforeEach(async () => { await TestBed.configureTestingModule({ imports: [MatChipsModule, ChipInputHarnessTest], @@ -49,6 +43,7 @@ describe('MatChipInputHarness', () => { expect(await harness.isRequired()).toBe(false); fixture.componentInstance.required = true; + fixture.changeDetectorRef.markForCheck(); expect(await harness.isRequired()).toBe(true); }); diff --git a/src/material/chips/testing/chip-listbox-harness.spec.ts b/src/material/chips/testing/chip-listbox-harness.spec.ts index 2e3b0030f814..6c36fce9f32e 100644 --- a/src/material/chips/testing/chip-listbox-harness.spec.ts +++ b/src/material/chips/testing/chip-listbox-harness.spec.ts @@ -1,6 +1,6 @@ import {HarnessLoader, parallel} from '@angular/cdk/testing'; import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed'; -import {Component, provideZoneChangeDetection} from '@angular/core'; +import {Component} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {MatChipsModule} from '../index'; import {MatChipListboxHarness} from './chip-listbox-harness'; @@ -8,11 +8,6 @@ import {MatChipListboxHarness} from './chip-listbox-harness'; describe('MatChipListboxHarness', () => { let fixture: ComponentFixture; let loader: HarnessLoader; - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [provideZoneChangeDetection()], - }); - }); beforeEach(async () => { await TestBed.configureTestingModule({ @@ -39,6 +34,7 @@ describe('MatChipListboxHarness', () => { expect(await harness.isMultiple()).toBe(false); fixture.componentInstance.isMultiple = true; + fixture.changeDetectorRef.markForCheck(); expect(await harness.isMultiple()).toBe(true); }); @@ -49,6 +45,7 @@ describe('MatChipListboxHarness', () => { expect(disabledChips.length).toBe(0); fixture.componentInstance.disabled = true; + fixture.changeDetectorRef.markForCheck(); enabledChips = await loader.getAllHarnesses(MatChipListboxHarness.with({disabled: false})); disabledChips = await loader.getAllHarnesses(MatChipListboxHarness.with({disabled: true})); }); @@ -58,6 +55,7 @@ describe('MatChipListboxHarness', () => { expect(await harness.isDisabled()).toBe(false); fixture.componentInstance.disabled = true; + fixture.changeDetectorRef.markForCheck(); expect(await harness.isDisabled()).toBe(true); }); @@ -66,6 +64,7 @@ describe('MatChipListboxHarness', () => { expect(await harness.isRequired()).toBe(false); fixture.componentInstance.required = true; + fixture.changeDetectorRef.markForCheck(); expect(await harness.isRequired()).toBe(true); }); @@ -77,6 +76,7 @@ describe('MatChipListboxHarness', () => { it('should get selection in single-selection mode', async () => { fixture.componentInstance.options[0].selected = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); const harness = await loader.getHarness(MatChipListboxHarness); @@ -89,6 +89,7 @@ describe('MatChipListboxHarness', () => { fixture.componentInstance.isMultiple = true; fixture.componentInstance.options[0].selected = true; fixture.componentInstance.options[1].selected = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); const harness = await loader.getHarness(MatChipListboxHarness); @@ -100,6 +101,7 @@ describe('MatChipListboxHarness', () => { it('should be able to select specific options', async () => { fixture.componentInstance.isMultiple = true; + fixture.changeDetectorRef.markForCheck(); fixture.detectChanges(); const harness = await loader.getHarness(MatChipListboxHarness); diff --git a/src/material/chips/testing/chip-row-harness.spec.ts b/src/material/chips/testing/chip-row-harness.spec.ts index ab249204d007..489cd9a896cd 100644 --- a/src/material/chips/testing/chip-row-harness.spec.ts +++ b/src/material/chips/testing/chip-row-harness.spec.ts @@ -1,6 +1,6 @@ import {HarnessLoader} from '@angular/cdk/testing'; import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed'; -import {Component, signal, provideZoneChangeDetection} from '@angular/core'; +import {Component, signal} from '@angular/core'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {MatChipsModule} from '../index'; import {MatChipRowHarness} from './chip-row-harness'; @@ -12,7 +12,6 @@ describe('MatChipRowHarness', () => { beforeEach(async () => { await TestBed.configureTestingModule({ imports: [MatChipsModule, ChipRowHarnessTest], - providers: [provideZoneChangeDetection()], }).compileComponents(); fixture = TestBed.createComponent(ChipRowHarnessTest); diff --git a/tools/public_api_guard/material/chips.md b/tools/public_api_guard/material/chips.md index 66249e1a9678..2df6784c6b24 100644 --- a/tools/public_api_guard/material/chips.md +++ b/tools/public_api_guard/material/chips.md @@ -19,6 +19,7 @@ import { FormGroupDirective } from '@angular/forms'; import * as i0 from '@angular/core'; import * as i1 from '@angular/material/core'; import { InjectionToken } from '@angular/core'; +import { Injector } from '@angular/core'; import { MatFormField } from '@angular/material/form-field'; import { MatFormFieldControl } from '@angular/material/form-field'; import { MatRipple } from '@angular/material/core'; @@ -84,6 +85,8 @@ export class MatChip implements OnInit, AfterViewInit, AfterContentInit, DoCheck _hasTrailingIcon(): boolean; highlighted: boolean; id: string; + // (undocumented) + protected _injector: Injector; _isBasicChip: boolean; _isRippleDisabled(): boolean; leadingIcon: MatChipAvatar; @@ -169,7 +172,7 @@ export interface MatChipEvent { } // @public -export class MatChipGrid extends MatChipSet implements AfterContentInit, AfterViewInit, ControlValueAccessor, DoCheck, MatFormFieldControl, OnDestroy { +export class MatChipGrid extends MatChipSet implements AfterContentInit, AfterViewInit, ControlValueAccessor, DoCheck, MatFormFieldControl, OnDestroy, OnInit { constructor(elementRef: ElementRef, changeDetectorRef: ChangeDetectorRef, dir: Directionality, parentForm: NgForm, parentFormGroup: FormGroupDirective, defaultErrorStateMatcher: ErrorStateMatcher, ngControl: NgControl); protected _allowFocusEscape(): void; _blur(): void; @@ -208,6 +211,8 @@ export class MatChipGrid extends MatChipSet implements AfterContentInit, AfterVi ngDoCheck(): void; // (undocumented) ngOnDestroy(): void; + // (undocumented) + ngOnInit(): void; _onChange: (value: any) => void; onContainerClick(event: MouseEvent): void; _onTouched: () => void;