|
| 1 | +import Neo from '../../../../src/Neo.mjs'; |
| 2 | +import * as core from '../../../../src/core/_export.mjs'; |
| 3 | +import {isDescriptor} from '../../../../src/core/ConfigSymbols.mjs'; |
| 4 | + |
| 5 | +// Level 1 |
| 6 | +class BaseComponent extends core.Base { |
| 7 | + static config = { |
| 8 | + className : 'Neo.Test.MultiLevel.BaseComponent', |
| 9 | + myConfig_ : 'baseValue', |
| 10 | + arrayConfig_ : { |
| 11 | + [isDescriptor]: true, |
| 12 | + value : [1, 2], |
| 13 | + merge : 'replace' |
| 14 | + }, |
| 15 | + objectConfig_: { |
| 16 | + [isDescriptor]: true, |
| 17 | + value : {a: 1, b: {c: 2}}, |
| 18 | + merge : 'deep' |
| 19 | + } |
| 20 | + } |
| 21 | +} |
| 22 | +Neo.setupClass(BaseComponent); |
| 23 | + |
| 24 | +// Level 2 |
| 25 | +class MidLevelComponent extends BaseComponent { |
| 26 | + static config = { |
| 27 | + className : 'Neo.Test.MultiLevel.MidLevelComponent', |
| 28 | + arrayConfig : [3, 4], |
| 29 | + objectConfig: {b: {c: 3, d: 4}, e: 5} |
| 30 | + } |
| 31 | +} |
| 32 | +Neo.setupClass(MidLevelComponent); |
| 33 | + |
| 34 | +// Level 3 |
| 35 | +class TopLevelComponent extends MidLevelComponent { |
| 36 | + static config = { |
| 37 | + className : 'Neo.Test.MultiLevel.TopLevelComponent', |
| 38 | + myConfig : 'topValue', |
| 39 | + objectConfig: {b: {d: 99}, f: 6} // Override again |
| 40 | + } |
| 41 | +} |
| 42 | +Neo.setupClass(TopLevelComponent); |
| 43 | + |
| 44 | + |
| 45 | +StartTest(t => { |
| 46 | + t.it('Initial values for a three-level hierarchy instance', t => { |
| 47 | + const instance = Neo.create(TopLevelComponent); |
| 48 | + |
| 49 | + // myConfig is defined in Base, overridden in Top (Mid doesn't touch it) |
| 50 | + t.is(instance.myConfig, 'topValue', 'myConfig should be the value from the top-level class'); |
| 51 | + |
| 52 | + // arrayConfig is defined in Base, overridden in Mid (Top doesn't touch it) |
| 53 | + t.isDeeplyStrict(instance.arrayConfig, [3, 4], 'arrayConfig should be replaced by the mid-level class value'); |
| 54 | + |
| 55 | + // objectConfig is defined in Base, merged in Mid, and merged again in Top |
| 56 | + const expectedObject = { |
| 57 | + a: 1, // from Base |
| 58 | + b: {c: 3, d: 99}, // c from Mid, d from Top |
| 59 | + e: 5, // from Mid |
| 60 | + f: 6 // from Top |
| 61 | + }; |
| 62 | + t.isDeeplyStrict(instance.objectConfig, expectedObject, 'objectConfig should be a deep merge of all three levels'); |
| 63 | + }); |
| 64 | + |
| 65 | + t.it('Instance-level config overrides on a three-level hierarchy', t => { |
| 66 | + const instance = Neo.create(TopLevelComponent, { |
| 67 | + myConfig : 'instanceValue', |
| 68 | + arrayConfig : [10, 11], |
| 69 | + objectConfig: {a: 100, b: {c: 101}, g: 102} |
| 70 | + }); |
| 71 | + |
| 72 | + t.is(instance.myConfig, 'instanceValue', 'myConfig should be the value from the instance config'); |
| 73 | + t.isDeeplyStrict(instance.arrayConfig, [10, 11], 'arrayConfig should be replaced by the instance config value'); |
| 74 | + |
| 75 | + const expectedObject = { |
| 76 | + a: 100, // from instance |
| 77 | + b: {c: 101, d: 99}, // c from instance, d from Top |
| 78 | + e: 5, // from Mid |
| 79 | + f: 6, // from Top |
| 80 | + g: 102 // from instance |
| 81 | + }; |
| 82 | + |
| 83 | + t.isDeeplyStrict(instance.objectConfig, expectedObject, 'objectConfig from instance should be deep-merged into the class hierarchy defaults'); |
| 84 | + }); |
| 85 | +}); |
0 commit comments