Reputation: 466
I'm currently working in an Angular 6 project where I have imported several of the new font-awesome 5 icons using the Fort-awesome module for angular.
As expected, by doing so now some of my Unit Tests (Karma + Jasmine) won't pass due to not being able to render the fa-icon selectors in my pages.
I understand that I could use a CUSTOM_ELEMENTS_SCHEMA in the TestBed for each component but I don't know if by doing so I may have other side effects that would make my unit tests less reliable (i.e. other sub-components may stop being tested).
Another option is to simply import the module in each of the required unit tests, and in each of those, also add the library.add() with the required icons. I do think, however, this could end up being tedious as there may be between 20 and 50 icons depending on the type of application.
I've also thought, but haven't tried yet, to add a stub module for the icons, so I simply "ignore" them. I think this could be reasonable, but not sure what the best practice would be in this case.
Below an excerpt of my imports in App.Module
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import { library } from '@fortawesome/fontawesome-svg-core';
import { faLock, faHourglassHalf, faLockOpen } from '@fortawesome/free-solid-svg-icons';
And in the constructor
export class AppModule {
constructor() {
library.add(
faHourglassHalf, // Task in progress
faLockOpen, // Archive task
faLock
);
}
}
Full repo here: https://github.com/Narshe1412/Code-Institute-Interactive-Frontend-Project/tree/taskman
As I know this is not debate forum I would simply ask:
Upvotes: 9
Views: 7285
Reputation: 161
You can now use font-awesome testing module like this:
import {FontAwesomeTestingModule} from '@fortawesome/angular-fontawesome/testing';
TestBed.configureTestingModule({imports: [ FontAwesomeTestingModule ]}).compileComponents();
Upvotes: 14
Reputation: 1067
I do not like the other solutions, even if they may work. To me it seems unclean importing the AppModule
in a unit test.
My solution is to separate the icons from the other stuff, as described below. This solution is kind of like the already accepted answer, but cleaner in my opinion:
import { NgModule } from '@angular/core';
import { FontAwesomeModule, FaIconLibrary } from '@fortawesome/angular-fontawesome';
import { faDownload, faUpload, faFileExport, faCircle, faChevronRight, faChevronDown, faPlus, faTimes } from '@fortawesome/free-solid-svg-icons';
@NgModule({
imports: [ FontAwesomeModule ],
exports: [ FontAwesomeModule ]
})
export class IconsModule {
constructor(library: FaIconLibrary) {
// add icons to the library for convenient access in other components
library.addIcons(faDownload, faUpload, faFileExport, faCircle, faChevronRight, faChevronDown, faPlus, faTimes);
}
}
Then import the IconsModule wherever you need it, be it in the application itself or in a test:
AppModule:
import { IconsModule } from './icons.module';
@NgModule({
declarations: [...],
imports: [
...
IconsModule,
],
bootstrap: [...]
})
export class AppModule {}
Unit Test:
describe('MyComponent', () => {
let component: MyComponent;
let fixture: ComponentFixture<MyComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ MyComponent ],
imports: [
...
IconsModule,
]
})
.compileComponents();
}));
...
});
HTML:
<fa-icon icon="download"></fa-icon>
Nice side effect: If you ever were to change the font library from Font Awesome to something else, this is much easier now, as you only have to change the IconsModule
and the respective HTML code for the icons.
Upvotes: 13
Reputation: 63
Looks like there is already an accepted answer for this issue, but I will try to supplement with info from a related topic.
You can mock everything from external modules, but the imported component's selectors. There is an easy way which is to disable this kind of errors as you mentioned.
Can't bind to 'icon' since it isn't a known property of 'fa-icon'
import { NO_ERRORS_SCHEMA } from '@angular/core';
...
TestBed.configureTestingModule({
schemas: [ NO_ERRORS_SCHEMA ],
...
The NO_ERRORS_SCHEMA tells the Angular compiler to ignore unrecognized elements and attributes.
Otherwise I would suggest to add FontAwesome directly into the testbed despite it being a tedious task. It improves readability and avoids importing redundant components in the test module. This mainly becomes a problem when you have more than one component.
TestBed.configureTestingModule({
imports: [
FontAwesomeModule
]
})
.compileComponents();
Upvotes: 0
Reputation: 11474
I would just like to throw out a 'third' option. This is the approach that my team and I have been using and prefer.
The module brings in the FontAwesomeModule.
import { NgModule } from '@angular/core';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
@NgModule({
declarations: [
AppComponent
],
imports: [
FontAwesomeModule
],
exports: [
FontAwesomeModule
]
})
export class AppModule { }
The component that actually uses the font awesome icons imports only the icons it needs to know about.
import {
Component
} from '@angular/core';
import { faLock } from '@fortawesome/free-solid-svg-icons';
@Component({
selector: 'app-fa-example',
template: '<fa-icon [icon]="faLock"></fa-icon>'
})
export class AppComponent {
faLock = faLock;
}
Then in our *.spec.ts
files, we have a setup like the following:
TestBed.configureTestingModule({
imports: [
AppModule
]
})
.compileComponents();
Since the FontAwesomeModule
is exported in the AppModule
it will be available to the test bed here through the AppModule
import. Since the icons are being imported explicitly in the component, there is no need to library.add(...)
here either specifying all of the font awesome icons used in the module/component.
Upvotes: 1