Skip to content

Commit

Permalink
Merge pull request #157 from Stabzs/master
Browse files Browse the repository at this point in the history
Merge from Stabzs/master for #152
  • Loading branch information
Stabzs committed Oct 23, 2015
2 parents 2dd9b05 + 7861518 commit 96c449a
Show file tree
Hide file tree
Showing 7 changed files with 310 additions and 18 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
node_modules
components
bower_components
coverage

# IntelliJ
.idea/
Expand Down
35 changes: 29 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,22 +105,45 @@ There are four types of body renderings: trustedHtml', 'template', 'templateWith
- directive
- Will use the `toast.body` argument to represent the name of a directive that you want to render as the toast's body, else it will fallback to the template bound to the `'body-template': 'toasterBodyTmpl.html'` configuration option.

```js
```js
// The toast pop call, passing in a directive name to be rendered
toaster.pop({
type: 'info',
body: 'bind-unsafe-html',
bodyOutputType: 'directive'
type: 'info',
body: 'bind-unsafe-html',
bodyOutputType: 'directive'
});
```
```js
```

```js
// The directive that will be dynamically rendered
.directive('bindUnsafeHtml', [function () {
return {
template: "<span style='color:orange'>Orange directive text!</span>"
};
}])
```
- Will use the `toast.directiveData` argument to accept data that will be bound to the directive's scope.

```js
// The toast pop call, passing in a directive name to be rendered
toaster.pop({
type: 'info',
body: 'bind-name',
bodyOutputType: 'directive',
directiveData: { name: 'Bob' }
});
```
```js
// The directive that will be dynamically rendered
.directive('bindName', [function () {
return {
template: "<span style='color:orange'>Hi {{directiveData.name}}!</span>"
};
}])
```
There are additional documented use cases in these [tests](test/directiveTemplateSpec.js).

All four options can be configured either globally for all toasts or individually per toast.pop() call. If the `body-output-type` option is configured on the toast, it will take precedence over the global configuration for that toast instance.

Expand Down
79 changes: 79 additions & 0 deletions karma.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Karma configuration
// Generated on Wed Oct 21 2015 12:37:04 GMT-0600 (Mountain Daylight Time)

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: [
'https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js',
'https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-mocks.js',
'toaster.js',
'test/**/*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: {
'toaster.js': ['coverage']
},


// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress', 'coverage'],


// 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: ['Chrome'],

plugins: [
'karma-chrome-launcher',
'karma-coverage',
'karma-jasmine'
],

// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,

coverageReporter: {
type: 'html',
dir: 'coverage/'
}
});
};
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@
"type": "git",
"url": "https://github.com/jirikavi/AngularJS-Toaster.git"
},
"dependencies": {
},
"dependencies": {},
"devDependencies": {
"angular": ">1.2.6",
"angular-animate": "~1.2.8"
"angular-animate": "~1.2.8",
"angular-mocks": "^1.4.7",
"karma": "^0.13.14",
"karma-coverage": "^0.5.3",
"karma-jasmine": "^0.3.6"
}
}
170 changes: 170 additions & 0 deletions test/directiveTemplateSpec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/* global describe global it global beforeEach global angular global inject global expect */

'use strict';

describe('directiveTemplate', function () {
createDirectives();

var toaster, scope, $compile;

beforeEach(function () {
// load dependencies
module('testApp');
module('toaster')

// inject the toaster service
inject(function (_toaster_, _$rootScope_, _$compile_) {
toaster = _toaster_;
scope = _$rootScope_;
$compile = _$compile_;
});
});

it('should load and render the referenced directive template text', function () {
var container = compileContainer();
pop({ type: 'info', body: 'bind-template-only', bodyOutputType: 'directive' });

expect(container[0].innerText).toBe('×here is some great new text! It was brought in via directive!');
});

it('should bind directiveData to the directive template', function () {
var container = compileContainer();
pop({ type: 'info', body: 'bind-template-with-data', bodyOutputType: 'directive', directiveData: { name: 'Bob' } });

expect(container[0].innerText).toBe('×Hello Bob');
});

it('should parse type string directiveData to an object', function () {
var container = compileContainer();
pop({ type: 'info', body: 'bind-template-with-data', bodyOutputType: 'directive', directiveData: '{ "name": "Bob" }' });

expect(container[0].innerText).toBe('×Hello Bob');
});

it('should render type number directiveData', function () {
var container = compileContainer();
pop({ type: 'info', body: 'bind-template-with-numeric-data', bodyOutputType: 'directive', directiveData: 2 });

expect(container[0].innerText).toBe('×1 + 1 = 2');
});

it('should bind Attribute-restricted templates', function () {
var container = compileContainer();
pop({ type: 'info', body: 'bind-template-only', bodyOutputType: 'directive', directiveData: { name: 'Bob' } });

expect(container[0].innerText).toBe('×here is some great new text! It was brought in via directive!');
});

it('should bind unrestricted templates', function () {
var container = compileContainer();
pop({ type: 'info', body: 'unrestricted-template', bodyOutputType: 'directive' });

expect(container[0].innerText).toBe('×Unrestricted Template');
});

it('should not bind Element-restricted templates', function () {
var container = compileContainer();
pop({ type: 'info', body: 'element-template', bodyOutputType: 'directive' });

expect(container[0].innerText).toBe('×');
expect(container[0].innerText).not.toBe('×Element Template');
});

it('should not bind Class-restricted templates', function () {
var container = compileContainer();
pop({ type: 'info', body: 'class-template', bodyOutputType: 'directive' });

expect(container[0].innerText).toBe('×');
expect(container[0].innerText).not.toBe('×Class Template');
});

it('should throw an error if directiveName argument is not passed via body', function () {
var container = compileContainer();
var hasError = false;

expect(container[0].innerText).toBe('');

try {
pop({ type: 'info', bodyOutputType: 'directive' });
} catch (e) {
expect(e.message).toBe('A valid directive name must be provided via the toast body argument when using bodyOutputType: directive');
hasError = true;
}

expect(container[0].innerText).toBe('×');
expect(hasError).toBe(true);
});

it('should throw an error if directiveName argument is an empty string', function () {
var container = compileContainer();
var hasError = false;

expect(container[0].innerText).toBe('');

try {
pop({ type: 'info', body: '', bodyOutputType: 'directive' });
} catch (e) {
expect(e.message).toBe('A valid directive name must be provided via the toast body argument when using bodyOutputType: directive');
hasError = true;
}

expect(container[0].innerText).toBe('×');
expect(hasError).toBe(true);
});

it('should throw an error if the directive could not be found', function () {
var hasError = false;

compileContainer();

try {
pop({ type: 'info', body: 'non-existent-directive', bodyOutputType: 'directive' });
} catch (e) {
expect(e.message).toBe('non-existent-directive could not be found.');
hasError = true;
}

expect(hasError).toBe(true);
});


function compileContainer() {
var element = angular.element('<toaster-container></toaster-container>');
$compile(element)(scope);
scope.$digest();

return element;
}

function pop(params) {
toaster.pop(params);

// force new toast to be rendered
scope.$digest();
}

function createDirectives() {
angular.module('testApp', [])
.directive('bindTemplateOnly', function () {
return {
restrict: 'A',
template: 'here is some great new text! <span style="color:orange">It was brought in via directive!</span>'
}
})
.directive('bindTemplateWithData', function () {
return { template: 'Hello {{directiveData.name}}' }
})
.directive('bindTemplateWithNumericData', function () {
return { template: '1 + 1 = {{directiveData}}' }
})
.directive('elementTemplate', function () {
return { restrict: 'E', template: 'Element Template' }
})
.directive('classTemplate', function () {
return { restrict: 'C', template: 'Class Template' }
})
.directive('unrestrictedTemplate', function () {
return { template: 'Unrestricted Template' }
});
}
})
Loading

0 comments on commit 96c449a

Please sign in to comment.