Skip to content

Commit

Permalink
update(panel): Adds tests for component logic (bindToController, cont…
Browse files Browse the repository at this point in the history
…rollerAs, controller, locals, resolve).
  • Loading branch information
ErinCoughlan committed Feb 9, 2016
1 parent 4e34413 commit 6c764cb
Show file tree
Hide file tree
Showing 3 changed files with 202 additions and 64 deletions.
127 changes: 68 additions & 59 deletions src/components/panel/panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,54 +80,60 @@ angular
* @description
* Creates a panel with the specified options.
*
* @param opt_config {Object=} Specific configuration object that may contain the
* following properties:
* @param opt_config {Object=} Specific configuration object that may contain
* the following properties:
*
* N/A
*
* TODO(ErinCoughlan): Add the following config options.
* - `groupName` - `{string=}`: Name of panel groups. This group name is used for
* configuring the number of open panels and identifying specific behaviors for
* groups. For instance, all tooltips will be identified using the same groupName.
* - `template` - `{string=}`: HTML template to show in the dialog. This **must** be
* trusted HTML with respect to Angular’s
* - `template` - `{string=}`: HTML template to show in the dialog. This
* **must** be trusted HTML with respect to Angular’s
* [$sce service](https://docs.angularjs.org/api/ng/service/$sce).
* - `templateUrl` - `{string=}`: The URL that will be used as the content of
* the panel.
* - `controller` - `{(function|string)=}`: The controller to associate with the
* panel. The controller can inject a reference to the returned
* panelRef, which allows the panel to be closed, hidden, and shown.
* Any fields passed in through locals or resolve will be bound to the controller.
* - `controllerAs` - `{string=}`: An alias to assign the controller to on the
* scope.
* - `locals` - `{Object=}`: An object containing key/value pairs. The keys will be
* used as names of values to inject into the controller. For example,
* `locals: {three: 3}` would inject `three` into the controller, with the value
* 3.
* - `controller` - `{(function|string)=}`: The controller to associate with
* the panel. The controller can inject a reference to the returned
* panelRef, which allows the panel to be closed, hidden, and shown. Any
* fields passed in through locals or resolve will be bound to the
* controller.
* - `controllerAs` - `{string=}`: An alias to assign the controller to on
* the scope.
* - `locals` - `{Object=}`: An object containing key/value pairs. The keys
* will be used as names of values to inject into the controller. For
* example, `locals: {three: 3}` would inject `three` into the controller,
* with the value 3.
* - `resolve` - `{Object=}`: Similar to locals, except it takes promises as
* values. The panel will not open until all of the promises resolve.
* - `attachTo` - `{Element=}`: The element to attach the panel to. Defaults to
* appending to the root element of the application.
* - `position` - `{$mdPanelPosition=}`: An $mdPanelPosition object that specifies
* the alignment of the panel. For more information, see $mdPanelPosition.
* - `animation` - `{$mdPanelAnimation=}`: An $mdPanelAnimation object that specifies
* the animation of the panel. For more information, see $mdPanelAnimation.
* - `hasBackdrop` - `{boolean=}`: Whether there should be an opaque backdrop behind
* the panel. Defaults to false.
* - `escapeToClose` - `{boolean=}`: Whether the user can press escape to close the
* panel. Defaults to false.
* - `clickOutsideToClose` - `{boolean=}`: Whether the user can click outside the
* panel to close it. Defaults to false.
* - `disableParentScroll` - `{boolean=}`: Whether the user can scroll the page
* - `attachTo` - `{Element=}`: The element to attach the panel to. Defaults
* to appending to the root element of the application.
*
* TODO(ErinCoughlan): Add the following config options.
* - `groupName` - `{string=}`: Name of panel groups. This group name is
* used for configuring the number of open panels and identifying specific
* behaviors for groups. For instance, all tooltips will be identified
* using the same groupName.
*
* - `position` - `{$mdPanelPosition=}`: An $mdPanelPosition object that
* specifies the alignment of the panel. For more information, see
* `$mdPanelPosition`.
* - `animation` - `{$mdPanelAnimation=}`: An $mdPanelAnimation object that
* specifies the animation of the panel. For more information, see
* `$mdPanelAnimation`.
* - `hasBackdrop` - `{boolean=}`: Whether there should be an opaque backdrop
* behind the panel. Defaults to false.
* - `fullScreen` - `{boolean=}`: Whether the panel should be full screen. Applies
* the class `.md-panel-fullscreen` to the panel on open. Defaults to false.
* - `trapFocus` - `{boolean=}`: Whether focus should be trapped within the panel.
* If `trapFocus` is true, the user will not be able to interact with the rest of
* the page until the panel is dismissed. Defaults to false.
* - `focusOnOpen` - `{boolean=}`: An option to override focus behavior on open.
* Only disable if focusing some other way, as focus management is required for
* panels to be accessible. Defaults to true.
* - `escapeToClose` - `{boolean=}`: Whether the user can press escape to
* close the panel. Defaults to false.
* - `clickOutsideToClose` - `{boolean=}`: Whether the user can click
* outside the panel to close it. Defaults to false.
* - `disableParentScroll` - `{boolean=}`: Whether the user can scroll the
* page behind the panel. Defaults to false.
* - `fullScreen` - `{boolean=}`: Whether the panel should be full screen.
* Applies the class `.md-panel-fullscreen` to the panel on open. Defaults
* to false.
* - `trapFocus` - `{boolean=}`: Whether focus should be trapped within the
* panel. If `trapFocus` is true, the user will not be able to interact
* with the rest of the page until the panel is dismissed. Defaults to
* false.
* - `focusOnOpen` - `{boolean=}`: An option to override focus behavior on
* open. Only disable if focusing some other way, as focus management is
* required for panels to be accessible. Defaults to true.
*
* @returns {MdPanelRef} panelRef
*/
Expand All @@ -154,7 +160,8 @@ angular
* @ngdoc method
* @name $mdPanel#setGroupMaxOpen
* @description
* Sets the maximum number of panels in a group that can be opened at a given time.
* Sets the maximum number of panels in a group that can be opened at a given
* time.
*
* @param groupName {string} The name of the group to configure.
* @param maxOpen {number} The max number of panels that can be opened.
Expand All @@ -170,21 +177,22 @@ angular
* @ngdoc object
* @name MdPanelRef
* @description
* A reference to a created panel. This reference contains a unique id for the panel,
* along with the following properties:
* - `id` - `{string}: The unique id for the panel. This id is used to track when
* a panel was interacted with.
* - `config` - `{Object=}`: The entire config object that was used in create.
* A reference to a created panel. This reference contains a unique id for the
* panel, along with the following properties:
* - `id` - `{string}: The unique id for the panel. This id is used to track
* when a panel was interacted with.
* - `config` - `{Object=}`: The entire config object that was used in
* create.
* - `isOpen` - `{boolean}`: Whether the panel is attached to the DOM.
* Visibility to the user does not factor into isOpen.
*
* TODO(ErinCoughlan): Add the following properties.
* - `isOpen` - `{boolean}`: Whether the panel is attached to the DOM. Visibility
* to the user does not factor into isOpen.
* - `isHidden` - `{boolean}`: Whether the panel is attached to the DOM, but not
* visible to the user.
* - `onDomAdded` - `{function=}`: Callback function used to announce when the
* panel is added to the DOM.
* - `onOpenComplete` - `{function=}`: Callback function used to announce when the
* open() action is finished.
* - `isHidden` - `{boolean}`: Whether the panel is attached to the DOM, but
* not visible to the user.
* - `onDomAdded` - `{function=}`: Callback function used to announce when
* the panel is added to the DOM.
* - `onOpenComplete` - `{function=}`: Callback function used to announce
* when the open() action is finished.
* - `onRemoving` - `{function=}`: Callback function used to announce the
* close/hide() action is starting. This allows developers to run custom
* animations in parallel the close animations.
Expand All @@ -196,16 +204,17 @@ angular
* @description
* If the panel is not visible, opens an already created and configured panel.
*
* @returns {angular.$q.Promise} A promise that is resolved when the panel is closed.
* @returns {angular.$q.Promise} A promise that is resolved when the panel is
* closed.
*/

/**
* @ngdoc method
* @name MdPanelRef#close
* @description
* If the panel is visible, closes the panel, resolving the promise that is returned
* from `MdPanelRef#open`. This method destroys the reference to the panel. In order
* to open the panel again, a new one must be created.
* If the panel is visible, closes the panel, resolving the promise that is
* returned from `MdPanelRef#open`. This method destroys the reference to the
* panel. In order to open the panel again, a new one must be created.
*/


Expand Down
115 changes: 111 additions & 4 deletions src/components/panel/panel.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
describe('$mdPanel', function() {
var $mdPanel, $rootScope, $rootEl;
var panelRef;
var attachedElements = [];

/**
Expand All @@ -26,14 +27,16 @@ describe('$mdPanel', function() {
el.remove();
});
attachedElements = [];

panelRef && panelRef.close();
});

it('should create a basic panel', function() {
var openResolved = false;
var closeResolved = false;
var config = {};

var panelRef = $mdPanel.create(config);
panelRef = $mdPanel.create(config);

expect(panelRef.id).toBeDefined();
expect(panelRef.open).toBeOfType('function');
Expand Down Expand Up @@ -61,7 +64,7 @@ describe('$mdPanel', function() {
var template = '<div id="panel">Hello World!</div>';
var config = { template: template };

var panelRef = $mdPanel.open(config);
panelRef = $mdPanel.open(config);
$rootScope.$apply();

expect('#panel').toExist();
Expand All @@ -78,7 +81,7 @@ describe('$mdPanel', function() {
var template = '<div id="panel">Hello World!</div>';
var config = { template: template };

var panelRef = $mdPanel.create(config);
panelRef = $mdPanel.create(config);

expect('#panel').not.toExist();

Expand All @@ -104,7 +107,7 @@ describe('$mdPanel', function() {
template: template
};

var panelRef = $mdPanel.create(config);
panelRef = $mdPanel.create(config);
panelRef.open();
$rootScope.$apply();

Expand All @@ -117,6 +120,110 @@ describe('$mdPanel', function() {
expect(parentEl.childElementCount).toEqual(0);
});

describe('component logic: ', function() {
it('should allow templateUrl to specify content',
inject(function($templateCache) {
var htmlContent = 'Hello World';
var template = '<div id="panel">' + htmlContent + '</div>';
$templateCache.put('template.html', template);

var config = { templateUrl: 'template.html' };

panelRef = $mdPanel.open(config);
$rootScope.$apply();

expect('#panel').toContainHtml(htmlContent);
}));

it('should allow template to specify content', function() {
var htmlContent = 'Hello World';
var template = '<div id="panel">' + htmlContent + '</div>';
var config = { template: template };

panelRef = $mdPanel.open(config);
$rootScope.$apply();

expect('#panel').toContainHtml(htmlContent);
});

it('should allow a controller to be specified', function() {
var htmlContent = 'Hello World';
var template = '<div id="panel">{{ content }}</div>';

var config = {
template: template,
controller: function Ctrl($scope) {
$scope['content'] = htmlContent;
}
};

panelRef = $mdPanel.open(config);
$rootScope.$apply();

expect('#panel').toContainHtml(htmlContent);
});

it('should allow controllerAs syntax', function() {
var htmlContent = 'Hello World';
var template = '<div id="panel">{{ ctrl.content }}</div>';

var config = {
template: template,
controller: function Ctrl() {
this.content = htmlContent;
},
controllerAs: 'ctrl'
};

panelRef = $mdPanel.open(config);
$rootScope.$apply();

expect('#panel').toContainHtml(htmlContent);
});

it('should bind resolves to the controller', function() {
var htmlContent = 'Hello World';
var template = '<div id="panel">{{ ctrl.content }}</div>';

var config = {
template: template,
controller: function Ctrl() {
this.content; // Populated via bindToController.
},
controllerAs: 'ctrl',
resolve: {
content: function($q) {
return $q.when(htmlContent);
}
}
};

panelRef = $mdPanel.open(config);
$rootScope.$apply();

expect('#panel').toContainHtml(htmlContent);
});

it('should bind locals to the controller', function() {
var htmlContent = 'Hello World';
var template = '<div id="panel">{{ ctrl.content }}</div>';

var config = {
template: template,
controller: function Ctrl() {
this.content; // Populated via bindToController.
},
controllerAs: 'ctrl',
locals: { content: htmlContent }
};

panelRef = $mdPanel.open(config);
$rootScope.$apply();

expect('#panel').toContainHtml(htmlContent);
});
});

/**
* Attached an element to document.body. Keeps track of attached elements
* so that they can be removed in an afterEach.
Expand Down
24 changes: 23 additions & 1 deletion test/angular-material-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,29 @@
};
}
};
}
},

/**
* Asserts that a given element contains a given substring in
* its innerHTML property.
*/
toContainHtml: function() {
return {
'compare': function(actual, expected) {
var el = typeof actual == 'string' ?
document.querySelector(actual) : actual;
var html = angular.element(el).html();
var pass = html.indexOf(expected) !== -1;
var not = pass ? 'not ' : '';

return {
'pass': pass,
'message': 'Expected element ' + not + 'to contain the html ' +
'[' + expected + '] in [' + html + ']'
};
}
};
},

});

Expand Down

0 comments on commit 6c764cb

Please sign in to comment.