unit test karma cases and angular typescript karma-jasmine

karma - testbed angular



la instancia[output.propName].subscribe no es una funciĆ³n resultante de polyfill (4)

Acabo de enfrentar este problema y al verificar el código que escribí, descubrí que se debió a una mala importación de la clase EventEmitter (realizada por la importación automática del código de estudio visual).

Solo necesitas cambiar

import { EventEmitter } from ''events'';

A

import { EventEmitter } from ''@angular/core'';

Y sobre la explicación del error. Angular mapea los eventos como observables, por lo que debe suscribirse a los eventos de los componentes secundarios y enviarlos a los componentes apropiados.

Buscando el paquete original, encontré su código fuente en: https://github.com/Gozala/events/blob/master/events.js

Y simplemente falla porque no hay un método .suscribe() en el EventEmitter que ha creado.

Estoy teniendo un problema extraño. He investigado el error y, en general, parece estar relacionado con el uso de @Output o EventEmitter , pero ese no es el caso aquí.

Recibo el siguiente error en mi solicitud si tengo un polyfill particular en su lugar:

TypeError: instance[output.propName].subscribe is not a function at createDirectiveInstance (http://localhost:9876/_karma_webpack_/webpack:/Users/stuart/localhost/projects/tt-new/work-group/node_modules/@angular/core/esm5/core.js:12319:71) at createViewNodes (http://localhost:9876/_karma_webpack_/webpack:/Users/stuart/localhost/projects/tt-new/work-group/node_modules/@angular/core/esm5/core.js:13776:38) at callViewAction (http://localhost:9876/_karma_webpack_/webpack:/Users/stuart/localhost/projects/tt-new/work-group/node_modules/@angular/core/esm5/core.js:14210:1) at execComponentViewsAction (http://localhost:9876/_karma_webpack_/webpack:/Users/stuart/localhost/projects/tt-new/work-group/node_modules/@angular/core/esm5/core.js:14119:1) at createViewNodes (http://localhost:9876/_karma_webpack_/webpack:/Users/stuart/localhost/projects/tt-new/work-group/node_modules/@angular/core/esm5/core.js:13804:1) at createRootView (http://localhost:9876/_karma_webpack_/webpack:/Users/stuart/localhost/projects/tt-new/work-group/node_modules/@angular/core/esm5/core.js:13665:1) at callWithDebugContext (http://localhost:9876/_karma_webpack_/webpack:/Users/stuart/localhost/projects/tt-new/work-group/node_modules/@angular/core/esm5/core.js:15090:26) at Object.debugCreateRootView [as createRootView] (http://localhost:9876/_karma_webpack_/webpack:/Users/stuart/localhost/projects/tt-new/work-group/node_modules/@angular/core/esm5/core.js:14373:1) at ComponentFactory_.webpackJsonp.../../../core/esm5/core.js.ComponentFactory_.create (http://localhost:9876/_karma_webpack_/webpack:/Users/stuart/localhost/projects/tt-new/work-group/node_modules/@angular/core/esm5/core.js:11260:26) at initComponent (http://localhost:9876/_karma_webpack_/webpack:/Users/stuart/localhost/projects/tt-new/work-group/node_modules/@angular/core/esm5/testing.js:1137:1)

El polyfill es el siguiente:

Object.prototype.clone = function(deep = false) { return (deep) ? JSON.parse(JSON.stringify(this)) // Deep clone - copies object property values in full. : Object.assign({}, this); // Shallow clone - copies property values (including object references rather than object). };

¿Alguien puede ayudarme a comprender por qué esto puede causar un error dentro de createDirectiveInstance ? Si comento este código, el error desaparece. No es simplemente tener un polyfill que cause problemas, hay otro, que agrega Array.prototype.upsert , que no causa problemas.


Descubrí que podría obtener este error al suscribirse accidentalmente en un método @Output lugar de en una propiedad.

Por ejemplo si tienes:

<app-thing (onReady)="..."> </app-thing>

Asegúrese de que en el componente hijo tiene:

@Output() onReady: Observable<...>

o:

@Output() get onReady(): Observable<...> { ... }

...NO:

@Output() onReady(): Observable<...> { ... }


En primer lugar, probablemente sea una mala idea implementar una función de clon no optimizada, especialmente cuando muchas bibliotecas ya la han implementado [1]. Habiendo dicho eso, esta respuesta puede ser útil si no puede agregar bibliotecas, o para otras personas como yo que buscan extender Object .

Esto parece ser el resultado de declarar incorrectamente una propiedad en Object.prototype . Supongo que hay una expectativa insatisfecha de que createDirectiveInstance tiene cuando enumera Object.clone (probablemente no debería enumerarlo). En su lugar, utilice el método Object.defineProperty :

Object.defineProperty( Object.prototype, ''clone'', { value: function (deep = false) { return (deep) ? JSON.parse(JSON.stringify(this)) // Deep clone - copies object property values in full. : Object.assign({}, this); // Shallow clone - copies property values (including object references rather than object). }, writable: false, enumerable: false } );

Eso podría ser refactorizado a la siguiente mecanografía:

function CloneThis(deep = false): any { return (deep) ? JSON.parse(JSON.stringify(this)) // Deep clone - copies object property values in full. : Object.assign({}, this); // Shallow clone - copies property values (including object references rather than object). } Object.defineProperty(Object.prototype, ''clone'', <PropertyDescriptor>{ value: CloneThis, writable: false, enumerable: false } );

Sin embargo, para obtener la inferencia de tipos de TypeScript, creo que también debe declarar una extensión a la interfaz global para Object:

declare global { interface Object { clone(deep?: boolean): any; } }

Para obtener más recursos sobre Object.defineProperty , consulte:

[1] Implementaciones de clones de Javascript:


Tuve el mismo problema y encontré una solución que funcionó para mí.

en los node_modules / @ angular / core / @ angular / core.es5.js del proyecto

10768: var /** @type {?} */ subscription = instance[((output.propName))].subscribe(...

De alguna manera, estaba obteniendo un propName llamado assign que no está en el objeto de instance . Simplemente coloque y escriba la declaración y asegúrese de que tenga una función de suscripción antes de llamarla. Algo como esto:

if (instance[((output.propName))] && typeof instance[((output.propName))].subscribe === ''function''){ var /** @type {?} */ subscription = instance[((output.propName))].subscribe(eventHandlerClosure(view, /** @type {?} */ ((def.parent)).index, output.eventName)); /** @type {?} */ ((view.disposables))[def.outputIndex + i] = subscription.unsubscribe.bind(subscription); }

Y es posible que también deba hacer una comprobación aquí:

12515: view.disposables[i]();

hice esto:

if (view.disposables[i] && typeof view.disposables[i] === ''function''){ view.disposables[i](); }

No recomendaría este parche de mono, pero funcionó para mí y hasta ahora no he tenido ningún error desde entonces. Espero que ayude o incluso ayude a alguien a encontrar una mejor solución.