angular-material-npfixed
Version:
The Angular Material project is an implementation of Material Design in Angular.js. This project provides a set of reusable, well-tested, and accessible Material Design UI components. Angular Material is supported internally at Google by the Angular.js, M
1,656 lines (1,304 loc) • 59.9 kB
JavaScript
describe('$mdDialog', function() {
var $mdDialog, $rootScope;
var runAnimation;
beforeEach(module('material.components.dialog', 'ngSanitize'));
beforeEach(inject(function($$q, $animate, $injector) {
$mdDialog = $injector.get('$mdDialog');
$rootScope = $injector.get('$rootScope');
// Spy on animation effects.
spyOn($animate, 'leave').and.callFake(function(element) {
element.remove();
return $$q.when();
});
spyOn($animate, 'enter').and.callFake(function(element, parent) {
parent.append(element);
return $$q.when();
});
}));
beforeEach(inject(function($material) {
runAnimation = function() {
$material.flushInterimElement();
};
}));
describe('md-dialog', function() {
it('should have `._md` class indicator', inject(function($compile, $rootScope) {
var element = $compile('<md-dialog></md-dialog>')($rootScope.$new());
expect(element.hasClass('_md')).toBe(true);
}));
});
describe('#alert()', function() {
hasConfigurationMethods('alert', [
'title', 'htmlContent', 'textContent', 'ariaLabel',
'ok', 'targetEvent', 'theme'
]);
it('shows a basic confirm dialog without content', inject(function($animate, $rootScope, $mdDialog) {
var parent = angular.element('<div>');
var resolved = false;
$mdDialog.show(
$mdDialog
.confirm()
.parent(parent)
.title('')
.css('someClass anotherClass')
.ok('Next')
.cancel("Back")
).then(function() {
resolved = true;
});
$rootScope.$apply();
runAnimation();
var mdContainer = angular.element(parent[0].querySelector('.md-dialog-container'));
var mdDialog = mdContainer.find('md-dialog');
var mdContent = mdDialog.find('md-dialog-content');
var title = mdContent.find('h2');
var contentBody = mdContent[0].querySelector('.md-dialog-content-body');
var buttons = parent.find('md-button');
var css = mdDialog.attr('class').split(' ');
expect(title.text()).toBe('');
expect(contentBody.textContent).toBe('');
expect(css).toContain('someClass');
expect(css).toContain('anotherClass');
buttons.eq(0).triggerHandler('click');
$rootScope.$apply();
runAnimation();
expect(resolved).toBe(true);
}));
it('shows a basic alert dialog', inject(function($animate, $rootScope, $mdDialog) {
var parent = angular.element('<div>');
var resolved = false;
$mdDialog.show(
$mdDialog
.alert()
.parent(parent)
.title('Title')
.textContent('Hello world')
.theme('some-theme')
.css('someClass anotherClass')
.ok('Next')
).then(function() {
resolved = true;
});
$rootScope.$apply();
runAnimation();
var mdContainer = angular.element(parent[0].querySelector('.md-dialog-container'));
var mdDialog = mdContainer.find('md-dialog');
var mdContent = mdDialog.find('md-dialog-content');
var title = mdContent.find('h2');
var contentBody = mdContent[0].querySelector('.md-dialog-content-body');
var buttons = parent.find('md-button');
var theme = mdDialog.attr('md-theme');
var css = mdDialog.attr('class').split(' ');
expect(title.text()).toBe('Title');
expect(contentBody.textContent).toBe('Hello world');
expect(buttons.length).toBe(1);
expect(buttons.eq(0).text()).toBe('Next');
expect(theme).toBe('some-theme');
expect(css).toContain('someClass');
expect(css).toContain('anotherClass');
expect(mdDialog.attr('role')).toBe('alertdialog');
buttons.eq(0).triggerHandler('click');
$rootScope.$apply();
runAnimation();
expect(resolved).toBe(true);
}));
it('should normally use the default theme', inject(function($animate, $rootScope, $mdDialog, $compile) {
var dialogParent = angular.element('<div>');
$mdDialog.show(
$mdDialog
.alert()
.parent(dialogParent)
.title("Title")
.textContent("Themed Dialog")
.ok('Close')
);
$rootScope.$apply();
runAnimation();
var mdContainer = angular.element(dialogParent[0].querySelector('.md-dialog-container'));
var mdDialog = mdContainer.find('md-dialog');
expect(mdDialog.attr('md-theme')).toBe('default');
}));
it('should apply the specified theme', inject(function($animate, $rootScope, $mdDialog, $compile) {
var dialogParent = angular.element('<div>');
$mdDialog.show(
$mdDialog
.alert()
.parent(dialogParent)
.title("Title")
.theme('myTheme')
.textContent("Themed Dialog")
.ok('Close')
);
$rootScope.$apply();
runAnimation();
var mdContainer = angular.element(dialogParent[0].querySelector('.md-dialog-container'));
var mdDialog = mdContainer.find('md-dialog');
expect(mdDialog.attr('md-theme')).toBe('myTheme');
}));
it('should focus `md-dialog-content` on open', inject(function($mdDialog, $rootScope, $document) {
jasmine.mockElementFocus(this);
var parent = angular.element('<div>');
$mdDialog.show(
$mdDialog.alert({
template: '<md-dialog>' +
'<md-dialog-content tabIndex="0" md-autofocus>' +
'<p>Muppets are the best</p>' +
'</md-dialog-content>' +
'</md-dialog>',
parent: parent
})
);
runAnimation(parent.find('md-dialog'));
expect($document.activeElement).toBe(parent[0].querySelector('md-dialog-content'));
}));
it('should warn if the template contains a ng-cloak', inject(function($mdDialog, $rootScope, $document, $log) {
var parent = angular.element('<div>');
// Enable spy on $log.warn
spyOn($log, 'warn');
$mdDialog.show(
$mdDialog.alert({
template:
'<md-dialog ng-cloak>' +
'<md-dialog-content>' +
'<p>Muppets are the best</p>' +
'</md-dialog-content>' +
'</md-dialog>',
parent: parent
})
);
runAnimation(parent.find('md-dialog'));
// The $mdDialog should throw a warning about the `ng-cloak`.
expect($log.warn).toHaveBeenCalled();
}));
it('should use the prefixed id from `md-dialog` for `md-dialog-content`', inject(function ($mdDialog, $rootScope, $document) {
jasmine.mockElementFocus(this);
var parent = angular.element('<div>');
$mdDialog.show(
$mdDialog.alert({
template: '<md-dialog id="demoid">' +
'<md-dialog-content>' +
'<p>Muppets are the best</p>' +
'</md-dialog-content>' +
'</md-dialog>',
parent: parent
})
);
runAnimation();
var dialog = parent.find('md-dialog');
var content = parent[0].querySelector('md-dialog-content');
expect(content.id).toBe('dialogContent_' + dialog[0].id);
}));
it('should not clobber the id from `md-dialog` when there is no content', inject(function ($mdDialog, $rootScope, $document) {
jasmine.mockElementFocus(this);
var parent = angular.element('<div>');
$mdDialog.show(
$mdDialog.alert({
template: '<md-dialog id="demoid">' +
'<p>Muppets are the best</p>' +
'</md-dialog>',
parent: parent
})
);
runAnimation();
var dialog = parent.find('md-dialog');
expect(dialog[0].id).toBe('demoid');
}));
it('should apply a prefixed id for `md-dialog-content`', inject(function ($mdDialog, $rootScope, $document) {
jasmine.mockElementFocus(this);
var parent = angular.element('<div>');
$mdDialog.show(
$mdDialog.alert({
template: '<md-dialog>' +
'<md-dialog-content>' +
'<p>Muppets are the best</p>' +
'</md-dialog-content>' +
'</md-dialog>',
parent: parent
})
);
runAnimation();
var dialog = parent.find('md-dialog');
var content = parent[0].querySelector('md-dialog-content');
expect(content.id).toMatch(/dialogContent_[0-9]+/g);
}));
it('should remove `md-dialog-container` on mousedown mouseup and remove', inject(function($mdDialog, $rootScope, $timeout) {
jasmine.mockElementFocus(this);
var container, parent = angular.element('<div>');
$mdDialog.show(
$mdDialog.alert({
template: '<md-dialog>' +
'<md-dialog-content tabIndex="0">' +
'<p>Muppets are the best</p>' +
'</md-dialog-content>' +
'</md-dialog>',
parent: parent,
clickOutsideToClose: true
})
);
runAnimation();
container = angular.element(parent[0].querySelector('.md-dialog-container'));
container.triggerHandler({
type: 'mousedown',
target: container[0]
});
container.triggerHandler({
type: 'mouseup',
target: container[0]
});
$timeout.flush();
runAnimation();
container = angular.element(parent[0].querySelector('.md-dialog-container'));
expect(container.length).toBe(0);
}));
it('should remove `md-dialog-container` on scope.$destroy()', inject(function($mdDialog, $rootScope, $timeout) {
var container, parent = angular.element('<div>');
$mdDialog.show(
$mdDialog.alert({
template: '' +
'<md-dialog>' +
' <md-dialog-content tabIndex="0">' +
' <p>Muppets are the best</p>' +
' </md-dialog-content>' +
'</md-dialog>',
parent: parent
})
);
runAnimation(parent.find('md-dialog'));
$rootScope.$destroy();
container = angular.element(parent[0].querySelector('.md-dialog-container'));
expect(container.length).toBe(0);
}));
});
describe('#confirm()', function() {
hasConfigurationMethods('confirm', [
'title', 'htmlContent', 'textContent', 'ariaLabel',
'ok', 'cancel', 'targetEvent', 'theme'
]);
it('shows a basic confirm dialog with simple text content', inject(function($rootScope, $mdDialog) {
var parent = angular.element('<div>');
var rejected = false;
$mdDialog.show(
$mdDialog.confirm({
parent: parent
})
.title('Title')
.textContent('Hello world')
.ok('Next')
.cancel('Forget it')
).catch(function() {
rejected = true;
});
runAnimation();
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
var dialog = parent.find('md-dialog');
var title = parent.find('h2');
var contentBody = parent[0].querySelector('.md-dialog-content-body');
var buttons = parent.find('md-button');
expect(dialog.attr('role')).toBe('dialog');
expect(title.text()).toBe('Title');
expect(contentBody.textContent).toBe('Hello world');
expect(buttons.length).toBe(2);
expect(buttons.eq(0).text()).toBe('Next');
expect(buttons.eq(1).text()).toBe('Forget it');
buttons.eq(1).triggerHandler('click');
runAnimation();
expect(parent.find('h2').length).toBe(0);
expect(rejected).toBe(true);
}));
it('should allow htmlContent with simple HTML tags', inject(function($mdDialog) {
var parent = angular.element('<div>');
$mdDialog.show(
$mdDialog.confirm({
parent: parent,
ok: 'Next',
cancel: 'Back',
title: 'Which Way ',
htmlContent: '<div class="mine">Choose</div>'
})
);
runAnimation();
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
var content = angular.element(container[0].querySelector('.mine'));
expect(content.text()).toBe('Choose');
}));
it('should support the deprecated `content` method as text', inject(function($mdDialog) {
var parent = angular.element('<div>');
$mdDialog.show(
$mdDialog.confirm({
parent: parent,
ok: 'Next',
cancel: 'Back',
title: 'Which Way ',
content: '<div class="mine">Choose</div>'
})
);
runAnimation();
var contentBody = parent[0].querySelector('.md-dialog-content-body');
expect(contentBody.textContent).toBe('<div class="mine">Choose</div>');
}));
it('should NOT allow custom elements in confirm htmlContent', inject(function($mdDialog) {
var parent = angular.element('<div>');
$mdDialog.show(
$mdDialog.confirm({
parent: parent,
ok: 'Next',
cancel: 'Back',
title: 'Which Way ',
htmlContent: '<my-content class="mine">Choose</my-content> breakfast'
})
);
runAnimation();
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
var contentBody = container[0].querySelector('.md-dialog-content-body');
expect(contentBody.textContent).toBe('Choose breakfast');
}));
it('should NOT evaluate angular templates in confirm htmlContent', inject(function($mdDialog) {
var parent = angular.element('<div>');
$mdDialog.show(
$mdDialog.confirm({
parent: parent,
ok: 'Next',
cancel: 'Back',
title: 'Which Way ',
htmlContent: '{{1 + 1}}'
})
);
runAnimation();
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
var contentBody = container[0].querySelector('.md-dialog-content-body');
expect(contentBody.textContent).toBe('{{1 + 1}}');
}));
it('should focus `md-button.dialog-close` on open', inject(function($mdDialog, $rootScope, $document, $timeout, $mdConstant) {
jasmine.mockElementFocus(this);
var parent = angular.element('<div>');
$mdDialog.show({
template: '' +
'<md-dialog>' +
' <md-dialog-actions>' +
' <button class="dialog-close">Close</button>' +
' </md-dialog-actions>' +
'</md-dialog>',
parent: parent
});
runAnimation();
expect($document.activeElement).toBe(parent[0].querySelector('.dialog-close'));
}));
it('should remove `md-dialog-container` after mousedown mouseup outside', inject(function($mdDialog, $rootScope, $timeout, $animate) {
jasmine.mockElementFocus(this);
var container, parent = angular.element('<div>');
$mdDialog.show(
$mdDialog.confirm({
template: '<md-dialog>' +
'<md-dialog-content tabIndex="0">' +
'<p>Muppets are the best</p>' +
'</md-dialog-content>' +
'</md-dialog>',
parent: parent,
clickOutsideToClose: true,
ok: 'OK',
cancel: 'CANCEL'
})
);
runAnimation();
container = angular.element(parent[0].querySelector('.md-dialog-container'));
container.triggerHandler({
type: 'mousedown',
target: container[0]
});
container.triggerHandler({
type: 'mouseup',
target: container[0]
});
runAnimation();
runAnimation();
container = angular.element(parent[0].querySelector('.md-dialog-container'));
expect(container.length).toBe(0);
}));
it('should not remove `md-dialog-container` after mousedown outside mouseup inside', inject(function($mdDialog, $rootScope, $timeout, $animate) {
jasmine.mockElementFocus(this);
var container, parent = angular.element('<div>');
$mdDialog.show(
$mdDialog.confirm({
template: '<md-dialog>' +
'<md-dialog-content tabIndex="0">' +
'<p>Muppets are the best</p>' +
'</md-dialog-content>' +
'</md-dialog>',
parent: parent,
clickOutsideToClose: true,
ok: 'OK',
cancel: 'CANCEL'
})
);
runAnimation();
container = angular.element(parent[0].querySelector('.md-dialog-container'));
var content = angular.element(parent[0].querySelector('md-dialog-content'));
container.triggerHandler({
type: 'mousedown',
target: container[0]
});
content.triggerHandler({
type: 'mouseup',
target: content[0]
});
runAnimation();
runAnimation();
container = angular.element(parent[0].querySelector('.md-dialog-container'));
expect(container.length).toBe(1);
}));
it('should not remove `md-dialog-container` after mousedown inside mouseup outside', inject(function($mdDialog, $rootScope, $timeout, $animate) {
jasmine.mockElementFocus(this);
var container, parent = angular.element('<div>');
$mdDialog.show(
$mdDialog.confirm({
template: '<md-dialog>' +
'<md-dialog-content tabIndex="0">' +
'<p>Muppets are the best</p>' +
'</md-dialog-content>' +
'</md-dialog>',
parent: parent,
clickOutsideToClose: true,
ok: 'OK',
cancel: 'CANCEL'
})
);
runAnimation();
container = angular.element(parent[0].querySelector('.md-dialog-container'));
var content = angular.element(parent[0].querySelector('md-dialog-content'));
content.triggerHandler({
type: 'mousedown',
target: content[0]
});
container.triggerHandler({
type: 'mouseup',
target: container[0]
});
runAnimation();
runAnimation();
container = angular.element(parent[0].querySelector('.md-dialog-container'));
expect(container.length).toBe(1);
}));
it('should remove `md-dialog-container` after ESCAPE key', inject(function($mdDialog, $rootScope, $timeout, $mdConstant) {
jasmine.mockElementFocus(this);
var container, parent = angular.element('<div>');
var response;
$mdDialog.show(
$mdDialog.confirm({
template: '<md-dialog>' +
'<md-dialog-content tabIndex="0">' +
'<p>Muppets are the best</p>' +
'</md-dialog-content>' +
'</md-dialog>',
parent: parent,
clickOutsideToClose: true,
escapeToClose: true,
ok: 'OK',
cancel: 'CANCEL'
})
).catch(function(reason) {
response = reason;
});
runAnimation();
parent.triggerHandler({
type: 'keydown',
keyCode: $mdConstant.KEY_CODE.ESCAPE
});
runAnimation();
runAnimation();
container = angular.element(parent[0].querySelector('.md-dialog-container'));
expect(container.length).toBe(0);
expect(response).toBe(undefined);
}));
});
describe('#prompt()', function() {
hasConfigurationMethods('prompt', ['title', 'htmlContent', 'textContent',
'content', 'placeholder', 'ariaLabel', 'ok', 'cancel', 'theme', 'css'
]);
it('shows a basic prompt dialog', inject(function($animate, $rootScope, $mdDialog) {
var parent = angular.element('<div>');
var resolved = false;
var promptAnswer;
$mdDialog.show(
$mdDialog
.prompt()
.parent(parent)
.title('Title')
.textContent('Hello world')
.placeholder('placeholder text')
.initialValue('initial value')
.theme('some-theme')
.css('someClass anotherClass')
.ok('Next')
.cancel('Cancel')
).then(function(answer) {
resolved = true;
promptAnswer = answer;
});
$rootScope.$apply();
runAnimation();
var mdContainer = angular.element(parent[0].querySelector('.md-dialog-container'));
var mdDialog = mdContainer.find('md-dialog');
var mdContent = mdDialog.find('md-dialog-content');
var title = mdContent.find('h2');
var contentBody = mdContent[0].querySelector('.md-dialog-content-body');
var inputElement = mdContent.find('input');
var buttons = parent.find('md-button');
var theme = mdDialog.attr('md-theme');
var css = mdDialog.attr('class').split(' ');
expect(title.text()).toBe('Title');
expect(contentBody.textContent).toBe('Hello world');
expect(inputElement[0].placeholder).toBe('placeholder text');
expect(inputElement.val()).toBe('initial value');
expect(buttons.length).toBe(2);
expect(buttons.eq(0).text()).toBe('Next');
expect(theme).toBe('some-theme');
expect(css).toContain('someClass');
expect(css).toContain('anotherClass');
expect(mdDialog.attr('role')).toBe('dialog');
inputElement.eq(0).text('responsetext');
inputElement.scope().$apply("dialog.result = 'responsetext'");
buttons.eq(0).triggerHandler('click');
$rootScope.$apply();
runAnimation();
expect(resolved).toBe(true);
expect(promptAnswer).toBe('responsetext');
}));
it('should focus the input element on open', inject(function($mdDialog, $rootScope, $document) {
jasmine.mockElementFocus(this);
var parent = angular.element('<div>');
$mdDialog.show(
$mdDialog
.prompt()
.parent(parent)
.textContent('Hello world')
.placeholder('placeholder text')
);
runAnimation(parent.find('md-dialog'));
expect($document.activeElement).toBe(parent[0].querySelector('input'));
}));
it('should cancel the first dialog when opening a second', inject(function($mdDialog, $rootScope, $document) {
var firstParent = angular.element('<div>');
var secondParent = angular.element('<div>');
var isCancelled = false;
$mdDialog.show(
$mdDialog
.prompt()
.parent(firstParent)
.textContent('Hello world')
.placeholder('placeholder text')
).catch(function() {
isCancelled = true;
});
$rootScope.$apply();
runAnimation();
expect(firstParent.find('md-dialog').length).toBe(1);
$mdDialog.show(
$mdDialog
.prompt()
.parent(secondParent)
.textContent('Hello world')
.placeholder('placeholder text')
);
$rootScope.$apply();
runAnimation();
expect(firstParent.find('md-dialog').length).toBe(0);
expect(secondParent.find('md-dialog').length).toBe(1);
expect(isCancelled).toBe(true);
}));
it('should submit after ENTER key', inject(function($mdDialog, $rootScope, $timeout, $mdConstant) {
jasmine.mockElementFocus(this);
var parent = angular.element('<div>');
var response;
$mdDialog.show(
$mdDialog
.prompt()
.parent(parent)
.textContent('Hello world')
.placeholder('placeholder text')
).then(function(answer) {
response = answer;
});
runAnimation();
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
var mdDialog = container.find('md-dialog');
var mdContent = mdDialog.find('md-dialog-content');
var inputElement = mdContent.find('input');
inputElement.scope().$apply("dialog.result = 'responsetext'");
inputElement.eq(0).triggerHandler({
type: 'keypress',
keyCode: $mdConstant.KEY_CODE.ENTER
});
runAnimation();
runAnimation();
expect(response).toBe('responsetext');
}));
});
describe('#build()', function() {
it('should support onShowing callbacks before `show()` starts', inject(function($mdDialog, $rootScope) {
var template = '<md-dialog>Hello</md-dialog>';
var parent = angular.element('<div>');
var showing = false;
$mdDialog.show({
template: template,
parent: parent,
onShowing: onShowing
});
$rootScope.$apply();
runAnimation();
function onShowing(scope, element, options) {
showing = true;
container = angular.element(parent[0].querySelector('.md-dialog-container'));
expect(container.length).toBe(0);
}
expect(showing).toBe(true);
}));
it('should support onComplete callbacks within `show()`', inject(function($mdDialog, $rootScope, $timeout, $mdConstant) {
var template = '<md-dialog>Hello</md-dialog>';
var parent = angular.element('<div>');
var ready = false;
$mdDialog.show({
template: template,
parent: parent,
onComplete: function(scope, element, options) {
ready = true;
}
});
$rootScope.$apply();
expect(ready).toBe(false);
runAnimation();
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
expect(container.length).toBe(1);
expect(ready).toBe(true);
}));
it('should support onRemoving callbacks when `hide()` starts', inject(function($mdDialog, $rootScope, $timeout, $mdConstant) {
var template = '<md-dialog>Hello</md-dialog>';
var parent = angular.element('<div>');
var closing = false;
$mdDialog.show({
template: template,
parent: parent,
escapeToClose: true,
onRemoving: function(scope, element) {
expect(arguments.length).toEqual(2);
closing = true;
}
});
$rootScope.$apply();
expect(closing).toBe(false);
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
runAnimation();
parent.triggerHandler({
type: 'keydown',
keyCode: $mdConstant.KEY_CODE.ESCAPE
});
$timeout.flush();
expect(closing).toBe(true);
}));
it('should support specifying a parent using a string selector', inject(function($mdDialog, $rootScope, $document) {
var body = angular.element($document[0].querySelector("body"));
var nodes = angular.element(''+
'<div class="wrapper">' +
' <md-content> </md-content>' +
' <div id="owner">' +
' </div>' +
'</div>'
);
body.append( nodes );
$mdDialog.show({
template: '<md-dialog>Hello</md-dialog>',
parent: "#owner",
});
$rootScope.$apply();
runAnimation();
var owner = angular.element(body[0].querySelector('#owner'));
var container = angular.element(body[0].querySelector('.md-dialog-container'));
expect(container[0].parentNode === owner[0]).toBe(true);
nodes.remove();
}));
describe('when autoWrap parameter is true (default)', function() {
it('should not wrap content with existing md-dialog', inject(function($mdDialog, $rootScope) {
var template = '<md-dialog><div id="rawContent">Hello</div></md-dialog>';
var parent = angular.element('<div>');
$mdDialog.show({
template: template,
parent: parent
});
$rootScope.$apply();
var container = parent[0].querySelectorAll('md-dialog');
expect(container.length).toBe(1);
}));
it('should wrap raw content with md-dialog', inject(function($mdDialog, $rootScope) {
var template = '<div id="rawContent">Hello</div>';
var parent = angular.element('<div>');
$mdDialog.show({
template: template,
parent: parent
});
$rootScope.$apply();
var container = parent[0].querySelectorAll('md-dialog');
expect(container.length).toBe(1);
}));
});
describe('when autoWrap parameter is false', function() {
it('should not wrap raw content with md-dialog', inject(function($mdDialog, $rootScope) {
var template = '<md-dialog id="rawContent">Hello</md-dialog>';
var parent = angular.element('<div>');
$mdDialog.show({
template: template,
parent: parent,
autoWrap: false
});
$rootScope.$apply();
var container = parent[0].querySelectorAll('md-dialog');
expect(container.length).toBe(1); // Should not have two dialogs; but one is required
}));
});
it('should append dialog within a md-dialog-container', inject(function($mdDialog, $rootScope) {
var template = '<md-dialog>Hello</md-dialog>';
var parent = angular.element('<div>');
$mdDialog.show({
template: template,
parent: parent
});
$rootScope.$apply();
var container = parent[0].querySelectorAll('.md-dialog-container');
expect(container.length).toBe(1);
}));
it('should escapeToClose == true', inject(function($mdDialog, $rootScope, $rootElement, $timeout, $animate, $mdConstant) {
var parent = angular.element('<div>');
$mdDialog.show({
template: '<md-dialog></md-dialog>',
parent: parent,
escapeToClose: true
});
$rootScope.$apply();
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
runAnimation();
expect(parent.find('md-dialog').length).toBe(1);
parent.triggerHandler({
type: 'keydown',
keyCode: $mdConstant.KEY_CODE.ESCAPE
});
$timeout.flush();
runAnimation();
expect(parent.find('md-dialog').length).toBe(0);
}));
it('should close on escape before the animation started',
inject(function($mdDialog, $rootScope, $rootElement, $timeout, $animate, $mdConstant) {
var parent = angular.element('<div>');
$mdDialog.show({
template: '<md-dialog></md-dialog>',
parent: parent,
escapeToClose: true
});
$rootScope.$apply();
expect(parent.find('md-dialog').length).toBe(1);
parent.triggerHandler({
type: 'keydown',
keyCode: $mdConstant.KEY_CODE.ESCAPE
});
$timeout.flush();
runAnimation();
expect(parent.find('md-dialog').length).toBe(0);
}));
it('should escapeToClose == false', inject(function($mdDialog, $rootScope, $rootElement, $timeout, $animate, $mdConstant) {
var parent = angular.element('<div>');
$mdDialog.show({
template: '',
parent: parent,
escapeToClose: false
});
$rootScope.$apply();
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
runAnimation();
expect(parent.find('md-dialog').length).toBe(1);
$rootElement.triggerHandler({type: 'keydown', keyCode: $mdConstant.KEY_CODE.ESCAPE});
runAnimation();
expect(parent.find('md-dialog').length).toBe(1);
}));
it('should clickOutsideToClose == true', inject(function($mdDialog, $rootScope, $timeout, $animate, $mdConstant) {
var parent = angular.element('<div>');
$mdDialog.show({
template: '',
parent: parent,
clickOutsideToClose: true
});
$rootScope.$apply();
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
runAnimation();
expect(parent.find('md-dialog').length).toBe(1);
container.triggerHandler({
type: 'mousedown',
target: container[0]
});
container.triggerHandler({
type: 'mouseup',
target: container[0]
});
runAnimation();
runAnimation();
expect(parent.find('md-dialog').length).toBe(0);
}));
it('should clickOutsideToClose == false', inject(function($mdDialog, $rootScope, $timeout, $animate) {
var parent = angular.element('<div>');
$mdDialog.show({
template: '',
parent: parent,
clickOutsideToClose: false
});
$rootScope.$apply();
expect(parent.find('md-dialog').length).toBe(1);
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
container.triggerHandler({
type: 'click',
target: container[0]
});
runAnimation();
expect(parent[0].querySelectorAll('md-dialog').length).toBe(1);
}));
it('should disableParentScroll == true', inject(function($mdDialog, $animate, $rootScope, $mdUtil) {
spyOn($mdUtil, 'disableScrollAround');
var parent = angular.element('<div>');
$mdDialog.show({
template: '',
parent: parent,
disableParentScroll: true
});
runAnimation();
expect($mdUtil.disableScrollAround).toHaveBeenCalled();
}));
it('should hasBackdrop == true', inject(function($mdDialog, $animate, $rootScope) {
var parent = angular.element('<div>');
$mdDialog.show({
template: '',
parent: parent,
hasBackdrop: true
});
runAnimation();
expect(parent.find('md-dialog').length).toBe(1);
expect(parent.find('md-backdrop').length).toBe(1);
}));
it('should hasBackdrop == false', inject(function($mdDialog, $rootScope) {
var parent = angular.element('<div>');
$mdDialog.show({
template: '',
parent: parent,
hasBackdrop: false
});
$rootScope.$apply();
expect(parent[0].querySelectorAll('md-dialog').length).toBe(1);
expect(parent[0].querySelectorAll('md-backdrop').length).toBe(0);
}));
it('should focusOnOpen == true', inject(function($mdDialog, $rootScope, $document, $timeout, $mdConstant) {
jasmine.mockElementFocus(this);
var parent = angular.element('<div>');
$mdDialog.show({
focusOnOpen: true,
parent: parent,
template:
'<md-dialog>' +
' <md-dialog-actions>' +
' <button id="a">A</md-button>' +
' <button id="focus-target">B</md-button>' +
' </md-dialog-actions>' +
'</md-dialog>'
});
$rootScope.$apply();
runAnimation();
expect($document.activeElement).toBe(parent[0].querySelector('#focus-target'));
}));
it('should restore the focus to the origin upon close', inject(function($mdDialog, $compile, $rootScope) {
var scope = $rootScope.$new();
var body = angular.element(document.body);
var parent = angular.element('<div>');
var button = $compile('<button ng-click="openDialog($event)">Open</button>')(scope);
// Append the button to the body, because otherwise the dialog is not able to determine
// the origin rectangle.
document.body.appendChild(button[0]);
scope.openDialog = function($event) {
$mdDialog.show({
parent: parent,
template: '<md-dialog>Test</md-dialog>',
targetEvent: $event,
scope: scope.$new()
});
};
// Emit a keyboard event to fake a keyboard interaction.
body.triggerHandler('keydown');
button.triggerHandler('click');
runAnimation();
expect(parent.find('md-dialog').length).toBe(1);
expect(document.activeElement).not.toBe(button[0]);
$mdDialog.hide();
runAnimation();
expect(parent.find('md-dialog').length).toBe(0);
expect(document.activeElement).toBe(button[0]);
button.remove();
}));
it('should not restore the focus without keyboard interaction', inject(function($mdDialog, $compile, $rootScope) {
var scope = $rootScope.$new();
var body = angular.element(document.body);
var parent = angular.element('<div>');
var button = $compile('<button ng-click="openDialog($event)">Open</button>')(scope);
// Append the button to the body, because otherwise the dialog is not able to determine
// the origin rectangle.
document.body.appendChild(button[0]);
scope.openDialog = function($event) {
$mdDialog.show({
parent: parent,
template: '<md-dialog>Test</md-dialog>',
targetEvent: $event,
scope: scope.$new()
});
};
// Emit a keyboard event to fake a mouse interaction.
body.triggerHandler('mousedown');
button.triggerHandler('click');
runAnimation();
expect(parent.find('md-dialog').length).toBe(1);
expect(document.activeElement).not.toBe(button[0]);
$mdDialog.hide();
runAnimation();
expect(parent.find('md-dialog').length).toBe(0);
expect(document.activeElement).not.toBe(button[0]);
button.remove();
}));
it('should focus the dialog element if no actions are set', inject(function($mdDialog, $rootScope, $document) {
jasmine.mockElementFocus(this);
var parent = angular.element('<div>');
$mdDialog.show({
parent: parent,
template:
'<md-dialog></md-dialog>'
});
$rootScope.$apply();
runAnimation();
expect($document.activeElement).toBe(parent[0].querySelector('md-dialog'));
}));
it('should focusOnOpen == false', inject(function($mdDialog, $rootScope, $document, $timeout, $mdConstant) {
jasmine.mockElementFocus(this);
var parent = angular.element('<div>');
$mdDialog.show({
focusOnOpen: false,
parent: parent,
template:
'<md-dialog>' +
'<md-dialog-actions>' +
'<button id="a">A</md-button>' +
'<button id="focus-target">B</md-button>' +
'</md-dialog-actions>' +
'</md-dialog>',
});
$rootScope.$apply();
runAnimation();
var container = angular.element(parent[0].querySelector('.md-dialog-container'));
runAnimation();
expect($document.activeElement).toBe(undefined);
}));
it('should focus the last `md-button` in md-dialog-actions open if no `.dialog-close`', inject(function($mdDialog, $rootScope, $document, $timeout, $mdConstant) {
jasmine.mockElementFocus(this);
var parent = angular.element('<div>');
$mdDialog.show({
template:
'<md-dialog>' +
' <md-dialog-actions>' +
' <button id="a">A</md-button>' +
' <button id="focus-target">B</md-button>' +
' </md-dialog-actions>' +
'</md-dialog>',
parent: parent
});
runAnimation();
expect($document.activeElement).toBe(parent[0].querySelector('#focus-target'));
}));
it('should only allow one open at a time', inject(function($mdDialog, $rootScope, $animate) {
var parent = angular.element('<div>');
$mdDialog.show({
template: '<md-dialog class="one">',
parent: parent
});
runAnimation();
expect(parent[0].querySelectorAll('md-dialog.one').length).toBe(1);
expect(parent[0].querySelectorAll('md-dialog.two').length).toBe(0);
$mdDialog.show({
template: '<md-dialog class="two">',
parent: parent
});
runAnimation();
expect(parent[0].querySelectorAll('md-dialog.one').length).toBe(0);
expect(parent[0].querySelectorAll('md-dialog.two').length).toBe(1);
}));
it('should hide dialog', inject(function($mdDialog, $rootScope, $animate) {
var parent = angular.element('<div>');
$mdDialog.show({
template: '<md-dialog class="one">',
parent: parent
});
runAnimation();
$mdDialog.hide();
runAnimation();
expect(parent[0].querySelectorAll('md-dialog.one').length).toBe(0);
}));
it('should allow opening new dialog after existing without corruption', inject(function($mdDialog, $rootScope, $animate) {
var parent = angular.element('<div>');
$mdDialog.show({
template: '<md-dialog class="one">',
parent: parent
});
runAnimation();
$mdDialog.hide();
runAnimation();
$mdDialog.show({
template: '<md-dialog class="two">',
parent: parent
});
runAnimation();
$mdDialog.hide();
runAnimation();
expect(parent[0].querySelectorAll('md-dialog.one').length).toBe(0);
expect(parent[0].querySelectorAll('md-dialog.two').length).toBe(0);
}));
it('should allow opening new dialog from existing without corruption', inject(function($mdDialog, $rootScope, $animate) {
var parent = angular.element('<div>');
$mdDialog.show({
template: '<md-dialog class="one">',
parent: parent
});
runAnimation();
$mdDialog.show({
template: '<md-dialog class="two">',
parent: parent
});
//First run is for the old dialog being hidden.
runAnimation();
//Second run is for the new dialog being shown.
runAnimation();
$mdDialog.hide();
runAnimation();
expect(parent[0].querySelectorAll('md-dialog.one').length).toBe(0);
expect(parent[0].querySelectorAll('md-dialog.two').length).toBe(0);
}));
describe('contentElement', function() {
var $mdDialog, $rootScope, $compile, $timeout;
beforeEach(inject(function($injector) {
$mdDialog = $injector.get('$mdDialog');
$rootScope = $injector.get('$rootScope');
$compile = $injector.get('$compile');
$timeout = $injector.get('$timeout');
}));
it('should correctly move the contentElement', function() {
var contentElement = $compile(
'<div class="md-dialog-container">' +
'<md-dialog>Dialog</md-dialog>' +
'</div>'
)($rootScope);
var parentEl = angular.element('<div>');
// Add the contentElement to the DOM.
document.body.appendChild(contentElement[0]);
$mdDialog.show({
contentElement: contentElement,
parent: parentEl,
escapeToClose: true
});
$rootScope.$apply();
runAnimation();
expect(contentElement[0].parentNode).toBe(parentEl[0]);
$mdDialog.hide();
runAnimation();
expect(contentElement[0].parentNode).toBe(document.body);
document.body.removeChild(contentElement[0]);
});
it('should support contentElement as a preset method', function() {
var contentElement = $compile(
'<div class="md-dialog-container">' +
'<md-dialog>Dialog</md-dialog>' +
'</div>'
)($rootScope);
var parentEl = angular.element('<div>');
// Add the contentElement to the DOM.
document.body.appendChild(contentElement[0]);
$mdDialog.show(
$mdDialog
.build()
.contentElement(contentElement)
.parent(parentEl)
.escapeToClose(true)
);
$rootScope.$apply();
runAnimation();
expect(contentElement[0].parentNode).toBe(parentEl[0]);
$mdDialog.hide();
runAnimation();
expect(contentElement[0].parentNode).toBe(document.body);
document.body.removeChild(contentElement[0]);
});
it('should correctly query for a contentElement', function() {
var contentElement = $compile(
'<div class="md-dialog-container" id="myId">' +
'<md-dialog>Dialog</md-dialog>' +
'</div>'
)($rootScope);
var parentEl = angular.element('<div>');
// Add the contentElement to the DOM.
document.body.appendChild(contentElement[0]);
$mdDialog.show({
contentElement: '#myId',
parent: parentEl,
escapeToClose: true
});
$rootScope.$apply();
runAnimation();
expect(contentElement[0].parentNode).toBe(parentEl[0]);
$mdDialog.hide();
runAnimation();
expect(contentElement[0].parentNode).toBe(document.body);
document.body.removeChild(contentElement[0]);
});
it('should also work with a virtual pre-compiled element', function() {
var contentElement = $compile(
'<div class="md-dialog-container" id="myId">' +
'<md-dialog>Dialog</md-dialog>' +
'</div>'
)($rootScope);
var parentEl = angular.element('<div>');
$mdDialog.show({
contentElement: contentElement,
parent: parentEl,
escapeToClose: true
});
$rootScope.$apply();
runAnimation();
expect(contentElement[0].parentNode).toBe(parentEl[0]);
$mdDialog.hide();
runAnimation();
expect(contentElement[0].offsetParent).toBeFalsy();
});
it('should properly toggle the fullscreen class', function() {
var contentElement = $compile(
'<div class="md-dialog-container" id="myId">' +
'<md-dialog>Dialog</md-dialog>' +
'</div>'
)($rootScope);
var parentEl = angular.element('<div>');
var dialogEl = contentElement.find('md-dialog');
// Show the dialog with fullscreen enabled.
$mdDialog.show({
contentElement: contentElement,
parent: parentEl,
escapeToClose: true,
fullscreen: true
});
$rootScope.$apply();
runAnimation();
expect(contentElement[0].parentNode).toBe(parentEl[0]);
expect(dialogEl).toHaveClass('md-dialog-fullscreen');
// Hide the dialog to allow the second dialog to show up.
$mdDialog.hide();
runAnimation();
// Show the dialog with fullscreen disabled
$mdDialog.show({
contentElement: contentElement,
parent: parentEl,
escapeToClose: true,
fullscreen: false
});
$rootScope.$apply();
runAnimation();
expect(contentElement[0].parentNode).toBe(parentEl[0]);
expect(dialogEl).not.toHaveClass('md-dialog-fullscreen');
// Hide the dialog to avoid issues with other tests.
$mdDialog.hide();
runAnimation();
});
it('should remove the transition classes', function() {
var contentElement = $compile(
'<div class="md-dialog-container" id="myId">' +
'<md-dialog>Dialog</md-dialog>' +
'</div>'
)($rootScope);
var parentEl = angular.element('<div>');
var dialogEl = contentElement.find('md-dialog');
// Show the dialog with fullscreen enabled.
$mdDialog.show({
contentElement: contentElement,
parent: parentEl,
escapeToClose: true,
fullscreen: true
});
$rootScope.$apply();
runAnimation();
expect(contentElement[0].parentNode).toBe(parentEl[0]);
expect(dialogEl).toHaveClass('md-transition-in');
// Hide the dialog to allow the second dialog to show up.
$mdDialog.hide();
runAnimation();
expect(dialogEl).not.toHaveClass('md-transition-in');
expect(dialogEl).not.toHaveClass('md-transition-out');
});
it('should restore the contentElement at its previous position', function() {
var contentElement = $compile(
'<div class="md-dialog-container">' +
'<md-dialog>Dialog</md-dialog>' +
'</div>'
)($rootScope);
var dialogParent = angular.element('<div>');
var contentParent = angular.element(
'<div>' +
'<span>Child Element</span>' +
'</div>'
);
// Append the content parent to the document, otherwise contentElement is not able
// to detect it properly.
document.body.appendChild(contentParent[0]);
contentParent.prepend(contentElement);
$mdDialog.show({
contentElement: contentElement,
parent: dialogParent,
escapeToClose: true
});
$rootScope.$apply();
runAnimation();
expect(contentElement[0].parentNode).toBe(dialogParent[0]);
$mdDialog.hide();
runAnimation();
expect(contentElement[0].parentNode).toBe(contentParent[0]);
var childNodes = [].slice.call(contentParent[0].children);
expect(childNodes.indexOf(contentElement[0])).toBe(0);
document.body.removeChild(contentParent[0]);
})
});
it('should have the dialog role', inject(function($mdDialog, $rootScope) {
var template = '<md-dialog>Hello</md-dialog>';
var parent = angular.element('<div>');
$mdDialog.show({
template: template,
parent: parent
});
$rootScope.$apply();
var dialog = angular.element(parent[0].querySelectorAll('md-dialog'));
expect(dialog.attr('role')).toBe('dialog');
}));
it('should create an ARIA label if one is missing', inject(function($mdDialog, $rootScope, $$rAF) {
var template = '<md-dialog>Hello</md-dialog>';
var parent = angular.element('<div>');
$mdDialog.show({
template: template,
parent: parent
});
runAnimation();
var dialog = angular.element(parent[0].querySelector('md-dialog'));
expect(dialog.attr('aria-label')).toEqual(dialog.text());
}));
it('should not modify an existing ARIA label', inject(function($mdDialog, $rootScope) {
var template = '<md-dialog aria-label="Some Other Thing">Hello</md-dialog>';
var parent = angular.element('<div>');
$mdDialog.show({
template: template,
parent: parent
});
runAnimation();
var dialog = angular.element(parent[0].querySelector('md-dialog'));
expect(dialog.attr('aria-label')).not.toEqual(dialog.text());
expect(dialog.attr('aria-label')).toEqual('Some Other Thing');
}));
it('should add an ARIA label if supplied through chaining', inject(function($mdDialog, $rootScope, $animate) {
var parent = angular.element('<d