簡體   English   中英

TypeError:您在需要 stream 的地方提供了“未定義”。 部署angular時可以提供Observable、Promise、Array或Iterable

[英]TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable when deploying angular

三天多來我一直在努力解決這個問題,但我無法確定錯誤的原因。 當我使用 ng 測試在 vscode 上本地運行它們時,我的所有測試用例都成功通過,但在使用 Jenkins 部署 angular 應用程序時失敗。只有當我有一個用於下面描述的組件的測試用例時,它才會失敗。 如果我刪除下面組件的規范文件,則應用程序會成功部署。

這是我的 component.ts

import { formatDate } from '@angular/common';
import { ChangeDetectorRef, Component, Inject, LOCALE_ID, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MatPaginator, PageEvent } from '@angular/material/paginator';
import { MatTableDataSource } from '@angular/material/table';
import { ActivatedRoute } from '@angular/router';
import { AuthService } from '@app/core/services/auth/auth.service';
import { DistributionsConstants } from '@app/distributions/distributions.constant';
import { ChangeType, ConsolidateModel, Rate, ResponseRateModel } from '@app/distributions/models/consolidateRate.model';
import { ResolveTermLoanService } from '@app/distributions/services/resolve/resolve-term-loan.service';
import { FidBaseComponent } from '@app/shared/components/base/fid.base';
import { DialogType } from '@app/shared/models/dialog.model';
import { NotificationType } from '@app/shared/models/notification-message';
import { TableColumn } from '@app/shared/models/table-column';
import { DialogService } from '@app/shared/services/dialog/dialog.service';
import { NotificationService } from '@app/shared/services/notification/notification.service';
import { takeUntil } from 'rxjs/operators';

@Component({
  selector: 'fid-resolve-term-loan',
  templateUrl: './resolve-term-loan.component.html',
  styleUrls: ['./resolve-term-loan.component.scss'],
})
export class ResolveTermLoanComponent extends FidBaseComponent implements OnInit {
  tableColumns: TableColumn[];
  noRecordsFoundText = 'No Records Found';
  tableColumns1: TableColumn[];
  @ViewChild('paginator') paginator: MatPaginator;
  @ViewChild('actionsTemplate', { static: true }) actionsTempRef: TemplateRef<any>;
  @ViewChild('commentTemplate', { static: true }) commentTempRef: TemplateRef<any>;
  @ViewChild('radioTemplate', { static: true }) radioTempRef: TemplateRef<any>;
  resolveIssuesForm: FormGroup;
  changeType = ChangeType;
  loansOfLoans: any;
  pageMetaData = DistributionsConstants.RESOLVE_TERM_LOAN_META_DATA;
  reviewType: string;
  resetId: string;
  readonly: boolean;
  consolidateModeldata: ConsolidateModel;
  filter: any;
  responseRateModeldata: ResponseRateModel = {
    resolveComments: '',
      selectedId: '',
      cusip: '',
      manualRate: null,
      manualDate: '',
      version: 0,
      resetId: 0,
      id: '',
      filter: {
        pageNum: 0,
        max: 0,
      },
  };
  dataSource: any;
  totalRows = 0;
  pageSize = 5;
  currentPage = 0;
  manualEntryDisabled = true;
  pageSizeOptions: number[] = [1, 5, 10, 20, 30, 50, 100];
  errMsgs: string = '';

  displayedColumns: string[] = ['loanNameAndSecurity', 'childTable', 'comments', 'action'];

  private manualRateValidators = [Validators.pattern(/^\d*\.?\d*$/)];

  private manualDateValidators = [Validators.pattern(/^\d{2}[/]\d{2}[/]\d{4}$/)];

  parentTableData: Rate[] = [];

  constructor(
    private activatedRoute: ActivatedRoute,
    private authService: AuthService,
    private notifyService: NotificationService,
    private resolveTermLoanService: ResolveTermLoanService,
    private dialogService: DialogService,
    private cd: ChangeDetectorRef,
    private fb: FormBuilder,
    @Inject(LOCALE_ID) public locale: string
  ) {
    super();
  }
  ngAfterViewInit() {
    this.dataSource = new MatTableDataSource(this.parentTableData);
    this.cd.detectChanges();
    this.dataSource.paginator = this.paginator;
  }

