@geogirafe/lib-geoportal
Version:
GeoGirafe is a flexible application to build online geoportals.
205 lines (204 loc) • 7.2 kB
JavaScript
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import StateManager from './statemanager';
import ThemeLayer from '../../models/layers/themelayer';
import LayerOsm from '../../models/layers/layerosm';
import MockHelper from '../tests/mockhelper';
let manager;
beforeAll(() => {
MockHelper.startMocking();
manager = StateManager.getInstance();
});
afterAll(() => {
MockHelper.stopMocking();
});
describe('StateManager.subscribe', () => {
it('subscribe should call callback immediately if value is not null, undefined, empty object, or empty array', () => {
let controlOldValue = undefined;
let controlValue = undefined;
let controlParent = undefined;
const callback = (oldValue, value, parent) => {
controlOldValue = oldValue;
controlValue = value;
controlParent = parent;
};
try {
manager.state.language = 'fr';
manager.subscribe('language', callback);
expect(controlOldValue).toBe(null);
expect(controlValue).toBe('fr');
expect(controlParent).toEqual(manager.state);
}
finally {
manager.unsubscribe(callback);
}
});
it('subscribe should not call callback immediately if value is null', () => {
let controlValue = 1;
const callback = () => {
controlValue = 2;
};
try {
manager.state.language = null;
manager.subscribe('language', callback);
expect(controlValue).toEqual(1);
}
finally {
manager.unsubscribe(callback);
}
});
it('subscribe should not call callback immediately if value is empty object', () => {
let controlValue = 1;
const callback = () => {
controlValue = 2;
};
try {
manager.state.ogcServers = {};
manager.subscribe('ogcServers', callback);
expect(controlValue).toEqual(1);
}
finally {
manager.unsubscribe(callback);
}
});
it('subscribe should not call callback immediately if value is empty array', () => {
let controlValue = 1;
const callback = () => {
controlValue = 2;
};
try {
manager.state.mouseCoordinates = [];
manager.subscribe('mouseCoordinates', callback);
expect(controlValue).toEqual(1);
}
finally {
manager.unsubscribe(callback);
}
});
it('subscribe should NOT raise an exception if the property does not exist, because it can be a regular expression', () => {
expect(() => {
manager.subscribe('nonExistentProperty.subproperty', () => { });
}).not.toThrowError();
expect(() => {
manager.subscribe(/nonExistentProperty\.subproperty/, () => { });
}).not.toThrowError();
});
it('subscribe should support regular expressions for attributes', () => {
let controlValue = 1;
const callback = () => {
controlValue = 2;
};
try {
manager.subscribe(/.*\.helpVisible/, callback);
expect(controlValue).toEqual(1);
manager.state.interface.helpVisible = true;
expect(controlValue).toEqual(2);
}
finally {
manager.unsubscribe(callback);
}
});
it('subscribe should support regular expressions for arrays', () => {
let controlValue = 1;
const callback = () => {
controlValue = 2;
};
try {
manager.state.extendedState = {
arr: [{ visible: false }, { visible: false }, { visible: false }]
};
manager.subscribe(/extendedState\.arr\.[0-9]+\.visible/, callback);
expect(controlValue).toEqual(1);
// @ts-ignore
manager.state.extendedState.arr[0].visible = true;
expect(controlValue).toEqual(2);
}
finally {
manager.unsubscribe(callback);
}
});
it('subscribe should not listen to properties whose name begins with underscode', () => {
let controlValue;
const callback = () => {
controlValue = 2;
};
try {
const theme = new ThemeLayer(1, 'test', 0, 'iconpath');
theme.children.push(new LayerOsm(0));
manager.state.themes._allThemes[theme.id] = theme;
manager.subscribe(/.*/, callback);
controlValue = 1;
manager.state.themes._allThemes[theme.id].children[0].name = 'new name';
expect(controlValue).toEqual(1);
manager.state.themes._allThemes[theme.id].name = 'new name';
expect(controlValue).toEqual(1);
}
finally {
manager.unsubscribe(callback);
}
});
});
describe('StateManager.unsubscribe', () => {
it('unsubscribe (one) should remove the specified callback', () => {
let callback1Called = false;
const callback1 = () => {
callback1Called = true;
};
let callback2Called = false;
const callback2 = () => {
callback2Called = true;
};
try {
manager.state.language = null;
manager.subscribe('language', callback1);
manager.subscribe('language', callback2);
// Unsubscribe the first callback
manager.unsubscribe(callback2);
// Trigger a change event
manager.state.language = 'fr';
// Ensure only the second callback is called
expect(callback1Called).toBe(true);
expect(callback2Called).toBe(false);
}
finally {
manager.unsubscribe(callback1);
}
});
it('unsubscribe multiple should remove specific objects', () => {
manager.state.language = null;
let callback1Called = false;
let callback2Called = false;
let callback3Called = false;
const callbacks = [
manager.subscribe('language', () => {
callback1Called = true;
}),
manager.subscribe('language', () => {
callback2Called = true;
})
];
const callback3 = manager.subscribe('language', () => {
callback3Called = true;
});
try {
// UnsubscribeAll (1, 2)
manager.unsubscribe(callbacks);
// Trigger a change event
manager.state.language = 'fr';
// Ensure only the third callback is called
expect(callback1Called).toBe(false);
expect(callback2Called).toBe(false);
expect(callback3Called).toBe(true);
}
finally {
manager.unsubscribe(callback3);
}
expect(() => {
manager.unsubscribe(() => { });
}).toThrowError();
});
it('unsubscribe should throw an error if callback is not found', () => {
expect(() => {
manager.unsubscribe(() => { });
}).toThrowError();
});
});