Testing Tabris.js applications
Unit Tests
Unit tests of tabris application code may be written with any JavaScript/TypeScript test tool (such as Mocha) that can run in node. However, if the code under test relies on the tabris
module it may initially produce errors such as:
tabris.js not started
JSX is not defined
$ is not defined
This is because the tabris
module needs to be initialized before it can be used. Usually this is done via platform-native code, i.e. the Tabris.js parts written specifically for iOS or Android. Within node that native code needs to be emulated, otherwise no instances of NativeObject
(which includes all widgets) can be created.
Initializing the Tabris module
You may create a example test setup when generating a compiled Tabris.js app with the CLI
tabris init
command. In that case the steps described below have already been taken care of.
To resolve the initialization problem Tabris.js provides the a sub-module identified as tabris/ClientMock
which exports the ClientMock
class. This class partially imitates the behavior and API of the platforms-native code and allows - with some limitations - code based on the tabris
module to run as it would in a production environment.
This quickest way to set up ClientMock
looks like this:
import {tabris} from 'tabris';
import ClientMock from 'tabris/ClientMock';
tabris._init(new ClientMock()); // do this before using tabris module
The first import statement technically only imports (and shadows) the already global
tabris
object, but is needed in TypeScript to access to the “internal”_init
method.
After the call to _init
the tabris module can be used. Depending on your application this needs to be done before the code under test is imported. This is the case if your application calls Tabris.js API at the root of a module. (Extending Tabris.js classes is fine, just not creating instances or calling methods.)
However, “import ... from ...
” statements can not be mixed with other code, you either have to use dynamic imports (which is cumbersome), or wrap the above code in its own module, e.g. init-tabris.js
. Then simply import that module as the first one in every test class. You project could look like this:
|-package.json
|-src
|- MyApp.js
|-test
|-init-tabris.js
|-MyApp.test.js
In which case init-tabris.js
contains the code above and MyApp.test.js
looks like this:
import './init-tabris';
import MyApp from '../src/MyApp';
describe('MyApp', function() {
//...
});
The _init
method may be called again at any point to reset the state of the tabris module. You may want to do this before or after each test.
beforeEach(function() {
tabris._init(new ClientMock());
});
Faking read-only properties
Many Tabris.js objects (instance of NativeObject
) have read-only properties that normally can not be set via JavaScript. This includes most properties on tabris.Device
and tabris.App
, but also Widget bounds
. You can set those for specific types during the initialization call on the ClientMode
:
tabris._init(new ClientMock({
'tabris.Device': {platform: 'Android'},
'tabris.App': {version: '1.0.0'}
}));