  ngOnInit(): void {
    this.resolveIssuesForm = this.fb.group({
      resolveRadio: [[''], [Validators.required]],
      manualRate: [{ value: '', disabled: this.manualEntryDisabled }, this.manualRateValidators],
      manualDate: [{ value: '', disabled: this.manualEntryDisabled }, this.manualDateValidators],
      comments: [[''], [Validators.required]],
    });

    this.authService.canAccess.subscribe((x) => {
      this.readonly = !x;
      console.log("x",x);
    });

    // this.consolidateModeldata = this.activatedRoute.snapshot.data[
    //   DistributionsConstants.RESOLVE_TERM_LOAN_META_DATA.resolver
    // ];

    this.activatedRoute.queryParamMap.subscribe((res) => {
      console.log("res",res);
      this.resetId = res.get('id');
      this.filter = {
        pageNum: this.currentPage,
        max: this.pageSize,
      };
      this.ResolveTermLoanRate(this.filter);
    });
    this.buildTableColumns();

    this.formChanges();
  }

  formChanges() {
    this.resolveIssuesForm.get('resolveRadio').valueChanges.subscribe((x) => {
      console.log("x form",x);
      if (x == 'on') {
        this.resolveIssuesForm.get('manualRate').setValidators(this.manualRateValidators.concat(Validators.required));
        this.resolveIssuesForm.get('manualDate').setValidators(this.manualDateValidators.concat(Validators.required));
        this.resolveIssuesForm.controls['manualRate'].enable();
        this.resolveIssuesForm.controls['manualDate'].enable();
      } else {
        this.resolveIssuesForm.get('manualRate').setValidators(this.manualRateValidators);
        this.resolveIssuesForm.get('manualDate').setValidators(this.manualDateValidators);
        this.resolveIssuesForm.controls['manualRate'].disable();
        this.resolveIssuesForm.controls['manualDate'].disable();
      }
    });
  }

  ResolveTermLoanRate(filter: any){
    this.resolveTermLoanService
      .getResolveTermLoan(parseInt(this.resetId), filter)
      .pipe(takeUntil(this.$ngUnsubscribe))
      .subscribe((res) => {
        this.consolidateModeldata = res;
        this.parentTableData = res.rates;
        this.totalRows = res.total;
        this.dataSource = new MatTableDataSource(this.parentTableData);
        console.log("ResolveTermLoanRate ",res);
      });
  }

  resolveIssueRates(element) {
    this.responseRateModeldata.cusip = element.securityNumber;
        this.responseRateModeldata.version = element.version;
        this.responseRateModeldata.id = element.termLoanRateId;
    this.resolveTermLoanService
      .postResolveIssue(this.responseRateModeldata)
      .pipe(takeUntil(this.$ngUnsubscribe))
      .subscribe(
        (res) => {
          this.consolidateModeldata = res;
          this.ResolveTermLoanRate(this.filter);
          this.notifyService.notifyUser({ message: 'Saved Successfully', notificationType: NotificationType.SUCCESS });
          this.responseRateModeldata = {
            resolveComments: '',
              selectedId: '',
              cusip: '',
              manualRate: null,
              manualDate: '',
              version: 0,
              resetId: 0,
              id: '',
              filter: {
                pageNum: 0,
                max: 0,
              },
          }
          this.resolveIssuesForm.reset();
        },
        (err) => {
          this.ResolveTermLoanRate(this.filter);
          this.dialogService.openDialog({
            type: DialogType.ALERT,
            data: { data: { alertMessage: err.error.errors ? err.error.errors : err.message } },
          });
          this.responseRateModeldata = {
            resolveComments: '',
              selectedId: '',
              cusip: '',
              manualRate: null,
              manualDate: '',
              version: 0,
              resetId: 0,
              id: '',
              filter: {
                pageNum: 0,
                max: 0,
              },
          }
          this.resolveIssuesForm.reset();
        }
      );
  }

  pageChanged(event: PageEvent) {
    this.pageSize = event.pageSize;
    this.currentPage = event.pageIndex;
    this.filter = {
      pageNum: this.currentPage,
      max: this.pageSize,
    };
    this.ResolveTermLoanRate(this.filter);
  }

  buildTableColumns() {
    this.tableColumns = [
      { name: 'Account', dataKey: 'portfolioAbbreviation', isSortable: true, template: this.radioTempRef },
      { name: 'Current Rate', dataKey: 'currentDayRateForRateReset', isSortable: true },
      { name: 'Current From Date', dataKey: 'wacStartDate', isSortable: true },
      { name: 'Settled Shares', dataKey: 'settledPartialQuantity', isSortable: true },
      { name: 'Missing Rollover', dataKey: 'missingRollover', isSortable: true },
    ];
  }

