我最近用 jest 添加了基本单元测试,现在由于某种原因,当我使用“ng serve”运行 angular 应用程序时,我的 mat-icons 显示为,并且我的 HttpClient 调用我的后端不会返回任何响应。我订阅了 observable,甚至尝试用 .pipe(finalize()) 捕获空的 observable,没有响应,并且网络没有显示任何正在发出的请求。运行 ng serve 的终端也没有显示任何错误。
我可以确认,当我通过节点服务器构建和提供文件以进行生产时(我知道我应该使用 ngnx),一切都按预期工作。后端 api 也正确响应邮递员和终端 curl 调用。
我觉得这与我如何配置 jest 或我在配置文件中搞砸的东西有关,但我似乎无法弄清楚。我也不知道这个 svg class="fake-testing-svg" 是如何被注入到 html 中的,因为我在代码中的任何地方都找不到它。
登录组件.ts
authenticateUser() : void {
// Retrieve core id and passsword from login form
let user_core_id = this.loginForm.value.user_core_id,
password = this.loginForm.value.password;
console.log("calling login service......");
this.loginService.adAuth(user_core_id, password)
.pipe(finalize(() => console.log('complete!')))
.subscribe(res => {
console.log("got a response from login service subscription......");
// Check if there was an error authenticating the user in the db
if(res.error) {
this.alertService.error("Invalid Credentials");
console.log("AD Authentication error: " + JSON.stringify(res));
}
else {
// User is authenticated in the AD
// cache user_core_id, user_display name and user AD base_dn
console.log(res.core_id + " is authenticated in the AD");
localStorage.setItem('user_core_id', res.core_id.toUpperCase());
localStorage.setItem('user_display_name', res.display_name );
localStorage.setItem('user_dn', res.base);
// Grab user data from the AD callback and send it to the db
let user_object = res;
// Update the user in the db
this.getIsAdmin(user_object);
}
},
err => {
// Error authenticating user against the AD
this.alertService.error("Invalid Credentials");
console.log("AD Auth error: " + JSON.stringify(err));
});
登录服务.ts
adAuth(user_core_id: string, password: string) : Observable<any> {
console.log("made it to the login service adAuth() method....");
let body = {
user_core_id: user_core_id,
password: password
}
return this.http.post<any>(`${environment.adApiUrl}/auth/user`, body);
}
server.js(不应影响 ng serve)
const express = require('express'),
bodyParser = require('body-parser'),
path = require('path'),
cors = require('cors'),
fs = require('fs');
// Set up express middleware, json parser, cors
const app = express();
app.use(bodyParser.json());
app.use(cors());
// For reading env variables
require('dotenv').config();
var staticRoot = __dirname + '/';
console.log("env: " + process.env.NODE_ENV);
if(process.env.NODE_ENV == 'production') {
app.use(express.static(path.join(staticRoot, 'dist/toolsportal-client-build-prod')));
app.use(function(req, res, next) {
// if the request is not html then move along
var accept = req.accepts('html', 'json', 'xml');
if(accept !== 'html') {
return next();
}
// if the request has a '.' assume that it's for a file, move along
var ext = path.extname(req.path);
if(ext !== '') {
return next();
}
fs.createReadStream(staticRoot + 'dist/toolsportal-client-build-prod/index.html').pipe(res);
});
}
const PORT = process.env.NODE_PORT || 3001;
app.listen(PORT, "0.0.0.0", function () {
console.log('SERVER RUNNING ON PORT:' + PORT)
});
// Kubernetes pod readiness/liveness probe
app.use('/kube/healthy', (req, res) => {
res.status(200).json({ healthy: true });
});
// Kubernetes pod readiness/liveness probe (backup)
app.get('/', (req, res) => {
res.status(200).json({ healthy: true });
});
// Catch errors
app.on('error', (error) => {
console.log("error: " + error);
});
process.on('uncaughtException', (error) => {
console.log("uncaughtException error: " + error);
});
角.json
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"toolsportal-client": {
"projectType": "application",
"schematics": {},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "src/api/dist/toolsportal-client-build-prod",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": true,
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
"src/styles.css",
"node_modules/bootstrap/dist/css/bootstrap.min.css"
],
"scripts": [
"node_modules/jquery/dist/jquery.min.js",
"node_modules/popper.js/dist/umd/popper.min.js",
"node_modules/bootstrap/dist/js/bootstrap.js",
"node_modules/hammerjs/hammer.min.js"
]
},
"configurations": {
"qa": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.qa.ts"
}
]
},
"dev": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.dev.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": false,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "toolsportal-client:build"
},
"configurations": {
"production": {
"browserTarget": "toolsportal-client:build:production"
},
"dev": {
"browserTarget": "toolsportal-client:build:dev"
},
"qa": {
"browserTarget": "toolsportal-client:build:qa"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "toolsportal-client:build"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json",
"e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "toolsportal-client:serve"
},
"configurations": {
"production": {
"devServerTarget": "toolsportal-client:serve:production"
}
}
}
}
}
},
"defaultProject": "toolsportal-client",
"cli": {
"analytics": "0db305fd-b474-49d5-a4ec-95ceec1c2bcf"
}
}
jest.config.js
const { pathsToModuleNameMapper } = require('ts-jest/utils');
const { compilerOptions } = require('./tsconfig');
module.exports = {
preset: 'jest-preset-angular',
roots: ['<rootDir>/src/'],
testMatch: ['**/+(*.)+(spec).+(ts)'],
setupFilesAfterEnv: ['<rootDir>/src/test.ts'],
collectCoverage: true,
coverageReporters: ['html'],
coverageDirectory: 'coverage/my-app',
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths || {}, {
prefix: '<rootDir>/'
})
};
tsconfig.json
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"module": "esnext",
"moduleResolution": "node",
"importHelpers": true,
"target": "es2015",
"lib": [
"es2018",
"dom"
],
"types": [
"jquery",
"bootstrap",
"node",
"jest"
]
},
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true
}
}
tsconfig.app.json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": []
},
"files": [
"src/main.ts",
"src/polyfills.ts"
],
"include": [
"src/**/*.d.ts"
],
"angularCompilerOptions": {
"enableIvy": false
}
}
包.json
{
"name": "toolsportal-client",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"serve-dev": "ng serve -c=dev --port=4201",
"serve-qa": "ng serve -c=qa --port=4202",
"start-node-log": "node src/api/server.js > src/api/app.log 2>&1",
"start-node": "node src/api/server.js",
"start-nodemon": "nodemon src/api/server.js",
"build": "ng build",
"build-prod": "ng build --prod",
"test": "jest",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "^9.1.12",
"@angular/cdk": "^9.2.4",
"@angular/common": "^9.1.12",
"@angular/compiler": "^9.1.12",
"@angular/core": "^9.1.12",
"@angular/forms": "^9.1.12",
"@angular/localize": "^9.1.12",
"@angular/material": "^9.2.4",
"@angular/platform-browser": "^9.1.12",
"@angular/platform-browser-dynamic": "^9.1.12",
"@angular/router": "^9.1.12",
"@kolkov/angular-editor": "^1.1.2",
"@ng-bootstrap/ng-bootstrap": "^6.2.0",
"@types/bootstrap": "^4.5.0",
"@types/jquery": "^3.5.0",
"body-parser": "^1.19.0",
"bootstrap": "^4.5.0",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"hammerjs": "^2.0.8",
"jira-connector": "^3.1.0",
"jquery": "^3.4.1",
"jsonwebtoken": "^8.5.1",
"jwt-decode": "^2.2.0",
"ldapjs": "^1.0.2",
"mongoose": "^5.9.24",
"node-rest-client": "^3.1.0",
"popper": "^1.0.1",
"popper.js": "^1.16.0",
"rxjs": "~6.5.5",
"rxjs-compat": "^6.6.0",
"tslib": "^1.13.0",
"zone.js": "~0.10.3"
},
"devDependencies": {
"@angular-devkit/build-angular": "^0.901.11",
"@angular/cli": "^9.1.11",
"@angular/compiler-cli": "^9.1.12",
"@angular/language-service": "^9.1.12",
"@types/jasmine": "^3.5.11",
"@types/jasminewd2": "^2.0.8",
"@types/jest": "^25.2.3",
"@types/node": "^13.13.14",
"codelyzer": "^5.2.2",
"jasmine-core": "~3.5.0",
"jasmine-spec-reporter": "~5.0.1",
"jest": "^26.1.0",
"jest-preset-angular": "^8.2.1",
"nodemon": "^2.0.4",
"protractor": "~5.4.3",
"ts-node": "~8.8.2",
"tslint": "~6.1.1",
"typescript": "~3.8.3"
}
}