Skip to content
This repository was archived by the owner on Feb 4, 2018. It is now read-only.

Commit 0612428

Browse files
authored
Merge pull request #72 from bem-sdk/qfox.feat-create
Create method
2 parents 5408901 + 740e8d1 commit 0612428

File tree

6 files changed

+212
-30
lines changed

6 files changed

+212
-30
lines changed

README.md

Lines changed: 54 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ new BemEntityName({
7575
});
7676
```
7777

78-
To describe the simple modifier field `mod.val` must be specified as `true`.
78+
To describe the simple modifier, field `mod.val` must be specified as `true`.
7979

8080
**Example:**
8181

@@ -103,10 +103,11 @@ API
103103
* [id](#id)
104104
* [type](#type)
105105
* [isEqual(entityName)](#isequalentityname)
106-
* [isBemEntityName(entityName)](#isbementitynameentityname)
107106
* [toString()](#tostring)
108107
* [valueOf()](#valueof)
109108
* [toJSON()](#tojson)
109+
* [#isBemEntityName(entityName)](#isbementitynameentityname)
110+
* [#create(object)](#createobject)
110111

111112
### constructor({ block, elem, mod })
112113

@@ -207,23 +208,6 @@ inputName.isEqual(buttonName); // false
207208
buttonName.isEqual(buttonName); // true
208209
```
209210

210-
### isBemEntityName(entityName)
211-
212-
Determines whether specified entity is instance of BemEntityName.
213-
214-
Parameter | Type | Description
215-
-------------|-----------------|-----------------------
216-
`entityName` | `BemEntityName` | The entity to check.
217-
218-
```js
219-
const BemEntityName = require('@bem/entity-name');
220-
221-
const entityName = new BemEntityName({ block: 'input' });
222-
223-
BemEntityName.isBemEntityName(entityName); // true
224-
BemEntityName.isBemEntityName({}); // false
225-
```
226-
227211
### toString()
228212

229213
Returns string representing the entity name.
@@ -255,6 +239,57 @@ name.valueOf();
255239

256240
Returns object for `JSON.stringify()` purposes.
257241

242+
### #isBemEntityName(entityName)
243+
244+
Determines whether specified entity is an instance of BemEntityName.
245+
246+
Parameter | Type | Description
247+
-------------|-----------------|-----------------------
248+
`entityName` | `BemEntityName` | The entity to check.
249+
250+
```js
251+
const BemEntityName = require('@bem/entity-name');
252+
253+
const entityName = new BemEntityName({ block: 'input' });
254+
255+
BemEntityName.isBemEntityName(entityName); // true
256+
BemEntityName.isBemEntityName({ block: 'button' }); // false
257+
```
258+
259+
### #create(object)
260+
261+
Creates BemEntityName instance by any object representation.
262+
263+
Helper for sugar-free simplicity.
264+
265+
Parameter | Type | Description
266+
-------------|--------------------|--------------------------
267+
`object` | `object` | Representation of entity name.
268+
269+
Passed Object could have the common field names for entities:
270+
271+
Object field | Type | Description
272+
-------------|----------|------------------------------
273+
`block` | `string` | The block name of entity.
274+
`elem` | `string` | The element name of entity.
275+
`mod` | `string`, `object` | The modifier of entity.<br><br> If specified value is `string` then it will be equivalent to `{ name: string, val: true }`.
276+
`val` | `string` | The modifier value of entity. Used if `mod` is a string.
277+
`mod.name` | `string` | The modifier name of entity.
278+
`mod.val` | `*` | The modifier value of entity.
279+
`modName` | `string` | The modifier name of entity. Used if `mod.name` wasn't specified.
280+
`modVal` | `*` | The modifier value of entity. Used if neither `mod.val` nor `val` were not specified.
281+
282+
```js
283+
const BemEntityName = require('@bem/entity-name');
284+
285+
BemEntityName.create({ block: 'my-button', mod: 'theme', val: 'red' });
286+
BemEntityName.create({ block: 'my-button', modName: 'theme', modVal: 'red' });
287+
// ➜ BemEntityName { block: 'my-button', mod: { name: 'theme', val: 'red' } }
288+
289+
BemEntityName.create({ block: 'my-button', mod: 'focused' });
290+
// ➜ BemEntityName { block: 'my-button', mod: { name: 'focused', val: true } }
291+
```
292+
258293
Debuggability
259294
-------------
260295

