Skip to content

Commit

Permalink
Merge pull request #127 from GannettDigital/issue-109
Browse files Browse the repository at this point in the history
Issue 109 Added stashing and retrieving components/states by dynamic area
  • Loading branch information
tomrdale authored Jul 19, 2018
2 parents 23bf744 + 1922952 commit 01d1d9b
Show file tree
Hide file tree
Showing 6 changed files with 945 additions and 150 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Pending Version

* Brian Fitzpatrick
* Added popping and pushing components/states by dynamic areas

* Tom Dale
* Added ability to specify report formats
* Supported flags: 'JSON'
Expand Down
2 changes: 1 addition & 1 deletion docs/_pages/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ This section details the different sections of a component
* `children`
* The computed children from executing the children function
* `dynamicArea`
* The dynamicArea given to the component upon creation
* The dynamicArea given to the component upon creation, a given component can have more than one dynamic area
* `getFromPage(key)`
* Gets a value from the current model of the page
* Parameters
Expand Down
19 changes: 19 additions & 0 deletions docs/_pages/expected-state.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,25 @@ This section documents functions for the expected state used throughout the tool
### pop()
* Pops the most recent stashed state

### stashDynamicArea(dynamicArea)
* Stashes the components and states of the passed dynamic area
* Parameters
* `dynamicArea` **required**
* A string denoting the dynamic area you wish to stash

### isDynamicAreaStashed(dynamicArea)
* Checks if the passed dynamic area is stashed
* Parameters
* `dynamicArea` **required**
* A string denoting the dynamic area you wish to check

### retrieveDynamicArea(dynamicArea)
* Retrieves the components and states from a stashed dynamic area
* Adds the retrieved components back to the dynamic area
* Parameters
* `dynamicArea` **required**
* A String denoting the dynamic area you wish to retrieve

