<commit_before>describe('LiveEditor', function() {
    beforeEach(function() {
        liveEditor = new LiveEditor({editor: '#live-editor-test-1', tabs: ['test 1', 'test 2'], url: 'site.html'});
        $liveEditor = $('.live-editor');
    });

    afterEach(function() {
        $liveEditor.empty();
        $('.btn-undo').remove();
        $('.modal').remove();
        $('#code-panel').remove();
        $('.code-panel-button').remove();
        $('ul.dropdown-menu[role]').remove();
    });

    describe('iframe onload', function() {
        beforeEach(function() {
            $iframe = $liveEditor.find('iframe');
            spyOn(liveEditor, 'domOutlineInit');
            spyOn(liveEditor, 'bindEvents');
            spyOn(liveEditor, 'saveBody');
            spyOn(liveEditor, 'updateBody');
            spyOn(liveEditor, 'codePanelUpdate');
            spyOn(liveEditor, 'dispatchLoadEvent');
            $iframe.load();
        });

        it('Should call domOutlineInit method', function() {
            expect(liveEditor.domOutlineInit).toHaveBeenCalled();
        });

        it('Should call bindEvents method', function() {
            expect(liveEditor.bindEvents).toHaveBeenCalled();
        });

        it('Should call saveBody method', function() {
            expect(liveEditor.saveBody).toHaveBeenCalled();
        });

        it('Should call updateBody method', function() {
            expect(liveEditor.updateBody).toHaveBeenCalled();
        });

        it('Should call codePanelUpdate method', function() {
            expect(liveEditor.codePanelUpdate).toHaveBeenCalled();
        });

        it('Should call dispatchLoadEvent method', function() {
            expect(liveEditor.dispatchLoadEvent).toHaveBeenCalled();
        });
    });

    describe('Build Tabs', function() {
        it('Should build tabs', function() {
            var $tabs = $liveEditor.find('.nav.nav-tabs');
            expect($tabs).toExist();
            expect($tabs.length).toBe(1);
        });
    });

    describe('Build Iframe', function() {
        it('Should build iframe', function() {
            var $iframe = $liveEditor.find('iframe');
            expect($iframe).toExist();
        });

        it('Should create a container element', function() {
            var $iframe = $liveEditor.find('iframe'),
                $container = $iframe.parent(),
                $spinner = $container.find('.spinner-container');
            expect($container).toHaveClass('live-editor-iframe-container');
            expect($spinner).toExist();
        });

        it('Initial Loading Spinner', function() {
            var $s = $('.spinner-container');

            expect($s.text()).toBe(' Loading...');
            expect($s.css('display')).toBe('inline');
        });

        it ('Loading Spinner disappears when iframe is fully loaded', function() {
            var $s = $('.spinner-container');

            liveEditor.$editorIframe.on('load', function() {
                expect($s.css('display')).toBe('none');
            });
        });
    });

    describe('Build Modals', function() {
        beforeEach(function() {
            waits(100);
            liveEditor.$editorIframe.load();
        });

        it('Should build Modals', function() {
            var $m1 = $('#edit-html-modal-live-editor-test-1'),
                $m2 = $('#edit-text-modal-live-editor-test-1'),
                $m3 = $('#edit-classes-modal-live-editor-test-1');

            expect($m1).toExist();
            expect($m2).toExist();
            expect($m3).toExist();
        });
    });

    describe('Build Panel', function() {
        beforeEach(function() {
            waits(100);
            liveEditor.$editorIframe.load();
        });

        it('Should build Panel', function() {
            var $p = $('#code-panel[live-editor-test-1]');
            expect($p).toExist();
        });
    });

    describe('Build DOM outline', function() {
        beforeEach(function() {
            waits(100);
            liveEditor.$editorIframe.load();
        });

        it('Should init DOM outline', function() {
            liveEditor.$editorIframe.on('load', function() {
                var $d = liveEditor.$editorIframe.contents().find('.DomOutline_box');
                expect($d).toExist();
                expect($d.css('display')).toBe('none');
            });
        });
    });

    describe('bindEvents method', function() {
        beforeEach(function() {
            waits(100);
            liveEditor.$editorIframe.load();
        });

        it('Click in any element should call setCurrentElement method', function() {
            var $p = liveEditor.$editorIframe.contents().find('p');

            spyOn(liveEditor, 'setCurrentElement');

            $p.trigger('mousemove').click();

            expect(liveEditor.setCurrentElement).toHaveBeenCalled();
        });

        it('Click in any element should call openCurrentMenu method', function() {
            var $p = liveEditor.$editorIframe.contents().find('p');

            spyOn(liveEditor, 'openCurrentMenu');

            $p.trigger('mousemove').click();

            expect(liveEditor.openCurrentMenu).toHaveBeenCalled();
        });

        it('Click in floating menu item should call operationInit method', function() {
            var $p = liveEditor.$editorIframe.contents().find('p');
            $p.trigger('mousemove').click();

            spyOn(liveEditor, 'operationInit');

            $('ul.dropdown-menu[role] li').click();

            expect(liveEditor.operationInit).toHaveBeenCalled();
        });

        it('When an element is already select and another one is clicked, should call unselectElements method', function() {
            var $p = liveEditor.$editorIframe.contents().find('p');
            $p.trigger('mousemove').click();

            spyOn(liveEditor, 'unselectElements');

            liveEditor.$editorIframe.contents().find('h1').trigger('mousemove').click();

            expect(liveEditor.unselectElements).toHaveBeenCalled();
        });

        it('Undo button click should call codePanelUpdate method if undoList is not empty', function() {
            liveEditor.experiments.test_1.scriptList.push('$("p").remove();');
            liveEditor.experiments.test_1.undoList.push('self.$editorIframe.contents().find("div").append("
Hello World
");');

            spyOn(liveEditor, 'codePanelUpdate');

            $('.btn-undo').click();

            expect(liveEditor.codePanelUpdate).toHaveBeenCalled();
        });

        it('Undo button click should not call codePanelUpdate method if undoList is empty', function() {
            spyOn(liveEditor, 'codePanelUpdate');

            $('.btn-undo').click();

            expect(liveEditor.codePanelUpdate).not.toHaveBeenCalled();
        });

        it('Undo button click should remove last item from undoList var', function() {
            liveEditor.experiments.test_1.undoList.push('self.$editorIframe.contents().find("div").append("
Hello World
");');
            liveEditor.experiments.test_1.undoList.push('self.$editorIframe.contents().find("div").append("
Hello World
");');

            expect(liveEditor.experiments.test_1.undoList.length).toBe(2);

            $('.btn-undo').click();

            expect(liveEditor.experiments.test_1.undoList.length).toBe(1);
        });

        it('Undo button click should remove last item from scriptList var', function() {
            liveEditor.experiments.test_1.undoList.push('self.$editorIframe.contents().find("div").append("
Hello World
");');
            liveEditor.experiments.test_1.scriptList.push('$("p").remove();');
            liveEditor.experiments.test_1.scriptList.push('$("p").remove();');

            expect(liveEditor.experiments.test_1.scriptList.length).toBe(2);

            $('.btn-undo').click();

            expect(liveEditor.experiments.test_1.scriptList.length).toBe(1);
        });

        it('Undo button click should run last undoList script', function() {
            liveEditor.experiments.test_1.undoList.push('self.$editorIframe.contents().find("body div").append("Hello World");');

            $('.btn-undo').click();

            expect(liveEditor.$editorIframe.contents().find("small").length).toBe(1);
        });

        // it('When an element is already select and ESC keydown, should call unselectElements method', function() {
        //     var $p = liveEditor.$editorIframe.contents().find('p');
        //     $p.trigger('mousemove').click();

        //     spyOn(liveEditor, 'unselectElements');

        //     liveEditor.$editorIframe.contents().find('html').trigger('keyup', {which: 27});

        //     expect(liveEditor.unselectElements).toHaveBeenCalled();
        // });

        it('tab click should call changeTab method', function() {
            spyOn(liveEditor, 'changeTab');
            $('.nav-tabs a[data-toggle="tab"]:last').click();
            expect(liveEditor.changeTab).toHaveBeenCalled();
        });

        it('tab click should call applyJs method', function() {
            spyOn(liveEditor, 'applyJs');
            $('.nav-tabs a[data-toggle="tab"]:last').click();
            expect(liveEditor.applyJs).toHaveBeenCalled();
        });

        it('tab click should call codePanelUpdate method', function() {
            spyOn(liveEditor, 'codePanelUpdate');
            $('.nav-tabs a[data-toggle="tab"]:last').click();
            expect(liveEditor.codePanelUpdate).toHaveBeenCalled();
        });
    });

    describe('setCurrentElement method', function() {
        beforeEach(function() {
            waits(100);
            liveEditor.$editorIframe.load();
        });

        it('set value to attributes', function() {
            var $p = liveEditor.$editorIframe.contents().find('p');

            expect(liveEditor.hasOwnProperty('currentSelected')).toBe(false);
            expect(liveEditor.hasOwnProperty('$currentSelected')).toBe(false);

            liveEditor.setCurrentElement($p);

            expect(liveEditor.currentSelected).toBe('html>body>div>p');
            expect(liveEditor.$currentSelected).toBe($p);
        });
    });

    describe('getElementPath method', function() {
        beforeEach(function() {
            waits(100);
            liveEditor.$editorIframe.load();
        });

        it('return correct path', function() {
            var $p = liveEditor.$editorIframe.contents().find('p'),
                path = liveEditor.getElementPath($p);

            expect(path).toBe('html>body>div>p');
        });
    });

    describe('dispatchLoadEvent method', function() {
        it('Should dispatch an event', function() {
            var counter = 0;

            document.addEventListener('LiveEditorLoaded', function (e) {
                counter ++;
            }, false);

            liveEditor.dispatchLoadEvent();

            expect(counter).toBe(1);
        });
    });

    describe('buildButtons method', function() {
        it('Should render undo button', function() {
            var $undoButton = $('.btn-undo');
            expect($undoButton).toExist();

            liveEditor.buildButtons();
            expect($('.btn-undo').length).toBe(2);
        });
    });

    describe('addToUndoList method', function() {
        it('Should append formated string inside undoList var', function() {
            liveEditor.addToUndoList('\nMy test\t with\t tabs\n and\t\n paragraphs');

            expect(liveEditor.experiments.test_1.undoList.length).toBe(1);
            expect(liveEditor.experiments.test_1.undoList[0]).toBe('My test with tabs and paragraphs');
        });
    });

    describe('addToScriptList method', function() {
        it('Should append formated string inside scriptList var', function() {
            liveEditor.addToScriptList('\nMy test\t with\t tabs\n and\t\n paragraphs');

            expect(liveEditor.experiments.test_1.scriptList.length).toBe(1);
            expect(liveEditor.experiments.test_1.scriptList[0]).toBe('My test with tabs and paragraphs');
        });
    });

    describe('codePanelUpdate method', function() {
        it('Should update aceEditor value with scriptList content', function() {
            liveEditor.experiments.test_1.scriptList.push('item 1');
            liveEditor.experiments.test_1.scriptList.push('item 2');
            liveEditor.experiments.test_1.scriptList.push('item 3');

            liveEditor.codePanelUpdate();

            var aceEditorValue = liveEditor.codePanel.aceEditor.aceEditor.getValue();

            expect(aceEditorValue).toBe('item 1 item 2 item 3')
        });
    });

    describe('operationInit method', function() {
        beforeEach(function() {
            waits(100);
        });

        it('always call codePanelUpdate method', function() {
            spyOn(liveEditor, 'codePanelUpdate');

            liveEditor.operationInit('fake');

            expect(liveEditor.codePanelUpdate).toHaveBeenCalled();
        });

        it('remove operation', function() {
            var $p = liveEditor.$editorIframe.contents().find('p');
            liveEditor.setCurrentElement($p);

            spyOn(liveEditor.actions, 'currentSelectedRemove');
            spyOn(liveEditor, 'unselectElements');

            liveEditor.operationInit('remove');

            expect(liveEditor.actions.currentSelectedRemove).toHaveBeenCalled();
            expect(liveEditor.unselectElements).toHaveBeenCalled();
        });

        it('add-event-click', function() {
            spyOn(liveEditor, 'unselectElements');
            spyOn(liveEditor.actions, 'currentSelectedAddEvent');

            liveEditor.operationInit('add-event-click');

            expect(liveEditor.unselectElements).toHaveBeenCalled();
            expect(liveEditor.actions.currentSelectedAddEvent).toHaveBeenCalledWith('click');
        });

        it('edit-html-save', function() {
            spyOn(liveEditor.actions, 'currentSelectedEditHtml');

            liveEditor.operationInit('edit-html-save');

            expect(liveEditor.actions.currentSelectedEditHtml).toHaveBeenCalled();
        });

        it('edit-text-save', function() {
            spyOn(liveEditor.actions, 'currentSelectedEditText');

            liveEditor.operationInit('edit-text-save');

            expect(liveEditor.actions.currentSelectedEditText).toHaveBeenCalled();
        });

        it('edit-classes-save', function() {
            spyOn(liveEditor.actions, 'currentSelectedEditClasses');

            liveEditor.operationInit('edit-classes-save');

            expect(liveEditor.actions.currentSelectedEditClasses).toHaveBeenCalled();
        });
    });

    describe('currentExperiment method', function() {
        it('Return correct value', function() {
            var c = liveEditor.currentExperiment();
            expect(c).toBe(liveEditor.experiments.test_1);
        });
    });

    describe('saveBody method', function() {
        beforeEach(function() {
            waits(100);
        });

        it('Should save jquery body', function() {
            expect(liveEditor.$iframeBody.prop('tagName')).toBe('BODY');
        });
    });

    describe('openCurrentMenu method', function() {
    });

    describe('unselectElements method', function() {
    });

    describe('modalEvents method', function() {
    });

    describe('getCurrentParentsPath method', function() {
    });
});
<commit_msg>currentMode method js test<commit_after>describe('LiveEditor', function() {
    beforeEach(function() {
        liveEditor = new LiveEditor({editor: '#live-editor-test-1', tabs: ['test 1', 'test 2'], url: 'site.html'});
        $liveEditor = $('.live-editor');
    });

    afterEach(function() {
        $liveEditor.empty();
        $('.btn-undo').remove();
        $('.modal').remove();
        $('#code-panel').remove();
        $('.code-panel-button').remove();
        $('ul.dropdown-menu[role]').remove();
    });

    describe('iframe onload', function() {
        beforeEach(function() {
            $iframe = $liveEditor.find('iframe');
            spyOn(liveEditor, 'domOutlineInit');
            spyOn(liveEditor, 'bindEvents');
            spyOn(liveEditor, 'saveBody');
            spyOn(liveEditor, 'updateBody');
            spyOn(liveEditor, 'codePanelUpdate');
            spyOn(liveEditor, 'dispatchLoadEvent');
            $iframe.load();
        });

        it('Should call domOutlineInit method', function() {
            expect(liveEditor.domOutlineInit).toHaveBeenCalled();
        });

        it('Should call bindEvents method', function() {
            expect(liveEditor.bindEvents).toHaveBeenCalled();
        });

        it('Should call saveBody method', function() {
            expect(liveEditor.saveBody).toHaveBeenCalled();
        });

        it('Should call updateBody method', function() {
            expect(liveEditor.updateBody).toHaveBeenCalled();
        });

        it('Should call codePanelUpdate method', function() {
            expect(liveEditor.codePanelUpdate).toHaveBeenCalled();
        });

        it('Should call dispatchLoadEvent method', function() {
            expect(liveEditor.dispatchLoadEvent).toHaveBeenCalled();
        });
    });

    describe('Build Tabs', function() {
        it('Should build tabs', function() {
            var $tabs = $liveEditor.find('.nav.nav-tabs');
            expect($tabs).toExist();
            expect($tabs.length).toBe(1);
        });
    });

    describe('Build Iframe', function() {
        it('Should build iframe', function() {
            var $iframe = $liveEditor.find('iframe');
            expect($iframe).toExist();
        });

        it('Should create a container element', function() {
            var $iframe = $liveEditor.find('iframe'),
                $container = $iframe.parent(),
                $spinner = $container.find('.spinner-container');
            expect($container).toHaveClass('live-editor-iframe-container');
            expect($spinner).toExist();
        });

        it('Initial Loading Spinner', function() {
            var $s = $('.spinner-container');

            expect($s.text()).toBe(' Loading...');
            expect($s.css('display')).toBe('inline');
        });

        it ('Loading Spinner disappears when iframe is fully loaded', function() {
            var $s = $('.spinner-container');

            liveEditor.$editorIframe.on('load', function() {
                expect($s.css('display')).toBe('none');
            });
        });
    });

    describe('Build Modals', function() {
        beforeEach(function() {
            waits(100);
            liveEditor.$editorIframe.load();
        });

        it('Should build Modals', function() {
            var $m1 = $('#edit-html-modal-live-editor-test-1'),
                $m2 = $('#edit-text-modal-live-editor-test-1'),
                $m3 = $('#edit-classes-modal-live-editor-test-1');

            expect($m1).toExist();
            expect($m2).toExist();
            expect($m3).toExist();
        });
    });

    describe('Build Panel', function() {
        beforeEach(function() {
            waits(100);
            liveEditor.$editorIframe.load();
        });

        it('Should build Panel', function() {
            var $p = $('#code-panel[live-editor-test-1]');
            expect($p).toExist();
        });
    });

    describe('Build DOM outline', function() {
        beforeEach(function() {
            waits(100);
            liveEditor.$editorIframe.load();
        });

        it('Should init DOM outline', function() {
            liveEditor.$editorIframe.on('load', function() {
                var $d = liveEditor.$editorIframe.contents().find('.DomOutline_box');
                expect($d).toExist();
                expect($d.css('display')).toBe('none');
            });
        });
    });

    describe('bindEvents method', function() {
        beforeEach(function() {
            waits(100);
            liveEditor.$editorIframe.load();
        });

        it('Click in any element should call setCurrentElement method', function() {
            var $p = liveEditor.$editorIframe.contents().find('p');

            spyOn(liveEditor, 'setCurrentElement');

            $p.trigger('mousemove').click();

            expect(liveEditor.setCurrentElement).toHaveBeenCalled();
        });

        it('Click in any element should call openCurrentMenu method', function() {
            var $p = liveEditor.$editorIframe.contents().find('p');

            spyOn(liveEditor, 'openCurrentMenu');

            $p.trigger('mousemove').click();

            expect(liveEditor.openCurrentMenu).toHaveBeenCalled();
        });

        it('Click in floating menu item should call operationInit method', function() {
            var $p = liveEditor.$editorIframe.contents().find('p');
            $p.trigger('mousemove').click();

            spyOn(liveEditor, 'operationInit');

            $('ul.dropdown-menu[role] li').click();

            expect(liveEditor.operationInit).toHaveBeenCalled();
        });

        it('When an element is already select and another one is clicked, should call unselectElements method', function() {
            var $p = liveEditor.$editorIframe.contents().find('p');
            $p.trigger('mousemove').click();

            spyOn(liveEditor, 'unselectElements');

            liveEditor.$editorIframe.contents().find('h1').trigger('mousemove').click();

            expect(liveEditor.unselectElements).toHaveBeenCalled();
        });

        it('Undo button click should call codePanelUpdate method if undoList is not empty', function() {
            liveEditor.experiments.test_1.scriptList.push('$("p").remove();');
            liveEditor.experiments.test_1.undoList.push('self.$editorIframe.contents().find("div").append("
Hello World
");');

            spyOn(liveEditor, 'codePanelUpdate');

            $('.btn-undo').click();

            expect(liveEditor.codePanelUpdate).toHaveBeenCalled();
        });

        it('Undo button click should not call codePanelUpdate method if undoList is empty', function() {
            spyOn(liveEditor, 'codePanelUpdate');

            $('.btn-undo').click();

            expect(liveEditor.codePanelUpdate).not.toHaveBeenCalled();
        });

        it('Undo button click should remove last item from undoList var', function() {
            liveEditor.experiments.test_1.undoList.push('self.$editorIframe.contents().find("div").append("
Hello World
");');
            liveEditor.experiments.test_1.undoList.push('self.$editorIframe.contents().find("div").append("
Hello World
");');

            expect(liveEditor.experiments.test_1.undoList.length).toBe(2);

            $('.btn-undo').click();

            expect(liveEditor.experiments.test_1.undoList.length).toBe(1);
        });

        it('Undo button click should remove last item from scriptList var', function() {
            liveEditor.experiments.test_1.undoList.push('self.$editorIframe.contents().find("div").append("
Hello World
");');
            liveEditor.experiments.test_1.scriptList.push('$("p").remove();');
            liveEditor.experiments.test_1.scriptList.push('$("p").remove();');

            expect(liveEditor.experiments.test_1.scriptList.length).toBe(2);

            $('.btn-undo').click();

            expect(liveEditor.experiments.test_1.scriptList.length).toBe(1);
        });

        it('Undo button click should run last undoList script', function() {
            liveEditor.experiments.test_1.undoList.push('self.$editorIframe.contents().find("body div").append("Hello World");');

            $('.btn-undo').click();

            expect(liveEditor.$editorIframe.contents().find("small").length).toBe(1);
        });

        // it('When an element is already select and ESC keydown, should call unselectElements method', function() {
        //     var $p = liveEditor.$editorIframe.contents().find('p');
        //     $p.trigger('mousemove').click();

        //     spyOn(liveEditor, 'unselectElements');

        //     liveEditor.$editorIframe.contents().find('html').trigger('keyup', {which: 27});

        //     expect(liveEditor.unselectElements).toHaveBeenCalled();
        // });

        it('tab click should call changeTab method', function() {
            spyOn(liveEditor, 'changeTab');
            $('.nav-tabs a[data-toggle="tab"]:last').click();
            expect(liveEditor.changeTab).toHaveBeenCalled();
        });

        it('tab click should call applyJs method', function() {
            spyOn(liveEditor, 'applyJs');
            $('.nav-tabs a[data-toggle="tab"]:last').click();
            expect(liveEditor.applyJs).toHaveBeenCalled();
        });

        it('tab click should call codePanelUpdate method', function() {
            spyOn(liveEditor, 'codePanelUpdate');
            $('.nav-tabs a[data-toggle="tab"]:last').click();
            expect(liveEditor.codePanelUpdate).toHaveBeenCalled();
        });
    });

    describe('setCurrentElement method', function() {
        beforeEach(function() {
            waits(100);
            liveEditor.$editorIframe.load();
        });

        it('set value to attributes', function() {
            var $p = liveEditor.$editorIframe.contents().find('p');

            expect(liveEditor.hasOwnProperty('currentSelected')).toBe(false);
            expect(liveEditor.hasOwnProperty('$currentSelected')).toBe(false);

            liveEditor.setCurrentElement($p);

            expect(liveEditor.currentSelected).toBe('html>body>div>p');
            expect(liveEditor.$currentSelected).toBe($p);
        });
    });

    describe('getElementPath method', function() {
        beforeEach(function() {
            waits(100);
            liveEditor.$editorIframe.load();
        });

        it('return correct path', function() {
            var $p = liveEditor.$editorIframe.contents().find('p'),
                path = liveEditor.getElementPath($p);

            expect(path).toBe('html>body>div>p');
        });
    });

    describe('dispatchLoadEvent method', function() {
        it('Should dispatch an event', function() {
            var counter = 0;

            document.addEventListener('LiveEditorLoaded', function (e) {
                counter ++;
            }, false);

            liveEditor.dispatchLoadEvent();

            expect(counter).toBe(1);
        });
    });

    describe('buildButtons method', function() {
        it('Should render undo button', function() {
            var $undoButton = $('.btn-undo');
            expect($undoButton).toExist();

            liveEditor.buildButtons();
            expect($('.btn-undo').length).toBe(2);
        });
    });

    describe('addToUndoList method', function() {
        it('Should append formated string inside undoList var', function() {
            liveEditor.addToUndoList('\nMy test\t with\t tabs\n and\t\n paragraphs');

            expect(liveEditor.experiments.test_1.undoList.length).toBe(1);
            expect(liveEditor.experiments.test_1.undoList[0]).toBe('My test with tabs and paragraphs');
        });
    });

    describe('addToScriptList method', function() {
        it('Should append formated string inside scriptList var', function() {
            liveEditor.addToScriptList('\nMy test\t with\t tabs\n and\t\n paragraphs');

            expect(liveEditor.experiments.test_1.scriptList.length).toBe(1);
            expect(liveEditor.experiments.test_1.scriptList[0]).toBe('My test with tabs and paragraphs');
        });
    });

    describe('codePanelUpdate method', function() {
        it('Should update aceEditor value with scriptList content', function() {
            liveEditor.experiments.test_1.scriptList.push('item 1');
            liveEditor.experiments.test_1.scriptList.push('item 2');
            liveEditor.experiments.test_1.scriptList.push('item 3');

            liveEditor.codePanelUpdate();

            var aceEditorValue = liveEditor.codePanel.aceEditor.aceEditor.getValue();

            expect(aceEditorValue).toBe('item 1 item 2 item 3')
        });
    });

    describe('operationInit method', function() {
        beforeEach(function() {
            waits(100);
        });

        it('always call codePanelUpdate method', function() {
            spyOn(liveEditor, 'codePanelUpdate');

            liveEditor.operationInit('fake');

            expect(liveEditor.codePanelUpdate).toHaveBeenCalled();
        });

        it('remove operation', function() {
            var $p = liveEditor.$editorIframe.contents().find('p');
            liveEditor.setCurrentElement($p);

            spyOn(liveEditor.actions, 'currentSelectedRemove');
            spyOn(liveEditor, 'unselectElements');

            liveEditor.operationInit('remove');

            expect(liveEditor.actions.currentSelectedRemove).toHaveBeenCalled();
            expect(liveEditor.unselectElements).toHaveBeenCalled();
        });

        it('add-event-click', function() {
            spyOn(liveEditor, 'unselectElements');
            spyOn(liveEditor.actions, 'currentSelectedAddEvent');

            liveEditor.operationInit('add-event-click');

            expect(liveEditor.unselectElements).toHaveBeenCalled();
            expect(liveEditor.actions.currentSelectedAddEvent).toHaveBeenCalledWith('click');
        });

        it('edit-html-save', function() {
            spyOn(liveEditor.actions, 'currentSelectedEditHtml');

            liveEditor.operationInit('edit-html-save');

            expect(liveEditor.actions.currentSelectedEditHtml).toHaveBeenCalled();
        });

        it('edit-text-save', function() {
            spyOn(liveEditor.actions, 'currentSelectedEditText');

            liveEditor.operationInit('edit-text-save');

            expect(liveEditor.actions.currentSelectedEditText).toHaveBeenCalled();
        });

        it('edit-classes-save', function() {
            spyOn(liveEditor.actions, 'currentSelectedEditClasses');

            liveEditor.operationInit('edit-classes-save');

            expect(liveEditor.actions.currentSelectedEditClasses).toHaveBeenCalled();
        });
    });

    describe('currentExperiment method', function() {
        it('Return correct value', function() {
            var c = liveEditor.currentExperiment();
            expect(c).toBe(liveEditor.experiments.test_1);
        });
    });

    describe('saveBody method', function() {
        beforeEach(function() {
            waits(100);
        });

        it('Should save jquery body', function() {
            expect(liveEditor.$iframeBody.prop('tagName')).toBe('BODY');
        });
    });

    describe('currentMode method', function() {
        it('Should return default edition mode', function() {
            var v = liveEditor.$modeSelect.val();
            expect(v).toBe(liveEditor.currentMode());
            expect('edit').toBe(liveEditor.currentMode());
        });

        it('Should return new value after select change', function() {
            liveEditor.$modeSelect.val('view');
            var v = liveEditor.$modeSelect.val();
            expect(v).toBe(liveEditor.currentMode());
            expect('view').toBe(liveEditor.currentMode());
        })
    });

    describe('updateBody method', function() {
    });

    describe('openCurrentMenu method', function() {
    });

    describe('unselectElements method', function() {
    });

    describe('modalEvents method', function() {
    });

    describe('getCurrentParentsPath method', function() {
    });
});
<|endoftext|>


<commit_before>angular.module( 'API', [] )
	.factory( 'API', [ '$rootScope', '$location', '$route', '$routeParams',
		function($rootScope, $location, $route, $routeParams){
			var API = {};
			API.Helpers = { path: undefined, popup: undefined };
			API.Resources = { Session: undefined };
			API.Scope = $rootScope;

			API.REST = {
				query: function(resource, key, params, callback){
		    		API.Scope.loader = true;
		    		API.Scope[key] = false;
		    		var params = params || {id: $routeParams.id};
		            API.Resources[resource].query(params)
		            	.$promise.then(
			                function(data){
			                    console.log('API Query: '+JSON.stringify(data.objects || data));
			                    API.Scope.loader = false;
			                    API.Scope[key] = data.objects || data;
			                    if(callback) callback();
			                },
			                function(data){
			                    //TODO
			                    API.Scope.loader = false;
			                }
			            );
		        },

		        select: function(key, value){
		        	API.Scope[key] = value;
		        	return true;
		        },

		        create: function(resource, object, block, callback){
		        	console.log(object);
		        	API.Scope.loader = true;
		            API.Resources[resource].create(object)
		            	.$promise.then(
			                function(data){
			                    console.log('API Create: '+JSON.stringify(data));
			                    API.Scope.loader = false;
			                    API.Helpers.popup(block, true);
			                    $route.reload();
			                    if(callback) callback();
			                },
			                function(data){
			                    //TODO
			                    API.Scope.loader = false;
			                }
			            );
		        },

		        update: function(resource, object, block, callback){
		        	console.log(object);
		        	API.Scope.loader = true;
		            API.Resources[resource].update(object)
		            	.$promise.then(
			                function(data){
			                    console.log('API Update: '+JSON.stringify(data));
			                    API.Scope.loader = false;
			                    API.Helpers.popup(block, true);
			                    if(callback) callback();
			                },
			                function(data){
			                    //TODO
			                    API.Scope.loader = false;
			                }
			            );
		        },

		        remove: function(resource, key, block, element, callback){
		        	object = API.Scope[key];
		        	console.log(object);
		        	API.Scope.loader = true;
		        	API.Resources[resource].remove({id:object.id})
		            	.$promise.then(
			                function(data){
			                    console.log('API Remove: '+JSON.stringify(data));
			                    API.Scope.loader = false;
			                    API.Helpers.popup(block, true);
			                    $(element+object.id).remove();
			                    if(callback) callback();
			                },
			                function(data){
			                    //TODO
			                    API.Scope.loader = false;
			                }
			            );
		        }
		    };

		    API.Session = {
		    	check: function(){
					user = window.SessionUser || false;
					console.log('check session: ' + user);
					if(user){
						API.Scope.user = user;
						console.log("Logged In " + user.first_name);
						if($location.path() == '/'){
							$location.path(API.Helpers.path());
						}
					}
					else {
						console.log("Not Logged In");
						$location.path('/');
						return false;
					}
				},

				login: function(credentials, callback){
					console.log(credentials);
			    	API.Scope.loader = true;
					API.Resources.Session.create(credentials).$promise.then(
						function(data){
							console.log(data);
							API.Scope.loader = false;
							window.SessionUser = data;
							API.Scope.user = data;
							if(callback) callback();
							$location.path(API.Helpers.path());
						},
						function(){
							API.Scope.loader = false;
						}
					);
				},

				logout: function(callback){
			    	console.log(API.Scope.user.type);
			    	API.Scope.loader = true;
					API.Resources.Session.remove({id: API.Scope.user.type}).$promise.then(
						function(data){
							API.Scope.loader = false;
							API.Scope.user = undefined;
							if( window.SessionUser || false ){
								window.SessionUser = undefined;
							}
							if(callback) callback();
							$location.path('/');
						},
						function(){
							API.Scope.loader = false;
						}
					);
			    }

		    }

			return API;
		}]);
<commit_msg>updated angular api<commit_after>angular.module( 'API', [] )
	.factory( 'API', [ '$rootScope', '$location', '$route', '$routeParams',
		function($rootScope, $location, $route, $routeParams){
			var API = {};
			API.Helpers = { path: undefined, popup: undefined };
			API.Resources = { Session: undefined };
			API.Scope = $rootScope;

			API.REST = {
				query: function(resource, key, params, callback){
		    		API.Scope.loader = true;
		    		API.Scope[key] = false;
		    		var params = params || {id: $routeParams.id};
		            API.Resources[resource].query(params)
		            	.$promise.then(
			                function(data){
			                    console.log('API Query: '+JSON.stringify(data.objects || data));
			                    API.Scope.loader = false;
			                    API.Scope[key] = data.objects || data;
			                    if(callback) callback();
			                },
			                function(data){
			                    //TODO
			                    API.Scope.loader = false;
			                }
			            );
		        },

		        select: function(key, value){
		        	API.Scope[key] = value;
		        	return true;
		        },

		        create: function(resource, object, block, callback){
		        	console.log(object);
		        	API.Scope.loader = true;
		            API.Resources[resource].create(object)
		            	.$promise.then(
			                function(data){
			                    console.log('API Create: '+JSON.stringify(data));
			                    API.Scope.loader = false;
			                    API.Helpers.popup(block, true);
			                    $route.reload();
			                    if(callback) callback();
			                },
			                function(data){
			                    //TODO
			                    API.Scope.loader = false;
			                }
			            );
		        },

		        update: function(resource, object, block, callback){
		        	console.log(object);
		        	API.Scope.loader = true;
		            API.Resources[resource].update(object)
		            	.$promise.then(
			                function(data){
			                    console.log('API Update: '+JSON.stringify(data));
			                    API.Scope.loader = false;
			                    API.Helpers.popup(block, true);
			                    if(callback) callback();
			                },
			                function(data){
			                    //TODO
			                    API.Scope.loader = false;
			                }
			            );
		        },

		        remove: function(resource, key, block, element, callback){
		        	object = API.Scope[key];
		        	console.log(object);
		        	API.Scope.loader = true;
		        	API.Resources[resource].remove({id:object.id})
		            	.$promise.then(
			                function(data){
			                    console.log('API Remove: '+JSON.stringify(data));
			                    API.Scope.loader = false;
			                    API.Helpers.popup(block, true);
			                    $(element+object.id).remove();
			                    if(callback) callback();
			                },
			                function(data){
			                    //TODO
			                    API.Scope.loader = false;
			                }
			            );
		        }
		    };

		    API.Session = {
		    	check: function(){
					user = window.SessionUser || false;
					console.log('check session: ' + user);
					if(user){
						API.Scope.user = user;
						console.log("Logged In " + user.username);
						if($location.path() == '/'){
							$location.path(API.Helpers.path());
						}
					}
					else {
						console.log("Not Logged In");
						$location.path('/');
						return false;
					}
				},

				login: function(credentials, callback){
					console.log(credentials);
			    	API.Scope.loader = true;
					API.Resources.Session.create(credentials).$promise.then(
						function(data){
							console.log(data);
							API.Scope.loader = false;
							window.SessionUser = data;
							API.Scope.user = data;
							if(callback) callback();
							$location.path(API.Helpers.path());
						},
						function(){
							API.Scope.loader = false;
						}
					);
				},

				logout: function(callback){
			    	console.log(API.Scope.user.username);
			    	API.Scope.loader = true;
					API.Resources.Session.remove({id: API.Scope.user.username}).$promise.then(
						function(data){
							API.Scope.loader = false;
							API.Scope.user = undefined;
							if( window.SessionUser || false ){
								window.SessionUser = undefined;
							}
							if(callback) callback();
							$location.path('/');
						},
						function(){
							API.Scope.loader = false;
						}
					);
			    }

		    }

			return API;
		}]);
<|endoftext|>


<commit_before>var _ = require('underscore');
var iconv = new require('iconv').Iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE');
var crypto = require('crypto');
var Parent = require('mbtiles');

module.exports = MBTiles;
require('util').inherits(MBTiles, Parent);

function MBTiles(uri, callback) {
    return Parent.call(this, uri, function(err, source) {
        source.emit('open', err);
        callback(err, source);
    });
};

// Implements carmen#getFeature method.
MBTiles.prototype.getFeature = function(id, callback) {
    this._db.get('SELECT key_name AS id, key_json AS data FROM keymap WHERE key_name = ?', id, function(err, row) {
        if (err) return callback(err);
        try { return callback(null, JSON.parse(row.data)); }
        catch(err) { return callback(err); }
    });
};

// Implements carmen#putFeature method.
MBTiles.prototype.putFeature = function(id, data, callback) {
    this.write('keymap', id, {
        key_name: id,
        key_json: JSON.stringify(data)
    }, callback);
};

// Implements carmen#getCarmen method.
var defer = typeof setImmediate === 'undefined' ? process.nextTick : setImmediate;
MBTiles.prototype.getCarmen = function(type, shard, callback) {
    if (!this._carmen) this._carmen = { freq: {}, term: {}, grid: {} };

    var shards = this._carmen[type];
    if (shards[shard]) return defer(function() {
        callback(null, shards[shard]);
    });

    return this._db.get('SELECT data FROM carmen_' + type + ' WHERE shard = ?', shard, function(err, row) {
        if (err) return callback(err);
        shards[shard] = row ? JSON.parse(row.data) : {};
        callback(null, shards[shard]);
    });
};

// Implements carmen#putCarmen method.
MBTiles.prototype.putCarmen = function(type, shard, data, callback) {
    if (!this._carmen) this._carmen = { freq: {}, term: {}, grid: {} };

    var shards = this._carmen[type];

    this.write('carmen_' + type, shard, {
        shard: shard,
        data: JSON.stringify(data)
    }, function(err) {
        if (err) return callback(err);
        shards[shard] = data;
        callback(null);
    });
};

// Implements carmen#indexable method.
MBTiles.prototype.indexable = function(pointer, callback) {
    pointer = pointer || {};
    pointer.limit = pointer.limit || 10000;
    pointer.offset = pointer.offset || 0;
    pointer.nogrids = 'nogrids' in pointer ? pointer.nogrids : false;

    // If 'carmen' option is passed in initial pointer, retrieve indexables from
    // carmen table. This option can be used to access the previously indexed
    // documents from an MBTiles database without having to know what search
    // field was used in the past (see comment below).
    if (pointer.table === 'carmen') return this._db.all("SELECT c.id, c.text, c.zxy, k.key_json FROM carmen c JOIN keymap k ON c.id = k.key_name LIMIT ? OFFSET ?", pointer.limit, pointer.offset, function(err, rows) {
        if (err) return callback(err);
        var docs = rows.map(function(row) {
            var doc = {};
            doc.id = row.id;
            doc.doc = JSON.parse(row.key_json);
            doc.text = row.text;
            doc.zxy = row.zxy.split(',');
            return doc;
        });
        pointer.offset += pointer.limit;
        return callback(null, docs, pointer);
    }.bind(this));

    // By default the keymap table contains all indexable documents.
    this.getInfo(function(err, info) {
        if (err) return callback(err);
        if (pointer.nogrids) {
            var sql = "SELECT key_name, key_json FROM keymap LIMIT ? OFFSET ?;";
            var args = [pointer.limit, pointer.offset];
        } else {
            var sql = "SELECT k.key_name, k.key_json, GROUP_CONCAT(zoom_level||'/'||tile_column ||'/'||tile_row,',') AS zxy FROM keymap k JOIN grid_key g ON k.key_name = g.key_name JOIN map m ON g.grid_id = m.grid_id WHERE m.zoom_level=? GROUP BY k.key_name LIMIT ? OFFSET ?;"
            var args = [info.maxzoom, pointer.limit, pointer.offset];
        }
        this._db.all(sql, args, function(err, rows) {
            if (err) return callback(err);
            var docs = rows.map(function(row) {
                var doc = {};
                doc.id = row.key_name;
                doc.doc = JSON.parse(row.key_json);
                // @TODO the doc field name for searching probably (?) belongs
                // in `metadata` and should be un-hardcoded in the future.
                doc.text = doc.doc.search || '';
                if (row.zxy) doc.zxy = row.zxy.split(',');
                return doc;
            });
            pointer.offset += pointer.limit;
            return callback(null, docs, pointer);
        }.bind(this));
    }.bind(this));
};

// Adds carmen schema to startWriting.
MBTiles.prototype.startWriting = _(MBTiles.prototype.startWriting).wrap(function(parent, callback) {
    parent.call(this, function(err) {
        if (err) return callback(err);
        var sql = '\
        CREATE INDEX IF NOT EXISTS map_grid_id ON map (grid_id);\
        CREATE TABLE IF NOT EXISTS carmen_freq(shard INTEGER PRIMARY KEY, data BLOB);\
        CREATE TABLE IF NOT EXISTS carmen_term(shard INTEGER PRIMARY KEY, data BLOB);\
        CREATE TABLE IF NOT EXISTS carmen_grid(shard INTEGER PRIMARY KEY, data BLOB);';
        this._db.exec(sql, function(err) {
            if (err) {
                return callback(err);
            } else {
                return callback();
            }
        });
    }.bind(this));
});

<commit_msg>Broader searchfield handling.<commit_after>var _ = require('underscore');
var iconv = new require('iconv').Iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE');
var crypto = require('crypto');
var Parent = require('mbtiles');

module.exports = MBTiles;
require('util').inherits(MBTiles, Parent);

function MBTiles(uri, callback) {
    return Parent.call(this, uri, function(err, source) {
        source.emit('open', err);
        callback(err, source);
    });
};

// Implements carmen#getFeature method.
MBTiles.prototype.getFeature = function(id, callback) {
    this._db.get('SELECT key_name AS id, key_json AS data FROM keymap WHERE key_name = ?', id, function(err, row) {
        if (err) return callback(err);
        try { return callback(null, JSON.parse(row.data)); }
        catch(err) { return callback(err); }
    });
};

// Implements carmen#putFeature method.
MBTiles.prototype.putFeature = function(id, data, callback) {
    this.write('keymap', id, {
        key_name: id,
        key_json: JSON.stringify(data)
    }, callback);
};

// Implements carmen#getCarmen method.
var defer = typeof setImmediate === 'undefined' ? process.nextTick : setImmediate;
MBTiles.prototype.getCarmen = function(type, shard, callback) {
    if (!this._carmen) this._carmen = { freq: {}, term: {}, grid: {} };

    var shards = this._carmen[type];
    if (shards[shard]) return defer(function() {
        callback(null, shards[shard]);
    });

    return this._db.get('SELECT data FROM carmen_' + type + ' WHERE shard = ?', shard, function(err, row) {
        if (err) return callback(err);
        shards[shard] = row ? JSON.parse(row.data) : {};
        callback(null, shards[shard]);
    });
};

// Implements carmen#putCarmen method.
MBTiles.prototype.putCarmen = function(type, shard, data, callback) {
    if (!this._carmen) this._carmen = { freq: {}, term: {}, grid: {} };

    var shards = this._carmen[type];

    this.write('carmen_' + type, shard, {
        shard: shard,
        data: JSON.stringify(data)
    }, function(err) {
        if (err) return callback(err);
        shards[shard] = data;
        callback(null);
    });
};

// Implements carmen#indexable method.
MBTiles.prototype.indexable = function(pointer, callback) {
    pointer = pointer || {};
    pointer.limit = pointer.limit || 10000;
    pointer.offset = pointer.offset || 0;
    pointer.nogrids = 'nogrids' in pointer ? pointer.nogrids : false;

    // If 'carmen' option is passed in initial pointer, retrieve indexables from
    // carmen table. This option can be used to access the previously indexed
    // documents from an MBTiles database without having to know what search
    // field was used in the past (see comment below).
    if (pointer.table === 'carmen') return this._db.all("SELECT c.id, c.text, c.zxy, k.key_json FROM carmen c JOIN keymap k ON c.id = k.key_name LIMIT ? OFFSET ?", pointer.limit, pointer.offset, function(err, rows) {
        if (err) return callback(err);
        var docs = rows.map(function(row) {
            var doc = {};
            doc.id = row.id;
            doc.doc = JSON.parse(row.key_json);
            doc.text = row.text;
            doc.zxy = row.zxy.split(',');
            return doc;
        });
        pointer.offset += pointer.limit;
        return callback(null, docs, pointer);
    }.bind(this));

    // By default the keymap table contains all indexable documents.
    this.getInfo(function(err, info) {
        if (err) return callback(err);
        if (pointer.nogrids) {
            var sql = "SELECT key_name, key_json FROM keymap LIMIT ? OFFSET ?;";
            var args = [pointer.limit, pointer.offset];
        } else {
            var sql = "SELECT k.key_name, k.key_json, GROUP_CONCAT(zoom_level||'/'||tile_column ||'/'||tile_row,',') AS zxy FROM keymap k JOIN grid_key g ON k.key_name = g.key_name JOIN map m ON g.grid_id = m.grid_id WHERE m.zoom_level=? GROUP BY k.key_name LIMIT ? OFFSET ?;"
            var args = [info.maxzoom, pointer.limit, pointer.offset];
        }
        this._db.all(sql, args, function(err, rows) {
            if (err) return callback(err);
            var docs = rows.map(function(row) {
                var doc = {};
                doc.id = row.key_name;
                doc.doc = JSON.parse(row.key_json);
                // @TODO the doc field name for searching probably (?) belongs
                // in `metadata` and should be un-hardcoded in the future.
                doc.text = doc.doc.search || doc.doc.name || '';
                if (row.zxy) doc.zxy = row.zxy.split(',');
                return doc;
            });
            pointer.offset += pointer.limit;
            return callback(null, docs, pointer);
        }.bind(this));
    }.bind(this));
};

// Adds carmen schema to startWriting.
MBTiles.prototype.startWriting = _(MBTiles.prototype.startWriting).wrap(function(parent, callback) {
    parent.call(this, function(err) {
        if (err) return callback(err);
        var sql = '\
        CREATE INDEX IF NOT EXISTS map_grid_id ON map (grid_id);\
        CREATE TABLE IF NOT EXISTS carmen_freq(shard INTEGER PRIMARY KEY, data BLOB);\
        CREATE TABLE IF NOT EXISTS carmen_term(shard INTEGER PRIMARY KEY, data BLOB);\
        CREATE TABLE IF NOT EXISTS carmen_grid(shard INTEGER PRIMARY KEY, data BLOB);';
        this._db.exec(sql, function(err) {
            if (err) {
                return callback(err);
            } else {
                return callback();
            }
        });
    }.bind(this));
});

<|endoftext|>


<commit_before>describe("Cosmos.Router", function() {

  var jsdom = require('jsdom');

  // jsdom creates a fresh new window object for every test case and React needs
  // to be required *after* the window and document globals are available. The
  // var references however must be declared globally in order to be accessible
  // in test cases as well.
  var React,
      utils,
      Cosmos,
      ComponentClass,
      componentElement,
      componentInstance,
      componentCallback;

  beforeEach(function() {
    global.window = jsdom.jsdom().createWindow('');
    global.document = global.window.document;
    global.navigator = global.window.navigator;

    React = require('react/addons');
    utils = React.addons.TestUtils;
    Cosmos = require('../build/cosmos.js');

    // Ignore native APIs
    spyOn(Cosmos.Router.prototype, '_bindPopStateEvent');
    spyOn(Cosmos.Router.prototype, '_replaceHistoryState');
    spyOn(Cosmos.Router.prototype, '_pushHistoryState');

    // The Cosmos.url lib is already tested in isolation
    spyOn(Cosmos.url, 'getParams').and.returnValue({
      component: 'List',
      dataUrl: 'users.json'
    });
    spyOn(Cosmos.url, 'isPushStateSupported').and.returnValue(true);

    // We just want a valid instance to work with, the Router props won't be
    // taken into consideration
    spyOn(Cosmos, 'render').and.callFake(function(props, container, callback) {
      componentCallback = callback;
      return componentInstance;
    });

    // Clean up previous component setups
    ComponentClass = null;
    componentElement = null;
    componentInstance = null;
  });

  it("should use props from URL query string", function() {
    var router = new Cosmos.Router();

    var propsSent = Cosmos.render.calls.mostRecent().args[0];
    expect(propsSent.component).toEqual('List');
    expect(propsSent.dataUrl).toEqual('users.json');
  });

  it("should extend default props", function() {
    var router = new Cosmos.Router({
      component: 'DefaultComponent',
      defaultProp: true
    });

    var propsSent = Cosmos.render.calls.mostRecent().args[0];
    expect(propsSent.component).toEqual('List');
    expect(propsSent.dataUrl).toEqual('users.json');
    expect(propsSent.defaultProp).toEqual(true);
  });

  it("should default to document.body as container", function() {
    var router = new Cosmos.Router();

    expect(Cosmos.render.calls.mostRecent().args[1]).toBe(document.body);
  });

  it("should attach router reference to component props on init", function() {
    var router = new Cosmos.Router();

    var propsSent = Cosmos.render.calls.mostRecent().args[0];
    expect(propsSent.router).toEqual(router);
  });

  it("should attach router reference to component on .goTo method", function() {
    var router = new Cosmos.Router();
    router.goTo('?component=List&dataUrl=users.json');

    var propsSent = Cosmos.render.calls.mostRecent().args[0];
    expect(propsSent.router).toEqual(router);
  });

  it("should attach router reference to component from PopState event", function() {
    var router = new Cosmos.Router();
    router.onPopState({
      state: {
        component: 'List',
        dataUrl: 'users.json'
      }
    });

    var propsSent = Cosmos.render.calls.mostRecent().args[0];
    expect(propsSent.router).toEqual(router);
  });

  it("should use props from .goTo method", function() {
    var router = new Cosmos.Router();
    router.goTo('?component=List&dataUrl=users.json');

    expect(Cosmos.render.calls.count()).toEqual(2);

    var propsSent = Cosmos.render.calls.mostRecent().args[0];
    expect(propsSent.component).toEqual('List');
    expect(propsSent.dataUrl).toEqual('users.json');
  });

  it("should extend default props when using .goTo method", function() {
    var router = new Cosmos.Router({
      component: 'DefaultComponent',
      defaultProp: true
    });
    router.goTo('?component=List&dataUrl=users.json');

    expect(Cosmos.render.calls.count()).toEqual(2);

    var propsSent = Cosmos.render.calls.mostRecent().args[0];
    expect(propsSent.component).toEqual('List');
    expect(propsSent.dataUrl).toEqual('users.json');
    expect(propsSent.defaultProp).toEqual(true);
  });

  it("should push component snapshot to state when using .goTo method",
     function() {
    ComponentClass = React.createClass({
      mixins: [Cosmos.mixins.PersistState],
      render: function() {
        return React.DOM.span();
      }
    });
    componentElement = React.createElement(ComponentClass, {
      component: 'List',
      dataUrl: 'users.json'
    });
    componentInstance = utils.renderIntoDocument(componentElement);

    // Simulate some state addition in the component
    spyOn(componentInstance, 'generateSnapshot').and.callFake(function() {
      return {
        component: 'List',
        dataUrl: 'users.json',
        state: {
          haveISeenThings: 'yes'
        }
      };
    });

    var router = new Cosmos.Router();
    router.goTo('?component=List&dataUrl=users.json');

    // Simulate React.render callback call
    componentCallback.call(componentInstance, 'testx');

    // The snapshot shouldn't been extracted from the component two times
    // 1. For previous component
    // 2. For just loaded component
    expect(componentInstance.generateSnapshot.calls.count()).toEqual(2);

    // It's a bit difficult to mock the native functions so we mocked the
    // private methods that wrap those calls
    expect(router._pushHistoryState.calls.count()).toEqual(1);
    expect(router._pushHistoryState.calls.mostRecent().args[0]).toEqual({
      component: 'List',
      dataUrl: 'users.json',
      state: {
        haveISeenThings: 'yes'
      }
    });
  });

  it("should use props from PopState event state", function() {
    var router = new Cosmos.Router();
    router.onPopState({
      state: {
        component: 'List',
        dataUrl: 'users.json'
      }
    });

    expect(Cosmos.render.calls.count()).toEqual(2);

    var propsSent = Cosmos.render.calls.mostRecent().args[0];
    expect(propsSent.component).toEqual('List');
    expect(propsSent.dataUrl).toEqual('users.json');
  });

  it("shouldn't extend default props when using PopState event", function() {
    var router = new Cosmos.Router({
      component: 'DefaultComponent',
      defaultProp: true
    });
    router.onPopState({
      state: {
        component: 'List',
        dataUrl: 'users.json'
      }
    });

    var propsSent = Cosmos.render.calls.mostRecent().args[0];
    expect(propsSent.component).toEqual('List');
    expect(propsSent.dataUrl).toEqual('users.json');
    expect(propsSent.defaultProp).toEqual(undefined);
  });

  it("should cache latest snapshot of previous Component", function() {
    /* Note: This is not a pure unit test, it depends on the internal logic
       of React components */
    ComponentClass = React.createClass({
      mixins: [Cosmos.mixins.PersistState],
      render: function() {
        return React.DOM.span();
      }
    });
    componentElement = React.createElement(ComponentClass, {
      component: 'List',
      dataUrl: 'users.json'
    });
    componentInstance = utils.renderIntoDocument(componentElement);

    var router = new Cosmos.Router();
    // We alter the current instance while it's bound to the current history
    // entry
    componentInstance.setProps({dataUrl: null, someNumber: 555});
    componentInstance.setState({amIState: true});

    // Before routing to a new Component configuration, the previous one
    // shouldn't been updated with our changes
    router.goTo('?component=User&dataUrl=user.json');

    // It's a bit difficult to mock the native functions so we mocked the
    // private methods that wrap those calls
    expect(router._replaceHistoryState.calls.count()).toEqual(1);
    expect(router._replaceHistoryState.calls.mostRecent().args[0]).toEqual({
      component: 'List',
      dataUrl: null,
      someNumber: 555,
      state: {
        amIState: true
      }
    });
  });
});
<commit_msg>Remove irrelevant asserts from tests #86<commit_after>describe("Cosmos.Router", function() {

  var jsdom = require('jsdom');

  // jsdom creates a fresh new window object for every test case and React needs
  // to be required *after* the window and document globals are available. The
  // var references however must be declared globally in order to be accessible
  // in test cases as well.
  var React,
      utils,
      Cosmos,
      ComponentClass,
      componentElement,
      componentInstance,
      componentCallback;

  beforeEach(function() {
    global.window = jsdom.jsdom().createWindow('');
    global.document = global.window.document;
    global.navigator = global.window.navigator;

    React = require('react/addons');
    utils = React.addons.TestUtils;
    Cosmos = require('../build/cosmos.js');

    // Ignore native APIs
    spyOn(Cosmos.Router.prototype, '_bindPopStateEvent');
    spyOn(Cosmos.Router.prototype, '_replaceHistoryState');
    spyOn(Cosmos.Router.prototype, '_pushHistoryState');

    // The Cosmos.url lib is already tested in isolation
    spyOn(Cosmos.url, 'getParams').and.returnValue({
      component: 'List',
      dataUrl: 'users.json'
    });
    spyOn(Cosmos.url, 'isPushStateSupported').and.returnValue(true);

    // We just want a valid instance to work with, the Router props won't be
    // taken into consideration
    spyOn(Cosmos, 'render').and.callFake(function(props, container, callback) {
      componentCallback = callback;
      return componentInstance;
    });

    // Clean up previous component setups
    ComponentClass = null;
    componentElement = null;
    componentInstance = null;
  });

  it("should use props from URL query string", function() {
    var router = new Cosmos.Router();

    var propsSent = Cosmos.render.calls.mostRecent().args[0];
    expect(propsSent.component).toEqual('List');
    expect(propsSent.dataUrl).toEqual('users.json');
  });

  it("should extend default props", function() {
    var router = new Cosmos.Router({
      component: 'DefaultComponent',
      defaultProp: true
    });

    var propsSent = Cosmos.render.calls.mostRecent().args[0];
    expect(propsSent.component).toEqual('List');
    expect(propsSent.dataUrl).toEqual('users.json');
    expect(propsSent.defaultProp).toEqual(true);
  });

  it("should default to document.body as container", function() {
    var router = new Cosmos.Router();

    expect(Cosmos.render.calls.mostRecent().args[1]).toBe(document.body);
  });

  it("should attach router reference to component props on init", function() {
    var router = new Cosmos.Router();

    var propsSent = Cosmos.render.calls.mostRecent().args[0];
    expect(propsSent.router).toEqual(router);
  });

  it("should attach router reference to component on .goTo method", function() {
    var router = new Cosmos.Router();
    router.goTo('?component=List&dataUrl=users.json');

    var propsSent = Cosmos.render.calls.mostRecent().args[0];
    expect(propsSent.router).toEqual(router);
  });

  it("should attach router reference to component from PopState event", function() {
    var router = new Cosmos.Router();
    router.onPopState({
      state: {
        component: 'List',
        dataUrl: 'users.json'
      }
    });

    var propsSent = Cosmos.render.calls.mostRecent().args[0];
    expect(propsSent.router).toEqual(router);
  });

  it("should use props from .goTo method", function() {
    var router = new Cosmos.Router();
    router.goTo('?component=List&dataUrl=users.json');

    var propsSent = Cosmos.render.calls.mostRecent().args[0];
    expect(propsSent.component).toEqual('List');
    expect(propsSent.dataUrl).toEqual('users.json');
  });

  it("should extend default props when using .goTo method", function() {
    var router = new Cosmos.Router({
      component: 'DefaultComponent',
      defaultProp: true
    });
    router.goTo('?component=List&dataUrl=users.json');

    var propsSent = Cosmos.render.calls.mostRecent().args[0];
    expect(propsSent.component).toEqual('List');
    expect(propsSent.dataUrl).toEqual('users.json');
    expect(propsSent.defaultProp).toEqual(true);
  });

  it("should push component snapshot to state when using .goTo method",
     function() {
    ComponentClass = React.createClass({
      mixins: [Cosmos.mixins.PersistState],
      render: function() {
        return React.DOM.span();
      }
    });
    componentElement = React.createElement(ComponentClass, {
      component: 'List',
      dataUrl: 'users.json'
    });
    componentInstance = utils.renderIntoDocument(componentElement);

    // Simulate some state addition in the component
    spyOn(componentInstance, 'generateSnapshot').and.callFake(function() {
      return {
        component: 'List',
        dataUrl: 'users.json',
        state: {
          haveISeenThings: 'yes'
        }
      };
    });

    var router = new Cosmos.Router();
    router.goTo('?component=List&dataUrl=users.json');

    // Simulate React.render callback call
    componentCallback.call(componentInstance, 'testx');

    // The snapshot should've been extracted from the component
    expect(componentInstance.generateSnapshot).toHaveBeenCalled();

    // It's a bit difficult to mock the native functions so we mocked the
    // private methods that wrap those calls
    expect(router._pushHistoryState.calls.mostRecent().args[0]).toEqual({
      component: 'List',
      dataUrl: 'users.json',
      state: {
        haveISeenThings: 'yes'
      }
    });
  });

  it("should use props from PopState event state", function() {
    var router = new Cosmos.Router();
    router.onPopState({
      state: {
        component: 'List',
        dataUrl: 'users.json'
      }
    });

    var propsSent = Cosmos.render.calls.mostRecent().args[0];
    expect(propsSent.component).toEqual('List');
    expect(propsSent.dataUrl).toEqual('users.json');
  });

  it("shouldn't extend default props when using PopState event", function() {
    var router = new Cosmos.Router({
      component: 'DefaultComponent',
      defaultProp: true
    });
    router.onPopState({
      state: {
        component: 'List',
        dataUrl: 'users.json'
      }
    });

    var propsSent = Cosmos.render.calls.mostRecent().args[0];
    expect(propsSent.component).toEqual('List');
    expect(propsSent.dataUrl).toEqual('users.json');
    expect(propsSent.defaultProp).toEqual(undefined);
  });

  it("should cache latest snapshot of previous Component", function() {
    /* Note: This is not a pure unit test, it depends on the internal logic
       of React components */
    ComponentClass = React.createClass({
      mixins: [Cosmos.mixins.PersistState],
      render: function() {
        return React.DOM.span();
      }
    });
    componentElement = React.createElement(ComponentClass, {
      component: 'List',
      dataUrl: 'users.json'
    });
    componentInstance = utils.renderIntoDocument(componentElement);

    var router = new Cosmos.Router();
    // We alter the current instance while it's bound to the current history
    // entry
    componentInstance.setProps({dataUrl: null, someNumber: 555});
    componentInstance.setState({amIState: true});

    // Before routing to a new Component configuration, the previous one
    // shouldn't been updated with our changes
    router.goTo('?component=User&dataUrl=user.json');

    // It's a bit difficult to mock the native functions so we mocked the
    // private methods that wrap those calls
    expect(router._replaceHistoryState.calls.mostRecent().args[0]).toEqual({
      component: 'List',
      dataUrl: null,
      someNumber: 555,
      state: {
        amIState: true
      }
    });
  });
});
<|endoftext|>


<commit_before>enyo.kind({
	name: "App",
	kind: enyo.VFlexBox,
	published: {
		filename: "test.md"
	},
	components: [
		{kind: "EditorPanel", flex: 1},
		{kind: "AppMenu", lazy: false, components: [
			{caption: "Documents", lazy: false, name:"docsMenu", components: [
				{caption: "Create New...", onclick: "sendNew"}
			]},
			{caption: "Share", components: [
				{caption: "Dropbox", onclick: "doDropbox"},
				{caption: "Email", onclick: "doEmail"},
				{caption: "Print", name:"print", onclick: "doPrint"}
			]},
			{caption: "Help", components: [
				{caption: "Syntax", onclick: "doSyntax"},
				{caption: "FAQ", onclick: "doFAQ"},
			]},
			]
		},
		{name: "markdownHelper", kind:"markdownHelper"},
		{name: "typewriterHelper", kind:"typewriterHelper"},
		{kind: "Scrim", name:"taboutscrim", layoutKind: "VFlexLayout", align:"center", pack:"center", style:"background-color: transparent; opacity: 1;", components: [
			{kind: "Image", src:"images/icon256.png", style: "opacity: 0.0;"}
		]},
		{kind: enyo.ApplicationEvents,
			onWindowDeactivated: "sleep",
			onWindowActivated: "wakeup",
			onUnload: "close"
		},
		{kind: "FileIO",
			onOpened: "handleOpened",
			onSaved: "handleSaved",
			onLogin: "handleLoginResult",
			onDirRead: "handleLoadFiles"
		},
		{name:"Demotext", kind:"Demotext" },
	],

	/* NEUE DATEI */

	sendNew: function(inSender, inResponse) {
		enyo.windows.openWindow("index.html", "", {wasLaunchedBy: window.name, action:"doNew"});
	},

	doNew: function() {
		this.$.fileIO.createNew();
	},

	/* DATEI ÖFFNEN */

	doLoadFiles: function(inSender, inEvent) {
		this.$.fileIO.listFiles();
	},

	handleLoadFiles: function(inSender, inResponse) {
		this.$.docsMenu.destroyControls();

		this.$.docsMenu.createComponent({
			caption: "Create New...",
			onclick: "sendNew",
			owner: this, // this part is important as the owner is the one who listens for the events
			kind: "AppMenuItem" // you might not need this. Might be that components are automatically turned into AppMenuItems
		});

		for(var i = 0; i < inResponse.length; i++) {
			this.$.docsMenu.createComponent({
				caption: inResponse[i].caption,
				onclick: "sendOpen",
				owner: this, // this part is important as the owner is the one who listens for the events
				kind: "AppMenuItem" // you might not need this. Might be that components are automatically turned into AppMenuItems
			});
		}
		this.$.docsMenu.render();
		this.$.appMenu.render();
	},

	sendOpen: function(inSender, inEvent) {
		enyo.windows.openWindow("index.html", "", {wasLaunchedBy: window.name, action:"doOpen", filename: inSender.caption + ".md"});
	},

	doOpen: function(inFilename) {
		this.$.fileIO.readFile(inFilename);
	},

	handleOpened: function(inSender, inResponse) {
		if(!inResponse.err) {
			this.$.editorPanel.setContent(inResponse.content, inResponse.filename);
			setInterval(enyo.hitch(this, "doSave"),5000);
		}
		else {
			this.$.editorPanel.setActive(false);
		}
	},

	/* SPEICHERN */

	doSave: function(inSender, inEvent) {
		this.$.fileIO.saveFile(this.$.editorPanel.getContent());
	},

	handleSaved: function(inSender, inResponse) {
	},

	/* SYNC */

	doDropbox: function(inSender, inEvent) {
		this.$.fileIO.syncFile();
	},

	/* LOGIN */

	rendered: function() {
		this.$.editorPanel.render();
		if(enyo.windowParams) {
			if(enyo.windowParams.action) {
				if(enyo.windowParams.action == "doOpen") {
					console.log("oeffne datei");
					this.doOpen(enyo.windowParams.filename);
				}
				if(enyo.windowParams.action == "doNew") {	// das muss irgendwie in rendered, ohne alles zu zerschmeissen
					console.log("neue datei");
					this.doNew();
				}
			}
			else {
				var lastfile = enyo.getCookie("lastfile") || "";
				if(lastfile == "") {
					this.$.editorPanel.setContent(this.$.Demotext.text, "");
					this.$.editorPanel.setActive(false);
				}
				else {
					this.doOpen(lastfile);
				}
			}
		}
		console.log(lastfile);
		//setInterval(enyo.hitch(this, "doSave"),5000);
		setInterval(enyo.hitch(this, "doLoadFiles"),15000);
		this.doLoadFiles();
	},

	/* BORING EVENTS */
	sleep: function() {
		//if(this.position == "down")
		//	this.$.top.node.style.height = enyo.fetchControlSize(this).h + "px";
		this.$.taboutscrim.show();
	},

	wakeup: function() {
		//this.$.top.node.style.height = (enyo.fetchControlSize(this).h - 55 - enyo.keyboard.height) + "px";
		this.$.taboutscrim.hide();
	},

	close: function() {
		this.$.fileIO.saveFile(this.$.editorPanel.getContent());
		enyo.setCookie("lastfile", this.$.fileIO.getFilename());
	},

	doPrint: function() {
		this.$.editorPanel.printDocument();
	},

	doHelp: function(inSender) {
		var r = new enyo.PalmService();
		r.service = "palm://com.palm.applicationManager/";
		r.method = "open";
		r.call({target: "http://www.typewriterwebos.com/markdown.html"});
	},

	doFAQ: function(inSender) {
		var r = new enyo.PalmService();
		r.service = "palm://com.palm.applicationManager/";
		r.method = "open";
		r.call({target: "http://www.typewriterwebos.com/faq.html"});
	}
})
<commit_msg>Share-Email-Knopf<commit_after>enyo.kind({
	name: "App",
	kind: enyo.VFlexBox,
	published: {
		filename: "test.md"
	},
	components: [
		{kind: "EditorPanel", flex: 1},
		{kind: "AppMenu", lazy: false, components: [
			{caption: "Documents", lazy: false, name:"docsMenu", components: [
				{caption: "Create New...", onclick: "sendNew"}
			]},
			{caption: "Share", components: [
				{caption: "Dropbox", onclick: "doDropbox"},
				{caption: "Email", onclick: "doEmail"},
				{caption: "Print", name:"print", onclick: "doPrint"}
			]},
			{caption: "Help", components: [
				{caption: "Syntax", onclick: "doSyntax"},
				{caption: "FAQ", onclick: "doFAQ"},
			]},
			]
		},
		{name: "markdownHelper", kind:"markdownHelper"},
		{name: "typewriterHelper", kind:"typewriterHelper"},
		{kind: "Scrim", name:"taboutscrim", layoutKind: "VFlexLayout", align:"center", pack:"center", style:"background-color: transparent; opacity: 1;", components: [
			{kind: "Image", src:"images/icon256.png", style: "opacity: 0.0;"}
		]},
		{kind: enyo.ApplicationEvents,
			onWindowDeactivated: "sleep",
			onWindowActivated: "wakeup",
			onUnload: "close"
		},
		{kind: "FileIO",
			onOpened: "handleOpened",
			onSaved: "handleSaved",
			onLogin: "handleLoginResult",
			onDirRead: "handleLoadFiles"
		},
		{name:"Demotext", kind:"Demotext" },
	],

	/* NEUE DATEI */

	sendNew: function(inSender, inResponse) {
		enyo.windows.openWindow("index.html", "", {wasLaunchedBy: window.name, action:"doNew"});
	},

	doNew: function() {
		this.$.fileIO.createNew();
	},

	/* DATEI ÖFFNEN */

	doLoadFiles: function(inSender, inEvent) {
		this.$.fileIO.listFiles();
	},

	handleLoadFiles: function(inSender, inResponse) {
		this.$.docsMenu.destroyControls();

		this.$.docsMenu.createComponent({
			caption: "Create New...",
			onclick: "sendNew",
			owner: this, // this part is important as the owner is the one who listens for the events
			kind: "AppMenuItem" // you might not need this. Might be that components are automatically turned into AppMenuItems
		});

		for(var i = 0; i < inResponse.length; i++) {
			this.$.docsMenu.createComponent({
				caption: inResponse[i].caption,
				onclick: "sendOpen",
				owner: this, // this part is important as the owner is the one who listens for the events
				kind: "AppMenuItem" // you might not need this. Might be that components are automatically turned into AppMenuItems
			});
		}
		this.$.docsMenu.render();
		this.$.appMenu.render();
	},

	sendOpen: function(inSender, inEvent) {
		enyo.windows.openWindow("index.html", "", {wasLaunchedBy: window.name, action:"doOpen", filename: inSender.caption + ".md"});
	},

	doOpen: function(inFilename) {
		this.$.fileIO.readFile(inFilename);
	},

	handleOpened: function(inSender, inResponse) {
		if(!inResponse.err) {
			this.$.editorPanel.setContent(inResponse.content, inResponse.filename);
			setInterval(enyo.hitch(this, "doSave"),5000);
		}
		else {
			this.$.editorPanel.setActive(false);
		}
	},

	/* SPEICHERN */

	doSave: function(inSender, inEvent) {
		this.$.fileIO.saveFile(this.$.editorPanel.getContent());
	},

	handleSaved: function(inSender, inResponse) {
	},

	/* SYNC */

	doDropbox: function(inSender, inEvent) {
		this.$.fileIO.syncFile();
	},

	/* LOGIN */

	rendered: function() {
		this.$.editorPanel.render();
		if(enyo.windowParams) {
			if(enyo.windowParams.action) {
				if(enyo.windowParams.action == "doOpen") {
					console.log("oeffne datei");
					this.doOpen(enyo.windowParams.filename);
				}
				if(enyo.windowParams.action == "doNew") {	// das muss irgendwie in rendered, ohne alles zu zerschmeissen
					console.log("neue datei");
					this.doNew();
				}
			}
			else {
				var lastfile = enyo.getCookie("lastfile") || "";
				if(lastfile == "") {
					this.$.editorPanel.setContent(this.$.Demotext.text, "");
					this.$.editorPanel.setActive(false);
				}
				else {
					this.doOpen(lastfile);
				}
			}
		}
		console.log(lastfile);
		//setInterval(enyo.hitch(this, "doSave"),5000);
		setInterval(enyo.hitch(this, "doLoadFiles"),15000);
		this.doLoadFiles();
	},

	/* BORING EVENTS */
	sleep: function() {
		//if(this.position == "down")
		//	this.$.top.node.style.height = enyo.fetchControlSize(this).h + "px";
		this.$.taboutscrim.show();
	},

	wakeup: function() {
		//this.$.top.node.style.height = (enyo.fetchControlSize(this).h - 55 - enyo.keyboard.height) + "px";
		this.$.taboutscrim.hide();
	},

	close: function() {
		this.$.fileIO.saveFile(this.$.editorPanel.getContent());
		enyo.setCookie("lastfile", this.$.fileIO.getFilename());
	},

	doPrint: function() {
		this.$.editorPanel.printDocument();
	},

	doEmail: function() {
		var r = new enyo.PalmService();
		r.service = "palm://com.palm.applicationManager/";
		r.method = "open";
		r.call({id: "com.palm.app.email",
			params: {
				text:"See attachment", summary: "Typewriter Document \"" + this.$.fileIO.getFilename().basename(".md") + "\"", attachments: [{fullPath: "file://media/internal/Typewriter/" + this.$.fileIO.getFilename()}]
			}
		});
	},

	doHelp: function(inSender) {
		var r = new enyo.PalmService();
		r.service = "palm://com.palm.applicationManager/";
		r.method = "open";
		r.call({target: "http://www.typewriterwebos.com/markdown.html"});
	},

	doFAQ: function(inSender) {
		var r = new enyo.PalmService();
		r.service = "palm://com.palm.applicationManager/";
		r.method = "open";
		r.call({target: "http://www.typewriterwebos.com/faq.html"});
	}
})
<|endoftext|>


<commit_before>class LinearScaleStrategy {
    constructor(redish, blueish, domain) {
        this.colorRedToBlueLinearScale = d3.scale.linear()
            .range([redish, blueish]);
        this.darkerRedToBlueLinearScale = this.colorRedToBlueLinearScale
            .copy()
            .range([redish.darker(), blueish.darker()]);

        this.colorRedToBlueLinearScale
            .domain(domain);
        this.darkerRedToBlueLinearScale
            .domain(domain);
    }

    getFill(d, parentColor) {
        return this.getColor(d, parentColor, this.colorRedToBlueLinearScale);
    }

    getStroke(d, parentColor) {
        return this.getColor(d, parentColor, this.darkerRedToBlueLinearScale);
    }
}

class AgeStrategy extends LinearScaleStrategy {
    constructor(redish, blueish) {
        super(redish, blueish, [0, 24]);
        this.maxAge = 24;
    }

    getColor(d, parentColor, scale) {
        if (d.children) {
            return parentColor;
        }

        var inverseAge = 0;
        if (d.data &&
            d.data['code-maat']) {

            var age = 'ageMonths' in d.data['code-maat']
                ? d.data['code-maat'].ageMonths
                : this.maxAge;
            console.log('Name: ' + d.name + ' age: ' + age);
            inverseAge = this.maxAge - (age);
        }
        return scale(inverseAge);
    }

}

class AuthorsStrategy extends LinearScaleStrategy {
    constructor(redish, blueish) {
        super(redish, blueish, [0, 20]);
    }

    getColor(d, parentColor, scale) {
        return d.children
            ? parentColor
            : scale(d.data['code-maat'] && d.data['code-maat'].nAuthors ? d.data['code-maat'].nAuthors : 0);
    }
}

class JsComplexityStrategy extends LinearScaleStrategy {
    constructor(redish, blueish) {
        super(redish, blueish, [0, 14]);
        this.maxComplexity = 14;
        this.nutralColor = d3.rgb('green');
    }

    getColor(d, parentColor, scale) {
        if (d.children) {
            return parentColor;
        }

        if (d.data.jscomplexity && 'cyclomatic' in d.data.jscomplexity) {
            return scale(this.maxComplexity - d.data.jscomplexity.cyclomatic);
        } else {
            return this.nutralColor;
        }
    }

    getStroke(d, parentColor) {
        if (d.children) {
            return parentColor;
        }
        if (d.data.jscomplexity && 'cyclomatic' in d.data.jscomplexity) {
            return this.getColor(d, parentColor, this.darkerRedToBlueLinearScale);
        } else {
            return this.nutralColor.darker();
        }
    }
}

class LanguageStrategy {
    constructor() {
        this.scale = d3.scale.category20();
        this.strokeColor = d3.rgb("black");
    }

    getFill(d, parentColor) {
        if (d.children) {
            return parentColor;
        }

        if (d.data && d.data.cloc && d.data.cloc.language) {
            return this.scale(d.data.cloc.language);
        }

        return this.scale(0);
    }

    getStroke(d, parentColor) {
        if (d.children) {
            return parentColor;
        }
        else {
           return this.strokeColor;
        }
    }
}

export default class TreeMap {
    constructor(maxTitleDepth = 4, minValueForTitle = 500) {
        this.w = 960;
        this.h = 700;
        this.paddingAllowance = 2;
        this.maxTitleDepth = maxTitleDepth;
        this.minValueForTitle = minValueForTitle;

        //this.color = d3.scale.category10();
        this.redish = d3.rgb("#E60D0D");
        this.blueish = d3.rgb("#0E34E0");
        this.parentStrokeColor = d3.rgb("#4E4545");
        this.parentFillColor = d3.rgb("#7D7E8C");

        this.colorRedToBlueLinearScale = d3.scale.linear()
            .range([this.redish, this.blueish]);
        this.darkerRedToBlueLinearScale = this.colorRedToBlueLinearScale
            .copy()
            .range([this.redish.darker(), this.blueish.darker()]);

        this.treemap = d3.layout.treemap()
            .size([this.w, this.h])
            .padding(d => {
                return this.showTitle()(d) ? [16,1,1,1] : 1
            })
            .value(d => d.data.cloc ? d.data.cloc.code : null);

        this.tooltip = d3
            .select("body")
            .append("div")
            .attr("class", "tooltip");

    }
    showTitle() { return (d) => {
        if (d.value < this.minValueForTitle) return 0;
        return d.children && d.depth <= this.maxTitleDepth;
    }}

    getStragegy(outputType) {
        switch (outputType) {
            case "age":
                return new AgeStrategy(this.redish, this.blueish);
            case 'authors':
                return new AuthorsStrategy(this.redish, this.blueish);
            case 'language':
                return new LanguageStrategy();
            case 'jscomplexity':
                return new JsComplexityStrategy(this.redish, this.blueish);
        }
    }

    mouseover() {
        return (d) => {
            console.log(this.tooltip);
            this.tooltip.transition()
                .duration(200);
            this.tooltip
                .style("opacity", 0.9);
            this.tooltip.html(this.formatTooltip(d))
                .style("left", (d3.event.pageX) + "px")
                .style("top", (d3.event.pageY) + "px");
        };
    }

    mouseout() {
        return (d) => {
            this.tooltip.transition()
                .duration(500)
                .style("opacity", 0);
        }
    }

    formatTooltip(d) {
            if (d.data) {
                return `${d.name}<pre>${JSON.stringify(d.data, null, 2)}</pre>`
            } else {
                //console.log(d);
                const {area, depth, value} = d;
                const data = {area, depth, value};
                return `${d.name}<pre>${JSON.stringify(data, null, 2)}</pre>`
            }
    }

    //outputType can be "age" or "authors"
    render(outputType) {
        var self = this;

        outputType = outputType || "age";

        var strategy = this.getStragegy(outputType);

        var svg = d3.select("body").append("svg")
            .style("position", "relative")
            .style("width", `${this.w}px`)
            .style("height", `${this.h}px`)
            .append("g")
            .attr("transform", "translate(-.5,-.5)");

        d3.json("/data/metrics.json", (json) => {
            var cell = svg.data([json]).selectAll("g")
                .data(self.treemap)
                .enter().append("g")
                .attr("class", "cell")
                .attr("transform", d => "translate(" + d.x + "," + d.y + ")");

            cell.on("mouseover", this.mouseover())
                .on("mouseout", this.mouseout());

            cell.append("rect")
                .attr("width", d => d.dx)
                .attr("height", d => d.dy)
                .style("fill", d => getCellFill(d))
                .style("stroke", d => getCellStroke(d))
                .style("z-index", d => -d.depth);

            cell.append("foreignObject")
                .attr("class", "foreignObject")
                .attr("width", d => Math.max(d.dx - self.paddingAllowance, 2))
                .attr("height", d => Math.max(d.dy - self.paddingAllowance, 2))
                .append("xhtml:body")
                .attr("class", "labelbody")
                .append("div")
                .attr("class", "label")
                .text(d => this.showTitle()(d) ? d.name : null)
                .attr("text-anchor", "middle");

            function getCellStroke(d) {
                return strategy.getStroke(d, self.parentStrokeColor, self.darkerRedToBlueLinearScale);
            }

            function getCellFill(d) {
                return strategy.getFill(d, self.parentFillColor, self.colorRedToBlueLinearScale);
            }
        });
    }
}

<commit_msg>refactoring to use es6 functions more and avoid 'this' shenanigans<commit_after>class LinearScaleStrategy {
    constructor(redish, blueish, domain) {
        this.colorRedToBlueLinearScale = d3.scale.linear()
            .range([redish, blueish]);
        this.darkerRedToBlueLinearScale = this.colorRedToBlueLinearScale
            .copy()
            .range([redish.darker(), blueish.darker()]);

        this.colorRedToBlueLinearScale
            .domain(domain);
        this.darkerRedToBlueLinearScale
            .domain(domain);
    }

    getFillFn(parentColor) {
        return (d) => this.getColor(d, parentColor, this.colorRedToBlueLinearScale);
    }

    getStrokeFn(parentColor) {
        return (d) => this.getColor(d, parentColor, this.darkerRedToBlueLinearScale);
    }
}

class AgeStrategy extends LinearScaleStrategy {
    constructor(redish, blueish) {
        super(redish, blueish, [0, 24]);
        this.maxAge = 24;
    }

    getColor(d, parentColor, scale) {
        if (d.children) {
            return parentColor;
        }

        var inverseAge = 0;
        if (d.data &&
            d.data['code-maat']) {

            var age = 'ageMonths' in d.data['code-maat']
                ? d.data['code-maat'].ageMonths
                : this.maxAge;
            console.log('Name: ' + d.name + ' age: ' + age);
            inverseAge = this.maxAge - (age);
        }
        return scale(inverseAge);
    }

}

class AuthorsStrategy extends LinearScaleStrategy {
    constructor(redish, blueish) {
        super(redish, blueish, [0, 20]);
    }

    getColor(d, parentColor, scale) {
        return d.children
            ? parentColor
            : scale(d.data['code-maat'] && d.data['code-maat'].nAuthors ? d.data['code-maat'].nAuthors : 0);
    }
}

class JsComplexityStrategy extends LinearScaleStrategy {
    constructor(redish, blueish) {
        super(redish, blueish, [0, 14]);
        this.maxComplexity = 14;
        this.nutralColor = d3.rgb('green');
    }

    getColor(d, parentColor, scale) {
        if (d.children) {
            return parentColor;
        }

        if (d.data.jscomplexity && 'cyclomatic' in d.data.jscomplexity) {
            return scale(this.maxComplexity - d.data.jscomplexity.cyclomatic);
        } else {
            return this.nutralColor;
        }
    }

    getStrokeFn(parentColor) {
        return (d) => {
            if (d.children) {
                return parentColor;
            }
            if (d.data.jscomplexity && 'cyclomatic' in d.data.jscomplexity) {
                return this.getColor(d, parentColor, this.darkerRedToBlueLinearScale);
            } else {
                return this.nutralColor.darker();
            }
        }
    }
}

class LanguageStrategy {
    constructor() {
        this.scale = d3.scale.category20();
        this.strokeColor = d3.rgb("black");
    }

    getFillFn(parentColor) {
        return (d) => {
            if (d.children) {
                return parentColor;
            }

            if (d.data && d.data.cloc && d.data.cloc.language) {
                return this.scale(d.data.cloc.language);
            }

            return this.scale(0);
        }
    }

    getStrokeFn(parentColor) {
        return (d) => {
            if (d.children) {
                return parentColor;
            }
            else {
                return this.strokeColor;
            }
        }
    }
}

export default class TreeMap {
    constructor(maxTitleDepth = 4, minValueForTitle = 500) {
        this.w = 960;
        this.h = 700;
        this.paddingAllowance = 2;
        this.maxTitleDepth = maxTitleDepth;
        this.minValueForTitle = minValueForTitle;

        //this.color = d3.scale.category10();
        this.redish = d3.rgb("#E60D0D");
        this.blueish = d3.rgb("#0E34E0");
        this.parentStrokeColor = d3.rgb("#4E4545");
        this.parentFillColor = d3.rgb("#7D7E8C");

        this.colorRedToBlueLinearScale = d3.scale.linear()
            .range([this.redish, this.blueish]);
        this.darkerRedToBlueLinearScale = this.colorRedToBlueLinearScale
            .copy()
            .range([this.redish.darker(), this.blueish.darker()]);

        this.treemap = d3.layout.treemap()
            .size([this.w, this.h])
            .padding(d => this.padding(d))
            .value(d => d.data.cloc ? d.data.cloc.code : null);

    }
    padding(d) {
        return this.showTitle(d) ? [16,1,1,1] : 1
    }

    showTitle(d) {
        if (d.value < this.minValueForTitle) return 0;
        return d.children && d.depth <= this.maxTitleDepth;
    }

    getStrategy(outputType) {
        switch (outputType) {
            case "age":
                return new AgeStrategy(this.redish, this.blueish);
            case 'authors':
                return new AuthorsStrategy(this.redish, this.blueish);
            case 'language':
                return new LanguageStrategy();
            case 'jscomplexity':
                return new JsComplexityStrategy(this.redish, this.blueish);
        }
    }

    mouseOver(d) {
            this.tooltip.transition()
                .duration(200);
            this.tooltip
                .style("opacity", 0.9);
            this.tooltip.html(this.formatTooltip(d))
                .style("left", (d3.event.pageX) + "px")
                .style("top", (d3.event.pageY) + "px");
    }

    mouseOut(d) {
            this.tooltip.transition()
                .duration(500)
                .style("opacity", 0);
    }

    formatTooltip(d) {
            if (d.data) {
                return `${d.name}<pre>${JSON.stringify(d.data, null, 2)}</pre>`
            } else {
                //console.log(d);
                const {area, depth, value} = d;
                const data = {area, depth, value};
                return `${d.name}<pre>${JSON.stringify(data, null, 2)}</pre>`
            }
    }

    //outputType can be "age" or "authors"
    render(outputType) {
        // TODO: render has all sorts of side effects - and there's no clean-up
        // needs thought on modularity, and the meaning of calling render multiple times.
        // the real goal would be to be able to render once, then use d3 magic to re-render
        //  with a different strategy, different root note, all the rest.

        outputType = outputType || "age";

        var strategy = this.getStrategy(outputType);

        this.tooltip = d3
            .select("body")
            .append("div")
            .attr("class", "tooltip");

        this.svg = d3.select("body").append("svg")
            .style("position", "relative")
            .style("width", `${this.w}px`)
            .style("height", `${this.h}px`)
            .append("g")
            .attr("transform", "translate(-.5,-.5)");

        d3.json("/data/metrics.json", (json) => {
            var cell = this.svg.data([json]).selectAll("g")
                .data(this.treemap)
                .enter().append("g")
                .attr("class", "cell")
                .attr("transform", d => "translate(" + d.x + "," + d.y + ")");

            cell.on("mouseover", d => this.mouseOver(d))
                .on("mouseout", d => this.mouseOut(d));

            cell.append("rect")
                .attr("width", d => d.dx)
                .attr("height", d => d.dy)
                .style("fill", strategy.getFillFn(this.parentFillColor, this.colorRedToBlueLinearScale))
                .style("stroke", strategy.getStrokeFn(this.parentStrokeColor, this.darkerRedToBlueLinearScale))
                .style("z-index", d => -d.depth);

            cell.append("foreignObject")
                .attr("class", "foreignObject")
                .attr("width", d => Math.max(d.dx - this.paddingAllowance, 2))
                .attr("height", d => Math.max(d.dy - this.paddingAllowance, 2))
                .append("xhtml:body")
                .attr("class", "labelbody")
                .append("div")
                .attr("class", "label")
                .text(d => this.showTitle(d) ? d.name : null)
                .attr("text-anchor", "middle");

        });
    }
}

<|endoftext|>


<commit_before>describe('App', () => {

  var clickerField = element(by.css('.text-input'));
  var clickerButton = element.all(by.className('button')).first();
  var removeButton = element(by.css('.button-outline-danger'));
  var clickerList = element(by.className('clickerList'));
  var message = element(by.className('message'));

  beforeEach(() => {
    browser.get('');
  });

  it('should have a title', () => {
    expect(browser.getTitle()).toEqual('Ionic');
  });

  it('should have <nav>', () => {
    expect(element(by.css('ion-navbar')).isPresent()).toEqual(true);
  });

  it('should have correct nav text for Home', () => {
    expect(element(by.css('ion-navbar:first-child')).getText()).toEqual('Clickers');
  });

  it('has a menu button that displays the left menu', () => {
    element(by.css('.bar-button-menutoggle')).click();
    expect(element(by.css('.toolbar-title')).getText()).toEqual('Menu');
  });

  it('the left menu has a link with title Clickers', () => {
    element(by.css('.bar-button-menutoggle')).click();
    expect(element.all(by.css('ion-label')).first().getText()).toEqual('Clickers');
  });

  it('should display Clickers when Clickers link is selected', () => {
    element(by.css('.bar-button-menutoggle')).click();
    element.all(by.css('ion-label')).first().click();
    clickerField.sendKeys('deal with protractor');
    clickerButton.click();
    expect(clickerList.getText()).toContain('deal with protractor');
  });

  it('the left menu has a link with title Goodbye Ionic', () => {
    element(by.css('.bar-button-menutoggle')).click();
    expect(element.all(by.css('ion-label')).last().getText()).toEqual('Goodbye Ionic');
  });

  it('should have correct text when Goodbye Ionic is selected', () => {
    element(by.css('.bar-button-menutoggle')).click();
    element.all(by.css('ion-label')).last().click();
    expect(message.getText()).toEqual('Bye!');
  });

  it('has an input box for new Clickers', () => {
    expect(element(by.css('.text-input')).isPresent()).toEqual(true);
  });

  it('should add a new Clicker to the page', () => {
    clickerField.sendKeys('deal with protractor');
    clickerButton.click();
    expect(clickerList.getText()).toContain('deal with protractor');
  });

  it('should delete a Clicker from the page when delete button selected', () => {
    clickerField.sendKeys('master angular');
    clickerButton.click();
    removeButton.click();
    expect(clickerList.getText()).not.toContain('master angular');
  });

});
<commit_msg>eliminated protractor warning on multiple elements found for locator clickerList<commit_after>describe('App', () => {

  var clickerField = element(by.css('.text-input'));
  var clickerButton = element.all(by.className('button')).first();
  var removeButton = element(by.css('.button-outline-danger'));
  var clickerList = element.all(by.className('clickerList')).first();
  var message = element(by.className('message'));

  beforeEach(() => {
    browser.get('');
  });

  it('should have a title', () => {
    expect(browser.getTitle()).toEqual('Ionic');
  });

  it('should have <nav>', () => {
    expect(element(by.css('ion-navbar')).isPresent()).toEqual(true);
  });

  it('should have correct nav text for Home', () => {
    expect(element(by.css('ion-navbar:first-child')).getText()).toEqual('Clickers');
  });

  it('has a menu button that displays the left menu', () => {
    element(by.css('.bar-button-menutoggle')).click();
    expect(element.all(by.css('.toolbar-title')).first().getText()).toEqual('Menu');
  });

  it('the left menu has a link with title Clickers', () => {
    element(by.css('.bar-button-menutoggle')).click();
    expect(element.all(by.css('ion-label')).first().getText()).toEqual('Clickers');
  });

  it('should display Clickers when Clickers link is selected', () => {
    element(by.css('.bar-button-menutoggle')).click();
    element.all(by.css('ion-label')).first().click();
    clickerField.sendKeys('deal with protractor');
    clickerButton.click();
    expect(clickerList.getText()).toContain('deal with protractor');
  });

  it('the left menu has a link with title Goodbye Ionic', () => {
    element(by.css('.bar-button-menutoggle')).click();
    expect(element.all(by.css('ion-label')).last().getText()).toEqual('Goodbye Ionic');
  });

  it('should have correct text when Goodbye Ionic is selected', () => {
    element(by.css('.bar-button-menutoggle')).click();
    element.all(by.css('ion-label')).last().click();
    expect(message.getText()).toEqual('Bye!');
  });

  it('has an input box for new Clickers', () => {
    expect(element(by.css('.text-input')).isPresent()).toEqual(true);
  });

  it('should add a new Clicker to the page', () => {
    clickerField.sendKeys('deal with protractor');
    clickerButton.click();
    expect(clickerList.getText()).toContain('deal with protractor');
  });

  it('should delete a Clicker from the page when delete button selected', () => {
    clickerField.sendKeys('master angular');
    clickerButton.click();
    removeButton.click();
    expect(clickerList.getText()).not.toContain('master angular');
  });

});
<|endoftext|>