diff --git a/package.json b/package.json
index ce17953..aa2a8c8 100644
--- a/package.json
+++ b/package.json
@@ -25,6 +25,7 @@
"devDependencies": {
"angular": "^1.6.3",
"angular-mocks": "^1.6.3",
+ "angular-ui-router": "^0.4.2",
"babel-cli": "^6.24.0",
"babel-eslint": "^7.2.0",
"babel-loader": "^6.4.1",
diff --git a/src/utilitybar/_index.js b/src/utilitybar/_index.js
deleted file mode 100644
index ee80dc3..0000000
--- a/src/utilitybar/_index.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import angular from 'angular';
-import Utilitybar from './component';
-import Transclude from './transclude.component';
-import Service from './service';
-
-export default angular.module('qtAngularUi.utilitybar', [])
-.directive('utilitybar', Utilitybar)
-.directive('utilitybarTransclude', Transclude)
-.provider('$utilitybar', Service)
-.name;
diff --git a/src/utilitybar/component.js b/src/utilitybar/component.js
index 3840914..46eb849 100644
--- a/src/utilitybar/component.js
+++ b/src/utilitybar/component.js
@@ -35,7 +35,7 @@ export default function ($compile, $stateParams, $utilitybar) {
*/
$scope.goback = function () {
if ($stateParams.hasOwnProperty('dt') && $stateParams.dt) {
- angular.redirect($stateParams.dt);
+ window.location.replace($stateParams.dt);
}
else if (0 < window.history.length) {
window.history.back();
diff --git a/src/utilitybar/index.js b/src/utilitybar/index.js
index dc6daf6..4b7810a 100644
--- a/src/utilitybar/index.js
+++ b/src/utilitybar/index.js
@@ -1,9 +1,12 @@
-if (window.angular && window.angular.env && window.angular.env.QT_UI_LOG) {
- window.console.log('qt-angular-ui/src/utilitybar load');
-}
-
import './index.scss';
-import component from './_index';
+import angular from 'angular';
+import Utilitybar from './component';
+import Transclude from './transclude.component';
+import Service from './service';
-export default component;
\ No newline at end of file
+export default angular.module('qtAngularUi.utilitybar', [])
+.directive('utilitybar', Utilitybar)
+.directive('utilitybarTransclude', Transclude)
+.provider('$utilitybar', Service)
+.name;
diff --git a/src/utilitybar/utilitybar.spec.js b/src/utilitybar/utilitybar.spec.js
new file mode 100644
index 0000000..3c14c31
--- /dev/null
+++ b/src/utilitybar/utilitybar.spec.js
@@ -0,0 +1,217 @@
+/* eslint max-nested-callbacks: off */
+/* eslint-env mocha */
+/* global expect */
+
+import angular from 'angular';
+import UIRouter from 'angular-ui-router';
+import 'angular-mocks';
+
+import $ from 'jquery';
+import Utilitybar from './index';
+
+/**
+ * $('a').click()无效的解决方法
+ * @param {element} el
+ * clickElement($('a')[0]);
+ */
+let clickElement = function (el) {
+ let ev = document.createEvent('MouseEvent');
+ ev.initMouseEvent('click', true, true, window, null, 0, 0, 0, 0, false, false, false, false, 0, null);
+ el.dispatchEvent(ev);
+};
+
+describe('Utilitybar 组件', function () {
+ const { module, inject } = angular.mock;
+
+ /**
+ * window.history.back() & window.location.replace() 在 phantomjs 中不作用
+ * 重写方法用于测试
+ */
+ const ORIGIN = window.location.origin;
+ const HREF = window.location.href;
+ const GOBACK = ORIGIN + '/goback';
+ const GOBACKDT = ORIGIN + '/gobackdt';
+
+ window.history.back = function () {
+ window.history.replaceState(null, null, GOBACK);
+ };
+
+ window.location.replace = function (dt) {
+ window.history.replaceState(null, null, dt);
+ };
+
+ beforeEach(function () {
+ module(UIRouter);
+
+ // 初始化 Utilitybar 组件
+ module(Utilitybar);
+
+ // url设置回默认值
+ window.location.replace(HREF);
+
+ // 清场
+ document.body.innerHTML = '';
+ });
+
+ describe('结构规范', function () {
+ it('会返回组件名称', function () {
+ expect(Utilitybar).to.be.a('string');
+ });
+
+ it('能够进行初始化', function () {
+ inject(function ($rootScope, $compile) {
+ let $element = $compile('')($rootScope.$new());
+
+ expect($element.find('a').length).to.equal(1);
+ });
+ });
+
+ it('拥有自己的作用域', function () {
+ inject(function ($rootScope, $compile) {
+ let $newScope = $rootScope.$new();
+ let $element = $compile('')($newScope);
+ let $scope = $element.children().scope();
+
+ expect($scope.$id).to.not.equal($newScope.$id);
+ });
+ });
+
+ it('拥有固定的结构', function () {
+ inject(function ($rootScope, $compile) {
+ let $element = $compile('')($rootScope.$new());
+ let $scope = $element.children().scope();
+
+ expect($scope.toggle).to.be.a('function');
+ expect($scope.goback).to.be.a('function');
+ });
+ });
+ });
+
+ describe('触发流程', function () {
+ it('能够显示和隐藏', function () {
+ inject(function ($rootScope, $compile) {
+ let $newScope = $rootScope.$new();
+ $newScope.isOpen = true;
+ let $element = $compile('')($newScope);
+ let $scope = $element.children().scope();
+
+ angular.element(document.body).append($element);
+ let $utilitybar = $('.utilitybar');
+
+ $scope.$digest();
+ expect($utilitybar.hasClass('active')).to.be.true;
+
+ $scope.toggle(false);
+ $scope.$digest();
+ expect($utilitybar.hasClass('active')).to.be.false;
+
+ // 非 Boolean 值无效
+ $scope.toggle('true');
+ $scope.$digest();
+ expect($utilitybar.hasClass('active')).to.be.false;
+ });
+ });
+
+ it('能够点击返回并有效返回', function () {
+ module(function ($stateProvider) {
+ $stateProvider
+ .state('test', {
+ url: '/?dt',
+ });
+ });
+
+ inject(function ($rootScope, $compile, $state) {
+ let $element = $compile('')($rootScope.$new());
+
+ angular.element(document.body).append($element);
+ expect(window.location.href).to.equal(HREF);
+
+ let $goback = $('[ng-click="goback()"]');
+
+ clickElement($goback[0]);
+ expect(window.location.href).to.equal(GOBACK);
+
+ $state.go('test', { dt: GOBACKDT });
+ $rootScope.$digest();
+ clickElement($goback[0]);
+ expect(window.location.href).to.equal(GOBACKDT);
+ });
+ });
+
+ it('能够嵌入内容,并可设置继承指令的scope或父的scope', function () {
+ inject(function ($rootScope, $compile) {
+ let $newScope = $rootScope.$new();
+ $newScope.test = false;
+ $newScope.goback = function () {
+ window.location.replace(GOBACKDT);
+ };
+
+ let tmlp = 'test';
+ let $element = $compile(tmlp)($newScope);
+
+ angular.element(document.body).append($element);
+ expect(window.location.href).to.equal(HREF);
+
+ let $goOrigin = $('.go-origin');
+ let $goback = $('.goback');
+
+ clickElement($goOrigin[0]);
+ expect(window.location.href).to.equal(GOBACKDT);
+
+ clickElement($goback[0]);
+ expect(window.location.href).to.equal(GOBACK);
+ });
+ });
+
+ it('销毁时,最后一个继承它的isOpen', function () {
+ inject(function ($rootScope, $compile) {
+ let $newScope = $rootScope.$new();
+ $newScope.isOpen = true;
+ let $element1 = $compile('')($newScope);
+ let $element2 = $compile('')($rootScope.$new());
+ let $element3 = $compile('')($rootScope.$new());
+ let $scope1 = $element1.children().scope();
+ let $scope2 = $element2.children().scope();
+ let $scope3 = $element3.children().scope();
+
+ expect($scope1.isOpen).to.be.true;
+ expect($scope2.isOpen).to.be.undefined;
+ expect($scope3.isOpen).to.be.undefined;
+
+ $scope1.$destroy();
+ expect($scope1.isOpen).to.be.true;
+ expect($scope2.isOpen).to.be.undefined;
+ expect($scope3.isOpen).to.be.true;
+ });
+ });
+ });
+
+ describe('服务', function () {
+ it('配置某些页面隐藏', function () {
+ module(function ($utilitybarProvider, $stateProvider) {
+ $stateProvider
+ .state('test', {
+ template:'',
+ });
+
+ $utilitybarProvider.configure({
+ filterModules: [
+ // 下面是 state 的名字
+ 'test',
+ ],
+ });
+ });
+
+ inject(function ($rootScope, $compile, $state) {
+ let $uiview = $compile('')($rootScope.$new());
+ angular.element(document.body).append($uiview);
+
+ $state.go('test');
+ $rootScope.$digest();
+
+ let utilitybar = $('.utilitybar');
+ expect(utilitybar.hasClass('active')).to.be.false;
+ });
+ });
+ });
+});