Guide on incorporating an external JavaScript library into an Angular component for testing purposes

Encountering an issue with a component that utilizes an external JavaScript library called Leader-Line. Every time I attempt to test this component, an error is thrown indicating that the function from the external library is not defined.

component file

declare var LeaderLine: any;

@Component({
  selector: 'app-flow-line',
  templateUrl: './flow-line.component.html',
  styleUrls: ['./flow-line.component.css']
})
export class FlowLineComponent implements AfterViewInit, OnDestroy {

  @Input() public flowPathConfig: any = new Array();
  public myLines: any = new Array();
  public ngAfterViewInit() {
    for (let config of this.flowPathConfig) {
      if (document.getElementById(config.fromStep) && document.getElementById(config.toStep)) {
        this.myLines.push(new LeaderLine(
          document.getElementById(config.fromStep),
          document.getElementById(config.toStep)
        ));
      }
    }
  }

spec file

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { FlowLineComponent } from './flow-line.component';
import { FundamentalNgxModule } from 'fundamental-ngx';


describe('FlowLineComponent', () => {
  let component: FlowLineComponent;
  let fixture: ComponentFixture<FlowLineComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [FlowLineComponent],
      imports: [FundamentalNgxModule]
    })
      .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(FlowLineComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('it should draw line with pathConfig', () => {
    component.flowPathConfig = [{ fromStep: '1', toStep: '2' }];
    let el1 = document.createElement('div');
    el1.setAttribute('id', '1');
    let el2 = document.createElement('div');
    el2.setAttribute('id', '2');
    document.body.appendChild(el1);
    document.body.appendChild(el2);
    fixture.detectChanges();
    component.ngAfterViewInit();
    expect(component.myLines.length).toEqual(0);
    expect(component).toBeTruthy();
  });
});

Error trace provided below shows a "ReferenceError" related to LeaderLine. The post referenced includes instructions on how to include the leader-line library in an Angular application:

HeadlessChrome 75.0.3770 (Mac OS X 10.14.6) FlowLineComponent it should draw line with pathConfig FAILED
        ReferenceError: LeaderLine is not defined
            at <Jasmine>
            at FlowLineComponent.LeaderLine [as ngAfterViewInit] (http://localhost:9876/_karma_webpack_/webpack:/src/app/flow/flow-line/flow-line.component.ts:34:43)
            at UserContext.<anonymous> (http://localhost:9876/_karma_webpack_/webpack:/src/app/flow/flow-line/flow-line.component.spec.ts:45:15)
            at ZoneDelegate../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone.js:391:1)
            at ProxyZoneSpec.push../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.onInvoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-testing.js:308:1)
            at ZoneDelegate../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone.js:390:1)
            at Zone../node_modules/zone.js/dist/zone.js.Zone.run (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone.js:150:1)
            at runInTestZone (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-testing.js:561:1)
            at UserContext.<anonymous> (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-testing.js:576:1)
            at <Jasmine>
