Skip to content
This repository has been archived by the owner on May 5, 2021. It is now read-only.

Commit

Permalink
[IMP] Core: add contains() on Modifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
Goaman committed Oct 21, 2020
1 parent 20ce823 commit dd7dc62
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 12 deletions.
44 changes: 32 additions & 12 deletions packages/core/src/Modifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Constructor, isConstructor } from '../../utils/src/utils';
import { EventMixin } from '../../utils/src/EventMixin';
import { VersionableArray } from './Memory/VersionableArray';

export class Modifiers extends EventMixin {
export class Modifiers extends EventMixin implements Iterable<Modifier> {
private _contents: Modifier[];
constructor(...modifiers: Array<Modifier | Constructor<Modifier>>) {
super();
Expand Down Expand Up @@ -247,6 +247,22 @@ export class Modifiers extends EventMixin {
toggle(modifier: Modifier | Constructor<Modifier>): void {
this.remove(modifier) || this.append(modifier);
}
/**
* Check that all `otherModifiers` ar contained within this ones.
*
* @param otherModifiers
*/
contains(otherModifiers: Modifiers): boolean {
for (const otherModifier of otherModifiers) {
const foundModifier = this.find(m => m.isSameAs(otherModifier));
// Modifier.isSameAs(undefined) could return true. See
// `Attribute.isSameAs`.
if (!foundModifier && !otherModifier.isSameAs(undefined)) {
return false;
}
}
return true;
}
/**
* Return true if the modifiers in this array are the same as the modifiers
* in the given array (as defined by the `isSameAs` methods of the
Expand All @@ -255,17 +271,7 @@ export class Modifiers extends EventMixin {
* @param otherModifiers
*/
areSameAs(otherModifiers: Modifiers): boolean {
const modifiersMap = new Map(
this._contents?.map(a => [a, otherModifiers.find(b => a.isSameAs(b))]) || [],
);
const aModifiers = Array.from(modifiersMap.keys());
const bModifiers = Array.from(modifiersMap.values());

const allAinB = aModifiers.every(a => a.isSameAs(modifiersMap.get(a)));
const allBinA = otherModifiers.every(
b => bModifiers.includes(b) || b.isSameAs(this.find(b)),
);
return allAinB && allBinA;
return this.contains(otherModifiers) && otherModifiers.contains(this);
}
/**
* Remove all modifiers.
Expand Down Expand Up @@ -306,6 +312,20 @@ export class Modifiers extends EventMixin {
map<T>(callbackfn: (value: Modifier, index: number, array: Modifier[]) => T): T[] {
return this._contents?.map(callbackfn) || [];
}
/**
* Iterate through all modifiers.
*/
[Symbol.iterator](): Iterator<Modifier> {
let index = -1;
const data = this._contents || [];

return {
next: (): IteratorResult<Modifier> => ({
value: data[++index],
done: !(index in data),
}),
};
}
/**
* @override
*/
Expand Down
55 changes: 55 additions & 0 deletions packages/core/test/Modifiers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ class ExtendedModifier extends Modifier {
return otherModifier instanceof ExtendedModifier && this.value === otherModifier.value;
}
}
class SameUndefinedModifier extends Modifier {
isSameAs(otherModifier: Modifier): boolean {
return otherModifier instanceof Modifier || typeof otherModifier === 'undefined';
}
}
describe('core', () => {
describe('Modifiers', () => {
describe('constructor()', () => {
Expand Down Expand Up @@ -505,6 +510,56 @@ describe('core', () => {
expect(modifiersMap[1] instanceof ExtendedModifier).to.be.true;
});
});
describe('contains()', () => {
it('should contain itself favorably', () => {
const m1 = new Modifier();
const m2 = new Modifier();
const modifiers1 = new Modifiers(m1, m2);
expect(modifiers1.contains(modifiers1)).to.be.true;
});
it('should contain a modifier that has the same favorably', () => {
const m1 = new ExtendedModifier(1);
const m2 = new ExtendedModifier(2);
const modifiers1 = new Modifiers(m1, m2);
const m1bis = new ExtendedModifier(1);
const m2bis = new ExtendedModifier(2);
const modifiers2 = new Modifiers(m1bis);
const modifiers3 = new Modifiers(m2bis);
const modifiers4 = new Modifiers(m1bis, m2bis);
expect(modifiers1.contains(modifiers2)).to.be.true;
expect(modifiers1.contains(modifiers3)).to.be.true;
expect(modifiers1.contains(modifiers4)).to.be.true;
});
it('should contain a modifier that has the same favorably even if their order is different', () => {
const m1 = new ExtendedModifier(1);
const m2 = new ExtendedModifier(2);
const modifiers1 = new Modifiers(m1, m2);
const modifiers2 = new Modifiers(m2, m1);
expect(modifiers1.contains(modifiers2)).to.be.true;
});
it('should contain a modifier that has the same favorably even if their order and instances are different', () => {
const m1 = new ExtendedModifier(1);
const m2 = new ExtendedModifier(2);
const modifiers1 = new Modifiers(m1, m2);
const m1bis = new ExtendedModifier(1);
const m2bis = new ExtendedModifier(2);
const modifiers2 = new Modifiers(m2bis, m1bis);
expect(modifiers1.contains(modifiers2)).to.be.true;
});
it('should match with modifiers that are the same with undefined', () => {
const m1 = new SameUndefinedModifier();
const modifiers1 = new Modifiers();
const modifiers2 = new Modifiers(m1);
expect(modifiers1.contains(modifiers2)).to.be.true;
});
it('should not contain the other modifiers', () => {
const m1 = new ExtendedModifier(1);
const modifiers1 = new Modifiers(m1);
const m2 = new ExtendedModifier(0);
const modifiers2 = new Modifiers(m2);
expect(modifiers1.contains(modifiers2)).to.be.false;
});
});
describe('areSameAs()', () => {
it('should know that an instance of Modifiers is the same as itself', () => {
const m1 = new Modifier();
Expand Down

0 comments on commit dd7dc62

Please sign in to comment.