Nova uses CompoDoc for documenting the APIs and usage instructions for its components. To run the documentation app in your development environment for any of the packages, open up a terminal with the root of the desired package (bits, charts, or dashboards) set as the current working directory, and run the npm start
command.
The start
task has two main procedures that it runs:
- compiling the CompoDoc API docs
- compiling the live examples of Nova's components.
Note: Depending on the size of the package, the example compilation may take a few minutes. So, if you don't see the examples show up in the browser right away, you likely haven't done anything wrong; it just takes some time to process the hundreds of examples that Nova has.
Each package serves up the docs on a different port. To see the app running in a browser, navigate to the following URL, replacing the placeholder with the correct port: http:\\localhost:<port>
Package | Port |
---|---|
Bits | 8080 |
Charts | 8070 |
Dashboards | 8090 |
All Nova projects (bits
, charts
and dashboards
) have the following npm commands to run and/or debug
e2e tests:
npm run e2e
- to compile the project and run e2e-testsnpm run e2e-dev
- to run ONLY the tests without compiling the project under test. Note: For this task to work, the project itself should be served up separately by runningnpm run start
in a separate console window.npm run e2e-debug
- similar toe2e-dev
, but used for e2e debugging purposes. It allowsdebugger
statements to be run.
Click to view instructions on debugging e2e tests
npm run e2e-debug
runs e2e tests using Protractor directly without the Angular e2e test wrapper (for
some reason the Angular version doesn't respond to debugger
statements). After you run
npm run e2e-debug
, the node process will indicate that it's waiting until the debugger is attached by
showing a message in the console.
After that go to chrome://inspect/#devices
and open the corresponding inspector under the target
category. The interpreter will now stop on debugger
statements.
You can create a debugger configuration for debugging e2e tests in VS Code. Here are two configurations
for the debugger that can be added to the launch.json
file under the .vscode
directory in the project:
{
"type": "node",
"request": "attach",
"name": "e2e attach",
"port": 9229
},
{
"type": "node",
"request": "attach",
"name": "e2e debug and attach",
"port": 9229,
"preLaunchTask": "e2e-debug"
}
e2e attach
just attaches to the hosted process after runningnpm run e2e-debug
.e2e debug and attach
first runsnpm run e2e-debug
and then attaches to the process (you should restart the debugger after you seeDebugger listening on...
in the console, because VS Code runs the task and debugger simultaneously)
To use the preLaunchTask
mentioned in the e2e debug and attach
configuration, add the following task
configuration to a tasks.json
file:
{
"version": "2.0.0",
"tasks": [
{
"label": "e2e-debug",
"command": "npm run e2e-debug",
"args": [],
"type": "shell"
}
]
}
Atoms are user friendly interfaces used to test components and directives. The main idea behind atoms is that the test environment should not need to know about:
- The internal structure of a component under test
- Class names that are applied in different component states
- The details of a component's implementation
- etc.
Atoms also provide information about their available features, states, attributes and nested components with intellisense right in the IDE. And, perhaps above all, they make tests more readable!
Click to view instructions on using Nova Atoms
-
Using its constructor. Code Example
dialog = new DialogAtom(element(by.className("nui-dialog")));
-
Finding an Atom in some context in the DOM. Code Example
busy = Atom.findIn(BusyAtom, element(by.id("nui-busy-test-basic")));
-
Declare a variable with the proper type.
let defaultDialogBtn: ButtonAtom;
-
browser.get() the test page make sure the page is loaded before trying to use an atom. If the page is not rendered, protractor obviously will throw the familiar "element not found" sorts of exceptions.
await browser.get(url);
-
Find atoms of the components before the tests run (use
beforeEach()
orbeforeAll()
).beforeAll(async () => { await Helper.prepareBrowser("dialog"); defaultDialogBtn = Atom.find(ButtonAtom, "nui-demo-default-dialog-btn"); });
-
Use the variable containing an atom to call it's methods or for viewing\asserting it in the context of your tests.
it("should add custom class to dialog", async () => { await customClassButton.click(); expect(await dialog.hasClass("demoDialogCustomClass")).toBe(true); });
Note: If needed, atoms can be instantiated during test as well, for instance, if a component appears on the page conditionally.
Atoms for different components or directives will expectedly have different API. The only thing they have in common, however, is the base class they're inherited from - the Atom class. Each atom has access to the methods of the base Atom class.
Atom base class public API explained
# | Field/Method | How it works |
---|---|---|
STATIC | ||
1 | static CSS_CLASS |
This is how atoms are found in the DOM - thanks to this static css class. Different atoms must have different values here. Example |
2 | static find(atomClass: IAtomClass<T>, id: string) |
Find a needed Atom within the parent element, found using it's unique id. This class uses findIn() method, described below. Example |
3 | static findIn(atomClass: IAtomClass<T>, parentElement: ElementFinder, index?: number) |
This is a basic method typically used to look for atoms in the DOM. It requires providing a desired atom name, the context where to look for it, and also an optional index parameter. The optional index param is used if there were more than one atom of a component found on the page, so the user can choose which one to take. Example |
4 | static async findCount(atomClass: IAtomClass<T>, parentElement: ElementFinder): Promise<number> |
Is used to get the number of atoms found within the given context. Returns a promise. |
5 | static async hasClass(el: ElementFinder, className: string): Promise<string> |
Is used to check that a certain css class has been applied to a selected element. |
6 | static async hasAnyClass(el: ElementFinder, classNamesToSearch: string[]): Promise<string> |
The same as hasClass() , with the only difference if can search for a number of classes in a given element. |
NON-STATIC | ||
7 | async isDisplayed() , async isPresent() |
A simple wrapper around the same protractor methods. |
8 | async hasClass(className: string) |
Does the same as the static one, but looks for the classes within the atom on which it was called. Example |
9 | getElement(): ElementFinder |
Used to get the ElementFinder of the Atom. |
10 | async isChildElementPresent(locator: any): Promise<boolean> |
Pretty self-explanatory, it looks for a child element within the atom using a given Locator and verifies if it's present. |
11 | async hover(el?: ElementFinder, location?: ILocation) |
If no params are provided then it hovers over itself. It will hover over the given element if ElementFinder is provided and over the given coordinates if ILocation is given. Example |
12 | async scrollTo() |
Scrolls to the current atom so it appears in the viewport. Useful in cases when a desired element on the page, but not within the viewport, and is therefore not clickable. Example |
To get your locally built library to be used as a dependency of another library or app you will need to do two things:
- Build the child library
- Link build output so it will be consumed instead of the package installed from artifactory
In each library's package.json
file there are couple of scripts for this. Check what are they doing.
Usually they are called assemble
, assemble:lib
, assemble:dev
, or something like that.
In the root package.json
there are scripts to run the builds of dependency libraries with a --watch
flag. They are build-watch:bits
and build-watch:charts
accordingly. It will do an incremental
build of your library on every file change which will in turn trigger a rebuild of your library/app if
it's running in watch mode too. Make sure to have separate terminal windows for running these tasks.
- The dev build of the library does not include schematics. Do the full
assemble
for this. - For updating global less and atoms or for regenerating css/fonts, you will need to restart the build task. These types of changes will not be picked up automatically.
As npm link
or yarn link
proved to not work reliably with angular libraries, we are using regular
symbolic linked folders (junction for Windows file system).
To link things with each other we have some scripts in the package.json
file.
charts-link:bits
- removes the@nova-ui/bits
folder from charts'node_modules
and replaces it with a symlink to thedist
folder from bits.dashboards-link:bits
- does the same replacement for dashboardsdashboards-link:charts
- links charts'dist
folder into dashboards'node_modules
in the same way as abovelink:all
- runs all the previous scripts that will link the internal dependencies
For reverting what was done by the "link" scripts, there is also a set of opposites:
charts-unlink:bits
, dashboards-unlink:bits
, dashboards-unlink:charts
and
unlink:all
. To unlink both dependencies for dashboards in a single shot there is also
dashboards-unlink
.
These scripts will remove the created symlinks and run npm install
in the project folder, thus returning
your node_modules
to its initial state.