UNPKG

rpd

Version:

RPD is a minimal framework for building Node-Based User Interfaces, powered by Reactive Programming

490 lines (371 loc) 17.8 kB
describe('navigation', function() { var networkUpdatesSpy; var networkErrorSpy; var changePathSpy; var SEPARATOR = '+'; beforeEach(function() { networkUpdatesSpy = jasmine.createSpy('network-updates'); Rpd.events.onValue(networkUpdatesSpy); //changePathSpy = jasmine.createSpy('change-path', Rpd.navigation.changePath).and.callThrough(); changePathSpy = spyOn(Rpd.navigation, 'changePath').and.callThrough(); networkErrorSpy = jasmine.createSpy('network-errors'); Rpd.events.onError(networkErrorSpy); Rpd.navigation.enable(); }); afterEach(function() { Rpd.navigation.disable(); Rpd.events.offValue(networkUpdatesSpy); }); describe('handling empty path', function() { it('leaves first added patch opened and updates path with it', function() { var firstPatch = Rpd.addPatch('first'); var secondPatch = Rpd.addPatch('second'); changePathSpy.calls.reset(); Rpd.navigation.handlePath(''); expect(networkUpdatesSpy).not.toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/close', patch: firstPatch })); expect(changePathSpy).toHaveBeenCalledWith(firstPatch.id); expect(changePathSpy).toHaveBeenCalledOnce(); }); it('opens first added patch if it was closed before', function() { var firstPatch = Rpd.addPatch('first'); firstPatch.close(); var secondPatch = Rpd.addPatch('second'); networkUpdatesSpy.calls.reset(); changePathSpy.calls.reset(); Rpd.navigation.handlePath(''); expect(networkUpdatesSpy).toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/open', patch: firstPatch })); expect(changePathSpy).toHaveBeenCalledWith(firstPatch.id); }); it('closes other patches except the first one', function() { var firstPatch = Rpd.addPatch('first'); var secondPatch = Rpd.addPatch('second'); changePathSpy.calls.reset(); Rpd.navigation.handlePath(''); expect(networkUpdatesSpy).toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/close', patch: secondPatch })); }); it('closes all other patches', function() { var firstPatch = Rpd.addPatch('first'); var secondPatch = Rpd.addPatch('second'); var thirdPatch = Rpd.addClosedPatch('third'); thirdPatch.open(); networkUpdatesSpy.calls.reset(); changePathSpy.calls.reset(); Rpd.navigation.handlePath(''); expect(networkUpdatesSpy).toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/close', patch: secondPatch })); expect(networkUpdatesSpy).toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/close', patch: thirdPatch })); expect(changePathSpy).toHaveBeenCalledWith(firstPatch.id); }); }); describe('when path contains wrong ID or gibberish', function() { var GIBBER = 'gibber'; it('fires an error, but opens first added patch', function() { var firstPatch = Rpd.addPatch('first'); var secondPatch = Rpd.addPatch('second'); networkUpdatesSpy.calls.reset(); changePathSpy.calls.reset(); Rpd.navigation.handlePath(GIBBER); expect(networkErrorSpy).toHaveBeenCalled(); expect(networkUpdatesSpy).toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/close', patch: secondPatch })); expect(networkUpdatesSpy).not.toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/close', patch: firstPatch })); expect(changePathSpy).toHaveBeenCalledWith(firstPatch.id); }); it('fires an error, opens first added patch even if it was closed before', function() { var firstPatch = Rpd.addPatch('first'); firstPatch.close(); var secondPatch = Rpd.addPatch('second'); networkUpdatesSpy.calls.reset(); changePathSpy.calls.reset(); Rpd.navigation.handlePath(GIBBER); expect(networkErrorSpy).toHaveBeenCalled(); expect(networkUpdatesSpy).toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/open', patch: firstPatch })); expect(changePathSpy).toHaveBeenCalledWith(firstPatch.id); }); it('fires an error, but yet closes all other patches', function() { var firstPatch = Rpd.addPatch('first'); var secondPatch = Rpd.addPatch('second'); var thirdPatch = Rpd.addClosedPatch('third'); thirdPatch.open(); networkUpdatesSpy.calls.reset(); changePathSpy.calls.reset(); Rpd.navigation.handlePath(GIBBER); expect(networkErrorSpy).toHaveBeenCalled(); expect(networkUpdatesSpy).toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/close', patch: secondPatch })); expect(networkUpdatesSpy).toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/close', patch: thirdPatch })); expect(changePathSpy).toHaveBeenCalledWith(firstPatch.id); }); it('fires an error when no patches were opened', function() { Rpd.navigation.handlePath(SEPARATOR + SEPARATOR); expect(networkErrorSpy).toHaveBeenCalled(); expect(changePathSpy).toHaveBeenCalledWith(''); }); }); describe('when path contains single patch ID', function() { it('leaves specified patch opened', function() { var firstPatch = Rpd.addPatch('first'); var secondPatch = Rpd.addPatch('second'); changePathSpy.calls.reset(); Rpd.navigation.handlePath(secondPatch.id); expect(networkUpdatesSpy).not.toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/close', patch: secondPatch })); expect(changePathSpy).not.toHaveBeenCalled(); }); it('opens specified patch if it was closed before', function() { var firstPatch = Rpd.addPatch('first'); var secondPatch = Rpd.addClosedPatch('second'); networkUpdatesSpy.calls.reset(); changePathSpy.calls.reset(); Rpd.navigation.handlePath(secondPatch.id); expect(networkUpdatesSpy).toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/open', patch: secondPatch })); expect(changePathSpy).not.toHaveBeenCalled(); }); it('closes other patches except the specified one', function() { var firstPatch = Rpd.addPatch('first'); var secondPatch = Rpd.addPatch('second'); changePathSpy.calls.reset(); Rpd.navigation.handlePath(secondPatch.id); expect(networkUpdatesSpy).toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/close', patch: firstPatch })); expect(changePathSpy).not.toHaveBeenCalled(); }); it('closes all other patches', function() { var firstPatch = Rpd.addPatch('first'); var secondPatch = Rpd.addPatch('second'); var thirdPatch = Rpd.addClosedPatch('third'); thirdPatch.open(); networkUpdatesSpy.calls.reset(); changePathSpy.calls.reset(); Rpd.navigation.handlePath(secondPatch.id); expect(networkUpdatesSpy).toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/close', patch: firstPatch })); expect(networkUpdatesSpy).toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/close', patch: thirdPatch })); expect(changePathSpy).not.toHaveBeenCalled(); }); it('handling same path is not causing changePath to be called next time', function() { var firstPatch = Rpd.addPatch('first'); //Rpd.navigation.handlePath(firstPatch.id); changePathSpy.calls.reset(); Rpd.navigation.handlePath(firstPatch.id); Rpd.navigation.handlePath(firstPatch.id); expect(changePathSpy).not.toHaveBeenCalled(); }); }); describe('when path contains several patch IDs', function() { it('opens all patches specified in the list while they exist', function() { var firstPatch = Rpd.addClosedPatch('first'); var secondPatch = Rpd.addPatch('second'); var thirdPatch = Rpd.addClosedPatch('third'); networkUpdatesSpy.calls.reset(); changePathSpy.calls.reset(); Rpd.navigation.handlePath(thirdPatch.id + SEPARATOR + firstPatch.id + SEPARATOR + secondPatch.id); expect(networkUpdatesSpy).toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/open', patch: firstPatch })); expect(networkUpdatesSpy).toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/open', patch: thirdPatch })); expect(networkUpdatesSpy).not.toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/close', patch: secondPatch })); expect(changePathSpy).not.toHaveBeenCalled(); }); it('opens all patches specified in the list while they exist, even if there\'s a separator in the end', function() { var firstPatch = Rpd.addClosedPatch('first'); var secondPatch = Rpd.addPatch('second'); var thirdPatch = Rpd.addClosedPatch('third'); networkUpdatesSpy.calls.reset(); changePathSpy.calls.reset(); Rpd.navigation.handlePath(thirdPatch.id + SEPARATOR + firstPatch.id + SEPARATOR + secondPatch.id + SEPARATOR); expect(networkUpdatesSpy).toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/open', patch: firstPatch })); expect(networkUpdatesSpy).toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/open', patch: thirdPatch })); expect(networkUpdatesSpy).not.toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/close', patch: secondPatch })); expect(changePathSpy).toHaveBeenCalledWith(thirdPatch.id + SEPARATOR + firstPatch.id + SEPARATOR + secondPatch.id); }); it('closed patches stay closed if they were not specified in the list', function() { var firstPatch = Rpd.addClosedPatch('first'); var secondPatch = Rpd.addPatch('second'); var thirdPatch = Rpd.addClosedPatch('third'); networkUpdatesSpy.calls.reset(); changePathSpy.calls.reset(); Rpd.navigation.handlePath(thirdPatch.id + SEPARATOR + secondPatch.id); expect(networkUpdatesSpy).not.toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/open', patch: firstPatch })); expect(networkUpdatesSpy).toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/open', patch: thirdPatch })); expect(changePathSpy).not.toHaveBeenCalled(); }) it('do not opens patches which don\'t exist, fires an error for them, but fixes path', function() { var firstPatch = Rpd.addClosedPatch('first'); var secondPatch = Rpd.addClosedPatch('second'); var thirdPatch = Rpd.addClosedPatch('third'); expect(changePathSpy).not.toHaveBeenCalled(); networkUpdatesSpy.calls.reset(); var GIBBER = 'gibber'; Rpd.navigation.handlePath(thirdPatch.id + SEPARATOR + firstPatch.id + SEPARATOR + /*!*/GIBBER/*!*/ + SEPARATOR); expect(networkErrorSpy).toHaveBeenCalled(); expect(networkUpdatesSpy).toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/open', patch: firstPatch })); expect(networkUpdatesSpy).toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/open', patch: thirdPatch })); expect(networkUpdatesSpy).not.toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/open', patch: secondPatch })); expect(changePathSpy).toHaveBeenCalledWith(thirdPatch.id + SEPARATOR + firstPatch.id); }); xit('when parent patch was closed, also closes the child patch', function() { var firstPatch = Rpd.addClosedPatch('first'); var secondPatch = Rpd.addPatch('second'); var thirdPatch = Rpd.addPatch('third'); secondPatch.open(thirdPatch); networkUpdatesSpy.calls.reset(); thirdPatch.close(); expect(networkUpdatesSpy).toHaveBeenCalledWith( jasmine.objectContaining({ type: 'patch/close', patch: secondPatch })); }); it('handling same path is not causing changePath to be called next time', function() { var firstPatch = Rpd.addPatch('first'); var secondPatch = Rpd.addPatch('second'); var bothPatchesPath = firstPatch.id + SEPARATOR + secondPatch.id; //Rpd.navigation.handlePath(bothPatchesPath); changePathSpy.calls.reset(); Rpd.navigation.handlePath(bothPatchesPath); Rpd.navigation.handlePath(bothPatchesPath); expect(changePathSpy).not.toHaveBeenCalled(); }); }); describe('reaction on patches opened by user', function() { it('writes every opened patch to a path', function() { var firstPatch = Rpd.addPatch('first'); expect(changePathSpy).toHaveBeenCalledWith(firstPatch.id); var secondPatch = Rpd.addPatch('second'); expect(changePathSpy).toHaveBeenCalledWith(firstPatch.id + SEPARATOR + secondPatch.id); var thirdPatch = Rpd.addPatch('third'); expect(changePathSpy).toHaveBeenCalledWith(firstPatch.id + SEPARATOR + secondPatch.id + SEPARATOR + thirdPatch.id); }); it('if one of the patches is closed, do not writes it to the path', function() { var firstPatch = Rpd.addPatch('first'); changePathSpy.calls.reset(); var secondPatch = Rpd.addClosedPatch('second'); expect(changePathSpy).not.toHaveBeenCalled(); var thirdPatch = Rpd.addPatch('third'); expect(changePathSpy).toHaveBeenCalledWith(firstPatch.id + SEPARATOR + thirdPatch.id); }); it('leaves single opened patch in a path and do not updates it if no patches were opened later', function() { var firstPatch = Rpd.addClosedPatch('first'); var secondPatch = Rpd.addPatch('second'); expect(changePathSpy).toHaveBeenCalledWith(secondPatch.id); changePathSpy.calls.reset(); var thirdPatch = Rpd.addClosedPatch('third'); expect(changePathSpy).not.toHaveBeenCalled(); }); it('follows opening and closing patches', function() { var firstPatch = Rpd.addPatch('first'); var secondPatch = Rpd.addClosedPatch('second'); var thirdPatch = Rpd.addPatch('third'); changePathSpy.calls.reset(); secondPatch.open(); expect(changePathSpy).toHaveBeenCalledWith(firstPatch.id + SEPARATOR + thirdPatch.id + SEPARATOR + secondPatch.id); thirdPatch.close(); expect(changePathSpy).toHaveBeenCalledWith(firstPatch.id + SEPARATOR + secondPatch.id); }); xit('when parent patch was passed to open method, stores it in the path in first position', function() { var firstPatch = Rpd.addClosedPatch('first'); var secondPatch = Rpd.addPatch('second'); var thirdPatch = Rpd.addPatch('third'); changePathSpy.calls.reset(); secondPatch.open(thirdPatch); expect(changePathSpy).toHaveBeenCalledWith(thirdPatch.id + SEPARATOR + secondPatch.id); }); }); });