mirror of
https://github.com/xodio/xod.git
synced 2026-03-24 17:46:56 +01:00
feat,test(xod-project): first step in flatten graph issue
This commit is contained in:
@@ -31,6 +31,7 @@ export const ERROR = {
|
||||
PIN_KEY_INVALID: 'Pin key should be generated with shortid',
|
||||
// other
|
||||
DATATYPE_INVALID: 'Invalid data type',
|
||||
IMPLEMENTATION_NOT_FOUND: 'Implementation not found',
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
77
packages/xod-project/src/flatten.js
Normal file
77
packages/xod-project/src/flatten.js
Normal file
@@ -0,0 +1,77 @@
|
||||
import R from 'ramda';
|
||||
import { Maybe } from 'ramda-fantasy';
|
||||
|
||||
import * as Project from './project';
|
||||
import * as Patch from './patch';
|
||||
import * as Node from './node';
|
||||
|
||||
// :: Monad a -> Monad a
|
||||
const reduceChainOver = R.reduce(R.flip(R.chain));
|
||||
|
||||
// :: String[] -> Project -> Path -> [Path, Patch, ...]
|
||||
const extractImplPatches = R.curry((impls, project, path, patch) => R.ifElse(
|
||||
Patch.hasImpl(impls),
|
||||
patchWithImpl => [path, patchWithImpl],
|
||||
R.compose(
|
||||
R.chain(R.compose(
|
||||
type => Project.getPatchByPath(type, project)
|
||||
.chain(extractImplPatches(impls, project, type)),
|
||||
Node.getNodeType
|
||||
)),
|
||||
Patch.listNodes
|
||||
)
|
||||
)(patch));
|
||||
|
||||
// :: Node -> Boolean
|
||||
const isNodeToImplPatch = implPatchPaths => R.compose(
|
||||
R.contains(R.__, implPatchPaths),
|
||||
Node.getNodeType
|
||||
);
|
||||
|
||||
// :: Project -> String[] -> Patch -> Node[]
|
||||
const extractNodes = (project, implPatchPaths) => R.compose(
|
||||
R.chain(R.ifElse(
|
||||
isNodeToImplPatch(implPatchPaths),
|
||||
R.identity,
|
||||
R.compose(
|
||||
R.chain(patch => extractNodes(project, implPatchPaths)(patch)),
|
||||
type => Project.getPatchByPath(type, project),
|
||||
Node.getNodeType
|
||||
)
|
||||
)
|
||||
),
|
||||
Patch.listNodes
|
||||
);
|
||||
|
||||
export default R.curry((project, path, impls) => {
|
||||
const patch = Project.getPatchByPath(path, project);
|
||||
|
||||
const implPatches = patch
|
||||
.map(extractImplPatches(impls, project, path))
|
||||
.chain(R.splitEvery(2));
|
||||
const assocImplPatches = implPatches.map(R.apply(Project.assocPatch));
|
||||
|
||||
let assocPatch = R.identity;
|
||||
|
||||
if (!patch.chain(Patch.hasImpl(impls))) {
|
||||
const implPatchPaths = R.pluck(0, implPatches);
|
||||
const nodes = patch.chain(extractNodes(project, implPatchPaths));
|
||||
const assocNodes = nodes.map(node => Patch.assocNode(node));
|
||||
|
||||
const newPatch = R.reduce(
|
||||
(p, fn) => fn(p),
|
||||
Patch.createPatch(),
|
||||
assocNodes
|
||||
);
|
||||
assocPatch = R.compose(
|
||||
R.chain,
|
||||
Project.assocPatch(path)
|
||||
)(newPatch);
|
||||
}
|
||||
|
||||
return R.compose(
|
||||
assocPatch,
|
||||
reduceChainOver(R.__, assocImplPatches),
|
||||
Maybe.of
|
||||
)(Project.createProject());
|
||||
});
|
||||
@@ -51,19 +51,33 @@ export const setPatchLabel = R.useWith(
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns a list of platforms for which a `patch` has native implementation
|
||||
* Returns a list of implementations for which a `patch` has native implementation
|
||||
*
|
||||
* For example, `['js', 'arduino', 'espruino', 'nodejs']`.
|
||||
*
|
||||
* @function listPatchPlatforms
|
||||
* @function listImpls
|
||||
* @param {Patch} patch
|
||||
* @returns {string[]}
|
||||
*/
|
||||
export const listPatchPlatforms = R.compose(
|
||||
export const listImpls = R.compose(
|
||||
R.keys,
|
||||
R.propOr({}, 'impls')
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns true if patch has any of specified implementations.
|
||||
*
|
||||
* @function hasImpl
|
||||
* @param {string[]} impls
|
||||
* @param {Patch} patch
|
||||
* @type {Boolean}
|
||||
*/
|
||||
export const hasImpl = R.curry((impls, patch) => R.compose(
|
||||
R.complement(R.isEmpty),
|
||||
R.intersection(impls),
|
||||
listImpls
|
||||
)(patch));
|
||||
|
||||
/**
|
||||
* @function validatePatch
|
||||
* @param {Patch} patch
|
||||
|
||||
@@ -141,6 +141,16 @@ export const listPatches = R.compose(
|
||||
getPatches
|
||||
);
|
||||
|
||||
/**
|
||||
* @function listPatchPaths
|
||||
* @param {Project} project - project bundle
|
||||
* @returns {String[]} list of all patche paths not sorted in any arbitrary order
|
||||
*/
|
||||
export const listPatchPaths = R.compose(
|
||||
R.keys,
|
||||
getPatches
|
||||
);
|
||||
|
||||
/**
|
||||
* Return a list of local patches (excluding external libraries)
|
||||
*
|
||||
|
||||
134
packages/xod-project/test/fixtures/blinkFlat.js
vendored
Normal file
134
packages/xod-project/test/fixtures/blinkFlat.js
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
const projectB = {
|
||||
patches: {
|
||||
'@/main': {
|
||||
nodes: {
|
||||
// blink
|
||||
'a/a': {
|
||||
id: 'a/a',
|
||||
type: 'xod/core/clock',
|
||||
pins: {
|
||||
interval: {
|
||||
injected: true,
|
||||
value: 0.2,
|
||||
},
|
||||
},
|
||||
},
|
||||
'a/b': {
|
||||
id: 'a/b',
|
||||
type: 'xod/core/latch',
|
||||
},
|
||||
'a/generatedNodeId__out': {
|
||||
id: 'a/generatedNodeId__out',
|
||||
type: 'xod/core/outputNumber',
|
||||
},
|
||||
// led
|
||||
'b/a': {
|
||||
id: 'b/a',
|
||||
type: 'xod/core/multiply',
|
||||
},
|
||||
'b/b': {
|
||||
id: 'b/b',
|
||||
type: 'xod/core/pwm-output',
|
||||
pins: {
|
||||
'hardware-pin': {
|
||||
injected: true,
|
||||
value: 13,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
links: {
|
||||
// blink
|
||||
'a/b': {
|
||||
id: 'a/b',
|
||||
output: {
|
||||
nodeId: 'a/a',
|
||||
pinKey: 'tick',
|
||||
},
|
||||
input: {
|
||||
nodeId: 'a/b',
|
||||
pinKey: 'toggle',
|
||||
},
|
||||
},
|
||||
// blink to led
|
||||
'a-b/c': {
|
||||
id: 'a-b/c',
|
||||
output: {
|
||||
nodeId: 'a/b',
|
||||
pinKey: 'out',
|
||||
},
|
||||
input: {
|
||||
nodeId: 'b/a',
|
||||
pinKey: 'in1',
|
||||
},
|
||||
},
|
||||
'a-b/d': {
|
||||
id: 'a-b/d',
|
||||
output: {
|
||||
nodeId: 'a/b',
|
||||
pinKey: 'out',
|
||||
},
|
||||
input: {
|
||||
nodeId: 'b/a',
|
||||
pinKey: 'in2',
|
||||
},
|
||||
},
|
||||
// led
|
||||
'b/c': {
|
||||
id: 'b/c',
|
||||
output: {
|
||||
nodeId: 'b/a',
|
||||
pinKey: 'out',
|
||||
},
|
||||
input: {
|
||||
nodeId: 'b/b',
|
||||
pinKey: 'duty',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'xod/core/multiply': {
|
||||
nodes: {},
|
||||
links: {},
|
||||
pins: {
|
||||
in1: {
|
||||
key: 'in1',
|
||||
type: 'number',
|
||||
direction: 'input',
|
||||
},
|
||||
in2: {
|
||||
key: 'in2',
|
||||
type: 'number',
|
||||
direction: 'input',
|
||||
},
|
||||
out: {
|
||||
key: 'out',
|
||||
type: 'number',
|
||||
direction: 'output',
|
||||
},
|
||||
},
|
||||
impls: {
|
||||
js: '//ok',
|
||||
},
|
||||
},
|
||||
'xod/core/pwm-output': {
|
||||
nodes: {},
|
||||
links: {},
|
||||
pins: {
|
||||
duty: {
|
||||
key: 'duty',
|
||||
type: 'number',
|
||||
direction: 'input',
|
||||
},
|
||||
'hardware-pin': {
|
||||
key: 'hardware-pin',
|
||||
type: 'number',
|
||||
direction: 'input',
|
||||
},
|
||||
},
|
||||
impls: {
|
||||
js: '//ok',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
244
packages/xod-project/test/fixtures/blinkOriginal.js
vendored
Normal file
244
packages/xod-project/test/fixtures/blinkOriginal.js
vendored
Normal file
@@ -0,0 +1,244 @@
|
||||
const projectA = {
|
||||
patches: {
|
||||
'@/main': {
|
||||
nodes: {
|
||||
a: {
|
||||
id: 'a',
|
||||
type: '@/blink',
|
||||
pins: {
|
||||
generatedNodeId__interval: {
|
||||
injected: true,
|
||||
value: 0.2,
|
||||
},
|
||||
},
|
||||
},
|
||||
b: {
|
||||
id: 'b',
|
||||
type: 'xod/core/led',
|
||||
pins: {
|
||||
generatedNodeId__hardwarePin: {
|
||||
injected: true,
|
||||
value: 13,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
links: {
|
||||
a: {
|
||||
id: 'a',
|
||||
output: {
|
||||
nodeId: 'a',
|
||||
pinKey: 'generatedNodeId__out',
|
||||
},
|
||||
input: {
|
||||
nodeId: 'b',
|
||||
pinKey: 'generatedNodeId__interval',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'@/blink': {
|
||||
nodes: {
|
||||
generatedNodeId__interval: {
|
||||
id: 'generatedNodeId__interval',
|
||||
type: 'xod/core/inputNumber',
|
||||
},
|
||||
a: {
|
||||
id: 'a',
|
||||
type: 'xod/core/clock',
|
||||
},
|
||||
b: {
|
||||
id: 'b',
|
||||
type: 'xod/core/latch',
|
||||
},
|
||||
generatedNodeId__out: {
|
||||
id: 'generatedNodeId__out',
|
||||
type: 'xod/core/outputNumber',
|
||||
},
|
||||
},
|
||||
links: {
|
||||
a: {
|
||||
id: 'a',
|
||||
output: {
|
||||
nodeId: 'generatedNodeId__interval',
|
||||
pinKey: 'out',
|
||||
},
|
||||
input: {
|
||||
nodeId: 'a',
|
||||
pinKey: 'interval',
|
||||
},
|
||||
},
|
||||
b: {
|
||||
id: 'b',
|
||||
output: {
|
||||
nodeId: 'a',
|
||||
pinKey: 'tick',
|
||||
},
|
||||
input: {
|
||||
nodeId: 'b',
|
||||
pinKey: 'toggle',
|
||||
},
|
||||
},
|
||||
c: {
|
||||
id: 'c',
|
||||
output: {
|
||||
nodeId: 'b',
|
||||
pinKey: 'out',
|
||||
},
|
||||
input: {
|
||||
nodeId: 'generatedNodeId__out',
|
||||
pinKey: 'in',
|
||||
},
|
||||
},
|
||||
},
|
||||
pins: {
|
||||
generatedNodeId__interval: {
|
||||
key: 'generatedNodeId__interval',
|
||||
type: 'number',
|
||||
direction: 'input',
|
||||
},
|
||||
generatedNodeId__out: {
|
||||
key: 'generatedNodeId__out',
|
||||
type: 'number',
|
||||
direction: 'output',
|
||||
},
|
||||
},
|
||||
},
|
||||
'xod/core/led': {
|
||||
nodes: {
|
||||
generatedNodeId__brightness: {
|
||||
id: 'generatedNodeId__brightness',
|
||||
type: 'xod/core/inputNumber',
|
||||
},
|
||||
generatedNodeId__hardwarePin: {
|
||||
id: 'generatedNodeId__hardwarePin',
|
||||
type: 'xod/core/inputNumber',
|
||||
},
|
||||
a: {
|
||||
id: 'a',
|
||||
type: 'xod/core/multiply',
|
||||
},
|
||||
b: {
|
||||
id: 'b',
|
||||
type: 'xod/core/pwm-output',
|
||||
},
|
||||
},
|
||||
links: {
|
||||
a: {
|
||||
id: 'a',
|
||||
output: {
|
||||
nodeId: 'generatedNodeId__brightness',
|
||||
pinKey: 'out',
|
||||
},
|
||||
input: {
|
||||
nodeId: 'a',
|
||||
pinKey: 'in1',
|
||||
},
|
||||
},
|
||||
b: {
|
||||
id: 'b',
|
||||
output: {
|
||||
nodeId: 'generatedNodeId__brightness',
|
||||
pinKey: 'out',
|
||||
},
|
||||
input: {
|
||||
nodeId: 'a',
|
||||
pinKey: 'in2',
|
||||
},
|
||||
},
|
||||
c: {
|
||||
id: 'c',
|
||||
output: {
|
||||
nodeId: 'a',
|
||||
pinKey: 'out',
|
||||
},
|
||||
input: {
|
||||
nodeId: 'b',
|
||||
pinKey: 'duty',
|
||||
},
|
||||
},
|
||||
d: {
|
||||
id: 'd',
|
||||
output: {
|
||||
nodeId: 'generatedNodeId__hardwarePin',
|
||||
pinKey: 'out',
|
||||
},
|
||||
input: {
|
||||
nodeId: 'b',
|
||||
pinKey: 'hardware-pin',
|
||||
},
|
||||
},
|
||||
},
|
||||
pins: {
|
||||
generatedNodeId__brightness: {
|
||||
key: 'generatedNodeId__brightness',
|
||||
type: 'number',
|
||||
direction: 'input',
|
||||
},
|
||||
generatedNodeId__hardwarePin: {
|
||||
key: 'generatedNodeId__hardwarePin',
|
||||
type: 'string',
|
||||
direction: 'input',
|
||||
},
|
||||
},
|
||||
},
|
||||
'xod/core/inputNumber': {
|
||||
nodes: {},
|
||||
links: {},
|
||||
pins: {
|
||||
out: {
|
||||
key: 'out',
|
||||
type: 'number',
|
||||
direction: 'output',
|
||||
},
|
||||
},
|
||||
},
|
||||
'xod/core/multiply': {
|
||||
nodes: {},
|
||||
links: {},
|
||||
pins: {
|
||||
in1: {
|
||||
key: 'in1',
|
||||
type: 'number',
|
||||
direction: 'input',
|
||||
},
|
||||
in2: {
|
||||
key: 'in2',
|
||||
type: 'number',
|
||||
direction: 'input',
|
||||
},
|
||||
out: {
|
||||
key: 'out',
|
||||
type: 'number',
|
||||
direction: 'output',
|
||||
},
|
||||
},
|
||||
},
|
||||
'xod/core/pwm-output': {
|
||||
nodes: {},
|
||||
links: {},
|
||||
pins: {
|
||||
duty: {
|
||||
key: 'duty',
|
||||
type: 'number',
|
||||
direction: 'input',
|
||||
},
|
||||
'hardware-pin': {
|
||||
key: 'hardware-pin',
|
||||
type: 'number',
|
||||
direction: 'input',
|
||||
},
|
||||
},
|
||||
impls: {
|
||||
js: '//ok',
|
||||
},
|
||||
},
|
||||
'xod/core/or': {
|
||||
nodes: {},
|
||||
links: {},
|
||||
impls: {
|
||||
js: '//ok',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -7,7 +7,7 @@
|
||||
"patches": {
|
||||
"xod/core/inputNumber": {
|
||||
"nodes": {},
|
||||
"links": [],
|
||||
"links": {},
|
||||
"label": "<InputNumber>",
|
||||
"pins": {
|
||||
"PIN": {
|
||||
@@ -19,7 +19,7 @@
|
||||
},
|
||||
"xod/core/pot": {
|
||||
"nodes": {},
|
||||
"links": [],
|
||||
"links": {},
|
||||
"pins": {
|
||||
"sample": {
|
||||
"key": "sample",
|
||||
@@ -38,7 +38,7 @@
|
||||
},
|
||||
"xod/core/and": {
|
||||
"nodes": {},
|
||||
"links": [],
|
||||
"links": {},
|
||||
"label": "and",
|
||||
"pins": {
|
||||
"a": {
|
||||
@@ -63,7 +63,7 @@
|
||||
},
|
||||
"xod/core/led": {
|
||||
"nodes": {},
|
||||
"links": [],
|
||||
"links": {},
|
||||
"label": "LED",
|
||||
"pins": {
|
||||
"brightness": {
|
||||
|
||||
138
packages/xod-project/test/flatten.spec.js
Normal file
138
packages/xod-project/test/flatten.spec.js
Normal file
@@ -0,0 +1,138 @@
|
||||
import R from 'ramda';
|
||||
import chai, { expect } from 'chai';
|
||||
import dirtyChai from 'dirty-chai';
|
||||
|
||||
import * as Helper from './helpers';
|
||||
import * as CONST from '../src/constants';
|
||||
import flatten from '../src/flatten';
|
||||
|
||||
chai.use(dirtyChai);
|
||||
|
||||
describe('Flatten', () => {
|
||||
describe('trivial', () => {
|
||||
const project = {
|
||||
patches: {
|
||||
'@/main': {
|
||||
nodes: {
|
||||
a: {
|
||||
id: 'a',
|
||||
type: 'xod/core/or',
|
||||
},
|
||||
},
|
||||
links: {},
|
||||
},
|
||||
'xod/core/or': {
|
||||
nodes: {},
|
||||
links: {},
|
||||
impls: {
|
||||
js: '//ok',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
it('should ignore not referred patches', () => {
|
||||
const flatProject = flatten(project, 'xod/core/or', ['js']);
|
||||
|
||||
expect(flatProject.isRight).to.be.true();
|
||||
Helper.expectEither(
|
||||
(newProject) => {
|
||||
expect(R.keys(newProject.patches))
|
||||
.to.be.deep.equal(['xod/core/or']);
|
||||
expect(newProject.patches['xod/core/or'])
|
||||
.to.be.deep.equal(project.patches['xod/core/or']);
|
||||
},
|
||||
flatProject
|
||||
);
|
||||
});
|
||||
|
||||
it('should return patch with dependency', () => {
|
||||
const flatProject = flatten(project, '@/main', ['js']);
|
||||
|
||||
expect(flatProject.isRight).to.be.true();
|
||||
Helper.expectEither(
|
||||
(newProject) => {
|
||||
expect(R.keys(newProject.patches))
|
||||
.to.be.deep.equal(['xod/core/or', '@/main']);
|
||||
expect(newProject.patches)
|
||||
.to.be.deep.equal(project.patches);
|
||||
},
|
||||
flatProject
|
||||
);
|
||||
});
|
||||
|
||||
// its('should return error if implementation not found', () => {
|
||||
// const flatProject = flatten(project, '@/main', ['cpp']);
|
||||
//
|
||||
// expect(flatProject.isLeft).to.be.true();
|
||||
// Helper.expectErrorMessage(expect, flatProject, CONST.ERROR.IMPLEMENTATION_NOT_FOUND);
|
||||
// });
|
||||
});
|
||||
|
||||
describe('recursive', () => {
|
||||
const project = {
|
||||
patches: {
|
||||
'@/main': {
|
||||
nodes: {
|
||||
a: {
|
||||
id: 'a',
|
||||
type: '@/foo',
|
||||
},
|
||||
},
|
||||
links: {},
|
||||
},
|
||||
'@/foo': {
|
||||
nodes: {
|
||||
a: {
|
||||
id: 'a',
|
||||
type: 'xod/core/or',
|
||||
},
|
||||
},
|
||||
links: {},
|
||||
},
|
||||
'xod/core/or': {
|
||||
nodes: {},
|
||||
links: {},
|
||||
impls: {
|
||||
js: '//ok',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
it('should ignore not referred patches', () => {
|
||||
const flatProject = flatten(project, '@/foo', ['js']);
|
||||
|
||||
expect(flatProject.isRight).to.be.true();
|
||||
Helper.expectEither(
|
||||
(newProject) => {
|
||||
expect(R.keys(newProject.patches))
|
||||
.to.be.deep.equal(['xod/core/or', '@/foo']);
|
||||
expect(newProject.patches['xod/core/or'])
|
||||
.to.be.deep.equal(project.patches['xod/core/or']);
|
||||
expect(newProject.patches['@/foo'])
|
||||
.to.be.deep.equal(project.patches['@/foo']);
|
||||
},
|
||||
flatProject
|
||||
);
|
||||
});
|
||||
|
||||
it('should return patch with dependency', () => {
|
||||
const flatProject = flatten(project, '@/main', ['js']);
|
||||
|
||||
expect(flatProject.isRight).to.be.true();
|
||||
Helper.expectEither(
|
||||
(newProject) => {
|
||||
expect(R.keys(newProject.patches))
|
||||
.to.be.deep.equal(['xod/core/or', '@/main']);
|
||||
expect(newProject.patches['xod/core/or'])
|
||||
.to.be.deep.equal(project.patches['xod/core/or']);
|
||||
expect(R.values(newProject.patches['@/main'].nodes)[0])
|
||||
.to.have.property('type')
|
||||
.that.equals('xod/core/or');
|
||||
},
|
||||
flatProject
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -89,9 +89,9 @@ describe('Patch', () => {
|
||||
.that.equals('[object Object]');
|
||||
});
|
||||
});
|
||||
describe('listPatchPlatforms', () => {
|
||||
describe('listImpls', () => {
|
||||
it('should return empty array for empty patch', () => {
|
||||
expect(Patch.listPatchPlatforms({}))
|
||||
expect(Patch.listImpls({}))
|
||||
.to.be.instanceof(Array)
|
||||
.to.be.empty();
|
||||
});
|
||||
@@ -102,11 +102,41 @@ describe('Patch', () => {
|
||||
espruino: '',
|
||||
},
|
||||
};
|
||||
expect(Patch.listPatchPlatforms(patch))
|
||||
expect(Patch.listImpls(patch))
|
||||
.to.be.an('array')
|
||||
.to.have.members(['js', 'espruino']);
|
||||
});
|
||||
});
|
||||
describe('hasImpl', () => {
|
||||
it('should return false for empty', () => {
|
||||
expect(Patch.hasImpl(['js'], {})).to.be.false();
|
||||
});
|
||||
it('should return false if impl not found', () => {
|
||||
const patch = {
|
||||
impls: {
|
||||
js: '//ok',
|
||||
},
|
||||
};
|
||||
expect(Patch.hasImpl(['cpp'], patch)).to.be.false();
|
||||
});
|
||||
it('should return true for the only correct impl', () => {
|
||||
const patch = {
|
||||
impls: {
|
||||
js: '//ok',
|
||||
},
|
||||
};
|
||||
expect(Patch.hasImpl(['js'], patch)).to.be.true();
|
||||
});
|
||||
it('should return true for a few existent impls', () => {
|
||||
const patch = {
|
||||
impls: {
|
||||
js: '//ok',
|
||||
nodejs: '//ok',
|
||||
},
|
||||
};
|
||||
expect(Patch.hasImpl(['js', 'nodejs'], patch)).to.be.true();
|
||||
});
|
||||
});
|
||||
|
||||
// entity getters
|
||||
describe('listNodes', () => {
|
||||
|
||||
@@ -446,6 +446,17 @@ describe('Project', () => {
|
||||
.and.have.lengthOf(2);
|
||||
});
|
||||
});
|
||||
describe('listPatchPaths', () => {
|
||||
it('should return empty array for empty project', () => {
|
||||
expect(Project.listPatchPaths({}))
|
||||
.to.be.instanceof(Array)
|
||||
.and.to.be.empty();
|
||||
});
|
||||
it('should return array with two keys', () => {
|
||||
expect(Project.listPatchPaths(project))
|
||||
.to.be.deep.equal(['@/test', 'external/patch']);
|
||||
});
|
||||
});
|
||||
describe('listLocalPatches', () => {
|
||||
it('should return empty array for empty project', () => {
|
||||
expect(Project.listLocalPatches({}))
|
||||
|
||||
Reference in New Issue
Block a user