test: nucleus/src/object done (#980)

This commit is contained in:
Ahmad Mirzaei
2022-11-01 11:13:22 +01:00
committed by GitHub
parent 204d2df55e
commit afebec0d26
11 changed files with 336 additions and 333 deletions

View File

@@ -7,16 +7,16 @@ https://github.com/qlik-oss/nebula.js/blob/master/.github/CONTRIBUTING.md#git
<!-- Write your motivation here -->
## Requirements checklist
<!-- Make sure you got these covered -->
- [ ] Api specification
- [ ] Ran `yarn spec`
- [ ] No changes ***OR*** API changes has been formally approved
- [ ] No changes **_OR_** API changes has been formally approved
- [ ] Unit/Component test coverage
- [ ] Correct PR title for the changes (fix, chore, feat)
When build and tests have passed:
- [ ] Add code reviewers, for example @qlik-oss/nebula-core

View File

@@ -0,0 +1,120 @@
import * as populatorModule from '../populator';
import * as initiateModule from '../initiate';
import create from '../create-session-object';
describe('create-session-object', () => {
let halo = {};
let types;
let sn;
let merged;
let populator;
let init;
let objectModel;
beforeEach(() => {
populator = jest.fn();
init = jest.fn();
jest.spyOn(populatorModule, 'default').mockImplementation(populator);
jest.spyOn(initiateModule, 'default').mockImplementation(init);
objectModel = { id: 'id', on: () => {}, once: () => {} };
types = {
get: jest.fn(),
};
halo = {
app: {
createSessionObject: jest.fn().mockResolvedValue(objectModel),
},
types,
};
init.mockReturnValue('api');
sn = { qae: { properties: { onChange: jest.fn() } } };
merged = { m: 'true' };
const t = {
initialProperties: jest.fn().mockResolvedValue(merged),
supernova: jest.fn().mockResolvedValue(sn),
};
types.get.mockReturnValue(t);
});
afterEach(() => {
jest.resetAllMocks();
jest.restoreAllMocks();
});
test('should call types.get with name and version', () => {
create({ type: 't', version: 'v', fields: 'f' }, halo);
expect(types.get).toHaveBeenCalledWith({ name: 't', version: 'v' });
});
test('should call initialProperties on returned type', () => {
const t = { initialProperties: jest.fn() };
t.initialProperties.mockReturnValue({ then: () => {} });
types.get.mockReturnValue(t);
create({ type: 't', version: 'v', fields: 'f', properties: 'props' }, halo);
expect(t.initialProperties).toHaveBeenCalledWith('props');
});
test('should populate fields', async () => {
await create({ type: 't', version: 'v', fields: 'f', properties: 'props' }, halo);
expect(populator).toHaveBeenCalledWith({ sn, properties: merged, fields: 'f' }, halo);
});
test('should call properties onChange handler when optional props are provided', async () => {
await create({ type: 't', version: 'v', fields: 'f', properties: 'props' }, halo);
expect(sn.qae.properties.onChange).toHaveBeenCalledWith(merged);
});
test('should not call onChange handler when optional props are not provided', async () => {
await create({ type: 't', version: 'v', fields: 'f' }, halo);
expect(sn.qae.properties.onChange).toHaveBeenCalledTimes(0);
});
test('should create a session object with merged props', async () => {
await create({ type: 't', version: 'v', fields: 'f', properties: 'props' }, halo);
expect(halo.app.createSessionObject).toHaveBeenCalledWith(merged);
});
test('should create a dummy session object when error is thrown', async () => {
types.get.mockImplementation(() => {
throw new Error('oops');
});
await create({ type: 't', version: 'v', fields: 'f', properties: 'props' }, halo);
expect(halo.app.createSessionObject).toHaveBeenCalledWith({
qInfo: { qType: 't' },
visualization: 't',
});
});
test('should call init', async () => {
const ret = await create(
{ type: 't', version: 'v', fields: 'f', properties: 'props', options: 'a', plugins: [] },
halo
);
expect(ret).toBe('api');
expect(init).toHaveBeenCalledWith(
objectModel,
{ options: 'a', plugins: [], element: undefined },
halo,
undefined,
expect.any(Function)
);
});
test('should catch and pass error', async () => {
const err = new Error('oops');
types.get.mockReturnValue(err);
const optional = { properties: 'props', element: 'el', options: 'opts' };
const ret = await create({ type: 't', ...optional }, halo);
expect(ret).toBe('api');
expect(init).toHaveBeenCalledWith(
objectModel,
{ options: 'opts', plugins: undefined, element: 'el' },
halo,
expect.objectContaining(err),
expect.any(Function)
);
});
});

View File

@@ -1,122 +0,0 @@
describe('create-session-object', () => {
let halo = {};
let types;
let sn;
let merged;
let create;
let populator;
let sandbox;
let init;
let objectModel;
before(() => {
sandbox = sinon.createSandbox();
populator = sandbox.stub();
init = sandbox.stub();
[{ default: create }] = aw.mock(
[
['**/populator.js', () => populator],
['**/initiate.js', () => init],
],
['../create-session-object.js']
);
});
beforeEach(() => {
objectModel = { id: 'id', on: () => {}, once: () => {} };
types = {
get: sandbox.stub(),
};
halo = {
app: {
createSessionObject: sandbox.stub().returns(Promise.resolve(objectModel)),
},
types,
};
init.returns('api');
sn = { qae: { properties: { onChange: sandbox.stub() } } };
merged = { m: 'true' };
const t = {
initialProperties: sandbox.stub().returns(Promise.resolve(merged)),
supernova: sandbox.stub().returns(Promise.resolve(sn)),
};
types.get.returns(t);
});
afterEach(() => {
sandbox.reset();
});
it('should call types.get with name and version', () => {
create({ type: 't', version: 'v', fields: 'f' }, halo);
expect(types.get).to.have.been.calledWithExactly({ name: 't', version: 'v' });
});
it('should call initialProperties on returned type', () => {
const t = { initialProperties: sinon.stub() };
t.initialProperties.returns({ then: () => {} });
types.get.returns(t);
create({ type: 't', version: 'v', fields: 'f', properties: 'props' }, halo);
expect(t.initialProperties).to.have.been.calledWithExactly('props');
});
it('should populate fields', async () => {
await create({ type: 't', version: 'v', fields: 'f', properties: 'props' }, halo);
expect(populator).to.have.been.calledWithExactly({ sn, properties: merged, fields: 'f' }, halo);
});
it('should call properties onChange handler when optional props are provided', async () => {
await create({ type: 't', version: 'v', fields: 'f', properties: 'props' }, halo);
expect(sn.qae.properties.onChange).to.have.been.calledWithExactly(merged);
});
it('should not call onChange handler when optional props are not provided', async () => {
await create({ type: 't', version: 'v', fields: 'f' }, halo);
expect(sn.qae.properties.onChange.callCount).to.equal(0);
});
it('should create a session object with merged props', async () => {
await create({ type: 't', version: 'v', fields: 'f', properties: 'props' }, halo);
expect(halo.app.createSessionObject).to.have.been.calledWithExactly(merged);
});
it('should create a dummy session object when error is thrown', async () => {
types.get.throws('oops');
await create({ type: 't', version: 'v', fields: 'f', properties: 'props' }, halo);
expect(halo.app.createSessionObject).to.have.been.calledWithExactly({
qInfo: { qType: 't' },
visualization: 't',
});
});
it('should call init', async () => {
const ret = await create(
{ type: 't', version: 'v', fields: 'f', properties: 'props', options: 'a', plugins: [] },
halo
);
expect(ret).to.equal('api');
expect(init).to.have.been.calledWithExactly(
objectModel,
{ options: 'a', plugins: [], element: undefined },
halo,
undefined,
sinon.match.func
);
});
it('should catch and pass error', async () => {
const err = new Error('oops');
types.get.throws(err);
const optional = { properties: 'props', element: 'el', options: 'opts' };
const ret = await create({ type: 't', ...optional }, halo);
expect(ret).to.equal('api');
expect(init).to.have.been.calledWithExactly(
objectModel,
{ options: 'opts', plugins: undefined, element: 'el' },
halo,
err,
sinon.match.func
);
});
});

View File

@@ -0,0 +1,54 @@
import * as initiateModule from '../initiate';
import create from '../get-object';
describe('get-object', () => {
let context = {};
let init;
let objectModel;
let model;
beforeEach(() => {
init = jest.fn();
jest.spyOn(initiateModule, 'default').mockImplementation(init);
model = {
id: 'model-x',
on: jest.fn(),
once: jest.fn(),
};
objectModel = jest.fn();
init.mockReturnValue('api');
context = { app: { id: 'appid', getObject: async () => Promise.resolve(objectModel) } };
});
afterEach(() => {
jest.resetAllMocks();
jest.restoreAllMocks();
});
test('should get object from app only once', async () => {
objectModel.mockReturnValue(model);
const spy = jest.spyOn(context.app, 'getObject').mockImplementation(objectModel);
await create({ id: 'x' }, context);
await create({ id: 'x' }, context);
await create({ id: 'x' }, context);
expect(spy).toHaveBeenCalledTimes(1);
expect(spy).toHaveBeenCalledWith('x');
});
test('should call init', async () => {
objectModel.mockReturnValue(model);
jest.spyOn(context.app, 'getObject').mockImplementation(objectModel);
const ret = await create({ id: 'x', options: 'op', plugins: [], element: 'el' }, context);
expect(ret).toBe('api');
expect(init).toHaveBeenCalledWith(
expect.objectContaining({
id: model.id,
on: expect.any(Function),
once: expect.any(Function),
}),
{ options: 'op', plugins: [], element: 'el' },
context
);
});
});

View File

@@ -1,45 +0,0 @@
describe('get-object', () => {
let context = {};
let create;
let sandbox;
let init;
let objectModel;
let model;
before(() => {
sandbox = sinon.createSandbox();
init = sandbox.stub();
[{ default: create }] = aw.mock([['**/initiate.js', () => init]], ['../get-object.js']);
model = {
id: 'model-x',
on: sandbox.spy(),
once: sandbox.spy(),
};
});
beforeEach(() => {
objectModel = sandbox.stub();
init.returns('api');
context = { app: { id: 'appid', getObject: async (id) => Promise.resolve(objectModel(id)) } };
});
afterEach(() => {
sandbox.reset();
});
it('should get object from app only once', async () => {
objectModel.withArgs('x').returns(model);
const spy = sandbox.spy(context.app, 'getObject');
await create({ id: 'x' }, context);
await create({ id: 'x' }, context);
await create({ id: 'x' }, context);
expect(spy.callCount).to.equal(1);
expect(spy).to.have.been.calledWithExactly('x');
});
it('should call init', async () => {
objectModel.withArgs('x').returns(model);
const ret = await create({ id: 'x', options: 'op', plugins: [], element: 'el' }, context);
expect(ret).to.equal('api');
expect(init).to.have.been.calledWithExactly(model, { options: 'op', plugins: [], element: 'el' }, context);
});
});

View File

@@ -1,24 +1,24 @@
import * as uidModule from '../uid';
import handler from '../hc-handler';
describe('hc-handler', () => {
let h;
let hc;
let def;
let handler;
before(() => {
[{ default: handler }] = aw.mock([['**/uid.js', () => () => 'uid']], ['../hc-handler.js']);
});
beforeEach(() => {
jest.spyOn(uidModule, 'default').mockImplementation(() => 'uid');
hc = {};
def = {
dimensions: {
added: sinon.stub(),
removed: sinon.stub(),
added: jest.fn(),
removed: jest.fn(),
min: () => 0,
max: () => 2,
},
measures: {
added: sinon.stub(),
removed: sinon.stub(),
added: jest.fn(),
removed: jest.fn(),
min: () => 0,
max: () => 3,
},
@@ -31,8 +31,8 @@ describe('hc-handler', () => {
});
});
it('should add default values', () => {
expect(hc).to.eql({
test('should add default values', () => {
expect(hc).toEqual({
qDimensions: [],
qMeasures: [],
qInterColumnSortOrder: [],
@@ -43,9 +43,9 @@ describe('hc-handler', () => {
});
describe('add dimension', () => {
it('from string', () => {
test('from string', () => {
h.addDimension('A');
expect(hc.qDimensions).to.eql([
expect(hc.qDimensions).toEqual([
{
qDef: {
cId: 'uid',
@@ -65,11 +65,11 @@ describe('hc-handler', () => {
]);
});
it('from object', () => {
test('from object', () => {
h.addDimension({
qTotalLabel: 'total',
});
expect(hc.qDimensions).to.eql([
expect(hc.qDimensions).toEqual([
{
qDef: {
cId: 'uid',
@@ -89,16 +89,16 @@ describe('hc-handler', () => {
]);
});
it('should not add more than 2', () => {
test('should not add more than 2', () => {
h.addDimension('A');
h.addDimension('B');
h.addDimension('C');
expect(hc.qDimensions.length).to.eql(2);
expect(hc.qDimensions.length).toBe(2);
});
it('should call added hook on definition', () => {
test('should call added hook on definition', () => {
h.addDimension({ a: 'b' });
expect(def.dimensions.added).to.have.been.calledWithExactly(
expect(def.dimensions.added).toHaveBeenCalledWith(
{
a: 'b',
qDef: {
@@ -119,11 +119,11 @@ describe('hc-handler', () => {
);
});
it('should add overflow to layoutExclude', () => {
test('should add overflow to layoutExclude', () => {
h.addDimension('A');
h.addDimension('B');
h.addDimension({ a: '=a' });
expect(hc.qLayoutExclude.qHyperCubeDef.qDimensions).to.eql([
expect(hc.qLayoutExclude.qHyperCubeDef.qDimensions).toEqual([
{
a: '=a',
qDef: {
@@ -143,10 +143,10 @@ describe('hc-handler', () => {
]);
});
it('should update qInterColumnSortOrder', () => {
test('should update qInterColumnSortOrder', () => {
h.addDimension('A');
h.addDimension('B');
expect(hc.qInterColumnSortOrder).to.eql([0, 1]);
expect(hc.qInterColumnSortOrder).toEqual([0, 1]);
});
});
@@ -156,26 +156,26 @@ describe('hc-handler', () => {
hc.qInterColumnSortOrder = [2, 1, 0];
});
it('by index', () => {
test('by index', () => {
h.removeDimension(1);
expect(hc.qDimensions).to.eql(['a', 'c']);
expect(hc.qDimensions).toEqual(['a', 'c']);
});
it('should call removed hook on definition', () => {
test('should call removed hook on definition', () => {
h.removeDimension(1);
expect(def.dimensions.removed).to.have.been.calledWithExactly('b', 'props', 1);
expect(def.dimensions.removed).toHaveBeenCalledWith('b', 'props', 1);
});
it('should update qInterColumnSortOrder', () => {
test('should update qInterColumnSortOrder', () => {
h.removeDimension(1);
expect(hc.qInterColumnSortOrder).to.eql([1, 0]);
expect(hc.qInterColumnSortOrder).toEqual([1, 0]);
});
});
describe('add measure', () => {
it('from string', () => {
test('from string', () => {
h.addMeasure('A');
expect(hc.qMeasures).to.eql([
expect(hc.qMeasures).toEqual([
{
qDef: {
cId: 'uid',
@@ -191,11 +191,11 @@ describe('hc-handler', () => {
]);
});
it('from object', () => {
test('from object', () => {
h.addMeasure({
bla: 'meh',
});
expect(hc.qMeasures).to.eql([
expect(hc.qMeasures).toEqual([
{
qDef: {
cId: 'uid',
@@ -211,17 +211,17 @@ describe('hc-handler', () => {
]);
});
it('should not add more than 3', () => {
test('should not add more than 3', () => {
h.addMeasure('A');
h.addMeasure('B');
h.addMeasure('C');
h.addMeasure('D');
expect(hc.qMeasures.length).to.eql(3);
expect(hc.qMeasures.length).toBe(3);
});
it('should call added hook on definition', () => {
test('should call added hook on definition', () => {
h.addMeasure({ a: 'b' });
expect(def.measures.added).to.have.been.calledWithExactly(
expect(def.measures.added).toHaveBeenCalledWith(
{
a: 'b',
qDef: { cId: 'uid' },
@@ -236,12 +236,12 @@ describe('hc-handler', () => {
);
});
it('should add overflow to layoutExclude', () => {
test('should add overflow to layoutExclude', () => {
h.addMeasure('A');
h.addMeasure('B');
h.addMeasure('C');
h.addMeasure({ a: '=a' });
expect(hc.qLayoutExclude.qHyperCubeDef.qMeasures).to.eql([
expect(hc.qLayoutExclude.qHyperCubeDef.qMeasures).toEqual([
{
a: '=a',
qDef: { cId: 'uid' },
@@ -255,12 +255,12 @@ describe('hc-handler', () => {
]);
});
it('should update qInterColumnSortOrder', () => {
test('should update qInterColumnSortOrder', () => {
hc.qDimensions = ['a', 'b'];
hc.qInterColumnSortOrder = [0, 1];
h.addMeasure('m1');
h.addMeasure('m2');
expect(hc.qInterColumnSortOrder).to.eql([0, 1, 2, 3]);
expect(hc.qInterColumnSortOrder).toEqual([0, 1, 2, 3]);
});
});
@@ -271,19 +271,19 @@ describe('hc-handler', () => {
hc.qInterColumnSortOrder = [2, 1, 0, 3];
});
it('by index', () => {
test('by index', () => {
h.removeMeasure(1);
expect(hc.qMeasures).to.eql(['b', 'd']);
expect(hc.qMeasures).toEqual(['b', 'd']);
});
it('should call removed hook on definition', () => {
test('should call removed hook on definition', () => {
h.removeMeasure(1);
expect(def.measures.removed).to.have.been.calledWithExactly('c', 'props', 1);
expect(def.measures.removed).toHaveBeenCalledWith('c', 'props', 1);
});
it('should update qInterColumnSortOrder', () => {
test('should update qInterColumnSortOrder', () => {
h.removeMeasure(1);
expect(hc.qInterColumnSortOrder).to.eql([1, 0, 2]);
expect(hc.qInterColumnSortOrder).toEqual([1, 0, 2]);
});
});
});

View File

@@ -0,0 +1,53 @@
/* eslint no-underscore-dangle:0 */
import * as vizModule from '../../viz';
import create from '../initiate';
describe('initiate api', () => {
const optional = 'optional';
const halo = 'halo';
const model = 'model';
let viz;
let api;
beforeEach(() => {
viz = jest.fn();
jest.spyOn(vizModule, 'default').mockImplementation(viz);
api = {
__DO_NOT_USE__: {
mount: jest.fn(),
options: jest.fn(),
plugins: jest.fn(),
},
};
viz.mockReturnValue(api);
});
afterEach(() => {
jest.resetAllMocks();
jest.restoreAllMocks();
});
test('should call viz api', async () => {
const initialError = 'err';
const onDestroy = () => {};
const ret = await create(model, optional, halo, initialError, onDestroy);
expect(viz).toHaveBeenCalledWith({ model, halo, initialError, onDestroy });
expect(ret).toEqual(api);
});
test('should call mount when element is provided ', async () => {
await create(model, { element: 'el' }, halo);
expect(api.__DO_NOT_USE__.mount).toHaveBeenCalledWith('el');
});
test('should call options when provided ', async () => {
await create(model, { options: 'opts' }, halo);
expect(api.__DO_NOT_USE__.options).toHaveBeenCalledWith('opts');
});
test('should call plugins when provided ', async () => {
const plugins = [{ info: { name: 'plugino' }, fn() {} }];
await create(model, { plugins }, halo);
expect(api.__DO_NOT_USE__.plugins).toHaveBeenCalledWith(plugins);
});
});

View File

@@ -1,54 +0,0 @@
/* eslint no-underscore-dangle:0 */
describe('initiate api', () => {
const optional = 'optional';
const halo = 'halo';
const model = 'model';
let create;
let sandbox;
let viz;
let api;
before(() => {
sandbox = sinon.createSandbox();
viz = sandbox.stub();
[{ default: create }] = aw.mock([['**/viz.js', () => viz]], ['../initiate.js']);
});
beforeEach(() => {
api = {
__DO_NOT_USE__: {
mount: sandbox.stub(),
options: sandbox.stub(),
plugins: sandbox.stub(),
},
};
viz.returns(api);
});
afterEach(() => {
sandbox.reset();
});
it('should call viz api', async () => {
const initialError = 'err';
const onDestroy = () => {};
const ret = await create(model, optional, halo, initialError, onDestroy);
expect(viz).to.have.been.calledWithExactly({ model, halo, initialError, onDestroy });
expect(ret).to.equal(api);
});
it('should call mount when element is provided ', async () => {
await create(model, { element: 'el' }, halo);
expect(api.__DO_NOT_USE__.mount).to.have.been.calledWithExactly('el');
});
it('should call options when provided ', async () => {
await create(model, { options: 'opts' }, halo);
expect(api.__DO_NOT_USE__.options).to.have.been.calledWithExactly('opts');
});
it('should call plugins when provided ', async () => {
const plugins = [{ info: { name: 'plugino' }, fn() {} }];
await create(model, { plugins }, halo);
expect(api.__DO_NOT_USE__.plugins).to.have.been.calledWithExactly(plugins);
});
});

View File

@@ -1,12 +1,10 @@
import * as uidModule from '../uid';
import handler from '../lo-container-handler';
describe('lo-container-handler', () => {
let h;
let loc;
let def;
let handler;
before(() => {
[{ default: handler }] = aw.mock([['**/uid.js', () => () => 'uid']], ['../lo-container-handler.js']);
});
const getMockDim = (cId) => ({
qDef: {
@@ -15,13 +13,14 @@ describe('lo-container-handler', () => {
});
beforeEach(() => {
jest.spyOn(uidModule, 'default').mockImplementation(() => 'uid');
loc = {
qDef: {},
};
def = {
dimensions: {
added: sinon.stub(),
removed: sinon.stub(),
added: jest.fn(),
removed: jest.fn(),
min: () => 0,
max: () => 2,
},
@@ -35,11 +34,11 @@ describe('lo-container-handler', () => {
});
});
it('addDimension should not update dimensions since it is provided from outside', () => {
test('addDimension should not update dimensions since it is provided from outside', () => {
h.addDimension(getMockDim());
expect(def.dimensions.added).calledOnce;
expect(h.dimensions()).to.deep.equal([]);
expect(def.dimensions.added).calledWithExactly(
expect(def.dimensions.added).toHaveBeenCalledTimes(1);
expect(h.dimensions()).toEqual([]);
expect(def.dimensions.added).toHaveBeenCalledWith(
{
qDef: {
cId: 'uid',
@@ -50,7 +49,7 @@ describe('lo-container-handler', () => {
);
});
it('removeDimension should pick correct dimension', () => {
test('removeDimension should pick correct dimension', () => {
const dim1 = getMockDim('id-1');
const dim2 = getMockDim('id-2');
const dim3 = getMockDim('id-3');
@@ -61,10 +60,10 @@ describe('lo-container-handler', () => {
dimensions: [dim1, dim2, dim3],
});
h.removeDimension(1);
expect(def.dimensions.removed).calledWithExactly(dim2, 'props', 1);
expect(def.dimensions.removed).toHaveBeenCalledWith(dim2, 'props', 1);
});
it('maxDimensions should call max func', () => {
test('maxDimensions should call max func', () => {
h = handler({
dc: loc,
def: {
@@ -73,10 +72,10 @@ describe('lo-container-handler', () => {
},
},
});
expect(h.maxDimensions()).to.equal('max hey hey');
expect(h.maxDimensions()).toBe('max hey hey');
});
it('maxDimensions should be read as a number when not a func', () => {
test('maxDimensions should be read as a number when not a func', () => {
h = handler({
dc: loc,
def: {
@@ -85,15 +84,15 @@ describe('lo-container-handler', () => {
},
},
});
expect(h.maxDimensions()).to.equal(3);
expect(h.maxDimensions()).toBe(3);
});
it('maxMeasures should be 0', () => {
test('maxMeasures should be 0', () => {
h = handler({ dc: loc });
expect(h.maxMeasures()).to.equal(0);
expect(h.maxMeasures()).toBe(0);
});
it('canAddDimension should be true', () => {
test('canAddDimension should be true', () => {
h = handler({
dc: loc,
dimensions: [{}, {}, {}],
@@ -103,10 +102,10 @@ describe('lo-container-handler', () => {
},
},
});
expect(h.canAddDimension()).to.equal(true);
expect(h.canAddDimension()).toBe(true);
});
it('canAddDimension should be false', () => {
test('canAddDimension should be false', () => {
h = handler({
dc: loc,
dimensions: [{}, {}, {}, {}],
@@ -116,11 +115,11 @@ describe('lo-container-handler', () => {
},
},
});
expect(h.canAddDimension()).to.equal(false);
expect(h.canAddDimension()).toBe(false);
});
it('canAddMeasure should always be false', () => {
test('canAddMeasure should always be false', () => {
h = handler({ dc: loc });
expect(h.canAddMeasure()).to.equal(false);
expect(h.canAddMeasure()).toBe(false);
});
});

View File

@@ -1,48 +1,45 @@
describe('populator', () => {
let handler;
let populate;
let sb;
let h;
let ft;
let warn;
import * as hcHandlerModule from '../hc-handler';
import populate, { fieldType as ft } from '../populator';
before(() => {
sb = sinon.createSandbox();
describe('populator', () => {
let h;
let warn;
let handler;
beforeEach(() => {
h = {
addMeasure: sb.stub(),
addDimension: sb.stub(),
addMeasure: jest.fn(),
addDimension: jest.fn(),
};
const fn = () => h;
handler = sb.spy(fn);
[{ default: populate, fieldType: ft }] = aw.mock(
[[require.resolve('../hc-handler'), () => handler]],
['../populator']
);
});
beforeEach(() => {
handler = jest.fn().mockImplementation(fn);
jest.spyOn(hcHandlerModule, 'default').mockImplementation(handler);
global.__NEBULA_DEV__ = true; // eslint-disable-line no-underscore-dangle
warn = sb.stub(console, 'warn');
sb.reset();
warn = jest.fn();
global.console = {
...global.console,
warn,
};
});
afterEach(() => {
global.__NEBULA_DEV__ = false; // eslint-disable-line no-underscore-dangle
sb.restore();
jest.resetAllMocks();
jest.restoreAllMocks();
});
it('should not throw if fields are not provided', () => {
test('should not throw if fields are not provided', () => {
const fn = () => populate({ sn: null, properties: {}, fields: [] });
expect(fn).to.not.throw();
expect(() => fn).not.toThrow();
});
it('should log warning if fields is provided but targets are not specified', () => {
test('should log warning if fields is provided but targets are not specified', () => {
const sn = { qae: { data: { targets: [] } } };
populate({ sn, properties: {}, fields: [1] });
expect(warn).to.have.been.calledWithExactly(
'Attempting to add fields to an object without a specified data target'
);
expect(warn).toHaveBeenCalledWith('Attempting to add fields to an object without a specified data target');
});
it('should initiate handler with resolved target', () => {
test('should initiate handler with resolved target', () => {
const target = {
propertyPath: 'a/b/c',
};
@@ -55,14 +52,14 @@ describe('populator', () => {
};
const resolved = { qDimensions: [] };
populate({ sn, properties: { a: { b: { c: resolved } } }, fields: [1] });
expect(handler).to.have.been.calledWithExactly({
expect(handler).toHaveBeenCalledWith({
dc: resolved,
def: target,
properties: { a: { b: { c: resolved } } },
});
});
it('should add dimension', () => {
test('should add dimension', () => {
const target = {
propertyPath: 'hc',
};
@@ -75,10 +72,10 @@ describe('populator', () => {
};
const resolved = { qDimensions: [] };
populate({ sn, properties: { a: { b: { c: resolved } } }, fields: ['A'] });
expect(h.addDimension).to.have.been.calledWithExactly('A');
expect(h.addDimension).toHaveBeenCalledWith('A');
});
it('should add measure', () => {
test('should add measure', () => {
const target = {
propertyPath: 'hc',
};
@@ -91,18 +88,18 @@ describe('populator', () => {
};
const resolved = { qDimensions: [] };
populate({ sn, properties: { a: { b: { c: resolved } } }, fields: ['=A'] });
expect(h.addMeasure).to.have.been.calledWithExactly('=A');
expect(h.addMeasure).toHaveBeenCalledWith('=A');
});
it("should identify field as measure when prefixed with '='", () => {
expect(ft('=a')).to.equal('measure');
test("should identify field as measure when prefixed with '='", () => {
expect(ft('=a')).toBe('measure');
});
it('should identify field as measure when object looks like NxMeasure', () => {
expect(ft({ qDef: { qDef: {} } })).to.equal('measure');
test('should identify field as measure when object looks like NxMeasure', () => {
expect(ft({ qDef: { qDef: {} } })).toBe('measure');
});
it("should identify field as measure when object contains a qLibraryId and type==='measure'", () => {
expect(ft({ qLibraryId: 'a', type: 'measure' })).to.equal('measure');
test("should identify field as measure when object contains a qLibraryId and type==='measure'", () => {
expect(ft({ qLibraryId: 'a', type: 'measure' })).toBe('measure');
});
});

View File

@@ -24,6 +24,7 @@ module.exports = {
'apis/nucleus/src/sn/*.{js,jsx}',
'apis/nucleus/src/stores/*.{js,jsx}',
'apis/nucleus/src/utils/*.{js,jsx}',
'apis/nucleus/src/object/*.{js,jsx}',
'apis/snapshooter/**/*.{js,jsx}',
'apis/supernova/**/*.{js,jsx}',
'apis/test-utils/**/*.{js,jsx}',