  changeData(dataItem: any, resetId: any, target: any, type: ChangeType) {
    this.responseRateModeldata.resetId = resetId;
    this.responseRateModeldata.filter = {
      pageNum: this.filter.pageNum,
      max: this.filter.max,
    }
    switch (type) {
      case ChangeType.Auto:
        this.manualEntryDisabled = false;
        this.responseRateModeldata.selectedId = dataItem['termLoanId'];
        this.responseRateModeldata.manualRate = dataItem['currentDayRateForRateReset'];
        this.responseRateModeldata.manualDate = dataItem['wacStartDate'] ? formatDate(dataItem['wacStartDate'], 'yyyy-MM-dd', this.locale) : '';
        break;
      case ChangeType.Manual:
        this.manualEntryDisabled = true;
        this.responseRateModeldata.selectedId = 'manual';
        break;
      case ChangeType.CurrentRate:
        this.responseRateModeldata.manualRate = +target.value;
        break;
      case ChangeType.CurrentFromDate:
        this.responseRateModeldata.manualDate = target.value;
        break;
      case ChangeType.Comments:
        this.responseRateModeldata.resolveComments = target.value;
        break;
    }
  }
}

這是我的 html:

<div class="content container-fluid">
  <!-- page header -->
  <div class="page-header">
    <div class="row">
      <div class="col-sm-6 mb-2 mb-sm-0">
        <nav aria-label="breadcrumb" class="page-breadcrumb">
          <ol class="breadcrumb breadcrumb-no-gutter">
            <li class="breadcrumb-item"><a class="breadcrumb-link" aria-current="page">Distributions</a></li>
            <li class="breadcrumb-item">
              <a class="breadcrumb-link" routerLink="/distributions/rate-reset-dashboard">Rate Reset Dashboard</a>
            </li>
            <li class="breadcrumb-item active" aria-current="page">Resolve Termloan Rate</li>
          </ol>
        </nav>
      </div>
    </div>
    <div class="row align-items-sm-center pr-3 justify-content-between">
      <h4 class="page-header-title mb-0 ml-3">{{ pageMetaData?.pageTitle }}</h4>
    </div>
  </div>
  <!-- no issues -->
  <ng-container *ngIf="!consolidateModeldata?.rates?.length">No Rate in Issue state.</ng-container>
  <!-- parent table -->
  <table mat-table [dataSource]="dataSource" class="col-lg-12">
    <form [formGroup]="resolveIssuesForm">
      <ng-container matColumnDef="loanNameAndSecurity">
        <th mat-header-cell *matHeaderCellDef></th>
        <td mat-cell *matCellDef="let element" class="page-header-title mb-0 ml-3">
          <b>
            {{ element.loanName }} <br />
            ({{ element.securityNumber }})
          </b>
        </td>
      </ng-container>
      <ng-container matColumnDef="childTable">
        <td mat-cell *matCellDef="let element">
          <!-- child table -->
          <fid-material-table
            [tableColumns]="tableColumns"
            [noRecordsFoundText]="noRecordsFoundText"
            [tableData]="element.loans"
          >
          </fid-material-table>
          <div class="col-lg-12">
            <div class="manual">
              <div class="">
                <mat-radio-button
                  [value]="manual"
                  formControlName="resolveRadio"
                  ngDefaultControl
                  (change)="changeData(dataItem, resetId, $event.target, changeType.Manual)"
                >
                  <span class="textmsg">Manual Entry</span>
                </mat-radio-button>
              </div>
              <div>
                <input
                  matInput
                  [value]=""
                  class="inputtext"
                  type="number"
                  formControlName="manualRate"
                  (change)="changeData(dataItem, resetId, $event.target, changeType.CurrentRate)"
                />
              </div>
              <div class="date-container">
                <input
                  type="date"
                  matInput
                  formControlName="manualDate"
                  class="inputtext"
                  [value]=""
                  (change)="changeData(dataItem, resetId, $event.target, changeType.CurrentFromDate)"
                />
              </div>
            </div>
          </div>
        </td>
      </ng-container>
      <ng-container matColumnDef="comments">
        <td mat-cell *matCellDef="let element">
          <mat-form-field class="textInput" appearance="outline">
            <textarea
              matInput
              [name]="element.termLoanRateId"
              [value]="responseRateModeldata?.resolveComments"
              rows="2"
              cols="30"
              formControlName="comments"
              (change)="changeData(dataItem, resetId, $event.target, changeType.Comments)"
            ></textarea>
          </mat-form-field>
        </td>
      </ng-container>
      <ng-container matColumnDef="action">
        <td mat-cell *matCellDef="let element">
          <button type="submit" form="ngForm" (click)="resolveIssueRates(element)" class="fid-btn">Resolve Issues</button>
        </td>
      </ng-container>
      <ng-template #radioTemplate let-dataItem>
        <mat-radio-button
          *ngIf="dataItem['eligibleForRateSelectionOnUi'] == true"
          class="mr-3"
          [value]="dataItem['portfolioAbbreviation']"
          formControlName="resolveRadio"
          ngDefaultControl
          (change)="changeData(dataItem, resetId, $event.target, changeType.Auto)"
        >
          {{ dataItem['portfolioAbbreviation'] }}
        </mat-radio-button>
        <ng-container *ngIf="!dataItem['eligibleForRateSelectionOnUi'] == true">{{
          dataItem['portfolioAbbreviation']
        }}</ng-container>
      </ng-template>
    </form>
    <tr mat-row *matRowDef="let emprow; columns: displayedColumns"></tr>
  </table>
  <mat-paginator
    #paginator
    [length]="totalRows"
    [pageIndex]="currentPage"
    [pageSize]="pageSize"
    (page)="pageChanged($event)"
    showFirstLastButtons
  ></mat-paginator>
  <ng-container *ngIf="consolidateModeldata?.rates?.length">
    If you have selected rates, pls resolve them before moving to next page
  </ng-container>