index.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,4 +285,52 @@ module.exports = class BemEntityName {
285285
static isBemEntityName(entityName) {
286286
return entityName && entityName.__isBemEntityName__;
287287
}
288+
289+
/**
290+
* Creates BemEntityName instance by any object representation.
291+
*
292+
* @param {object} obj — representation of entity name.
293+
* @param {string} obj.block — the block name of entity.
294+
* @param {string} [obj.elem] — the element name of entity.
295+
* @param {object|string} [obj.mod] — the modifier of entity.
296+
* @param {string} [obj.val] - the modifier value of entity. Used if `obj.mod` is a string.
297+
* @param {string} [obj.mod.name] — the modifier name of entity.
298+
* @param {string} [obj.mod.val] — the modifier value of entity.
299+
* @param {string} [obj.modName] — the modifier name of entity. Used if `obj.mod.name` wasn't specified.
300+
* @param {string} [obj.modVal] — the modifier value of entity.
301+
* Used if neither `obj.mod.val` nor `obj.val` were not specified.
302+
*
303+
* @returns {BemEntityName} An object representing entity name.
304+
* @example
305+
* const BemEntityName = require('@bem/entity-name');
306+
*
307+
* BemEntityName.create('my-button_theme_red');
308+
* BemEntityName.create({ block: 'my-button', mod: 'theme', val: 'red' });
309+
* BemEntityName.create({ block: 'my-button', modName: 'theme', modVal: 'red' });
310+
* // BemEntityName { block: 'my-button', mod: { name: 'theme', val: 'red' } }
311+
*/
312+
static create(obj) {
313+
if (BemEntityName.isBemEntityName(obj)) {
314+
return obj;
315+
}
316+
317+
const data = { block: obj.block };
318+
const mod = obj.mod;
319+
320+
obj.elem && (data.elem = obj.elem);
321+
322+
if (mod || obj.modName) {
323+
const isString = typeof mod === 'string';
324+
const modName = (isString ? mod : mod && mod.name) || obj.modName;
325+
const modObj = !isString && mod || obj;
326+
const hasModVal = modObj.hasOwnProperty('val') || obj.hasOwnProperty('modVal');
327+
328+
data.mod = {
329+
name: modName,
330+
val: hasModVal ? modObj.val || obj.modVal : true
331+
};
332+
}
333+
334+
return new BemEntityName(data);
335+
}
288336
};

test/valid.test.js renamed to test/construct.test.js

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,30 @@ const test = require('ava');
22

33
const BemEntityName = require('../index');
44

