Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions src/toast/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ export default function ($timeout) {
options : '=?toastOptions',
},
link ($scope, $element) {
let defaults = _.defaults(Config, $scope.options);
let defaults = _.defaultsDeep($scope.options, Config);

$scope.isOpen = false;
$scope.type = defaults.type || '';

/**
* 显示
Expand All @@ -30,6 +33,7 @@ export default function ($timeout) {
$timeout(() => {
$element.addClass(options.enterClass);
$timeout(callback.bind(null), options.during);
$scope.isOpen = true;
});
};

Expand All @@ -43,8 +47,9 @@ export default function ($timeout) {

options = _.defaults(defaults, options);

$element.addClass(options.leaveClass);
$element.removeClass(options.enterClass).addClass(options.leaveClass);
$timeout(callback.bind(null), options.during);
$scope.isOpen = false;
};

/**
Expand All @@ -63,10 +68,12 @@ export default function ($timeout) {

$scope.show(function () {
setTimeout(function () {
$scope.hide();
$scope.dismiss();
},
defaults.delay || 1500);
});

$scope.$digest();
}
};
}
6 changes: 5 additions & 1 deletion src/toast/index.jade
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
.toast(ng-transclude)
.toast(ng-class='{\
correct : "correct" === type,\
error : "error" === type,\
info : "info" === type,\
}', ng-transclude)
14 changes: 7 additions & 7 deletions src/toast/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
if (window.angular && window.angular.env && window.angular.env.QT_UI_LOG) {
window.console.log('qt-angular-ui/src/toast load');
}

import './index.scss';
import angular from 'angular';
import Component from './component';
import Service from './service';

import component from './_index';

export default component;
export default angular.module('qtAngularUi.toast', [])
.directive('toast', Component)
.provider('$toast', Service)
.name;
174 changes: 174 additions & 0 deletions src/toast/index.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/* eslint max-nested-callbacks: off */
/* eslint-env mocha */
/* global expect */

import _ from 'lodash';
import angular from 'angular';
import 'angular-mocks';

import sinon from 'sinon';
import $ from 'jquery';
import Toast from './index';
import Config from './config';

describe('Toast 组件', function () {
const NEST_CONTENT = 'Message';
const { module, inject } = angular.mock;

beforeEach(function () {
// 设置延迟消失时间为 0
Config.during = 10;
Config.delay = 10;

// 初始化 Toast 组件
module(Toast);

// 清场
document.body.innerHTML = '';
});


describe('结构规范', function () {
it('会返回组件名称', function () {
expect('Toast').to.be.a('string');
});

it('能进行初始化, 并且能自定义信息', function () {
inject(function ($rootScope, $compile) {
let $scope = $rootScope.$new();
let $toast = $compile(`<toast>${NEST_CONTENT}</toast>`)($scope);

expect($toast.text()).to.equal(NEST_CONTENT);
});
});

it('拥有自己的作用域', function () {
inject(function ($rootScope, $compile) {
let $scope = $rootScope.$new();
let $element = $compile(`<toast>${NEST_CONTENT}</toast>`)($scope);
let $nestScope = angular.element($element[0].childNodes[0]).scope();

expect($scope.$id).to.not.equal($nestScope.$id);
});
});

it('应该拥有额定的结构', function () {
inject(function ($rootScope, $compile) {
let $element = $compile(`<toast>${NEST_CONTENT}</toast>`)($rootScope.$new());
let $scope = angular.element($element[0].childNodes[0]).scope();

expect($scope.show).to.be.a('function');
expect($scope.hide).to.be.a('function');
expect($scope.dismiss).to.be.a('function');
expect($scope.isOpen).to.be.a('boolean');
});
});

});

describe('触发流程', function () {
it('能够自动完成淡入淡出', function (done) {
this.timeout(1000);

inject(function ($rootScope, $compile, $timeout) {
let $element = $compile(`<toast>${NEST_CONTENT}</toast>`)($rootScope.$new());
let $scope = angular.element($element[0].childNodes[0]).scope();

angular.element(document.body).append($element);
expect($scope.isOpen).to.be.false;
expect(document.getElementsByClassName('toast').length).to.equal(1);

let hideCompleted = function () {
expect($scope.isOpen).to.be.false;
expect(document.getElementsByClassName('toast').length).to.equal(0);
done();
};

let delayCompleted = function () {
expect($scope.dismiss.calledOnce).to.be.true;
expect($scope.hide.called).to.be.true;
expect($scope.isOpen).to.be.false;

$timeout.flush();
setTimeout(hideCompleted, Config.during);
};

let showCompleted = function () {
expect($scope.isOpen).to.be.true;

$timeout.flush();
setTimeout(delayCompleted, Config.delay);
};

// 监听 hide 事件
sinon.spy($scope, 'dismiss');
sinon.spy($scope, 'hide');

// 开始淡入窗口
$timeout.flush();
setTimeout(showCompleted, Config.during);

});
});
});

describe('服务', function () {

it('能淡入到 body 中', function (done) {
this.timeout(1000);

inject(function ($toast, $timeout) {
$toast.create(NEST_CONTENT, Config);

let $jqToast = $('.toast');
let $scope = angular.element($jqToast[0].childNodes[0]).scope();

// 检查 DOM 节点
expect($jqToast.length).to.equal(1);
expect($jqToast.text()).to.equal(NEST_CONTENT);


// 检查属性
expect($scope.isOpen).to.be.false;

// FadeIn
$timeout.flush();
setTimeout(function () {
expect($scope.isOpen).to.be.true;

// FadeOut
$timeout.flush();
setTimeout(function () {
expect($scope.isOpen).to.be.false;

done();
}, Config.during + Config.delay + 10);
}, 1);
});
});

it('能更改类型', function () {
inject(function ($toast) {
_.forEach(['correct', 'error', 'info'], function (type) {
$toast.create(NEST_CONTENT, _.assign(Config, { type }));

let $jqToast = $(`.toast.${type}`);

let scope = angular.element($jqToast[0].childNodes[0]).scope();
expect(scope.type).to.equal(type);
expect($(`.toast.${type}`).length).to.equal(1);
});
});
});

it('能同时触发', function () {
inject(function ($toast) {
$toast.create(NEST_CONTENT);
$toast.create(NEST_CONTENT);

expect(document.getElementsByClassName('toast').length).to.equal(2);
});
});

});
});
8 changes: 5 additions & 3 deletions src/toast/service.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ export default class toastService {

return {
create (message, options = defaults) {
if (_.isString(options)) {
return this.create(message, { type: options });
}

let $toast = angular.element(`<toast>${message}</toast>`);
let $scope = $rootScope.$new();

Expand All @@ -24,9 +28,7 @@ export default class toastService {
}

let $element = $compile($toast)($scope);
angular.element(document).ready(function () {
angular.element(document.body).append($element);
});
angular.element(document.body).append($element);

openScopes.push($scope);
},
Expand Down