HeadlessChrome 75.0.3770 (Mac OS X 10.14.6): Executed 13 of 16 (1 FAILED) (0 secs / 3.274 secs)
HeadlessChrome 75.0.3770 (Mac OS X 10.14.6) FlowLineComponent it should draw line with pathConfig FAILED
        ReferenceError: LeaderLine is not defined
            at <Jasmine>
            at FlowLineComponent.LeaderLine [as ngAfterViewInit] (http://localhost:9876/_karma_webpack_/webpack:/src/app/flow/flow-line/flow-line.component.ts:34:43)
            at UserContext.<anonymous> (http://localhost:9876/_karma_webpack_/webpack:/src/app/flow/flow-line/flow-line.component.spec.ts:45:15)
            at ZoneDelegate../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone.js:391:1)
            at ProxyZoneSpec.push../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.onInvoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-testing.js:308:1)
            at ZoneDelegate../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone.js:390:1)
            at Zone../node_modules/zone.js/dist/zone.js.Zone.run (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone.js:150:1)
            at runInTestZone (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-testing.js:561:1)
            at UserContext.<anonymous> (http://localhost:9876/_karma_webpack_/webpack:/node_modules/zone.js/dist/zone-testing.js:576:1)

Answer №1

My suggestion is to approach the library import in this manner:

import * as LeaderLine from 'leader-line';

Have you tested if only the tests are failing, or does your app also throw errors when running?

Answer №2

When incorporating methods into the component, I opt for the function declaration method.

declare function A();

To exclusively test the component's methods without considering imported ones from an external js file, a mock file named <external.js> can be created to substitute the original during testing. It is essential to include this mock file in the angular.json configuration under test settings.

"test": {
      "builder": "@angular-devkit/build-angular:karma",
      "options": {
        "main": "src/test.ts",
        "polyfills": "src/polyfills.ts",
        "tsConfig": "src/tsconfig.spec.json",
        "karmaConfig": "src/karma.conf.js",
        "sourceMap": true,
        "assets": [
          "src/favicon.ico",
          "src/assets",
          "src/env.js"
        ],
        "styles": [
          "src/styles.css",
          "src/sass/intracom-light.scss"
        ],
        "scripts": [
          "src/assets/mock/js/maps.js"
        ]
      }
    },

To establish the testing behavior, modify the content of the called methods accordingly.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Enhancing the functionality of the onclick function within the ng-repeat by incorporating a scope

I am looking to pass a parameter to a function that is called via onclick within an ng-repeat: <!-- Sliding bar (bottom) --> <div ng-show="currentSVG && currentLanguage && currentWidth && bannerHeight" pageslide ps-open=" ...

Is it possible for a JWT generated using RS256 to be decoded on the jwt.io platform?

After setting up my first Express server and implementing user authentication with jwt, I'm now searching for a method to encrypt the jwt in order to prevent users from viewing the payload on the website. I am curious if anyone is aware of an encryp ...

What is the best way to retrieve the Object key for the connected object in angularFire2?

When I search the database using a user key, I check if an associated object exists: let url = ``/userMember/${userKey}``; const userMemberRef = this.af.database.object(url, { preserveSnapshot: true }); userMemberRef.subscribe(data => { if(data.val ...

Why is the "class" attribute of an SVG node not being applied when I change it?

I am having trouble changing the "class" attribute of a node in SVG using my AngularJS Directive. Even though I've written the code to do so, it doesn't seem to be applied properly. This is the code snippet from my Directive: node = node.data(f ...

Ensure that each of the two divs maintains a 16:9 aspect ratio, and utilize one div to fill any remaining empty space through the

This layout is what I am aiming for: https://i.sstatic.net/uZdty.png While I can achieve a fixed aspect ratio with a 16:9 image by setting the img width to 100%, I run into an issue where the height scaling of flexbox becomes non-responsive. The height re ...

What is the purpose of utilizing "({ })" syntax in jQuery?

What is the purpose of using ({ }) in this context? Does it involve delegation? Can you explain the significance of utilizing this syntax? What elements are being encapsulated within it? For instance: $.ajaxSetup ({ // <-- HERE error: fError, ...

The chosen state does not save the newly selected option

Operating System: Windows 10 Pro Browser: Opera I am currently experiencing an issue where, upon making a selection using onChange(), the selected option reverts back to its previous state immediately. Below is the code I am using: cont options = [ ...

Having issues with handling ajax response in a Node.js application?

I am encountering an issue with my ajax post request to my node js backend. After sending the request and receiving a response, instead of updating just the resulttoken in the view, the entire HTML page seems to be loaded according to the console. I am see ...

Enhancing Angular: Creating a custom HttpInterceptor for handling unique scenarios

In Angular there is the HTTPInterceptor feature called @Injectable() export class HTTPRequestInterceptor implements HttpInterceptor { intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { return next ...

Leveraging CDK Context Variables in C# Lambda Initialization Code

I have a .NET Lambda function written in C# that is implemented as a .NET Minimal API according to the guidance provided here. To define AWS resources, I am utilizing CDK (TypeScript). Within my build pipeline, there is shell scripting involved to supply ...

The new Date function is malfunctioning on Firefox

Could you please explain why this particular function is not functioning correctly in Firefox (V 34 latest)? It appears to be working successfully on all other browsers, but 'DatePosted' is displaying as Invalid Date. Do you have any insights on ...

How to dynamically incorporate methods into a TypeScript class

I'm currently attempting to dynamically inject a method into an external class in TypeScript, but I'm encountering the following error. Error TS2339: Property 'modifyLogger' does not exist on type 'extclass'. Here's the ...

Simulating a mobile device screen size using an embedded iframe

Imagine this scenario: What if instead of adjusting the browser window size to showcase a responsive web design, we could load the site into an IFRAME with the dimensions of a mobile screen. Could this concept actually work? Picture having an IFRAME like ...

Determining the depth difference of nodes between two elements using JQuery

Is there a simple method to calculate the node depth difference between 2 elements? Example : <div id="1"> <div id="2"></div> <div id="3"> <div id="4"></div> </div> </div> <div id="5"></d ...

Managing the state of dynamically generated tabs within a NextJS application

Looking to develop a web app in Next.js that includes tabs components. The goal is to manage various entities within each tab, such as utilizing a search bar to select different products. Upon selecting a product, a new tab will be generated with the produ ...

Guide to integrating validators into a formModel with Angular's reactive forms

Currently, I am in the process of learning about reactive forms in Angular and have a question regarding how to set a property as required or any other validator when using class model for defining form groups. You can find more information on reactive fo ...

Intercepting 401 with Angular 5 HTTP Interceptor recognizes it as status code 0

One issue I am currently facing is the inability to intercept a 401 status and redirect to the login page, which is a common practice in most applications. My interceptor code seems pretty standard: intercept(request: HttpRequest<any&g ...

Execute functions during jquery's .animate() operation

This is a snippet of code I use to smoothly scroll the browser back to the top: $('html, body').animate({scrollTop: 0}, 500, "easeOutQuart"); Now, I am looking for a way to prevent the user from scrolling while this animation is running. Once t ...

Trouble with Adding and Showing Arrays

function resetValues() { var p = parseFloat($("#IA").val()); var q = parseFloat($("#IB").val()); var m = parseFloat($("#CGCD").val()); var aR = []; aR.push("GCD(" + p + "," + q + ")=" + m); document.getElementById("PGCD").innerHTM ...

Using ng-bootstrap with Bootstrap 4 beta as an npm dependency

After updating my npm dependencies in package.json to Bootstrap 4 beta and ng-bootstrap to 1.0.0-beta.5, I encountered an "UNMET PEER DEPENDENCY" for popper.js when running npm install due to its new addition as a dependency in Bootstrap 4 beta. Despite th ...