ตอนที่ผ่านมา ของ unit test AngularJS เราได้เขียน unit test ของ controller แล้ว มาวันนี้เราจะได้มาลองเขียน AngularJS Directive unit test กันครับ
ผมคิดว่าการสร้าง unit test Angular directive ค่อนข้างมีความซับซ้อนมากกว่า test controller และ service ดังนั้น ค่อยๆ ทำความเข้าใจไปด้วยกันนะครับ
ขั้นตอนต่างๆ เป็นดังนี้
#สร้าง Angular directive สำหรับ subscribe ด้วย email ให้เราสร้าง JavaScript file ใหม่ใน folder src ตั้งชื่อว่า emailSubscriptionDirective.js แล้วแก้ไข file เป็นดังนี้
src/emailSubscriptionDirective.js
var app = angular.module('emailSubscriptionTestApp', []);
app.directive('emailSubscription', function () {
var emailSuscriptionDirective = {
restrict: 'E',
scope: {
email: "="
},
controller: function ($scope) {
$scope.hasSubscribed = false;
$scope.subscribe = function () {
$scope.hasSubscribed = true;
console.log("Thank you for subscribing, we will send email to " + $scope.email);
};
},
template: '<input id="txtEmail" type="text" ng-model="email" /> ' +
'<input id="btnSubscribe" type="button" ng-click="subscribe()" />'
};
return emailSuscriptionDirective;
});
อธิบายคำสั่ง
ให้เราสร้าง JavaScript file ใหม่ใน folder spec ตั้งชื่อว่า emailSubscriptionDirectiveSpec.js แล้วแก้ไข file เป็นดังนี้
spec/emailSubscriptionDirectiveSpec.js
describe("myDirective", function () {
it('user click subscribe, then scope.hasSubscribed changed to true', function () {
var el = null;
var scope = null;
angular.mock.module('emailSubscriptionTestApp');
angular.mock.inject(function ($compile, $rootScope) {
$rootScope.email = null;
var htmlElement = angular.element('<email-subscription email="email"></email-subscription>');
el = $compile(htmlElement)($rootScope);
$rootScope.$digest();
scope = el.isolateScope();
});
var emailTextInput = el.find("#txtEmail");
emailTextInput.val("[email protected]");
emailTextInput.trigger('input');
var button = el.find("#btnSubscribe");
button.trigger("click");
expect(scope.hasSubscribed).toBe(true);
});
});
อธิบายคำสั่ง
!!! อย่าลืมเพิ่ม jQuery เข้าไปใน karma config file ก่อน run test
แก้ไข kamar.conf.js เป็นดังนี้ kamar.conf.js
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],
// list of files / patterns to load in the browser
files: [
'lib/jquery-2.2.0.min.js',
'lib/angular-1.5.0/angular.min.js',
'lib/angular-1.5.0/angular-mocks.js',
'src/**/*.js',
'spec/**/*.js'
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity
})
};
ไปที่ root ของ project เปิด Windows command line หรือ terminal แล้วพิมพ์คำสั่งต่อไปนี้ เพื่อทดสอบการทำงานของ unit test
npm test
ผลลัพลัพธ์ที่หน้าจอ command line
คำสั่งเพื่อทดสอบว่า email ที่เรากรอกไปถูก set ค่าถูกต้องหรือไม่ เราเพิ่ม test case เข้าไปใน describe callback function ได้เลยครับ
it('user click subscribe, scope email set correctly', function () {
var el = null;
var scope = null;
angular.mock.module('emailSubscriptionTestApp');
angular.mock.inject(function ($compile, $rootScope) {
$rootScope.email = null;
var htmlElement = angular.element('<email-subscription email="email"></email-subscription>');
el = $compile(htmlElement)($rootScope);
$rootScope.$digest();
scope = el.isolateScope();
});
var emailTextInput = el.find("#txtEmail");
var email = "[email protected]";
emailTextInput.val(email);
emailTextInput.trigger('input');
var button = el.find("#btnSubscribe");
button.trigger("click");
expect(scope.email).toBe(email);
});
ผลลัพธ์การทำงาน
หลังจากได้เรียนรู้การเขียน unit test สำหรับ directive ผมหวังว่าผู้อ่านจะได้แนวคิดการใช้งาน และสามารถนำไปประยุกต์ต่อได้ การเขียน unit test directive ค่อนข้างมีความซับซ้อนมากกว่า service และ controller แต่เราก็ไม่อยากจะปล่อยผ่านไม่ test ส่วนนี้ เพราะเมื่อใดที่เราแก้ไข เราก็ไม่รู้เลยว่า function การทำงาน ยังทำถูกต้องอยู่อีกไหม และต้องมา manual test อีกรอบ
หลังจากได้อ่านกันแล้ว ใครมีคำถามข้อสงสัยใดๆ comment มาได้เลยนะครับ ขอให้ทุกคนสนุกกับการเขียน code, codesanook ขอบคุณครับ
เมื่อโหลดไปแล้วใช้คำสั่ง npm install package ต่างๆ ก็จะโหลดให้โดยอัตโนมัติครับ