AngularJS in Horizon Documentation
This patch is a first pass at reducing the levels of "tribal knowledge" and making the AngularJS codebase more accessible. It details code style, file structures, testing and translation. Change-Id: I22e6e5627216739fc92a5c9a5b417c6c6b16476d Closes-Bug: 1373310
This commit is contained in:
parent
bc3e3b6934
commit
8d2792f19f
@ -125,6 +125,8 @@ The community's guidelines for etiquette are fairly simple:
|
|||||||
a piece of code, it's polite (though not required) to thank them in your
|
a piece of code, it's polite (though not required) to thank them in your
|
||||||
commit message.
|
commit message.
|
||||||
|
|
||||||
|
.. _translatability:
|
||||||
|
|
||||||
Translatability
|
Translatability
|
||||||
===============
|
===============
|
||||||
Horizon gets translated into multiple languages. The pseudo translation tool
|
Horizon gets translated into multiple languages. The pseudo translation tool
|
||||||
@ -432,32 +434,6 @@ Required
|
|||||||
$window.gettext('translatable text');
|
$window.gettext('translatable text');
|
||||||
|
|
||||||
|
|
||||||
JSHint
|
|
||||||
------
|
|
||||||
JSHint is a great tool to be used during your code editing to improve
|
|
||||||
JavaScript quality by checking your code against a configurable list of checks.
|
|
||||||
Therefore, JavaScript developers should configure their editors to use JSHint
|
|
||||||
to warn them of any such errors so they can be addressed. Since JSHint has a
|
|
||||||
ton of configuration options to choose from, links are provided below to the
|
|
||||||
options Horizon wants enforced along with the instructions for setting up
|
|
||||||
JSHint for Eclipse, Sublime Text, Notepad++ and WebStorm/PyCharm.
|
|
||||||
|
|
||||||
JSHint configuration file: `.jshintrc`_
|
|
||||||
|
|
||||||
Instructions for setting up JSHint: `JSHint setup instructions`_
|
|
||||||
|
|
||||||
.. Note ::
|
|
||||||
JSHint is part of the automated unit tests performed by Jenkins. The
|
|
||||||
automated test use the default configurations, which are less strict than
|
|
||||||
the configurations we recommended to run in your local development
|
|
||||||
environment.
|
|
||||||
|
|
||||||
.. _.jshintrc: https://wiki.openstack.org/wiki/Horizon/Javascript/EditorConfig/Settings#.jshintrc
|
|
||||||
.. _JSHint setup instructions: https://wiki.openstack.org/wiki/Horizon/Javascript/EditorConfig
|
|
||||||
.. _provided: https://wiki.openstack.org/wiki/Horizon/Javascript/EditorConfig
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CSS
|
CSS
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -78,6 +78,8 @@ the following topic guides.
|
|||||||
topics/policy
|
topics/policy
|
||||||
topics/testing
|
topics/testing
|
||||||
topics/table_actions
|
topics/table_actions
|
||||||
|
topics/angularjs
|
||||||
|
topics/javascript_testing
|
||||||
|
|
||||||
API Reference
|
API Reference
|
||||||
-------------
|
-------------
|
||||||
|
@ -189,15 +189,6 @@ For more detailed code analysis you can run::
|
|||||||
|
|
||||||
The output will be saved in ``./pylint.txt``.
|
The output will be saved in ``./pylint.txt``.
|
||||||
|
|
||||||
JsHint
|
|
||||||
------
|
|
||||||
|
|
||||||
For code analysis of JavaScript files::
|
|
||||||
|
|
||||||
./run_tests.sh --jshint
|
|
||||||
|
|
||||||
You need to have jshint installed before running the command.
|
|
||||||
|
|
||||||
Tab Characters
|
Tab Characters
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
180
doc/source/topics/angularjs.rst
Normal file
180
doc/source/topics/angularjs.rst
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
=====================
|
||||||
|
AngularJS Topic Guide
|
||||||
|
=====================
|
||||||
|
|
||||||
|
.. Note::
|
||||||
|
This guide is a work in progress. It has been uploaded to encourage faster
|
||||||
|
reviewing and code development in Angular, and to help the community
|
||||||
|
standardize on a set of guidelines. There are notes inline on sections
|
||||||
|
that are likely to change soon, and the docs will be updated promptly
|
||||||
|
after any changes.
|
||||||
|
|
||||||
|
Getting Started
|
||||||
|
===============
|
||||||
|
|
||||||
|
The tooling for AngularJS testing and code linting relies on npm, the
|
||||||
|
node package manager, and thus relies on Node.js. While it is not a
|
||||||
|
prerequisite to developing with Horizon, it is advisable to install Node.js,
|
||||||
|
either through `downloading <https://nodejs.org/download/>`_ or
|
||||||
|
`via a package manager <https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager>`_.
|
||||||
|
|
||||||
|
Once you have npm available on your system, run ``npm install`` from the
|
||||||
|
horizon root directory.
|
||||||
|
|
||||||
|
.. _js_code_style:
|
||||||
|
|
||||||
|
Code Style
|
||||||
|
==========
|
||||||
|
|
||||||
|
We currently use the `Angular Style Guide`_ by John Papa as reference material.
|
||||||
|
When reviewing AngularJS code, it is helpful to link directly to the style
|
||||||
|
guide to reinforce a point, e.g.
|
||||||
|
https://github.com/johnpapa/angular-styleguide#style-y024
|
||||||
|
|
||||||
|
.. _Angular Style Guide: https://github.com/johnpapa/angular-styleguide
|
||||||
|
|
||||||
|
ESLint
|
||||||
|
------
|
||||||
|
|
||||||
|
ESLint is a tool for identifying and reporting on patterns in your JS code, and
|
||||||
|
is part of the automated tests run by Jenkins. You can run ESLint from the
|
||||||
|
horizon root directory with ``npm run lint``, or alternatively on a specific
|
||||||
|
directory or file with ``eslint file.js``.
|
||||||
|
|
||||||
|
Horizon includes a `.eslintrc` in its root directory, that is used by the
|
||||||
|
local tests. An explanation of the options, and details of others you may want
|
||||||
|
to use, can be found in the
|
||||||
|
`ESLint user guide <http://eslint.org/docs/user-guide/configuring>`_.
|
||||||
|
|
||||||
|
.. _js_file_structure:
|
||||||
|
|
||||||
|
File Structure
|
||||||
|
==============
|
||||||
|
|
||||||
|
Each component should have its own folder, with the code broken up into one JS
|
||||||
|
component per file. (See `Single Responsibility <https://github.com/johnpapa/angular-styleguide#single-responsibility>`_
|
||||||
|
in the style guide).
|
||||||
|
Each folder may include styling (``.scss``), as well as templates(``.html``)
|
||||||
|
and tests (``.spec.js``).
|
||||||
|
You may also include examples, by appending ``.example``.
|
||||||
|
|
||||||
|
Reusable components are in ``horizon/static/framework/``. These are a
|
||||||
|
collection of pieces, such as modals or wizards where the functionality
|
||||||
|
is likely to be used across many parts of horizon.
|
||||||
|
When adding code to horizon, consider whether it is panel-specific or should be
|
||||||
|
broken out as a reusable utility or widget.
|
||||||
|
|
||||||
|
Panel-specific code is in ``openstack_dashboard/static/dashboard/``.
|
||||||
|
|
||||||
|
The modal directive is a good example of the file structure. This is a reusable
|
||||||
|
component:
|
||||||
|
::
|
||||||
|
|
||||||
|
horizon/static/framework/widgets/modal/
|
||||||
|
├── modal.controller.js
|
||||||
|
├── modal.factory.js
|
||||||
|
├── modal.module.js
|
||||||
|
├── modal.spec.js
|
||||||
|
└── simple-modal.html
|
||||||
|
|
||||||
|
For larger components, such as workflows with multiple steps, consider breaking
|
||||||
|
the code down further. The Angular **Launch Instance** workflow,
|
||||||
|
for example, has one directory per step
|
||||||
|
(``openstack_dashboard/static/dashboard/launch-instance/``)
|
||||||
|
|
||||||
|
Testing
|
||||||
|
=======
|
||||||
|
|
||||||
|
1. Open <dev_server_ip>/jasmine in a browser. The development server can be run
|
||||||
|
with``./run_tests.sh --runserver`` from the horizon root directory.
|
||||||
|
2. ``npm run test`` from the horizon root directory.
|
||||||
|
|
||||||
|
For more detailed information, see :doc:`javascript_testing`.
|
||||||
|
|
||||||
|
Translation (Internationalization and Localization)
|
||||||
|
===================================================
|
||||||
|
|
||||||
|
.. Note::
|
||||||
|
This is likely to change soon, after the
|
||||||
|
`Angular Translation <https://blueprints.launchpad.net/horizon/+spec/angular-translate-makemessages>`_
|
||||||
|
blueprint has been completed.
|
||||||
|
|
||||||
|
Translations are handled in Transifex, as with Django. They are merged daily
|
||||||
|
with the horizon upstream codebase. See
|
||||||
|
`Translations <https://wiki.openstack.org/wiki/Translations>`_ in the
|
||||||
|
OpenStack wiki to learn more about this process.
|
||||||
|
|
||||||
|
Use either ``gettext`` (singular) or ``ngettext`` (plural):
|
||||||
|
::
|
||||||
|
|
||||||
|
gettext('text to be translated');
|
||||||
|
ngettext('text to be translated');
|
||||||
|
|
||||||
|
The :ref:`translatability` section contains information about the
|
||||||
|
pseudo translation tool, and how to make sure your translations are working
|
||||||
|
locally.
|
||||||
|
|
||||||
|
Creating your own panel
|
||||||
|
=======================
|
||||||
|
|
||||||
|
.. Note::
|
||||||
|
This section will be extended as standard practices are adopted upstream.
|
||||||
|
Currently, it may be useful to use
|
||||||
|
`this patch <https://review.openstack.org/#/c/190852/>`_ and its dependants
|
||||||
|
as an example.
|
||||||
|
|
||||||
|
.. Note::
|
||||||
|
File inclusion is likely to be automated soon, after this
|
||||||
|
`blueprint <https://blueprints.launchpad.net/horizon/+spec/auto-js-file-finding>`_
|
||||||
|
is completed.
|
||||||
|
|
||||||
|
This section serves as a basic introduction to writing your own panel for
|
||||||
|
horizon, using AngularJS. A panel may be included with the plugin system, or it may be
|
||||||
|
part of the upstream horizon project.
|
||||||
|
|
||||||
|
Upstream
|
||||||
|
--------
|
||||||
|
|
||||||
|
If you are adding a panel to horizon, add the relevant ``.js`` and ``.spec.js``
|
||||||
|
files to one of the dashboards in ``openstack_dashboard/enabled/``.
|
||||||
|
An example can be found at ``openstack_dashboard/enabled/_10_project.py``:
|
||||||
|
::
|
||||||
|
|
||||||
|
LAUNCH_INST = 'dashboard/launch-instance/'
|
||||||
|
|
||||||
|
ADD_JS_FILES = [
|
||||||
|
...
|
||||||
|
LAUNCH_INST + 'launch-instance.js',
|
||||||
|
LAUNCH_INST + 'launch-instance.model.js',
|
||||||
|
LAUNCH_INST + 'source/source.js',
|
||||||
|
LAUNCH_INST + 'flavor/flavor.js',
|
||||||
|
...
|
||||||
|
]
|
||||||
|
|
||||||
|
ADD_JS_SPEC_FILES = [
|
||||||
|
...
|
||||||
|
LAUNCH_INST + 'launch-instance.spec.js',
|
||||||
|
LAUNCH_INST + 'launch-instance.model.spec.js',
|
||||||
|
LAUNCH_INST + 'source/source.spec.js',
|
||||||
|
LAUNCH_INST + 'flavor/flavor.spec.js',
|
||||||
|
...
|
||||||
|
]
|
||||||
|
|
||||||
|
Plugins
|
||||||
|
-------
|
||||||
|
|
||||||
|
Add a new panel/ panel group/ dashboard (See :doc:`tutorial`). Add your files
|
||||||
|
to the relevant arrays in your new enabled files:
|
||||||
|
::
|
||||||
|
|
||||||
|
ADD_JS_FILES = [
|
||||||
|
...
|
||||||
|
'path_to/my_angular_code.js',
|
||||||
|
...
|
||||||
|
]
|
||||||
|
|
||||||
|
ADD_JS_SPEC_FILES = [
|
||||||
|
...
|
||||||
|
'path_to/my_angular_code.spec.js',
|
||||||
|
...
|
||||||
|
]
|
294
doc/source/topics/javascript_testing.rst
Normal file
294
doc/source/topics/javascript_testing.rst
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
==================
|
||||||
|
JavaScript Testing
|
||||||
|
==================
|
||||||
|
|
||||||
|
There are multiple components in our JavaScript testing framework:
|
||||||
|
* `Jasmine`_ is our testing framework, so this defines the syntax and file
|
||||||
|
structure we use to test our JavaScript.
|
||||||
|
* `Karma`_ is our test runner. Amongst other things, this lets us run the
|
||||||
|
tests against multiple browsers and generate test coverage reports.
|
||||||
|
Alternatively, tests can be run inside the browser with the Jasmine spec
|
||||||
|
runner.
|
||||||
|
* `PhantomJS`_ provides a headless WebKit (the browser engine). This gives us
|
||||||
|
native support for many web features without relying on specific browsers
|
||||||
|
being installed.
|
||||||
|
* `ESLint`_ is a pluggable code linting utilty. This will catch small errors
|
||||||
|
and inconsistencies in your JS, which may lead to bigger issues later on.
|
||||||
|
See :ref:`js_code_style` for more detail.
|
||||||
|
|
||||||
|
Jasmine uses specs (``.spec.js``) which are kept with the JavaScript files
|
||||||
|
that they are testing. See the :ref:`js_file_structure` section or the `Examples`_
|
||||||
|
below for more detail on this.
|
||||||
|
|
||||||
|
.. _Jasmine: https://jasmine.github.io/2.3/introduction.html
|
||||||
|
.. _Karma: https://karma-runner.github.io/
|
||||||
|
.. _PhantomJS: http://phantomjs.org/
|
||||||
|
.. _ESLint: http://eslint.org/
|
||||||
|
|
||||||
|
Running Tests
|
||||||
|
=============
|
||||||
|
|
||||||
|
Tests can be run in two ways:
|
||||||
|
|
||||||
|
1. Open <dev_server_ip>/jasmine in a browser. The development server can be
|
||||||
|
run with ``./run_tests.sh --runserver`` from the horizon root directory.
|
||||||
|
2. ``npm run test`` from the horizon root directory. This runs Karma,
|
||||||
|
so it will run all the tests against PhantomJS and generate coverage
|
||||||
|
reports.
|
||||||
|
|
||||||
|
The code linting job can be run with ``npm run lint``.
|
||||||
|
|
||||||
|
Coverage Reports
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Our Karma setup includes a plugin to generate test coverage reports. When
|
||||||
|
developing, be sure to check the coverage reports on the master branch and
|
||||||
|
compare your development branch; this will help identify missing tests.
|
||||||
|
|
||||||
|
To generate coverage reports, run ``npm run test``. The coverage reports can be
|
||||||
|
found at ``horizon/.coverage-karma/`` (framework tests) and
|
||||||
|
``openstack_dashboard/.coverage-karma/`` (dashboard tests). Load
|
||||||
|
``<browser>/index.html`` in a browser to view the reports.
|
||||||
|
|
||||||
|
Writing Tests
|
||||||
|
=============
|
||||||
|
|
||||||
|
.. Note::
|
||||||
|
File inclusion is likely to be automated soon, after this
|
||||||
|
`blueprint <https://blueprints.launchpad.net/horizon/+spec/auto-js-file-finding>`_
|
||||||
|
is completed.
|
||||||
|
|
||||||
|
Jasmine uses suites and specs:
|
||||||
|
* Suites begin with a call to ``describe``, which takes two parameters; a
|
||||||
|
string and a function. The string is a name or title for the spec suite,
|
||||||
|
whilst the function is a block that implements the suite.
|
||||||
|
* Specs begin with a call to ``it``, which also takes a string and a function
|
||||||
|
as parameters. The string is a name or title, whilst the function is a
|
||||||
|
block with one or more expectations (``expect``) that test the state of
|
||||||
|
the code. An expectation in Jasmine is an assertion that is either true or
|
||||||
|
false; every expectation in a spec must be true for the spec to pass.
|
||||||
|
|
||||||
|
Horizon Tests
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Horizon tests are included in
|
||||||
|
``horizon/test/jasmine/jasmine_tests.py``.
|
||||||
|
|
||||||
|
Add your test to the ``specs`` array, code sources to the ``dashboard_sources``
|
||||||
|
array, and any templates to the ``externalTemplates`` array. Horizon tests
|
||||||
|
cover reusable components, as well as api functionality, whilst dashboard
|
||||||
|
tests cover specific panels and their logic. The tests themselves are kept in
|
||||||
|
the same directory as the implementation they are testing.
|
||||||
|
|
||||||
|
OpenStack Dashboard Tests
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Dashboard tests are included in the relevant dashboard enabled file, such as
|
||||||
|
``openstack_dashboard/enabled/_10_project.py``.
|
||||||
|
|
||||||
|
Add your tests to the ``ADD_JS_SPEC_FILES`` array.
|
||||||
|
|
||||||
|
Examples
|
||||||
|
========
|
||||||
|
|
||||||
|
.. Note::
|
||||||
|
The code below is just for example purposes, and may not be current in
|
||||||
|
horizon. Ellipses (...) are used to represent code that has been
|
||||||
|
removed for the sake of brevity.
|
||||||
|
|
||||||
|
Example 1 - A reusable component in the **horizon** directory
|
||||||
|
-------------------------------------------------------------
|
||||||
|
|
||||||
|
File tree:
|
||||||
|
::
|
||||||
|
|
||||||
|
horizon/static/framework/widgets/modal
|
||||||
|
├── modal.controller.js
|
||||||
|
├── modal.factory.js
|
||||||
|
├── modal.module.js
|
||||||
|
└── modal.spec.js
|
||||||
|
|
||||||
|
Lines added to ``horizon/test/jasmine/jasmine_tests.py``:
|
||||||
|
::
|
||||||
|
|
||||||
|
class ServicesTests(test.JasmineTests):
|
||||||
|
sources = [
|
||||||
|
...
|
||||||
|
'framework/widgets/modal/modal.module.js',
|
||||||
|
'framework/widgets/modal/modal.controller.js',
|
||||||
|
'framework/widgets/modal/modal.factory.js',
|
||||||
|
...
|
||||||
|
]
|
||||||
|
|
||||||
|
specs = [
|
||||||
|
...
|
||||||
|
'framework/widgets/modal/modal.spec.js',
|
||||||
|
...
|
||||||
|
]
|
||||||
|
|
||||||
|
``modal.spec.js``:
|
||||||
|
::
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
describe('horizon.framework.widgets.modal module', function() {
|
||||||
|
|
||||||
|
beforeEach(module('horizon.framework.widgets.modal'));
|
||||||
|
|
||||||
|
describe('simpleModalCtrl', function() {
|
||||||
|
var scope;
|
||||||
|
var modalInstance;
|
||||||
|
var context;
|
||||||
|
var ctrl;
|
||||||
|
|
||||||
|
beforeEach(inject(function($controller) {
|
||||||
|
scope = {};
|
||||||
|
modalInstance = {
|
||||||
|
close: function() {},
|
||||||
|
dismiss: function() {}
|
||||||
|
};
|
||||||
|
context = { what: 'is it' };
|
||||||
|
ctrl = $controller('simpleModalCtrl', {
|
||||||
|
$scope: scope,
|
||||||
|
$modalInstance: modalInstance,
|
||||||
|
context: context
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('establishes a controller', function() {
|
||||||
|
expect(ctrl).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets context on the scope', function() {
|
||||||
|
expect(scope.context).toBeDefined();
|
||||||
|
expect(scope.context).toEqual({ what: 'is it' });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets action functions', function() {
|
||||||
|
expect(scope.submit).toBeDefined();
|
||||||
|
expect(scope.cancel).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('makes submit close the modal instance', function() {
|
||||||
|
expect(scope.submit).toBeDefined();
|
||||||
|
spyOn(modalInstance, 'close');
|
||||||
|
scope.submit();
|
||||||
|
expect(modalInstance.close.calls.count()).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('makes cancel close the modal instance', function() {
|
||||||
|
expect(scope.cancel).toBeDefined();
|
||||||
|
spyOn(modalInstance, 'dismiss');
|
||||||
|
scope.cancel();
|
||||||
|
expect(modalInstance.dismiss).toHaveBeenCalledWith('cancel');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
|
Example 2 - Panel-specific code in the **openstack_dashboard** directory
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
|
||||||
|
File tree:
|
||||||
|
::
|
||||||
|
|
||||||
|
openstack_dashboard/static/dashboard/launch-instance/network/
|
||||||
|
├── network.help.html
|
||||||
|
├── network.html
|
||||||
|
├── network.js
|
||||||
|
├── network.scss
|
||||||
|
└── network.spec.js
|
||||||
|
|
||||||
|
|
||||||
|
Lines added to ``openstack_dashboard/enabled/_10_project.py``:
|
||||||
|
::
|
||||||
|
|
||||||
|
LAUNCH_INST = 'dashboard/launch-instance/'
|
||||||
|
|
||||||
|
ADD_JS_FILES = [
|
||||||
|
...
|
||||||
|
LAUNCH_INST + 'network/network.js',
|
||||||
|
...
|
||||||
|
]
|
||||||
|
|
||||||
|
ADD_JS_SPEC_FILES = [
|
||||||
|
...
|
||||||
|
LAUNCH_INST + 'network/network.spec.js',
|
||||||
|
...
|
||||||
|
]
|
||||||
|
|
||||||
|
``network.spec.js``:
|
||||||
|
::
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
(function(){
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
describe('Launch Instance Network Step', function() {
|
||||||
|
|
||||||
|
describe('LaunchInstanceNetworkCtrl', function() {
|
||||||
|
var scope;
|
||||||
|
var ctrl;
|
||||||
|
|
||||||
|
beforeEach(module('hz.dashboard.launch-instance'));
|
||||||
|
|
||||||
|
beforeEach(inject(function($controller) {
|
||||||
|
scope = {
|
||||||
|
model: {
|
||||||
|
newInstanceSpec: {networks: ['net-a']},
|
||||||
|
networks: ['net-a', 'net-b']
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ctrl = $controller('LaunchInstanceNetworkCtrl', {$scope:scope});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('has correct network statuses', function() {
|
||||||
|
expect(ctrl.networkStatuses).toBeDefined();
|
||||||
|
expect(ctrl.networkStatuses.ACTIVE).toBeDefined();
|
||||||
|
expect(ctrl.networkStatuses.DOWN).toBeDefined();
|
||||||
|
expect(Object.keys(ctrl.networkStatuses).length).toBe(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has correct network admin states', function() {
|
||||||
|
expect(ctrl.networkAdminStates).toBeDefined();
|
||||||
|
expect(ctrl.networkAdminStates.UP).toBeDefined();
|
||||||
|
expect(ctrl.networkAdminStates.DOWN).toBeDefined();
|
||||||
|
expect(Object.keys(ctrl.networkStatuses).length).toBe(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('defines a multiple-allocation table', function() {
|
||||||
|
expect(ctrl.tableLimits).toBeDefined();
|
||||||
|
expect(ctrl.tableLimits.maxAllocation).toBe(-1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('contains its own labels', function() {
|
||||||
|
expect(ctrl.label).toBeDefined();
|
||||||
|
expect(Object.keys(ctrl.label).length).toBeGreaterThan(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('contains help text for the table', function() {
|
||||||
|
expect(ctrl.tableHelpText).toBeDefined();
|
||||||
|
expect(ctrl.tableHelpText.allocHelpText).toBeDefined();
|
||||||
|
expect(ctrl.tableHelpText.availHelpText).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('uses scope to set table data', function() {
|
||||||
|
expect(ctrl.tableDataMulti).toBeDefined();
|
||||||
|
expect(ctrl.tableDataMulti.available).toEqual(['net-a', 'net-b']);
|
||||||
|
expect(ctrl.tableDataMulti.allocated).toEqual(['net-a']);
|
||||||
|
expect(ctrl.tableDataMulti.displayedAllocated).toEqual([]);
|
||||||
|
expect(ctrl.tableDataMulti.displayedAvailable).toEqual([]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
});
|
||||||
|
})();
|
Loading…
Reference in New Issue
Block a user