</div>

這是我現在的 spec.ts:

import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
import { MatDialogModule } from '@angular/material/dialog';
import { RouterTestingModule } from '@angular/router/testing';
import { AppConfig } from '@app/app.config';
import { AuthModule } from 'angular-auth-oidc-client';
import { ToastrModule, ToastrService } from 'ngx-toastr';
import { ResolveTermLoanComponent } from './resolve-term-loan.component';

describe('ResolveTermLoanComponent', () => {
  let component: ResolveTermLoanComponent;
  let fixture: ComponentFixture<ResolveTermLoanComponent>;
  let fb: FormBuilder;
  let toasterService;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [ResolveTermLoanComponent],
      imports: [
        RouterTestingModule.withRoutes([]),
        HttpClientTestingModule,
        ToastrModule.forRoot(),
        AuthModule.forRoot(),
        MatDialogModule,
        ReactiveFormsModule,
      ],
      providers: [AppConfig],
    }).compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(ResolveTermLoanComponent);
    toasterService = TestBed.inject(ToastrService);
    component = fixture.componentInstance;
    fb = TestBed.inject(FormBuilder);
    fixture.detectChanges();
  });

  it('should create', () => {
    component.ngOnInit();
    expect(component).toBeTruthy();
  });

});

我制作測試用例的原因是香草是為了確定導致錯誤的區域,但我仍然無法找到它,因為即使使用這個基本規范文件,我也會收到此錯誤:

