I'm using #angular#9.0.7, #ngneat/spectator#5.3.1 (with Jest), Inputmask#5.0.3 in a project and everything works on application when I run ng serve or even ng build, but it fails when I try to run a test suite for a #Pipe that uses Inputmask:
#Pipe:
import { Pipe, PipeTransform } from '#angular/core';
import Inputmask from 'inputmask';
#Pipe({
name: 'appSomePipe',
})
export class SomePipe implements PipeTransform {
transform(value: string): string {
return Inputmask.format(value, {
jitMasking: true,
mask: '1111-1',
});
}
}
#Spec:
import { createPipeFactory, SpectatorPipe } from '#ngneat/spectator/jest';
import { SomePipe } from './some.pipe';
describe('SomePipe', () => {
let spectator: SpectatorPipe<SomePipe>;
const createPipe = createPipeFactory(SomePipe);
it('test', () => {
spectator = createPipe(`{{ '11111' | appSome }}`);
expect(spectator.element).toHaveText('1111-1');
});
});
When I run ng test, it shows:
ReferenceError: customElements is not defined
2 |
> 3 | import Inputmask from 'inputmask';
PS: This error just appears for Angular 9, in Angular 8 all tests were successfully passed.
A quick search into inputmask repository shows that it uses customElements which is a feature implemented by modern browsers in order to create native web components (without a framework).
When looking at Jest documentation we can see that the default testEnvironment is jsdom, which is an implementation of the DOM that runs without a browser. This library implements custom elements since version 16.2.0 and this version is pretty recent, and is not yet used by jest (the last version of jest uses jsdom v15.1.1).
So you just have to wait for jest to update the jsdom dependency, and then update your project to use the latest version of jest.
Another option: you can use jest-browser which runs Jest in a headless browser based on puppeteer.
Update 05-2020:
Upgrade to (at least) Jest 26.0.0 which uses jsdom 16.2.0 (Source)
jsdom does not support customElements until v16.2.0 as Guerric P wrote.
To get jest running with jsdom v 16 you need to do the following
yarn add jest-environment-jsdom-sixteen
Then in you jest.config.js add this
module.exports = {
testEnvironment: 'jest-environment-jsdom-sixteen',
...
}
this will force jest to use a newer implementation.
and this should solve your problem.
I remember stumbling upon your question and I stumbled upon something else related to ngx-bootstrap with regards to an import not working in Angular 9.
https://valor-software.com/ngx-bootstrap/#/datepicker
Check out the usage section and its warning about Angular 9.
Try doing import InputMask from 'inputmask/somethingMoreSpecificHere'; or `import { somethingSpecificHere } from 'inputmask';
The problem is that you are not injecting the Inputmask dependency into your test.
This is because you are using a javascript import. There are Angular libraries to do this (ngx-mask).
In Angular we use Dependency Injection with IOC, so for this example I'll use an InputMaskService to create the angular dependency.
Pipe
import { Pipe, PipeTransform } from '#angular/core';
import { InputMaskService } from './inputmask.service';
#Pipe({
name: 'appSomePipe',
})
export class SomePipe implements PipeTransform {
constructor(private inputMaskService: InputMaskService){}
transform(value: string): string {
return this.inputMaskService.format(value, {
jitMasking: true,
mask: '1111-1',
});
}
}
Note that I'm injecting the service in the constructor and using that instance in the transform method.
Test
You can create an instance of your pipe passing the service reference
beforeEach(() => {
const inputMaskService = new InputMaskService();
const pipe = new SomePipe(inputMaskService);
});
Related
I have created a Service for an Angular App which is working fine as expected.
Its a Notification Service Wrapper for the package 'awesome-notifications'.
If I transfer the Service to the lib and use it from the lib i am getting kind of an import error its telling me something like constructor is not defined. Its referencing to the line :
'import AWN from "awesome-notifications"' which is the first line of the service.
its needed to create the notifier in the Service. Because its a Wrapper.
it seems like angular can not inject the service i wrote.
But if i am using it in an existing app it works, its really strange. does someone have experience with that ?
Code
import { Injectable } from '#angular/core';
import AWN from 'awesome-notifications';
export interface NotificationRequestModel {
message:string;
title?:string;
}
#Injectable({
providedIn: 'root'
})
export class NotificationService {
notifier = new AWN();
constructor() {
}
success(req:NotificationRequestModel) {
this.notifier.success(req.message, {
labels: { success: req?.title },
})
} etc..
ERROR TypeError: awesome_notifications__WEBPACK_IMPORTED_MODULE_0__ is not a constructor
This looks like a build/bundle issue with webpack/typescript. Since one can't reproduce your setup you should provide an example with more information. Its probably the default import for your native library. I can only guess:
Do you have allowSyntheticDefaultImports set in your ts config?
I am trying to call the javascript function into the angular here is the plugin I am using "npm I global payments-3ds" of which I copied javascript files from node_modules and tried to call in my component
Below is the example :
import {
Component,
OnInit
} from '#angular/core';
import {
handleInitiateAuthentication
} from './globalpayments-3ds/types/index';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
name = 'Angular';
ngOnInit(): void {
const status: any = "CHALLENGE_REQUIRED"
const resp = {
challenge: {
encodedChallengeRequest: "abcd",
requestUrl: "url,
},
challengeMandated: "MANDATED",
dsTransactionId: "44444",
id: "444444",
status: status,
};
const windowSize: any = "WINDOWED_600X400";
const displayMode: any = "lightbox";
const challengeWindow = {
windowSize: windowSize,
displayMode: displayMode,
};
handleInitiateAuthentication(resp, challengeWindow)
}
}
I am trying to call the handleInitiateAuthentication() which is giving me the below error
Here is the file structure
from index.d.ts i am calling the handleInitiateAuthentication() function
Here is Stackblitz code for the same
https://stackblitz.com/edit/angular-vodezz?file=src%2Fapp%2Fapp.component.ts
Please help I never used the js function in angular I tried to add in assets not worked
I have tried to create an angular library and add the js files in it and update the package, by converting the file to .tgz but nothing working it showing always the same error,
Why am I doing is I have to update one of the files from node_modules, basically I wanna change files from node modules which is why i copied those files locally
this is also giving error
You have to import directly js file.
// #ts-ignore
import { handleInitiateAuthentication } from './globalpayments-3ds/globalpayments-3ds.esm.js';
For error about module, it's because you have to define type of your module in TypeScript. You can directly use // #ts-ignore.
See this stackblitz : https://stackblitz.com/edit/angular-xz4kmp?file=src%2Fapp%2Fapp.component.ts
You don't need to import a library like that. First of all install the library to your project:
npm i globalpayments-3ds --save
then in your ts file:
import { handleInitiateAuthentication } from 'globalpayments-3ds';
see this stackblitz
The recommended way to make your own modified versions from open source libraries is to fork them and build your own versions.
Also note that you must take into account the license of that NPM package which in the case of https://github.com/globalpayments/globalpayments-js is GPL-v2, so if you will use it for commercial purposes you must follow the agreement. Check this branch: GNU General Public License (v2): can a company use the licensed software for free?.
Taking a look to your Stackblitz code, you may notice that there are several JS versions of the same module in src/app/global-payments-3ds/ folder:
globalpayments-3ds.js (CommonJS, used in Node environments).
globalpayments-3ds.min.js (CommonJS minified).
globalpayments-3ds.js.map (CommonJS minified map file to reference during debugging).
globalpayments-3ds.esm.js (ESM, ECMA Standard Module).
...
To use an external JS Module in an Angular App, as it is JavaScript and not TypeScript, you must tell TypeScript Compiler that you want to allow JS modules by enabling allowJS: true in tsconfig.ts file at the root of the project.
After that you should be be able to import the ESM version (globalpayments-3ds.esm.js) in your Angular App, or if you want to use the CommonJS version, you can also enable esModuleInterop: true in tsconfig.ts to allow importing CommonJS/AMD/UMD JS modules in your project, like globalpayments-3ds.js.
After installed angular-autofocus-fix
imported the AutofocusModule
When i run the angular projects its shows below error:
ERROR in node_modules/angular-autofocus-fix/index.d.ts:4:23 - error TS2314: Generic type 'ModuleWithProviders<T>' requires 1 type argument(s).
static forRoot(): ModuleWithProviders
When i check in that node_mudule
I am using angular 10 in my project.
By adding this below given code snippet in app.module.ts fixed the issue
declare module "#angular/core" {
interface ModuleWithProviders<T = any> {
ngModule: Type<T>;
providers?: Provider[];
}
}
#NgModule({
// ......
})
export class AppModule { }
In my case, this problem happened when I upgraded ng-bootstrap version in angular-10.
it seems it is not updated for Angular 10, ModuleWithProviders can no longer be used witthout generic (https://angular.io/guide/updating-to-version-10#new-removals-of-deprecated-apis)
there is an issue on the repo about it: https://github.com/korniychuk/angular-autofocus-fix/issues/14
Please try Observable to fix this issue.
I am unable to use Panzoom Javascript library in Angular. I get
ERROR
Error: panzoom is not defined
Here is the stackblitz of what i have done till now .
Here is the working demo of how it should work
Can any one help me troubleshoot ? Thanks
I have followed all the steps mentioned in this post
It seems Panzoom does have typescript definitions Github Issue
here is a working stackblitz
import { Component, AfterViewInit, ElementRef, ViewChild } from '#angular/core';
import panzoom from "panzoom";
#Component({
selector: 'hello',
template: `<img id="scene" #scene src="https://www.probytes.net/wp-content/uploads/2018/01/5-1.png">`,
styles: []
})
export class HelloComponent implements AfterViewInit {
#ViewChild('scene', { static: false }) scene: ElementRef;
ngAfterViewInit() {
// panzoom(document.querySelector('#scene'));
panzoom(this.scene.nativeElement);
}
}
There is an easy way to do this.
Open your angular project in cmd terminal (root of your project, the same foler which contains /src).
Type npm install panzoom --save (that will add panzoom npm package to your angular.json and install it).
In your component add import import * as panzoom from "panzoom" (your project should automaticaly link it with the right file from node_modules.
in ngOnInit or anywhere needed add this line panzoom.default(document.querySelector('#lipsum'));
You should generally incject this PanZoom package in your component constructor after importing it from node_modules but I'm not sure if there is an integration provided by an author.
Definitely check NPM documentation of this plugin for more info
am trying to import JS sdk into ionic 2 app, but i keep getting parse is undefined
In ionic 1.x ,parse js sdk is loaded via
<script ..parse.js </script>
and exposed as a global var, how do import in ionic 2 ,am using the npm module ,and tried
import * as parse from 'parse'
Do npm install parse --save in your project directory
Then import parse using
import { Parse } from 'parse';
It is better to create an parse provider.
You can use this starter template as a guide. It is a simple GameScores application in ionic to get you started.
https://github.com/Reinsys/Ionic-Parse
It shows how to create and read data from parse server. I also includes paging with ion-infinite-scroll scrolling.
After searching for a solution I came up with my own.
After installing the package and the typings, I opened the index.js of the node-module ionic-gulp-scripts-copy and added 'node_modules/parse/dist/parse.min.js' to the defaultSrc array.
Then, in my index.html, I included the script above the cordova.js.
Now I just need to declare var Parse: any; in every Component I want to use the SDK in.
For example, in my app.ts:
import {Component} from '#angular/core';
import {Platform, ionicBootstrap} from 'ionic-angular';
import {StatusBar} from 'ionic-native';
import {TabsPage} from './pages/tabs/tabs';
import{LoginPage} from './pages/login/login';
declare var Parse: any;
#Component({
template: '<ion-nav [root]="rootPage"></ion-nav>',
})
export class MyApp {
private rootPage: any;
private parse;
constructor(private platform: Platform) {
//this.rootPage = TabsPage;
this.rootPage = LoginPage;
platform.ready().then(() => {
console.log("Platform ready!");
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
StatusBar.styleDefault();
Parse.initialize('myStartUp', 'someKey');
Parse.serverURL = 'http://localhost:1337/parse';
});
}
}
ionicBootstrap(MyApp);
I do not think this is the way it should be used, but in the end I can use the SDK pretty easy and without much lines of implementation code.