5+
test('should create object for block', t => {
6+
const data = { block: 'b' };
7+
8+
t.deepEqual((new BemEntityName(data)).valueOf(), data);
9+
});
10+
11+
test('should create object for block and elem', t => {
12+
const data = { block: 'b', elem: 'e' };
13+
14+
t.deepEqual((new BemEntityName(data)).valueOf(), data);
15+
});
16+
17+
test('should create object for block and mod', t => {
18+
const data = { block: 'b', mod: { name: 'm', val: 'v' } };
19+
20+
t.deepEqual((new BemEntityName(data)).valueOf(), data);
21+
});
22+
23+
test('should create object and normalize boolean modifier', t => {
24+
const entity = new BemEntityName({ block: 'block', mod: { name: 'mod' } });
25+
26+
t.deepEqual(entity.valueOf(), { block: 'block', mod: { name: 'mod', val: true } });
27+
});
28+
529
test('should throw error for if entity object is not valid', t => {
630
t.throws(
731
() => new BemEntityName({ elem: 'elem' }),
@@ -22,10 +46,3 @@ test('should throw error for if mod name is undefined', t => {
2246
'This is not valid BEM entity: the field `mod.name` is undefined.'
2347
);
2448
});
25-
26-
test('should throw error for if modName is undefined', t => {
27-
t.throws(
28-
() => new BemEntityName({ block: 'block', modVal: 'val' }),
29-
'This is not valid BEM entity: the field `mod.name` is undefined.'
30-
);
31-
});

test/create.test.js

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
const test = require('ava');
2+
3+
const BemEntityName = require('../index');
4+
5+
test('should return object as is if it`s a BemEntityName', t => {
6+
const entity = new BemEntityName({ block: 'b' });
7+
8+
t.is(BemEntityName.create(entity), entity);
9+
});
10+
11+
test('should create BemEntityName for block from obj', t => {
12+
const entity = BemEntityName.create({ block: 'b' });
13+
14+
t.pass(entity instanceof BemEntityName, 'Should be an instance of BemEntityName');
15+
t.deepEqual(entity.valueOf(), { block: 'b' }, 'Should contain a name for same entity');
16+
});
17+
18+
test('should create entity for elem from obj', t => {
19+
const entity = BemEntityName.create({ block: 'b', elem: 'e' });
20+
21+
t.deepEqual(entity.valueOf(), { block: 'b', elem: 'e' });
22+
});
23+
24+
test('should create entity from obj with deps mods without value', t => {
25+
const entity = BemEntityName.create({ block: 'b', mod: 'm' });
26+
27+
t.deepEqual(entity.valueOf(), { block: 'b', mod: { name: 'm', val: true } });
28+
});
29+
30+
test('should create entity from obj with deps mods', t => {
31+
const entity = BemEntityName.create({ block: 'b', mod: 'm', val: 'v' });
32+
33+
t.deepEqual(entity.valueOf(), { block: 'b', mod: { name: 'm', val: 'v' } });
34+
});
35+
36+
test('should normalize boolean modifier', t => {
37+
const entity = BemEntityName.create({ block: 'block', mod: { name: 'mod' } });
38+
39+
t.true(entity.mod.val);
40+
});
41+
42+
test('should normalize short entry for boolean modifier', t => {
43+
const entity = BemEntityName.create({ block: 'block', mod: 'mod' });
44+
45+
t.true(entity.mod.val);
46+
});
47+
48+
test('should support `modName` and `modVal` fields', t => {
49+
const entity = BemEntityName.create({ block: 'block', modName: 'mod', modVal: 'val' });
50+
51+
t.deepEqual(entity.mod, { name: 'mod', val: 'val' });
52+
});
53+
54+
test('should support `modName` field only', t => {
55+
const entity = BemEntityName.create({ block: 'block', modName: 'mod' });
56+
57+
t.deepEqual(entity.mod, { name: 'mod', val: true });
58+
});
59+
60+
test('should use `mod.name` field instead of `modName`', t => {
61+
const entity = BemEntityName.create({ block: 'block', mod: { name: 'mod1' }, modName: 'mod2' });
62+
63+
t.is(entity.mod.name, 'mod1');
64+
});
65+
66+
test('should use `mod.val` field instead of `modVal`', t => {
67+
const entity = BemEntityName.create({ block: 'block', mod: { name: 'm', val: 'v1' }, modVal: 'v2' });
68+
69+
t.is(entity.mod.val, 'v1');
70+
});
71+
72+
test('should use `mod.name` and `mod.val` instead of `val`', t => {
73+
const entity = BemEntityName.create({ block: 'block', mod: { name: 'm', val: 'v1' }, val: 'v3'});
74+
75+
t.is(entity.mod.val, 'v1');
76+
});
77+
78+
test('should use `mod.name` and `mod.val` instead of `modVal` and `val`', t => {
79+
const entity = BemEntityName.create({ block: 'block', mod: { name: 'm', val: 'v1' }, modVal: 'v2', val: 'v3'});
80+
81+
t.is(entity.mod.val, 'v1');
82+
});

test/to-string.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,15 @@ test('should use `naming.stringify()` for elem', t => {
2626
});
2727

2828
test('should use `naming.stringify()` for block modifier', t => {
29-
const entity = new BemEntityName({ block: 'block', modName: 'mod', modVal: 'val' });
29+
const entity = new BemEntityName({ block: 'block', mod: { name: 'mod', val: 'val' } });
3030

3131
entity.toString();
3232

3333
t.truthy(spy.calledWith({ block: 'block', modName: 'mod', modVal: 'val' }));
3434
});
3535

3636
test('should use naming.stringify() for element modifier', t => {
37-
const entity = new BemEntityName({ block: 'block', elem: 'elem', modName: 'mod', modVal: 'val' });
37+
const entity = new BemEntityName({ block: 'block', elem: 'elem', mod: { name: 'mod', val: 'val' } });
3838

3939
entity.toString();
4040

test/type.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ test('should determine block', t => {
99
});
1010

1111
test('should determine modifier of block', t => {
12-
const entityName = new BemEntityName({ block: 'block', mod: 'mod' });
12+
const entityName = new BemEntityName({ block: 'block', mod: { name: 'mod' } });
1313

1414
t.is(entityName.type, 'blockMod');
1515
});
@@ -21,7 +21,7 @@ test('should determine elem', t => {
2121
});
2222

2323
test('should determine modifier of element', t => {
24-
const entityName = new BemEntityName({ block: 'block', elem: 'elem', mod: 'mod' });
24+
const entityName = new BemEntityName({ block: 'block', elem: 'elem', mod: { name: 'mod' } });
2525

2626
t.is(entityName.type, 'elemMod');
2727
});

0 commit comments

Comments
 (0)