15:20:22  [INFO] Chrome Headless 91.0.4449.6 (Linux x86_64) ERROR
15:20:22  [INFO]   An error was thrown in afterAll
15:20:22  [INFO]   error properties: Object({ longStack: 'TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
15:20:22  [INFO]       at subscribeTo (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/rxjs/_esm2015/internal/util/subscribeTo.js:27:1)
15:20:22  [INFO]       at innerSubscribe (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/rxjs/_esm2015/internal/innerSubscribe.js:69:23)
15:20:22  [INFO]       at MergeMapSubscriber._innerSub (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/rxjs/_esm2015/internal/operators/mergeMap.js:57:49)
15:20:22  [INFO]       at MergeMapSubscriber._tryNext (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/rxjs/_esm2015/internal/operators/mergeMap.js:51:1)
15:20:22  [INFO]       at MergeMapSubscriber._next (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/rxjs/_esm2015/internal/operators/mergeMap.js:34:1)
15:20:22  [INFO]       at MergeMap ...
15:20:22  [INFO]   TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
15:20:22  [INFO]       at subscribeTo (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/rxjs/_esm2015/internal/util/subscribeTo.js:27:1)
15:20:22  [INFO]       at innerSubscribe (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/rxjs/_esm2015/internal/innerSubscribe.js:69:23)
15:20:22  [INFO]       at MergeMapSubscriber._innerSub (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/rxjs/_esm2015/internal/operators/mergeMap.js:57:49)
15:20:22  [INFO]       at MergeMapSubscriber._tryNext (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/rxjs/_esm2015/internal/operators/mergeMap.js:51:1)
15:20:22  [INFO]       at MergeMapSubscriber._next (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/rxjs/_esm2015/internal/operators/mergeMap.js:34:1)
15:20:22  [INFO]       at MergeMapSubscriber.next (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/rxjs/_esm2015/internal/Subscriber.js:49:1)
15:20:22  [INFO]       at Observable._subscribe (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/rxjs/_esm2015/internal/util/subscribeToArray.js:3:1)
15:20:22  [INFO]       at Observable._trySubscribe (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/rxjs/_esm2015/internal/Observable.js:42:1)
15:20:22  [INFO]       at Observable.subscribe (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/rxjs/_esm2015/internal/Observable.js:28:1)
15:20:22  [INFO]       at MergeMapOperator.call (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/rxjs/_esm2015/internal/operators/mergeMap.js:19:1)
15:20:22  [INFO]       at <Jasmine>
15:20:22  [INFO]       at Object.onScheduleTask (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/zone.js/dist/zone-testing.js:117:1)
15:20:22  [INFO]       at ZoneDelegate.scheduleTask (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/zone.js/dist/zone-evergreen.js:378:1)
15:20:22  [INFO]       at Object.onScheduleTask (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/zone.js/dist/zone-evergreen.js:272:1)
15:20:22  [INFO]       at ZoneDelegate.scheduleTask (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/zone.js/dist/zone-evergreen.js:378:1)
15:20:22  [INFO]       at Zone.scheduleTask (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/zone.js/dist/zone-evergreen.js:210:1)
15:20:22  [INFO]       at Zone.scheduleMacroTask (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/zone.js/dist/zone-evergreen.js:233:1)
15:20:22  [INFO]       at scheduleMacroTaskWithCurrentZone (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/zone.js/dist/zone-evergreen.js:1134:1)
15:20:22  [INFO]       at http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/zone.js/dist/zone-evergreen.js:2586:1
15:20:22  [INFO]   error properties: Object({ longStack: 'TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
15:20:22  [INFO]       at subscribeTo (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/rxjs/_esm2015/internal/util/subscribeTo.js:27:1)
15:20:22  [INFO]       at innerSubscribe (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/rxjs/_esm2015/internal/innerSubscribe.js:69:23)
15:20:22  [INFO]       at MergeMapSubscriber._innerSub (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/rxjs/_esm2015/internal/operators/mergeMap.js:57:49)
15:20:22  [INFO]       at MergeMapSubscriber._tryNext (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/rxjs/_esm2015/internal/operators/mergeMap.js:51:1)
15:20:22  [INFO]       at MergeMapSubscriber._next (http://localhost:9876/fpcmsreapp/jenkins/workspace/FFIO/cogtl-ui/866/node_modules/rxjs/_esm2015/internal/operators/mergeMap.js:34:1)
15:20:22  [INFO]       at MergeMap ...
15:20:22  [INFO]   TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.

很難理解錯誤的原因,因為當我在本地運行 ng test 時,所有測試用例都沒有錯誤或失敗地通過,但我只是在嘗試使用 Jenkins 部署我的代碼時才遇到這些錯誤。

這是我的本地測試運行器的業力測試配置:

// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular-devkit/build-angular'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage-istanbul-reporter'),
      require('@angular-devkit/build-angular/plugins/karma'),
    ],
    client: {
      clearContext: false, // leave Jasmine Spec Runner output visible in browser
    },
    coverageIstanbulReporter: {
      dir: require('path').join(__dirname, '../../coverage/term-loans'),
      reports: ['html', 'lcovonly', 'text-summary'],
      fixWebpackSourcePaths: true,
    },
    reporters: ['progress', 'kjhtml', 'coverage-istanbul'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false,
    restartOnFileChange: true,
  });
};

這是我對 Jenkins (karma.conf.ci.js) 的測試配置:

var baseConfig = require('./karma.conf.js');

module.exports = function(config){
    // Load base config
    baseConfig(config);

    // Override base config
    config.set({
        singleRun: true,
        autoWatch: false,
        browsers : ['ChromeHeadless']
    });
};

但即使我使用 Jenkins 測試配置運行 ng 測試,所有測試用例也會通過。 因此我無法理解為什么它只在部署時失敗。

任何幫助將不勝感激,如果需要更多信息,請告訴我。

  1. 不要直接調用 ngOnInit。 這是一種代碼味道。 它應該由組件的生命周期調用。

  2. 由於 ngAfterViewInit 在 ngOnInit 之后被調用,因此您的 parentTableData 未設置,因此出現錯誤,您沒有可迭代的。

簡單地嘗試

 it('should create', () => {
    expect(component).toBeTruthy();
  });

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM