I am trying to run spec for my Angular component using Cypress. But I've got the following error in Cypress logs:
The following error originated from your test code, not from Cypress.
> Cannot access 'TextsFilterComponent' before initialization
When Cypress detects uncaught errors originating from your test code it will automatically fail the current test.
Cypress could not associate this error to any specific test.
We dynamically generated a new test to display this failure.
View stack trace
Print to console
at Module.TextsFilterComponent (http://localhost:8080/__cypress/src/spec-1.js:80491:69)
at 36283 (webpack://angular/./src/app/shared/components/games/texts-filter/texts-filter.module.ts:12:17)
at __webpack_require__ (http://localhost:8080/__cypress/src/runtime.js:23:42)
at 70275 (http://localhost:8080/__cypress/src/spec-1.js:80476:78)
at __webpack_require__ (http://localhost:8080/__cypress/src/runtime.js:23:42)
at 44549 (http://localhost:8080/__cypress/src/spec-1.js:80241:78)
at __webpack_require__ (http://localhost:8080/__cypress/src/runtime.js:23:42)
at 37511 (http://localhost:8080/__cypress/src/spec-1.js:79929:69)
at __webpack_require__ (http://localhost:8080/__cypress/src/runtime.js:23:42)
at 67953 (http://localhost:8080/__cypress/src/spec-1.js:27564:82)
at __webpack_require__ (http://localhost:8080/__cypress/src/runtime.js:23:42)
at 70111 (http://localhost:8080/__cypress/src/spec-1.js:26774:74)
at __webpack_require__ (http://localhost:8080/__cypress/src/runtime.js:23:42)
at 12063 (http://localhost:8080/__cypress/src/spec-1.js:17404:67)
at __webpack_require__ (http://localhost:808
My spec looks like this:
import { CommonModule } from '@angular/common';
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { NgSelectModule } from '@ng-select/ng-select';
import { TranslateModule } from '@ngx-translate/core';
import { FormFieldModule } from '../form-field/form-field.module';
import { TextsFilterComponent } from './texts-filter.component';
import { TextsFilterModule } from './texts-filter.module';
import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import {
ChangeDetectorRef, EventEmitter,
} from '@angular/core';
import { TextsService, SyllablesService, WordsService } from '../../../../core/services/games';
import { AuthService } from '../../../../core/services';
it('mounts', () => {
cy.mount(TextsFilterComponent, {
imports: [
TextsFilterModule,
CommonModule,
FormFieldModule,
FormsModule,
ReactiveFormsModule,
NgSelectModule,
TranslateModule,
MatInputModule,
MatSelectModule,
],
providers: [
TextsService,
ChangeDetectorRef,
AuthService,
WordsService,
SyllablesService,
],
componentProperties: {
parametersForm: new FormGroup({
test: new FormControl('x'),
}),
hasError: new EventEmitter(),
customMinItems: 1,
},
});
});
My spec is in the same folder with component, so all imports are correct.
I've placed all services injected to my component in the providers
. And all imports from module to imports
. Also I passed some values for 2 inputs and 1 output of the component in the componentProperties
section.
Componennt's module:
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { NgSelectModule } from '@ng-select/ng-select';
import { TranslateModule } from '@ngx-translate/core';
import { FormFieldModule } from '../form-field/form-field.module';
import { TextsFilterComponent } from './texts-filter.component';
import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
@NgModule({
declarations: [TextsFilterComponent],
exports: [TextsFilterComponent],
imports: [
CommonModule,
FormFieldModule,
FormsModule,
ReactiveFormsModule,
NgSelectModule,
TranslateModule,
MatInputModule,
MatSelectModule,
],
})
export class TextsFilterModule {}
And my component:
// ...
@Component({
selector: 'texts-filter',
templateUrl: './texts-filter.component.html',
styleUrls: ['./texts-filter.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class TextsFilterComponent
extends AbstractFiltersMixin(BaseFilters)
implements OnDestroy, AfterViewInit, OnChanges {
constructor(
private _textsService: TextsService,
private _cdr: ChangeDetectorRef,
private _authService: AuthService,
private _wordsService: WordsService,
private _syllablesService: SyllablesService,
) {
super();
}
// ...
}
And my cypress/support/component.ts
:
import { mount } from 'cypress/angular'
declare global {
namespace Cypress {
interface Chainable {
mount: typeof mount
}
}
}
Cypress.Commands.add('mount', mount)
The main problem was in
index.ts
file. I've used them to export all services from the folder to simplify imports:index.ts
But this approach leads to circullar dependencies.
The best solution is to get ride of
index.ts
and import each service from it's file.But in my case I have already had thousands of imports and I didn't want to fix all of them. So, I found another solution that helped my Jasmine and Cypress tests run.
I've added
"emitDecoratorMetadata": false
property totsconfig.json
and error disappeared!tsconfig.json