Tech stack:Angel V15和Cypress V12.
My example component that I'm testing:个
import { Component } from '@angular/core';
import { UserHttp } from '../../services';
@Component({
selector: 'example-view',
templateUrl: './example.component.html',
})
export class ExampleComponent {
constructor(
private userHttp: UserHttp,
) { }
}
My example component test个
import { HttpClientModule } from '@angular/common/http';
import { ExampleComponent } from './example.component';
import { UserHttp } from '../../services';
describe('Example component', () => {
beforeEach(() => {
cy.mount(ExampleComponent, {
providers: [UserHttp],
imports: [HttpClientModule]
});
});
it('should display default title', () => {
cy.get('h2').should('exist');
});
});
My UserHttp service that I'm injecting:个
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
@Injectable()
export class UserHttp {
test(): Observable<any> {
return of({});
}
}
Current status:个
The above test will fail if I leave the import as: import { Http } from '..';
But if I change it to this it works: import { Http } from './http';
我将其作为从‘..’导入的{http}的原因是因为我使用索引文件来导出所有服务,如下所示:
// index.ts: services:
import { UserHttp } from './http/user.http';
import { StorageService } from './storage.service';
export * from './http/user.http';
export * from './storage.service';
export const SERVICES = [
StorageService,
UserHttp,
];
My StorageService:个
import { Injectable } from '@angular/core';
import { environment } from '../../environments/environment';
@Injectable()
export class StorageService {
baseKey: string = environment.baseStorageKey;
constructor() {}
setLocalStorage(key: string, value: any): void {
this.removeLocalStorage(key);
localStorage.setItem(`${this.baseKey}${key}`, JSON.stringify(value));
}
getLocalStorage(key: string): any {
const item = localStorage.getItem(`${this.baseKey}${key}`);
return item !== null ? JSON.parse(item) : '';
}
removeLocalStorage(key: string): void {
localStorage.removeItem(`${this.baseKey}${key}`);
}
removeBatchLocalStorage(keys: string[]): void {
keys.forEach((key: string) => {
localStorage.removeItem(`${this.baseKey}${key}`);
});
}
}
This is my cypress config:个
import { defineConfig } from "cypress";
export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
chromeWebSecurity: false,
screenshotsFolder: "cypress/snapshots",
trashAssetsBeforeRuns: true,
viewportWidth: 1400,
viewportHeight: 1200,
video: false,
env: {
local: "http://localhost:4200/",
staging: "https://hidden.co.uk/",
user: {
email: "hidden",
password: "hidden",
},
},
component: {
devServer: {
framework: "angular",
bundler: "webpack",
},
specPattern: "**/*.cy.ts",
},
});
有没有办法将index.ts文件方法设置为在tsconfig或cypress配置中工作?
Current Error I get:个
TypeError
The following error originated from your test code, not from Cypress.
> Cannot read properties of undefined (reading 'StorageService')
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.
My TS Config file:个
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"forceConsistentCasingInFileNames": true,
"strict": false,
"strictPropertyInitialization": false,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"esModuleInterop": true,
"emitDecoratorMetadata": true,
"moduleResolution": "node",
"importHelpers": true,
"target": "es2020",
"module": "es2020",
"skipLibCheck": true,
"allowJs": true,
"types": [
"node"
],
"lib": [
"es2018",
"dom"
],
"paths": {
"@app/*": ["src/app/*"],
"@services/*": ["src/app/services/*"]
}
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": false,
"strictInputAccessModifiers": false,
"strictTemplates": false
}
}
My http.ts server that is extended by the userHttp service:个
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { environment } from '../../../environments/environment';
@Injectable()
export abstract class Http {
protected baseUrl = environment.baseUrl;
protected headers: HttpHeaders;
constructor(public httpClient: HttpClient) {}
protected get<T>(path: string, options: any = {}, noBaseUrl = false): Observable<T> {
const url: string = this.createUrlString(path, noBaseUrl);
const params: HttpParams = this.getHttpParams(options.queryString);
return this.httpClient.get<T>(url, { params });
}
protected post<T>(path: string, data = {}, noBaseUrl = false): Observable<T> {
const url: string = this.createUrlString(path, noBaseUrl);
const options = { headers: this.headers };
return this.httpClient.post<T>(url, { ...data, lang: 'uk' }, options);
}
protected createUrlString(resourcePath: string, noBaseUrl: boolean): string {
return noBaseUrl ? `${resourcePath}` : `${this.baseUrl}${resourcePath}`;
}
protected getHttpParams(params: any): HttpParams {
let httpParams: HttpParams = new HttpParams();
if (params) {
for (const prop in params) {
if (params.hasOwnProperty(prop)) {
const parameterValue: string = params[prop].toString();
httpParams = httpParams.append(prop, parameterValue);
}
}
}
return httpParams;
}
}
Gui error message个