
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
angular-unit-component-driver
Advanced tools
Test Angular components in jasmine with component drivers
Test your Angular components in an easiest way with component drivers ! 🚕
Create a class that extends the ComponentDriver class :
class MyComponentDriver extends ComponentDriver<MyComponent> {}
The componentTestingSetup is used to set up the component driver. Create a function that returns the result of the componentTestingSetup by passing at least your component class and the driver associated to the component :
function testingSetup() {
return componentTestingSetup({
componentClass: MyComponent,
driver: MyComponentDriver
})
}
Other optional parameters can be defined in the conf passed to this method :
{
componentClass: any
driver: any
servicesToStub?: any[]
declarations?: any[]
providers?: any[]
overrideProviders?: any[]
imports?: any[]
}
servicesToSub (optional) refers to the services that need a mock by creating a Spy. It uses the jasmine-auto-spies package under the hood.overrideProviders (optional) refers to the component provided services that need a mock by creating a Spy.declarations, providers, imports are optionals and are used in the same way that if you declare the TestBed configurations (because it uses the TestBed behind the scenes)Get your component driver by calling the componentTestingSetup method returned by componentTestingSetup
describe('ComponentDriver', () => {
let questionComponentDriver: QuestionComponentDriver
beforeEach(() => {
myComponentDriver = testingSetup().createComponentDriver()
})
})
You can easily access to the fixture properties like this :
myComponentDriver.componentInstance
myComponentDriver.detectChanges()
...
You can access to DOM elements, directives and components defined inside the component you are testing.
In your MyComponentDriver class, you have to add the appropriate methods to query what you need. For example :
class MyComponentDriver extends ComponentDriver<MyComponent> {
get questionElement() {
return this.querySelector('.my-element')
}
get buttonElements() {
return this.querySelectorAll<HTMLButtonElement>('button')
}
get firstMyDirective() {
return this.queryDirective(MyDirective)
}
get myChildComponents() {
return this.queryDirectiveAll(MyChildComponent)
}
}
The ComponentDriver class exposes 4 methods to query elements and directives (components) :
querySelector<T = HTMLElement>: (cssSelector: string) => T
querySelectorAll<T = HTMLElement>: (cssSelector: string) => T[]
queryDirective<T>: (directive: Type<T>) => T
queryDirectiveAll<T>: (directive: Type<T>) => T[]
For querySelector and querySelectorAll methods, you can specify the type of the queried element (HTMLElement by default).
For queryDirective and queryDirectiveAll methods, you don't have to specify the type, it is automatically returned.
You can easily access to the injector to get services :
import { Spy } from 'jasmine-auto-spies'
describe('ComponentDriver', () => {
let myServiceSpy: Spy<MyService>
beforeEach(() => {
myServiceSpy = myComponentDriver.injector.get(MyService)
})
})
jasmine-auto-spies is used behind the scenes, click on the link to get more informations about how to create mocks in the easiest way you can find 😉
"Creating spies has never been EASIER! 💪👏", Shai Reznik, author of jasmine-auto-spies
function testingSetup() {
return componentTestingSetup({
componentClass: MyComponent,
driver: MyComponentDriver,
// 1 - add services to mock here
servicesToStub: [myService]
})
}
describe('ComponentDriver', () => {
let myComponentDriver: MyComponentDriver
let myServiceSpy: Spy<MyService>
beforeEach(() => {
myComponentDriver = testingSetup().createComponentDriver()
// 2 - get the spied service via the injector
myServiceSpy = myComponentDriver.injector.get(MyService)
// 3 - Mock the returned value, visit the jasmine-auto-spies page to get more informations
questionServiceSpy.getQuestion.and.nextWith(questionData)
})
})
the componentTestingSetup method sets up the TestBed under the hood. You still can access it if needed like this :
componentDriver.TestBed
In this example, we use the jasmine-given library to write our test suite with Given, When, Then functions.
Given : describe the inputWhen : describe the actionThen : describe the outputYou can use one of my other packages angular-karma-gwt to setup everything you need to use
jasmine-givenand some other cool stuff. A simpleng add angular-karma-gwtwill download the packages and set up everything you need automatically.
Let's assume that our app is composed by :
@Component({
template: `
<div class="question">{{ questionData.question }}</div>
<div *ngFor="let answer of questionData.answers" [answerDirective]="answer">{{ answer }}</div>
<button>Previous</button>
<button>Next</button>
`,
providers: [LoggerService]
})
class QuestionComponent {
questionData: QuestionData
constructor(questionService: QuestionService) {
questionService
.getQuestion()
.pipe(first())
.subscribe(question => {
logger.log(question)
this.questionData = question
})
}
}
@Injectable()
class QuestionService {
@AsyncSpyable() // => Decorator from the jasmine-auto-spies package
getQuestion(): Observable<QuestionData> {
return of(null)
}
}
@Injectable()
export class LoggerService {
log(data): void {
console.log(data)
}
}
@Directive({
selector: '[answerDirective]'
})
class AnswerDirective {
@Input('answerDirective') answer: string
}
This class can be empty and only extend the ComponentDriver class. But here, we added some methods to query some elements (DOM and directives) of our component to test the UI.
You can query child component in the same way you query directives (components are directives).
class QuestionComponentDriver extends ComponentDriver<QuestionComponent> {
get questionElement() {
return this.querySelector('.question')
}
get buttonElements() {
return this.querySelectorAll<HTMLButtonElement>('button')
}
get firstAnswerDirective() {
return this.queryDirective(AnswerDirective)
}
get answerDirectives() {
return this.queryDirectiveAll(AnswerDirective)
}
}
2 - Write your test suite
function testingSetup() {
return componentTestingSetup({
componentClass: QuestionComponent,
driver: QuestionComponentDriver,
servicesToStub: [QuestionService],
declarations: [AnswerDirective]
})
}
describe('QuestionComponent', () => {
let questionComponentDriver: QuestionComponentDriver
let questionServiceSpy: Spy<QuestionService>
const loggerService: Spy<LoggerService> = createSpyFromClass(LoggerService)
beforeEach(() => {
questionComponentDriver = testingSetup(loggerService).createComponentDriver()
questionServiceSpy = questionComponentDriver.injector.get(QuestionService)
})
// jasmine-given magic here
describe('GIVEN a question is available THEN it is displayed', () => {
let questionData: QuestionData
// Input
Given(() => {
questionData = {
question: 'What do you prefer ?',
answers: ['pizza', 'burger']
}
questionServiceSpy.getQuestion.and.nextWith(questionData)
})
// Action
When(() => {
questionComponentDriver.detectChanges()
})
// Output
Then(() => {
// testing our component data
expect(questionComponentDriver.componentInstance.questionData).toEqual(questionData)
// testing the DOM element that displays the question
expect(questionComponentDriver.questionElement.textContent).toContain(questionData.question)
// testing the buttons 'previous' and 'next'
const [btnPrevious, btnNext] = questionComponentDriver.buttonElements
expect(btnPrevious.textContent).toContain('Previous')
expect(btnNext.textContent).toContain('Next')
// testing the first AnswerDirective
expect(questionComponentDriver.firstAnswerDirective.answer).toBe(questionData.answers[0])
//testing all the AnswerDirectives
const [firstAnswer, secondAnswer] = questionComponentDriver.answerDirectives
expect(firstAnswer.answer).toBe(questionData.answers[0])
expect(secondAnswer.answer).toBe(questionData.answers[1])
expect(loggerService.log).toHaveBeenCalledWith(questionData)
})
})
})
FAQs
Test Angular components in jasmine with component drivers
The npm package angular-unit-component-driver receives a total of 4 weekly downloads. As such, angular-unit-component-driver popularity was classified as not popular.
We found that angular-unit-component-driver demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.