Вопрос или проблема
Я тестирую компонент в своем приложении Angular v15. Пока что только один тест не прошел, мой тест снимка:
describe('Снимок', () => {
it('базовый', waitForAsync(() => {
fixture.detectChanges();
expect(fixture).toMatchSnapshot();
}));
});
Все остальные тесты проходят. Ошибка, которую я получаю, следующая:
TypeError: Невозможно прочитать свойства неопределенного (чтение 'value')
в <ИмяКомпонента>_Шаблон (ng:/<ИмяКомпонента>.js:360:65)
в executeTemplate (node_modules/@angular/core/fesm2020/core.mjs:10441:9)
в refreshView (node_modules/@angular/core/fesm2020/core.mjs:10326:13)
в refreshComponent (node_modules/@angular/core/fesm2020/core.mjs:11385:13)
в refreshChildComponents (node_modules/@angular/core/fesm2020/core.mjs:10116:9)
в refreshView (node_modules/@angular/core/fesm2020/core.mjs:10376:13)
в detectChangesInternal (node_modules/@angular/core/fesm2020/core.mjs:11529:9)
в RootViewRef.detectChanges (node_modules/@angular/core/fesm2020/core.mjs:12020:9)
в ComponentFixture._tick (node_modules/@angular/core/fesm2020/testing.mjs:126:32)
в node_modules/@angular/core/fesm2020/testing.mjs:139:22
в _ZoneDelegate.Object.<анонимный>._ZoneDelegate.invoke (node_modules/zone.js/dist/zone-node.js:400:30)
в AsyncTestZoneSpec.Object.<анонимный>.AsyncTestZoneSpec.onInvoke (node_modules/zone.js/dist/async-test.js:127:47)
в ProxyZoneSpec.Object.<анонимный>.ProxyZoneSpec.onInvoke (node_modules/zone.js/dist/proxy.js:123:43)
в _ZoneDelegate.Object.<анонимный>._ZoneDelegate.invoke (node_modules/zone.js/dist/zone-node.js:399:56)
в Object.onInvoke (node_modules/@angular/core/fesm2020/core.mjs:24210:33)
в _ZoneDelegate.Object.<анонимный>._ZoneDelegate.invoke (node_modules/zone.js/dist/zone-node.js:399:56)
в Zone.Object.<анонимный>.Zone.run (node_modules/zone.js/dist/zone-node.js:160:47)
в NgZone.run (node_modules/@angular/core/fesm2020/core.mjs:24064:28)
в ComponentFixture.detectChanges (node_modules/@angular/core/fesm2020/testing.mjs:138:25)
в src/modules/action-template/media-type-form/<ИмяКомпонента>/<ИмяКомпонента>.component.spec.ts:685:15
в _ZoneDelegate.Object.<анонимный>._ZoneDelegate.invoke (node_modules/zone.js/dist/zone-node.js:400:30)
в AsyncTestZoneSpec.Object.<анонимный>.AsyncTestZoneSpec.onInvoke (node_modules/zone.js/dist/async-test.js:127:47)
в ProxyZoneSpec.Object.<анонимный>.ProxyZoneSpec.onInvoke (node_modules/zone.js/dist/proxy.js:123:43)
в _ZoneDelegate.Object.<анонимный>._ZoneDelegate.invoke (node_modules/zone.js/dist/zone-node.js:399:56)
в Zone.Object.<анонимный>.Zone.runGuarded (node_modules/zone.js/dist/zone-node.js:171:51)
в runInTestZone (node_modules/zone.js/dist/async-test.js:272:33)
в node_modules/zone.js/dist/async-test.js:223:21
в новом ZoneAwarePromise (node_modules/zone.js/dist/zone-node.js:1270:25)
в node_modules/zone.js/dist/async-test.js:222:24
в _ZoneDelegate.Object.<анонимный>._ZoneDelegate.invoke (node_modules/zone.js/dist/zone-node.js:400:30)
в ProxyZoneSpec.Object.<анонимный>.ProxyZoneSpec.onInvoke (node_modules/zone.js/dist/proxy.js:126:43)
в _ZoneDelegate.Object.<анонимный>._ZoneDelegate.invoke (node_modules/zone.js/dist/zone-node.js:399:56)
в Zone.Object.<анонимный>.Zone.run (node_modules/zone.js/dist/zone-node.js:160:47)
в Object.<анонимный> (node_modules/jest-zone-patch/index.js:50:27)
HTML использует formGroup, названный form
, чтобы его можно было ссылаться как this.form.value.<formControlName>
.
Поскольку журнал ошибок очень неинформативен, я не знаю, где искать решение. Страница работает прекрасно, ошибок нет. Только тесты не проходят.
Фрагмент HTML:
<CompanyCustomTextInput label-position="above">
<label slot="label" for="title-input">{{'TITLE' | translate}}</label>
<input
slot="input"
type="text"
class="text-input"
id="title-input"
placeholder="{{'TITLE_PLACEHOLDER' | translate}}"
formControlName="title"
[maxlength]="maxLengthTitle"
/>
</CompanyCustomTextInput>
Есть еще более вводов разного и одинакового типа, но все они следуют этому шаблону.
Я пытался удалить все this.form.value
из полей ввода, пытался изменить formControlName
. Без успеха.
Ответ или решение
Ошибка "Cannot read properties of undefined (reading ‘value’)" во время выполнения теста snapshot в вашем приложении на Angular v15 может быть вызвана рядом факторов, связанных с конфигурацией ваших форм и их состоянием при запуске тестов. В этом ответе мы подробно рассмотрим возможные причины и решения данной проблемы.
1. Проверка инициализации FormGroup
Убедитесь, что ваш FormGroup
корректно инициализирован до того, как вызывается fixture.detectChanges()
. Часто эта ошибка возникает, если form
не инициализирован и остается undefined
, когда компоненты пытаются получить доступ к его свойствам.
Пример корректной инициализации FormGroup
может выглядеть так:
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms';
import { ComponentName } from './component-name.component';
describe('ComponentName', () => {
let component: ComponentName;
let fixture: ComponentFixture<ComponentName>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [ReactiveFormsModule],
declarations: [ComponentName]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ComponentName);
component = fixture.componentInstance;
component.form = new FormGroup({
title: new FormControl('')
// другие элементы формы
});
fixture.detectChanges();
});
it('basic', () => {
expect(fixture).toMatchSnapshot();
});
});
2. Актуализация значений формы
Перед выполнением теста убедитесь, что все значения для элементов вашей формы установлены:
component.form.get('title').setValue('Тестовое значение');
Таким образом, вы можете устранить возможность появления ошибок при попытке чтения значений из undefined
.
3. Проверка HTML-шаблона
Убедитесь, что правильно указан formControlName
для каждого элемента в вашем HTML и что эти контроллеры существуют в FormGroup
. В вашем HTML-коде:
<CompanyCustomTextInput label-position="above">
<label slot="label" for="title-input">{{'TITLE' | translate}}</label>
<input
slot="input"
type="text"
class="text-input"
id="title-input"
placeholder="{{'TITLE_PLACEHOLDER' | translate}}"
formControlName="title"
[maxlength]="maxLengthTitle"
/>
</CompanyCustomTextInput>
Убедитесь, что formControlName="title"
соответствует ключу в вашем FormGroup
.
4. Взаимодействие с асинхронными действиями
Если ваша форма или её элементы зависят от каких-либо асинхронных действий (например, загрузка данных), может потребоваться использование fakeAsync
и tick()
, чтобы убедиться, что все асинхронные операции завершились до выполнения теста.
5. Отладка
В случае продолжения проблемы используйте инструменты отладки, такие как console.log()
, чтобы вывести текущее состояние form
и его контроллеров перед выполнением fixture.detectChanges()
:
console.log(this.form);
Это поможет вам увидеть, загружены ли данные потенциально неправильно, или у вас просто проблема с доступом к свойствам.
Заключение
Проблема "Cannot read properties of undefined (reading ‘value’)" может возникнуть по множеству причин, но основные шаги, которые следует предпринимать, включают в себя правильную инициализацию FormGroup
, актуализацию значений формы и тщательную проверку HTML-шаблона. Применение вышеперечисленных рекомендаций должно помочь в устранении ошибки и успешном выполнении ваших snapshot-тестов. Если проблема сохраняется, рассмотрите возможность более глубокого анализа конфигурации вашего компонента и форм.