## eventEmitter
* An event emitter instance wherein the events returned from the `events` function are registered
* Use this emitter to emit events to other components
155 changes: 117 additions & 38 deletions lib/util/expected-state.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module.exports = ExpectedState = {
expectedState._components = new Map();
expectedState._dynamicAreas = new Map();
expectedState._stashedDynamicAreas = [];
expectedState._stashedDynamicAreasComponentsAndStates = new Map();
expectedState._stashedComponents = [];
expectedState.eventEmitter = new EventEmitter();
expectedState._dataStore = dataStore;
Expand All @@ -28,44 +29,75 @@ module.exports = ExpectedState = {
clonedState._state= {};
clonedState._pageState = _.cloneDeep(this._pageState);
clonedState._components = new Map();
for (let [type, component] of this._components.entries()) {
let componentState = _.cloneDeep(this._state[type]);
let componentOptions = _.cloneDeep(component.options);
clonedState.createAndAddComponent({
type: component.type,
name: component.name,
state: componentState,
options: componentOptions,
dynamicArea: component.dynamicArea,
cloning: true,
});
}

clonedState._stashedStates = _.cloneDeep(this._stashedStates);
for (let stashedComponentMap of this._stashedComponents) {
let components = new Map();
for (let [name, component] of stashedComponentMap.entries()) {
let componentOptions = _.cloneDeep(component.options);
let myComponent = clonedState.createComponent({
type: component.type,
name: name,
options: componentOptions,
dynamicArea: component.dynamicArea,
});
components.set(myComponent.name, myComponent);
}
clonedState._stashedComponents.push(components);
}
for (let dynamicArea of this._stashedDynamicAreas) {
let clonedDynamicArea = new Map();
for (let [dynamicAreaName, components] of dynamicArea.entries()) {
clonedDynamicArea.set(dynamicAreaName, new Set(components));
}
clonedState._stashedDynamicAreas.push(clonedDynamicArea);
}

clonedState._cloneAndAddComponents(this._components, this._state);
clonedState._cloneStashedComponents(this._stashedComponents);
clonedState._cloneStashedDynamicAreas(this._stashedDynamicAreas);
clonedState._cloneStashedDynamicAreasComponentsAndStates(this._stashedDynamicAreasComponentsAndStates);

callback(clonedState);
});
},
_cloneComponent(component) {
let componentOptions = _.cloneDeep(component.options);
return this.createComponent({
type: component.type,
name: component.name,
options: componentOptions,
dynamicArea: component.dynamicArea,
});
},
_cloneAndAddComponents(components, state) {
for (let [type, component] of components.entries()) {
let componentState = _.cloneDeep(state[type]);
let componentOptions = _.cloneDeep(component.options);
this.createAndAddComponent({
type: component.type,
name: component.name,
state: componentState,
options: componentOptions,
dynamicArea: component.dynamicArea,
cloning: true,
});
}
},
_cloneStashedComponents(stashedComponents) {
for (let stashedComponentMap of stashedComponents) {
let components = new Map();
for (let component of stashedComponentMap.values()) {
let myComponent = this._cloneComponent(component);
components.set(myComponent.name, myComponent);
}
this._stashedComponents.push(components);
}
},
_cloneStashedDynamicAreas(stashedDynamicAreas) {
for (let dynamicArea of stashedDynamicAreas) {
let clonedDynamicArea = new Map();
for (let [dynamicAreaName, components] of dynamicArea.entries()) {
clonedDynamicArea.set(dynamicAreaName, new Set(components));
}
this._stashedDynamicAreas.push(clonedDynamicArea);
}
},
_cloneStashedDynamicAreasComponentsAndStates(stashedDynamicAreasComponentsAndStates) {
for (let [dynamicAreaName, stashedData] of stashedDynamicAreasComponentsAndStates.entries()) {
let components = new Map();
for (let component of stashedData.components.values()) {
let clonedComponent = this._cloneComponent(component);
components.set(clonedComponent.name, clonedComponent);
}

let states = new Map();
for (let [componentName, state] of stashedData.states) {
states.set(componentName, _.cloneDeep(state));
}

this._stashedDynamicAreasComponentsAndStates.set(dynamicAreaName, {components, states});
}
},
createComponent(componentConfig) {
let {type, name, options, dynamicArea} = componentConfig;
let newComponent;
Expand Down Expand Up @@ -102,6 +134,9 @@ module.exports = ExpectedState = {
newComponent.name = name;
newComponent.type = type;
newComponent.options = options || {};
if (dynamicArea) {
newComponent.dynamicArea = dynamicArea;
}
newComponent.elements = newComponent.elements();
ExpectedState.emit('validators.validateElements', newComponent.elements, name, type);
newComponent.model = newComponent.model();
Expand All @@ -120,18 +155,14 @@ module.exports = ExpectedState = {
'validators.validateChildren', newComponent.children, name, type
);
}

if (dynamicArea) {
newComponent.dynamicArea = dynamicArea;
}
});
return newComponent;
},
addComponent(component, state, cloning) {
if (!(typeof state === 'object') || Array.isArray(state)) {
throw new SimulatoError.ACTION.EXPECTED_STATE_ERROR(
`component with name '${component.name}'`
+ `must have a state object to add to expecte state`
+ `must have a state object to add to expected state`
);
}

Expand Down Expand Up @@ -263,6 +294,37 @@ module.exports = ExpectedState = {
this._components = new Map();
this._dynamicAreas = new Map();
},
stashDynamicArea(dynamicArea) {
let stashedDynamicAreaComponents = new Map();
let stashedDynamicAreaStates = new Map();
let dynamicAreaComponentNames;
if (this._dynamicAreas.get(dynamicArea)) {
dynamicAreaComponentNames = this._dynamicAreas.get(dynamicArea);

for (let dynamicAreaComponentName of dynamicAreaComponentNames) {
let component = this.getComponent(dynamicAreaComponentName);
stashedDynamicAreaComponents.set(dynamicAreaComponentName, component);
stashedDynamicAreaStates.set(dynamicAreaComponentName, this._state[dynamicAreaComponentName]);
}

this._stashedDynamicAreasComponentsAndStates.set(
dynamicArea,
{
components: stashedDynamicAreaComponents,
states: stashedDynamicAreaStates,
}
);

this.clearDynamicArea(dynamicArea);
} else {
throw new SimulatoError.ACTION.EXPECTED_STATE_ERROR(
`could not find the dynamic area attempting to be stashed`
);
}
},
isDynamicAreaStashed(dynamicArea) {
return this._stashedDynamicAreasComponentsAndStates.has(dynamicArea);
},
pop() {
if (this._stashedStates.length === 0) {
throw new SimulatoError.ACTION.EXPECTED_STATE_ERROR('Failed to pop. No stashed states.');
Expand All @@ -274,6 +336,23 @@ module.exports = ExpectedState = {
this._dynamicAreas = this._stashedDynamicAreas.pop() || new Map();
[...this._components.values()].map(this._registerEvents, this);
},
retrieveDynamicArea(dynamicArea) {
if (this.isDynamicAreaStashed(dynamicArea) === false) {
throw new SimulatoError.ACTION.EXPECTED_STATE_ERROR(`The dynamic area '${dynamicArea}' is not stashed.`);
} else {
this.clearDynamicArea(dynamicArea);
this._stashedDynamicAreasComponentsAndStates
.get(dynamicArea)
.components
.forEach((value, key) => {
this.addComponent(
value,
this._stashedDynamicAreasComponentsAndStates.get(dynamicArea).states.get(key),
true);
});
this._stashedDynamicAreasComponentsAndStates.delete(dynamicArea);
}
},
};

Emitter.mixIn(ExpectedState, globalEventDispatch);
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 01d1d9b

Please sign in to comment.