From 18d4fe06200c09e315dc2b7b4efb18cbff3aaa68 Mon Sep 17 00:00:00 2001 From: Artur Arseniev Date: Tue, 23 Nov 2021 16:44:14 +0100 Subject: [PATCH] Add getFullName to Selectors --- src/selector_manager/model/Selectors.js | 25 ++++++ .../selector_manager/model/SelectorModels.js | 50 +++++++++++ test/specs/style_manager/index.js | 87 ++++++++++++++++++- 3 files changed, 161 insertions(+), 1 deletion(-) diff --git a/src/selector_manager/model/Selectors.js b/src/selector_manager/model/Selectors.js index 9d2fa91ce..98143525b 100644 --- a/src/selector_manager/model/Selectors.js +++ b/src/selector_manager/model/Selectors.js @@ -2,6 +2,15 @@ import { filter } from 'underscore'; import { Collection } from 'common'; import Selector from './Selector'; +const combine = (tail, curr) => { + return tail.reduce( + (acc, item, n) => { + return acc.concat(combine(tail.slice(n + 1), `${curr}${item}`)); + }, + [curr] + ); +}; + export default class Selectors extends Collection { modelId(attr) { return `${attr.name}_${attr.type || Selector.TYPE_CLASS}`; @@ -26,6 +35,22 @@ export default class Selectors extends Collection { coll.forEach(selector => result.push(selector.getFullName(opts))); return result.join('').trim(); } + + getFullName(opts = {}) { + const { combination, array } = opts; + let result = []; + const sels = this.map(s => s.getFullName(opts)).sort(); + + if (combination) { + sels.forEach((sel, n) => { + result = result.concat(combine(sels.slice(n + 1), sel)); + }); + } else { + result = sels; + } + + return array ? result : combination ? result.join(',') : result.join(''); + } } Selectors.prototype.model = Selector; diff --git a/test/specs/selector_manager/model/SelectorModels.js b/test/specs/selector_manager/model/SelectorModels.js index b261c0926..74c2ec486 100644 --- a/test/specs/selector_manager/model/SelectorModels.js +++ b/test/specs/selector_manager/model/SelectorModels.js @@ -61,4 +61,54 @@ describe('Selectors', () => { obj.add([{ name: 'test' }, { name: 'test2', type: Selector.TYPE_ID }]); expect(obj.getFullString()).toEqual('.test#test2'); }); + + test('getFullName with combination of 2 classes', () => { + obj.add([{ name: 'a' }, { name: 'b' }]); + expect( + obj.getFullName({ + combination: true, + array: true + }) + ).toEqual(['.a', '.a.b', '.b']); + + expect(obj.getFullName({ combination: true })).toEqual('.a,.a.b,.b'); + expect(obj.getFullName({ array: true })).toEqual(['.a', '.b']); + expect(obj.getFullName()).toEqual('.a.b'); + }); + + test('getFullName with combination of 3 classes', () => { + obj.add([{ name: 'c' }, { name: 'b' }, { name: 'a' }]); + expect( + obj.getFullName({ + combination: true, + array: true + }) + ).toEqual(['.a', '.a.b', '.a.b.c', '.a.c', '.b', '.b.c', '.c']); + }); + + test('getFullName with combination of 4 classes', () => { + obj.add([{ name: 'd' }, { name: 'c' }, { name: 'b' }, { name: 'a' }]); + expect( + obj.getFullName({ + combination: true, + array: true + }) + ).toEqual([ + '.a', + '.a.b', + '.a.b.c', + '.a.b.c.d', + '.a.b.d', + '.a.c', + '.a.c.d', + '.a.d', + '.b', + '.b.c', + '.b.c.d', + '.b.d', + '.c', + '.c.d', + '.d' + ]); + }); }); diff --git a/test/specs/style_manager/index.js b/test/specs/style_manager/index.js index 6e5926c33..90d18330f 100644 --- a/test/specs/style_manager/index.js +++ b/test/specs/style_manager/index.js @@ -4,10 +4,22 @@ describe('StyleManager', () => { describe('Main', () => { let obj; let em; + let domc; + let dv; + let cssc; + let sm; beforeEach(() => { - em = new Editor({}); + em = new Editor({ + mediaCondition: 'max-width', + avoidInlineStyle: true + }); + domc = em.get('DomComponents'); + cssc = em.get('CssComposer'); + dv = em.get('DeviceManager'); + sm = em.get('SelectorManager'); obj = em.get('StyleManager'); + em.get('PageManager').onLoad(); }); afterEach(() => { @@ -115,6 +127,79 @@ describe('StyleManager', () => { expect(obj.render()).toBeTruthy(); }); + describe.only('Parent rules', () => { + test('No parents without selection', () => { + expect(obj.getSelectedParents()).toEqual([]); + }); + + test('Single class, multiple devices', done => { + const cmp = domc.addComponent(`
`); + const [rule1, rule2] = cssc.addRules(` + .cls { color: red; } + @media (max-width: 992px) { + .cls { color: blue; } + } + `); + dv.select('tablet'); + em.setSelected(cmp); + setTimeout(() => { + expect(obj.getLastSelected()).toBe(rule2); + expect(obj.getSelectedParents()).toEqual([rule1]); + done(); + }); + }); + + test('With ID, multiple devices', done => { + sm.setComponentFirst(true); + const cmp = domc.addComponent(`
`); + const [rule1, rule2] = cssc.addRules(` + #id-test { color: red; } + @media (max-width: 992px) { + #id-test { color: blue; } + } + `); + dv.select('tablet'); + em.setSelected(cmp); + setTimeout(() => { + expect(obj.getLastSelected()).toBe(rule2); + expect(obj.getSelectedParents()).toEqual([rule1]); + done(); + }); + }); + + test('With ID + class, multiple devices', done => { + sm.setComponentFirst(true); + const cmp = domc.addComponent(`
`); + const [rule1, rule2] = cssc.addRules(` + .cls { color: red; } + @media (max-width: 992px) { + #id-test { color: blue; } + } + `); + dv.select('tablet'); + em.setSelected(cmp); + setTimeout(() => { + expect(obj.getLastSelected()).toBe(rule2); + expect(obj.getSelectedParents()).toEqual([rule1]); + done(); + }); + }); + + test('Mixed classes', done => { + const cmp = domc.addComponent(`
`); + const [rule1, rule2] = cssc.addRules(` + .cls1 { color: red; } + .cls1.cls2 { color: blue; } + `); + em.setSelected(cmp); + setTimeout(() => { + // expect(obj.getLastSelected()).toBe(rule2); + // expect(obj.getSelectedParents()).toEqual([rule1]); + done(); + }); + }); + }); + describe('Init with configuration', () => { beforeEach(() => { em = new Editor({