<commit_before>import { exec } from 'child_process';
import fs from 'fs';
import Packer from '../../src/util/packer';
import { list, read, write, mkdir, exist, copy } from '../../src/util/fs-promise';

describe('Base lib', () => {
    describe('Packer', () => {
        describe('class method # sort', () => {
            const rects = [{
                width: 30,
                height: 60
            }, {
                width: 40,
                height: 50
            }, {
                width: 100,
                height: 50
            }, {
                width: 120,
                height: 120
            }];
            it('should sort rects with maxSide', () => {
                const sorted = Packer.sort(rects, 'maxSide');
                expect(sorted).toEqual([{
                    width: 120,
                    height: 120
                }, {
                    width: 100,
                    height: 50
                }, {
                    width: 30,
                    height: 60
                }, {
                    width: 40,
                    height: 50
                }]);
            });
            it('should sort rects with area', () => {
                const sorted = Packer.sort(rects, 'area');
                expect(sorted).toEqual([{
                    width: 120,
                    height: 120
                }, {
                    width: 100,
                    height: 50
                }, {
                    width: 40,
                    height: 50
                }, {
                    width: 30,
                    height: 60
                }]);
            });
            it('should sort rects with width', () => {
                const sorted = Packer.sort(rects, 'width');
                expect(sorted).toEqual([{
                    width: 120,
                    height: 120
                }, {
                    width: 100,
                    height: 50
                }, {
                    width: 40,
                    height: 50
                }, {
                    width: 30,
                    height: 60
                }]);
            });
            it('should sort rects with height', () => {
                const sorted = Packer.sort(rects, 'height');
                expect(sorted).toEqual([{
                    width: 120,
                    height: 120
                }, {
                    width: 30,
                    height: 60
                }, {
                    width: 100,
                    height: 50
                }, {
                    width: 40,
                    height: 50
                }]);
            });
            it('should not sort rects if not set sort type', () => {
                const sorted = Packer.sort(rects);
                expect(sorted).toBe(rects);
            });
        });

        describe('class method # verticalPack/horizontalPack', () => {
            const rects = [{
                width: 30,
                height: 60
            }, {
                width: 40,
                height: 50
            }, {
                width: 100,
                height: 50
            }, {
                width: 120,
                height: 120
            }];
            it('should correctly pack rects (vertical)', () => {
                const pack = Packer.verticalPack(rects);
                expect(pack).toEqual({
                    width: 120,
                    height: 280
                });
                expect(rects).toEqual([{
                    width: 120,
                    height: 120,
                    pack: {
                        x: 0,
                        y: 0
                    }
                }, {
                    width: 100,
                    height: 50,
                    pack: {
                        x: 0,
                        y: 120
                    }
                }, {
                    width: 40,
                    height: 50,
                    pack: {
                        x: 0,
                        y: 170
                    }
                }, {
                    width: 30,
                    height: 60,
                    pack: {
                        x: 0,
                        y: 220
                    }
                }]);
            });

            it('should correctly pack rects (horizontal)', () => {
                const pack = Packer.horizontalPack(rects);
                expect(pack).toEqual({
                    width: 290,
                    height: 120
                });
                expect(rects).toEqual([{
                    width: 120,
                    height: 120,
                    pack: {
                        x: 0,
                        y: 0
                    }
                }, {
                    width: 30,
                    height: 60,
                    pack: {
                        x: 120,
                        y: 0
                    }
                }, {
                    width: 100,
                    height: 50,
                    pack: {
                        x: 150,
                        y: 0
                    }
                }, {
                    width: 40,
                    height: 50,
                    pack: {
                        x: 250,
                        y: 0
                    }
                }]);
            });
        });

        describe('instance method # pack', () => {
            it('should correctly pack rects', () => {
                const sorted = [{
                    width: 120,
                    height: 120
                }, {
                    width: 100,
                    height: 50
                }, {
                    width: 30,
                    height: 60
                }, {
                    width: 40,
                    height: 50
                }];
                const { right, down, ...root } = new Packer().pack(sorted);
                sorted.forEach(({ pack }) => {
                    delete pack.right;
                    delete pack.down;
                    delete pack.used;
                });
                expect(root).toEqual({
                    x: 0,
                    y: 0,
                    used: true,
                    width: 220,
                    height: 120
                });
                expect(sorted).toEqual([{
                    width: 120,
                    height: 120,
                    pack: {
                        x: 0,
                        y: 0,
                        width: 120,
                        height: 120
                    }
                }, {
                    width: 100,
                    height: 50,
                    pack: {
                        x: 120,
                        y: 0,
                        width: 100,
                        height: 120
                    }
                }, {
                    width: 30,
                    height: 60,
                    pack: {
                        x: 120,
                        y: 50,
                        width: 100,
                        height: 70
                    }
                }, {
                    width: 40,
                    height: 50,
                    pack: {
                        x: 150,
                        y: 50,
                        width: 70,
                        height: 60
                    }
                }]);
            });
        });
    });

    describe('fs-promise', () => {
        const rootDir = process.cwd() + '/src';
        const tmpDir = process.cwd() + '/.tmp';

        describe('list', () => {
            it('should list all files at pwd if not set rootDir', (done) => {
                list().then((files) => {
                    expect(files.length).toEqual(3);
                    done();
                }).catch((err) => done.fail(err));
            });
            it('should list all files successfully if set rootDir', (done) => {
                list(rootDir).then((files) => {
                    expect(files.length).toEqual(1);
                    expect(files[0]).toEqual(rootDir + '/index.js');
                    done();
                }).catch((err) => done.fail(err));
            });
            it('should list no files if rootDir not exists', (done) => {
                list(rootDir + '/utils').then((files) => {
                    expect(files.length).toEqual(0);
                    done();
                }).catch((err) => done.fail(err));
            });
            it('should list all files with complex pattern', (done) => {
                list(rootDir, ['*.js', 'util/*', '!util/fs-promise.js']).then((files) => {
                    expect(files.length).toEqual(4);
                    expect(files).toEqual(jasmine.arrayContaining([
                        rootDir + '/index.js',
                        rootDir + '/util/image.js',
                        rootDir + '/util/packer.js',
                        rootDir + '/util/style.js']));
                    done();
                }).catch((err) => done.fail(err));
            });
            it('should report error', (done) => {
                const original = fs.readdir;
                const error = new Error('mock fs.readdir error');
                fs.readdir = (path, cb) => {
                    process.nextTick(() => {
                        cb(error)
                    });
                };
                list(rootDir).then(() => {
                    fs.readdir = original;
                    done.fail('should not invoke');
                }).catch((err) => {
                    fs.readdir = original;
                    expect(err).toBe(error);
                    done();
                });
            });
        });

        describe('write', () => {
            beforeAll((done) => {
                exec('rm -rf .tmp', (err) => {
                    err ? done.fail(err) : done();
                });
            });
            afterAll((done) => {
                exec('rm -rf .tmp', (err) => {
                    err ? done.fail(err) : done();
                });
            });
            it('should fail to write file if dir not exists and set createDirIfNotExists to false', (done) => {
                write(tmpDir + '/hi.txt', 'hi', false).then(() => {
                    done.fail('should not write file');
                }).catch((err) => {
                    expect(err).toBeTruthy();
                    done();
                });
            });
            it('should write file successfully if dir not exists and set createDirIfNotExists to true', (done) => {
                write(tmpDir + '/hi.txt', 'hi', true).then((content) => {
                    expect(content).toBeUndefined();
                    done();
                }).catch((err) => {
                    done.fail(err);
                });
            });
        });

        describe('read', () => {
            const content = 'hi';
            const filepath = tmpDir + '/hi.txt';
            beforeAll((done) => {
                write(filepath, content, true).then((content) => {
                    done();
                }).catch((err) => {
                    done.fail(err);
                });
            });
            afterAll((done) => {
                exec('rm -rf .tmp', (err) => {
                    err ? done.fail(err) : done();
                });
            });
            it('should fail to read file if file not exists', (done) => {
                read(filepath + '.md').then(() => {
                    done.fail('should not read unexists file');
                }).catch((err) => {
                    expect(err).not.toBeNull();
                    done();
                });
            });
            it('should read file successfully', (done) => {
                read(filepath).then((content) => {
                    expect(content).toEqual(content);
                    done();
                }).catch((err) => {
                    done.fail(err);
                });
            });
        });

        describe('mkdir', () => {
            beforeAll((done) => {
                exec('rm -rf .tmp', (err) => {
                    err ? done.fail(err) : done();
                });
            });
            afterAll((done) => {
                exec('rm -rf .tmp', (err) => {
                    err ? done.fail(err) : done();
                });
            });
            it('should create dir successfully', (done) => {
                mkdir(tmpDir + '/deep').then(() => {
                    done();
                }).catch((err) => {
                    done.fail(err);
                });
            });
            it('should fail to create dir if permission denied', (done) => {
                mkdir('/etc/.tmp').then(() => {
                    done.fail('should not invoke');
                }).catch((err) => {
                    expect(err).toBeTruthy();
                    done();
                });
            });
        });
    });
});
<commit_msg>add semi<commit_after>import { exec } from 'child_process';
import fs from 'fs';
import Packer from '../../src/util/packer';
import { list, read, write, mkdir, exist, copy } from '../../src/util/fs-promise';

describe('Base lib', () => {
    describe('Packer', () => {
        describe('class method # sort', () => {
            const rects = [{
                width: 30,
                height: 60
            }, {
                width: 40,
                height: 50
            }, {
                width: 100,
                height: 50
            }, {
                width: 120,
                height: 120
            }];
            it('should sort rects with maxSide', () => {
                const sorted = Packer.sort(rects, 'maxSide');
                expect(sorted).toEqual([{
                    width: 120,
                    height: 120
                }, {
                    width: 100,
                    height: 50
                }, {
                    width: 30,
                    height: 60
                }, {
                    width: 40,
                    height: 50
                }]);
            });
            it('should sort rects with area', () => {
                const sorted = Packer.sort(rects, 'area');
                expect(sorted).toEqual([{
                    width: 120,
                    height: 120
                }, {
                    width: 100,
                    height: 50
                }, {
                    width: 40,
                    height: 50
                }, {
                    width: 30,
                    height: 60
                }]);
            });
            it('should sort rects with width', () => {
                const sorted = Packer.sort(rects, 'width');
                expect(sorted).toEqual([{
                    width: 120,
                    height: 120
                }, {
                    width: 100,
                    height: 50
                }, {
                    width: 40,
                    height: 50
                }, {
                    width: 30,
                    height: 60
                }]);
            });
            it('should sort rects with height', () => {
                const sorted = Packer.sort(rects, 'height');
                expect(sorted).toEqual([{
                    width: 120,
                    height: 120
                }, {
                    width: 30,
                    height: 60
                }, {
                    width: 100,
                    height: 50
                }, {
                    width: 40,
                    height: 50
                }]);
            });
            it('should not sort rects if not set sort type', () => {
                const sorted = Packer.sort(rects);
                expect(sorted).toBe(rects);
            });
        });

        describe('class method # verticalPack/horizontalPack', () => {
            const rects = [{
                width: 30,
                height: 60
            }, {
                width: 40,
                height: 50
            }, {
                width: 100,
                height: 50
            }, {
                width: 120,
                height: 120
            }];
            it('should correctly pack rects (vertical)', () => {
                const pack = Packer.verticalPack(rects);
                expect(pack).toEqual({
                    width: 120,
                    height: 280
                });
                expect(rects).toEqual([{
                    width: 120,
                    height: 120,
                    pack: {
                        x: 0,
                        y: 0
                    }
                }, {
                    width: 100,
                    height: 50,
                    pack: {
                        x: 0,
                        y: 120
                    }
                }, {
                    width: 40,
                    height: 50,
                    pack: {
                        x: 0,
                        y: 170
                    }
                }, {
                    width: 30,
                    height: 60,
                    pack: {
                        x: 0,
                        y: 220
                    }
                }]);
            });
            it('should not pack rects (vertical) if there is no valid rects', () => {
                const pack = Packer.verticalPack('hi');
                expect(pack).toBe(false);
            });

            it('should correctly pack rects (horizontal)', () => {
                const pack = Packer.horizontalPack(rects);
                expect(pack).toEqual({
                    width: 290,
                    height: 120
                });
                expect(rects).toEqual([{
                    width: 120,
                    height: 120,
                    pack: {
                        x: 0,
                        y: 0
                    }
                }, {
                    width: 30,
                    height: 60,
                    pack: {
                        x: 120,
                        y: 0
                    }
                }, {
                    width: 100,
                    height: 50,
                    pack: {
                        x: 150,
                        y: 0
                    }
                }, {
                    width: 40,
                    height: 50,
                    pack: {
                        x: 250,
                        y: 0
                    }
                }]);
            });
            it('should not pack rects (horizontal) if there is no valid rects', () => {
                const pack = Packer.horizontalPack('hi');
                expect(pack).toBe(false);
            });
        });

        describe('instance method # pack', () => {
            it('should correctly pack rects', () => {
                const sorted = [{
                    width: 120,
                    height: 120
                }, {
                    width: 100,
                    height: 50
                }, {
                    width: 30,
                    height: 60
                }, {
                    width: 40,
                    height: 50
                }];
                const { right, down, ...root } = new Packer().pack(sorted);
                sorted.forEach(({ pack }) => {
                    delete pack.right;
                    delete pack.down;
                    delete pack.used;
                });
                expect(root).toEqual({
                    x: 0,
                    y: 0,
                    used: true,
                    width: 220,
                    height: 120
                });
                expect(sorted).toEqual([{
                    width: 120,
                    height: 120,
                    pack: {
                        x: 0,
                        y: 0,
                        width: 120,
                        height: 120
                    }
                }, {
                    width: 100,
                    height: 50,
                    pack: {
                        x: 120,
                        y: 0,
                        width: 100,
                        height: 120
                    }
                }, {
                    width: 30,
                    height: 60,
                    pack: {
                        x: 120,
                        y: 50,
                        width: 100,
                        height: 70
                    }
                }, {
                    width: 40,
                    height: 50,
                    pack: {
                        x: 150,
                        y: 50,
                        width: 70,
                        height: 60
                    }
                }]);
            });
            it('should not pack rects if there is no valid rects', () => {
                const pack = new Packer().pack();
                expect(pack).toBe(false);
            });
        });
    });

    describe('fs-promise', () => {
        const rootDir = process.cwd() + '/src';
        const tmpDir = process.cwd() + '/.tmp';

        describe('list', () => {
            it('should list all files at pwd if not set rootDir', (done) => {
                list().then((files) => {
                    expect(files.length).toEqual(3);
                    done();
                }).catch((err) => done.fail(err));
            });
            it('should list all files successfully if set rootDir', (done) => {
                list(rootDir).then((files) => {
                    expect(files.length).toEqual(1);
                    expect(files[0]).toEqual(rootDir + '/index.js');
                    done();
                }).catch((err) => done.fail(err));
            });
            it('should list no files if rootDir not exists', (done) => {
                list(rootDir + '/utils').then((files) => {
                    expect(files.length).toEqual(0);
                    done();
                }).catch((err) => done.fail(err));
            });
            it('should list all files with complex pattern', (done) => {
                list(rootDir, ['*.js', 'util/*', '!util/fs-promise.js']).then((files) => {
                    expect(files.length).toEqual(4);
                    expect(files).toEqual(jasmine.arrayContaining([
                        rootDir + '/index.js',
                        rootDir + '/util/image.js',
                        rootDir + '/util/packer.js',
                        rootDir + '/util/style.js']));
                    done();
                }).catch((err) => done.fail(err));
            });
            it('should report error', (done) => {
                const original = fs.readdir;
                const error = new Error('mock fs.readdir error');
                fs.readdir = (path, cb) => {
                    process.nextTick(() => {
                        cb(error);
                    });
                };
                list(rootDir).then(() => {
                    fs.readdir = original;
                    done.fail('should not invoke');
                }).catch((err) => {
                    fs.readdir = original;
                    expect(err).toBe(error);
                    done();
                });
            });
        });

        describe('write', () => {
            beforeAll((done) => {
                exec('rm -rf .tmp', (err) => {
                    err ? done.fail(err) : done();
                });
            });
            afterAll((done) => {
                exec('rm -rf .tmp', (err) => {
                    err ? done.fail(err) : done();
                });
            });
            it('should fail to write file if dir not exists and set createDirIfNotExists to false', (done) => {
                write(tmpDir + '/hi.txt', 'hi', false).then(() => {
                    done.fail('should not write file');
                }).catch((err) => {
                    expect(err).toBeTruthy();
                    done();
                });
            });
            it('should write file successfully if dir not exists and set createDirIfNotExists to true', (done) => {
                write(tmpDir + '/hi.txt', 'hi', true).then((content) => {
                    expect(content).toBeUndefined();
                    done();
                }).catch((err) => {
                    done.fail(err);
                });
            });
        });

        describe('read', () => {
            const content = 'hi';
            const filepath = tmpDir + '/hi.txt';
            beforeAll((done) => {
                write(filepath, content, true).then((content) => {
                    done();
                }).catch((err) => {
                    done.fail(err);
                });
            });
            afterAll((done) => {
                exec('rm -rf .tmp', (err) => {
                    err ? done.fail(err) : done();
                });
            });
            it('should fail to read file if file not exists', (done) => {
                read(filepath + '.md').then(() => {
                    done.fail('should not read unexists file');
                }).catch((err) => {
                    expect(err).not.toBeNull();
                    done();
                });
            });
            it('should read file successfully', (done) => {
                read(filepath).then((content) => {
                    expect(content).toEqual(content);
                    done();
                }).catch((err) => {
                    done.fail(err);
                });
            });
        });

        describe('mkdir', () => {
            beforeAll((done) => {
                exec('rm -rf .tmp', (err) => {
                    err ? done.fail(err) : done();
                });
            });
            afterAll((done) => {
                exec('rm -rf .tmp', (err) => {
                    err ? done.fail(err) : done();
                });
            });
            it('should create dir successfully', (done) => {
                mkdir(tmpDir + '/deep').then(() => {
                    done();
                }).catch((err) => {
                    done.fail(err);
                });
            });
            it('should fail to create dir if permission denied', (done) => {
                mkdir('/etc/.tmp').then(() => {
                    done.fail('should not invoke');
                }).catch((err) => {
                    expect(err).toBeTruthy();
                    done();
                });
            });
        });
    });
});
<|endoftext|>


<commit_before>// ** I18N
Calendar._DN = new Array
("Zondag",
 "Maandag",
 "Dinsdag",
 "Woensdag",
 "Donderdag",
 "Vrijdag",
 "Zaterdag",
 "Zondag");

Calendar._SDN_len = 2;

Calendar._MN = new Array
("Januari",
 "Februari",
 "Maart",
 "April",
 "Mei",
 "Juni",
 "Juli",
 "Augustus",
 "September",
 "Oktober",
 "November",
 "December");

// tooltips
Calendar._TT = {};
Calendar._TT["INFO"] = "Info";

Calendar._TT["ABOUT"] =
"DHTML Datum/Tijd Selector\n" +
"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" +
"Ga voor de meest recente versie naar: http://www.dynarch.com/projects/calendar/\n" +
"Verspreid onder de GNU LGPL. Zie http://gnu.org/licenses/lgpl.html voor details." +
"\n\n" +
"Datum selectie:\n" +
"- Gebruik de \xab \xbb knoppen om een jaar te selecteren\n" +
"- Gebruik de " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " knoppen om een maand te selecteren\n" +
"- Houd de muis ingedrukt op de genoemde knoppen voor een snellere selectie.";
Calendar._TT["ABOUT_TIME"] = "\n\n" +
"Tijd selectie:\n" +
"- Klik op een willekeurig onderdeel van het tijd gedeelte om het te verhogen\n" +
"- of Shift-klik om het te verlagen\n" +
"- of klik en sleep voor een snellere selectie.";

//Calendar._TT["TOGGLE"] = "Selecteer de eerste week-dag";
Calendar._TT["PREV_YEAR"] = "Vorig jaar (ingedrukt voor menu)";
Calendar._TT["PREV_MONTH"] = "Vorige maand (ingedrukt voor menu)";
Calendar._TT["GO_TODAY"] = "Ga naar Vandaag";
Calendar._TT["NEXT_MONTH"] = "Volgende maand (ingedrukt voor menu)";
Calendar._TT["NEXT_YEAR"] = "Volgend jaar (ingedrukt voor menu)";
Calendar._TT["SEL_DATE"] = "Selecteer datum";
Calendar._TT["DRAG_TO_MOVE"] = "Klik en sleep om te verplaatsen";
Calendar._TT["PART_TODAY"] = " (vandaag)";
//Calendar._TT["MON_FIRST"] = "Toon Maandag eerst";
//Calendar._TT["SUN_FIRST"] = "Toon Zondag eerst";

Calendar._TT["DAY_FIRST"] = "Toon %s eerst";

Calendar._TT["WEEKEND"] = "0,6";

Calendar._TT["CLOSE"] = "Sluiten";
Calendar._TT["TODAY"] = "(vandaag)";
Calendar._TT["TIME_PART"] = "(Shift-)Klik of sleep om de waarde te veranderen";

// date formats
Calendar._TT["DEF_DATE_FORMAT"] = "%d-%m-%Y";
Calendar._TT["TT_DATE_FORMAT"] = "%a, %e %b %Y";

Calendar._TT["WK"] = "wk";
Calendar._TT["TIME"] = "Tijd:";<commit_msg>fix for nl<commit_after>// ** I18N
Calendar._DN = new Array
("Zondag",
 "Maandag",
 "Dinsdag",
 "Woensdag",
 "Donderdag",
 "Vrijdag",
 "Zaterdag",
 "Zondag");

Calendar._SDN_len = 2;

Calendar._SDN = new Array
("Zo",
 "Ma",
 "Di",
 "Wo",
 "Do",
 "Vr",
 "Za",
 "Zo");

 // First day of the week. "0" means display Sunday first, "1" means display
// Monday first, etc.
Calendar._FD = 0;

Calendar._MN = new Array
("Januari",
 "Februari",
 "Maart",
 "April",
 "Mei",
 "Juni",
 "Juli",
 "Augustus",
 "September",
 "Oktober",
 "November",
 "December");

 // short month names
Calendar._SMN = new Array
("Jan",
 "Feb",
 "Mrt",
 "Apr",
 "Mei",
 "Jun",
 "Jul",
 "Aug",
 "Sep",
 "Okt",
 "Nov",
 "Dec");

// tooltips
Calendar._TT = {};
Calendar._TT["INFO"] = "Over de kalender";

Calendar._TT["ABOUT"] =
"DHTML Datum/Tijd Selectie\n" +
"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" +
"Ga voor de meest recente versie naar: http://www.dynarch.com/projects/calendar/\n" +
"Verspreid onder de GNU LGPL. Zie http://gnu.org/licenses/lgpl.html voor details." +
"\n\n" +
"Datum selectie:\n" +
"- Gebruik de \xab \xbb knoppen om een jaar te selecteren\n" +
"- Gebruik de " + String.fromCharCode(0x2039) + ", " + String.fromCharCode(0x203a) + " knoppen om een maand te selecteren\n" +
"- Houd de muis ingedrukt op de genoemde knoppen voor een snellere selectie.";
Calendar._TT["ABOUT_TIME"] = "\n\n" +
"Tijd selectie:\n" +
"- Klik op een willekeurig onderdeel van het tijd gedeelte om het te verhogen\n" +
"- of Shift-klik om het te verlagen\n" +
"- of klik en sleep voor een snellere selectie.";

//Calendar._TT["TOGGLE"] = "Selecteer de eerste week-dag";
Calendar._TT["PREV_YEAR"] = "Vorig jaar (ingedrukt voor menu)";
Calendar._TT["PREV_MONTH"] = "Vorige maand (ingedrukt voor menu)";
Calendar._TT["GO_TODAY"] = "Ga naar Vandaag";
Calendar._TT["NEXT_MONTH"] = "Volgende maand (ingedrukt voor menu)";
Calendar._TT["NEXT_YEAR"] = "Volgend jaar (ingedrukt voor menu)";
Calendar._TT["SEL_DATE"] = "Selecteer datum";
Calendar._TT["DRAG_TO_MOVE"] = "Klik en sleep om te verplaatsen";
Calendar._TT["PART_TODAY"] = " (vandaag)";
//Calendar._TT["MON_FIRST"] = "Toon Maandag eerst";
//Calendar._TT["SUN_FIRST"] = "Toon Zondag eerst";

Calendar._TT["DAY_FIRST"] = "Toon %s eerst";

Calendar._TT["WEEKEND"] = "0,6";

Calendar._TT["CLOSE"] = "Sluiten";
Calendar._TT["TODAY"] = "(vandaag)";
Calendar._TT["TIME_PART"] = "(Shift-)Klik of sleep om de waarde te veranderen";

// date formats
Calendar._TT["DEF_DATE_FORMAT"] = "%d-%m-%Y";
Calendar._TT["TT_DATE_FORMAT"] = "%a, %e %b %Y";

Calendar._TT["WK"] = "wk";
Calendar._TT["TIME"] = "Tijd:";<|endoftext|>


<commit_before>describe('Upon creation, a Channel', function() {
  var channel, channelName, name = 'test',
  eventKeys, requestKeys, commandKeys, channelKeys,
  eventIntersect, requestIntersect, commandIntersect;

  beforeEach(function() {
    channel = new Backbone.Radio.Channel(name);
    channelName = channel._channelName;

    channelKeys = _.keys(channel);

    eventKeys = _.keys(Backbone.Events);
    requestKeys = _.keys(Backbone.Radio.Requests);
    commandKeys = _.keys(Backbone.Radio.Commands);

    eventIntersect = _.intersection(eventKeys, channelKeys);
    requestIntersect = _.intersection(requestKeys, channelKeys);
    commandIntersect = _.intersection(commandKeys, channelKeys);
  });

  it('should have its name set', function() {
    expect(channelName).to.equal(name);
  });

  it('should have all of the Backbone.Events methods', function() {
    expect(eventIntersect.length).to.equal(eventKeys.length);
  });

  it('should have all of the Radio.Commands methods', function() {
    expect(commandIntersect.length).to.equal(commandKeys.length);
  });

  it('should have all of the Radio.Requests methods', function() {
    expect(requestIntersect.length).to.equal(requestKeys.length);
  });
});

describe('Executing the `reset` method of a Channel', function() {

  var channel, returned,
  offStub, stopListeningStub,
  stopReactingStub, stopRespondingStub;

  beforeEach(function() {
    channel = new Backbone.Radio.Channel('test');
    offStub = sinon.stub(channel, 'off');
    stopListeningStub = sinon.stub(channel, 'stopListening');
    stopReactingStub  = sinon.stub(channel, 'stopReacting');
    stopRespondingStub  = sinon.stub(channel, 'stopResponding');

    returned = channel.reset();
  });

  afterEach(function() {
    offStub.restore();
    stopListeningStub.restore();
    stopReactingStub.restore();
    stopRespondingStub.restore();
    channel.reset();
  });

  it('should call the reset functions of Backbone.Events', function() {
    expect(offStub).to.have.been.calledOnce;
    expect(stopListeningStub).to.have.been.calledOnce;
  });

  it('should call the reset functions of Backbone.Radio.Commands', function() {
    expect(stopReactingStub).to.have.been.calledOnce;
  });

  it('should call the reset functions of Backbone.Radio.Requests', function() {
    expect(stopRespondingStub).to.have.been.calledOnce;
  });

  it('should return the Channel', function() {
    expect(returned).to.equal(channel);
  });
});

describe('When passing an event hash to `connectEvents`', function() {
  var channel, eventOne = 'one', eventTwo = 'two',
  cbOne, cbTwo, internalEvents, eventsHash;

  beforeEach(function() {
    cbOne = function() {};
    cbTwo = function() {};
    channel = Backbone.Radio.channel('test');

    eventsHash = {};
    eventsHash[eventTwo] = cbOne;
    eventsHash[eventOne] = cbTwo;

    channel.connectEvents(eventsHash);

    internalEvents = channel._events;
  });

  afterEach(function() {
    channel.reset();
  });

  it('should attach the listeners to the Channel', function() {
    expect(internalEvents).to.have.keys(eventTwo, eventOne);
  });
});

describe('When passing a commands hash to `connectCommands`', function() {
  var channel, commandOne = 'one', commandTwo = 'two',
  cbOne, cbTwo, internalCommands, commandsHash, returned;

  beforeEach(function() {
    cbOne = function() {};
    cbTwo = function() {};
    channel = Backbone.Radio.channel('test');

    commandsHash = {};
    commandsHash[commandTwo] = cbOne;
    commandsHash[commandOne] = cbTwo;

    channel.connectCommands(commandsHash);

    internalCommands = channel._commands;
  });

  afterEach(function() {
    channel.reset();
  });

  it('should attach the listeners to the Channel', function() {
    expect(internalCommands).to.have.keys(commandTwo, commandOne);
  });
});

describe('When passing a requests hash to `connectRequests`', function() {
  var channel, requestOne = 'one', requestTwo = 'two',
  cbOne, cbTwo, internalRequests, requestsHash, returned;

  beforeEach(function() {
    cbOne = function() {};
    cbTwo = function() {};
    channel = Backbone.Radio.channel('test');

    requestsHash = {};
    requestsHash[requestTwo] = cbOne;
    requestsHash[requestOne] = cbTwo;

    channel.connectRequests(requestsHash);

    internalRequests = channel._requests;
  });

  afterEach(function() {
    channel.reset();
  });

  it('should attach the listeners to the Channel', function() {
    expect(internalRequests).to.have.keys(requestTwo, requestOne);
  });
});
<commit_msg>Added test for calling channel w.o. a name<commit_after>describe('When calling Radio.channel with no name', function() {
  var channelStub;

  beforeEach(function() {
    channelStub = sinon.spy(Backbone.Radio, 'channel');
  });

  afterEach(function() {
    channelStub.restore();
  });

  it('should throw an error', function() {
    expect(channelStub).to.throw(Error, 'You must provide a name for the channel.');
  });
});

describe('Upon creation, a Channel', function() {
  var channel, channelName, name = 'test',
  eventKeys, requestKeys, commandKeys, channelKeys,
  eventIntersect, requestIntersect, commandIntersect;

  beforeEach(function() {
    channel = new Backbone.Radio.Channel(name);
    channelName = channel._channelName;

    channelKeys = _.keys(channel);

    eventKeys = _.keys(Backbone.Events);
    requestKeys = _.keys(Backbone.Radio.Requests);
    commandKeys = _.keys(Backbone.Radio.Commands);

    eventIntersect = _.intersection(eventKeys, channelKeys);
    requestIntersect = _.intersection(requestKeys, channelKeys);
    commandIntersect = _.intersection(commandKeys, channelKeys);
  });

  it('should have its name set', function() {
    expect(channelName).to.equal(name);
  });

  it('should have all of the Backbone.Events methods', function() {
    expect(eventIntersect.length).to.equal(eventKeys.length);
  });

  it('should have all of the Radio.Commands methods', function() {
    expect(commandIntersect.length).to.equal(commandKeys.length);
  });

  it('should have all of the Radio.Requests methods', function() {
    expect(requestIntersect.length).to.equal(requestKeys.length);
  });
});

describe('Executing the `reset` method of a Channel', function() {

  var channel, returned,
  offStub, stopListeningStub,
  stopReactingStub, stopRespondingStub;

  beforeEach(function() {
    channel = new Backbone.Radio.Channel('test');
    offStub = sinon.stub(channel, 'off');
    stopListeningStub = sinon.stub(channel, 'stopListening');
    stopReactingStub  = sinon.stub(channel, 'stopReacting');
    stopRespondingStub  = sinon.stub(channel, 'stopResponding');

    returned = channel.reset();
  });

  afterEach(function() {
    offStub.restore();
    stopListeningStub.restore();
    stopReactingStub.restore();
    stopRespondingStub.restore();
    channel.reset();
  });

  it('should call the reset functions of Backbone.Events', function() {
    expect(offStub).to.have.been.calledOnce;
    expect(stopListeningStub).to.have.been.calledOnce;
  });

  it('should call the reset functions of Backbone.Radio.Commands', function() {
    expect(stopReactingStub).to.have.been.calledOnce;
  });

  it('should call the reset functions of Backbone.Radio.Requests', function() {
    expect(stopRespondingStub).to.have.been.calledOnce;
  });

  it('should return the Channel', function() {
    expect(returned).to.equal(channel);
  });
});

describe('When passing an event hash to `connectEvents`', function() {
  var channel, eventOne = 'one', eventTwo = 'two',
  cbOne, cbTwo, internalEvents, eventsHash;

  beforeEach(function() {
    cbOne = function() {};
    cbTwo = function() {};
    channel = Backbone.Radio.channel('test');

    eventsHash = {};
    eventsHash[eventTwo] = cbOne;
    eventsHash[eventOne] = cbTwo;

    channel.connectEvents(eventsHash);

    internalEvents = channel._events;
  });

  afterEach(function() {
    channel.reset();
  });

  it('should attach the listeners to the Channel', function() {
    expect(internalEvents).to.have.keys(eventTwo, eventOne);
  });
});

describe('When passing a commands hash to `connectCommands`', function() {
  var channel, commandOne = 'one', commandTwo = 'two',
  cbOne, cbTwo, internalCommands, commandsHash, returned;

  beforeEach(function() {
    cbOne = function() {};
    cbTwo = function() {};
    channel = Backbone.Radio.channel('test');

    commandsHash = {};
    commandsHash[commandTwo] = cbOne;
    commandsHash[commandOne] = cbTwo;

    channel.connectCommands(commandsHash);

    internalCommands = channel._commands;
  });

  afterEach(function() {
    channel.reset();
  });

  it('should attach the listeners to the Channel', function() {
    expect(internalCommands).to.have.keys(commandTwo, commandOne);
  });
});

describe('When passing a requests hash to `connectRequests`', function() {
  var channel, requestOne = 'one', requestTwo = 'two',
  cbOne, cbTwo, internalRequests, requestsHash, returned;

  beforeEach(function() {
    cbOne = function() {};
    cbTwo = function() {};
    channel = Backbone.Radio.channel('test');

    requestsHash = {};
    requestsHash[requestTwo] = cbOne;
    requestsHash[requestOne] = cbTwo;

    channel.connectRequests(requestsHash);

    internalRequests = channel._requests;
  });

  afterEach(function() {
    channel.reset();
  });

  it('should attach the listeners to the Channel', function() {
    expect(internalRequests).to.have.keys(requestTwo, requestOne);
  });
});
<|endoftext|>


<commit_before>describe("iD.presets", function() {
    var p = {
        point: {
            tags: {},
            geometry: ['point']
        },
        line: {
            tags: {},
            geometry: ['line']
        },
        residential: {
            tags: {
                highway: 'residential'
            },
            geometry: ['line']
        },
        park: {
            tags: {
                leisure: 'park'
            },
            geometry: ['point', 'area']
        }
    };

    var c = iD.presets().load({presets: p});

    describe("#match", function() {
        it("returns a collection containing presets matching a geometry and tags", function() {
            var way = iD.Way({tags: { highway: 'residential'}}),
                graph = iD.Graph([way]);
            expect(c.match(way, graph).id).to.eql('residential');
        });

        it("returns the appropriate fallback preset when no tags match", function() {
            var point = iD.Node(),
                line = iD.Way({tags: {foo: 'bar'}}),
                graph = iD.Graph([point, line]);
            expect(c.match(point, graph).id).to.eql('point');
            expect(c.match(line, graph).id).to.eql('line');
        });
    });

    describe("#areaKeys", function() {
        var presets = iD.presets().load({
            presets: {
                'amenity/fuel/shell': {
                    tags: { 'amenity': 'fuel' },
                    geometry: ['point','area'],
                    suggestion: true
                },
                'golf/water_hazard': {
                    tags: { 'golf': 'water_hazard' },
                    geometry: ['line','area']
                },
                'highway/foo': {
                    tags: { 'highway': 'foo' },
                    geometry: ['area']
                },
                'natural': {
                    tags: { 'natural': '*' },
                    geometry: ['point', 'vertex', 'area']
                },
                'natural/peak': {
                    tags: { 'natural': 'peak' },
                    geometry: ['point', 'vertex']
                },
                'natural/tree_row': {
                    tags: { 'natural': 'tree_row' },
                    geometry: ['line']
                }
                'natural/wood': {
                    tags: { 'natural': 'wood' },
                    geometry: ['point', 'area']
                }
            }
        });

        it("whitelists keys for presets with area geometry", function() {
            expect(presets.areaKeys()).to.have.key('natural');
        });

        it("blacklists key-values for presets with a line geometry", function() {
            expect(presets.areaKeys().natural).to.have.key('tree_row');
            expect(presets.areaKeys().natural.tree_row).to.eq(true);
        });

        it("does not blacklist key-values for presets with both area and line geometry", function() {
            expect(presets.areaKeys().golf).not.to.have.key('water_hazard');
        });

        it("does not blacklist key-values for presets with neither area nor line geometry", function() {
            expect(presets.areaKeys().natural).not.to.have.key('peak');
        });

        it("does not blacklist generic '*' key-values", function() {
            expect(presets.areaKeys().natural).not.to.have.key('natural');
        });

        it("ignores keys like 'highway' that are assumed to be lines", function() {
            expect(presets.areaKeys()).not.to.have.key('highway');
        });

        it("ignores suggestion presets", function() {
            expect(presets.areaKeys()).not.to.have.key('amenity');
        });

    });

    describe("expected matches", function() {
        var presets;

        before(function() {
            presets = iD.presets().load(iD.data.presets);
        });

        it("prefers building to multipolygon", function() {
            var relation = iD.Relation({tags: {type: 'multipolygon', building: 'yes'}}),
                graph    = iD.Graph([relation]);
            expect(presets.match(relation, graph).id).to.eql('building');
        });

        it("prefers building to address", function() {
            var way   = iD.Way({tags: {area: 'yes', building: 'yes', 'addr:housenumber': '1234'}}),
                graph = iD.Graph([way]);
            expect(presets.match(way, graph).id).to.eql('building');
        });

        it("prefers pedestrian to area", function() {
            var way   = iD.Way({tags: {area: 'yes', highway: 'pedestrian'}}),
                graph = iD.Graph([way]);
            expect(presets.match(way, graph).id).to.eql('highway/pedestrian');
        });
    });
});
<commit_msg>Fix areaKeys tests - parse error, chai `include` keys<commit_after>describe("iD.presets", function() {
    var p = {
        point: {
            tags: {},
            geometry: ['point']
        },
        line: {
            tags: {},
            geometry: ['line']
        },
        residential: {
            tags: {
                highway: 'residential'
            },
            geometry: ['line']
        },
        park: {
            tags: {
                leisure: 'park'
            },
            geometry: ['point', 'area']
        }
    };

    var c = iD.presets().load({presets: p});

    describe("#match", function() {
        it("returns a collection containing presets matching a geometry and tags", function() {
            var way = iD.Way({tags: { highway: 'residential'}}),
                graph = iD.Graph([way]);
            expect(c.match(way, graph).id).to.eql('residential');
        });

        it("returns the appropriate fallback preset when no tags match", function() {
            var point = iD.Node(),
                line = iD.Way({tags: {foo: 'bar'}}),
                graph = iD.Graph([point, line]);
            expect(c.match(point, graph).id).to.eql('point');
            expect(c.match(line, graph).id).to.eql('line');
        });
    });

    describe("#areaKeys", function() {
        var presets = iD.presets().load({
            presets: {
                'amenity/fuel/shell': {
                    tags: { 'amenity': 'fuel' },
                    geometry: ['point','area'],
                    suggestion: true
                },
                'golf/water_hazard': {
                    tags: { 'golf': 'water_hazard' },
                    geometry: ['line', 'area']
                },
                'highway/foo': {
                    tags: { 'highway': 'foo' },
                    geometry: ['area']
                },
                'natural': {
                    tags: { 'natural': '*' },
                    geometry: ['point', 'vertex', 'area']
                },
                'natural/peak': {
                    tags: { 'natural': 'peak' },
                    geometry: ['point', 'vertex']
                },
                'natural/tree_row': {
                    tags: { 'natural': 'tree_row' },
                    geometry: ['line']
                },
                'natural/wood': {
                    tags: { 'natural': 'wood' },
                    geometry: ['point', 'area']
                }
            }
        });

        it("whitelists keys for presets with area geometry", function() {
            expect(presets.areaKeys()).to.include.keys('natural');
        });

        it("blacklists key-values for presets with a line geometry", function() {
            expect(presets.areaKeys().natural).to.include.keys('tree_row');
            expect(presets.areaKeys().natural.tree_row).to.be.true;
        });

        it("does not blacklist key-values for presets with both area and line geometry", function() {
            expect(presets.areaKeys().golf).not.to.include.keys('water_hazard');
        });

        it("does not blacklist key-values for presets with neither area nor line geometry", function() {
            expect(presets.areaKeys().natural).not.to.include.keys('peak');
        });

        it("does not blacklist generic '*' key-values", function() {
            expect(presets.areaKeys().natural).not.to.include.keys('natural');
        });

        it("ignores keys like 'highway' that are assumed to be lines", function() {
            expect(presets.areaKeys()).not.to.include.keys('highway');
        });

        it("ignores suggestion presets", function() {
            expect(presets.areaKeys()).not.to.include.keys('amenity');
        });

    });

    describe("expected matches", function() {
        var presets;

        before(function() {
            presets = iD.presets().load(iD.data.presets);
        });

        it("prefers building to multipolygon", function() {
            var relation = iD.Relation({tags: {type: 'multipolygon', building: 'yes'}}),
                graph    = iD.Graph([relation]);
            expect(presets.match(relation, graph).id).to.eql('building');
        });

        it("prefers building to address", function() {
            var way   = iD.Way({tags: {area: 'yes', building: 'yes', 'addr:housenumber': '1234'}}),
                graph = iD.Graph([way]);
            expect(presets.match(way, graph).id).to.eql('building');
        });

        it("prefers pedestrian to area", function() {
            var way   = iD.Way({tags: {area: 'yes', highway: 'pedestrian'}}),
                graph = iD.Graph([way]);
            expect(presets.match(way, graph).id).to.eql('highway/pedestrian');
        });
    });
});
<|endoftext|>


<commit_before>const expect = require('chai').expect;

let lib = '../../lib';

if (process.env.COVERAGE) {

    lib = '../../lib-cov';

}

const raspar = require(`${lib}/raspar`);

describe('raspar', () => {

    it('should make as basic request', (done) => {

        raspar.get('http://google.com/humans.txt').then((content) => {

            expect(content).to.not.have.property('cached');

            done();

        });

    });

    it('should make as basic request (cached)', (done) => {

        raspar.get('http://google.com/humans.txt', {
            'cacheDirectory': false
        }).then((content) => {

            // expect(content).to.have.property('cached');

            done();

        });

    });

    it('should make as basic request for an array of URLs', (done) => {

        raspar.get(['http://google.com/humans.txt']).then((contents) => {

            expect(contents).to.have.length(1);

            done();

        });

    });

    it('should error on invalid URL', (done) => {

        raspar.get('test').catch(() => {

            done();

        });

    });

});
<commit_msg>Changed test to point to locally cached files.<commit_after>const expect = require('chai').expect;

let lib = '../../lib';

if (process.env.COVERAGE) {

    lib = '../../lib-cov';

}

const raspar = require(`${lib}/raspar`);

describe('raspar', () => {

    it('should make as basic request', (done) => {

        raspar.get('http://google.com/humans.txt').then((content) => {

            expect(content).to.not.have.property('cached');

            done();

        });

    });

    it('should make as basic request (cached)', (done) => {

        raspar.get('http://google.com/humans.txt', {
            'cacheDirectory': 'temp/cache/'
        }).then((content) => {

            expect(content).to.have.property('cached');

            done();

        });

    });

    it('should make as basic request for an array of URLs', (done) => {

        raspar.get(['http://google.com/humans.txt']).then((contents) => {

            expect(contents).to.have.length(1);

            done();

        });

    });

    it('should error on invalid URL', (done) => {

        raspar.get('test').catch(() => {

            done();

        });

    });

});
<|endoftext|>


<commit_before>const jsonSchema = require('../utils/json-schema');
const config = require('../../../../../../shared/config');
const i18n = require('../../../../../../shared/i18n');
const errors = require('@tryghost/errors');
const {imageSize, blogIcon} = require('../../../../../lib/image');

const profileImage = (frame) => {
    return imageSize.getImageSizeFromPath(frame.file.path).then((response) => {
        // save the image dimensions in new property for file
        frame.file.dimensions = response;

        // CASE: file needs to be a square
        if (frame.file.dimensions.width !== frame.file.dimensions.height) {
            return Promise.reject(new errors.ValidationError({
                message: i18n.t('errors.api.images.isNotSquare')
            }));
        }
    });
};

const icon = (frame) => {
    const iconExtensions = (config.get('uploads').icons && config.get('uploads').icons.extensions) || [];

    const validIconFileSize = (size) => {
        return (size / 1024) <= 100;
    };

    // CASE: file should not be larger than 100kb
    if (!validIconFileSize(frame.file.size)) {
        return Promise.reject(new errors.ValidationError({
            message: i18n.t('errors.api.icons.invalidFile', {extensions: iconExtensions})
        }));
    }

    return blogIcon.getIconDimensions(frame.file.path).then((response) => {
        // save the image dimensions in new property for file
        frame.file.dimensions = response;

        // CASE: file needs to be a square
        if (frame.file.dimensions.width !== frame.file.dimensions.height) {
            return Promise.reject(new errors.ValidationError({
                message: i18n.t('errors.api.icons.invalidFile', {extensions: iconExtensions})
            }));
        }

        // CASE: icon needs to be bigger than or equal to 60px
        // .ico files can contain multiple sizes, we need at least a minimum of 60px (16px is ok, as long as 60px are present as well)
        if (frame.file.dimensions.width < 60) {
            return Promise.reject(new errors.ValidationError({
                message: i18n.t('errors.api.icons.invalidFile', {extensions: iconExtensions})
            }));
        }

        // CASE: icon needs to be smaller than or equal to 1000px
        if (frame.file.dimensions.width > 1000) {
            return Promise.reject(new errors.ValidationError({
                message: i18n.t('errors.api.icons.invalidFile', {extensions: iconExtensions})
            }));
        }
    });
};

module.exports = {
    upload(apiConfig, frame) {
        return Promise.resolve()
            .then(() => {
                return jsonSchema.validate(apiConfig, frame);
            })
            .then(() => {
                if (frame.data.purpose === 'profile_image') {
                    return profileImage(frame);
                }
            })
            .then(() => {
                if (frame.data.purpose === 'icon') {
                    return icon(frame);
                }
            });
    }
};
<commit_msg>Replaced i18n.t w/ tpl in core/server/api/v3/utils/validators/input/images.js (#13530)<commit_after>const jsonSchema = require('../utils/json-schema');
const config = require('../../../../../../shared/config');
const tpl = require('@tryghost/tpl');
const errors = require('@tryghost/errors');
const {imageSize, blogIcon} = require('../../../../../lib/image');

const messages = {
    isNotSquare: 'Please select a valid image file with square dimensions.',
    invalidFile: 'Icon must be a square .ico or .png file between 60px – 1,000px, under 100kb.'
};

const profileImage = (frame) => {
    return imageSize.getImageSizeFromPath(frame.file.path).then((response) => {
        // save the image dimensions in new property for file
        frame.file.dimensions = response;

        // CASE: file needs to be a square
        if (frame.file.dimensions.width !== frame.file.dimensions.height) {
            return Promise.reject(new errors.ValidationError({
                message: tpl(messages.isNotSquare)
            }));
        }
    });
};

const icon = (frame) => {
    const iconExtensions = (config.get('uploads').icons && config.get('uploads').icons.extensions) || [];

    const validIconFileSize = (size) => {
        return (size / 1024) <= 100;
    };

    // CASE: file should not be larger than 100kb
    if (!validIconFileSize(frame.file.size)) {
        return Promise.reject(new errors.ValidationError({
            message: tpl(messages.invalidFile, {extensions: iconExtensions})
        }));
    }

    return blogIcon.getIconDimensions(frame.file.path).then((response) => {
        // save the image dimensions in new property for file
        frame.file.dimensions = response;

        // CASE: file needs to be a square
        if (frame.file.dimensions.width !== frame.file.dimensions.height) {
            return Promise.reject(new errors.ValidationError({
                message: tpl(messages.invalidFile, {extensions: iconExtensions})
            }));
        }

        // CASE: icon needs to be bigger than or equal to 60px
        // .ico files can contain multiple sizes, we need at least a minimum of 60px (16px is ok, as long as 60px are present as well)
        if (frame.file.dimensions.width < 60) {
            return Promise.reject(new errors.ValidationError({
                message: tpl(messages.invalidFile, {extensions: iconExtensions})
            }));
        }

        // CASE: icon needs to be smaller than or equal to 1000px
        if (frame.file.dimensions.width > 1000) {
            return Promise.reject(new errors.ValidationError({
                message: tpl(messages.invalidFile, {extensions: iconExtensions})
            }));
        }
    });
};

module.exports = {
    upload(apiConfig, frame) {
        return Promise.resolve()
            .then(() => {
                return jsonSchema.validate(apiConfig, frame);
            })
            .then(() => {
                if (frame.data.purpose === 'profile_image') {
                    return profileImage(frame);
                }
            })
            .then(() => {
                if (frame.data.purpose === 'icon') {
                    return icon(frame);
                }
            });
    }
};<|endoftext|>


<commit_before>
import Firebase from 'firebase'
import * as Actions from './actions'

export default (url, config) => {
  return next => (reducer, initialState) => {

    const defaultConfig = {
      userProfile: null
    }

    const store = next(reducer, initialState)

    const {dispatch} = store

    const ref = new Firebase(url)

    const configs = Object.assign({}, defaultConfig, config)

    const firebase = {
      ref,
      _: {
        watchers: {},
        config: configs,
        authUid: null
      },
    }

    const set = (path, value, onComplete) => ref.child(path).set(value, onComplete)
    const push = (path, value, onComplete) => ref.child(path).push(value, onComplete)
    const remove = (path, onComplete) => ref.child(path).remove(onComplete)
    const login = credentials => Actions.login(dispatch, firebase, credentials)
    const logout = () => Actions.logout(dispatch, firebase)
    const createUser = (credentials, profile) => Actions.createUser(dispatch, firebase, credentials, profile)
    const resetPassword = (credentials) => Actions.resetPassword(dispatch, firebase, credentials)
    const changePassword = (credentials) => Actions.changePassword(dispatch, firebase, credentials)

    firebase.helpers = {
      set, push, remove,
      createUser,
      login, logout,
      resetPassword, changePassword
    }

    Actions.init(dispatch,  firebase)

    store.firebase = firebase

    return store

  }
}

<commit_msg>expose watchEvent and unWatchEvent<commit_after>
import Firebase from 'firebase'
import * as Actions from './actions'

export default (url, config) => {
  return next => (reducer, initialState) => {

    const defaultConfig = {
      userProfile: null
    }

    const store = next(reducer, initialState)

    const {dispatch} = store

    const ref = new Firebase(url)

    const configs = Object.assign({}, defaultConfig, config)

    const firebase = {
      ref,
      _: {
        watchers: {},
        config: configs,
        authUid: null
      },
    }

    const set = (path, value, onComplete) => ref.child(path).set(value, onComplete)
    const push = (path, value, onComplete) => ref.child(path).push(value, onComplete)
    const remove = (path, onComplete) => ref.child(path).remove(onComplete)
    const watchEvent = (eventName, eventPath) => Actions.watchEvent(firebase, dispatch, eventName, eventPath)
    const unWatchEvent = (eventName, eventPath) => Actions.unWatchEvent(firebase, dispatch, eventName, eventPath)
    const login = credentials => Actions.login(dispatch, firebase, credentials)
    const logout = () => Actions.logout(dispatch, firebase)
    const createUser = (credentials, profile) => Actions.createUser(dispatch, firebase, credentials, profile)
    const resetPassword = (credentials) => Actions.resetPassword(dispatch, firebase, credentials)
    const changePassword = (credentials) => Actions.changePassword(dispatch, firebase, credentials)

    firebase.helpers = {
      set, push, remove,
      createUser,
      login, logout,
      resetPassword, changePassword,
      watchEvent, unWatchEvent
    }

    Actions.init(dispatch,  firebase)

    store.firebase = firebase

    return store

  }
}

<|endoftext|>


<commit_before>import React, {Component, PropTypes} from 'react'
import {watchEvents, unWatchEvents} from './actions'
import { isEqual } from 'lodash'

const defaultEvent = {
    path: '',
    type: 'value',
    isListenOnlyOnDelta: false
}

const fixPath = (path) =>  ((path.substring(0,1) == '/') ? '': '/') + path

const ensureCallable = maybeFn =>
    typeof maybeFn === 'function' ? maybeFn : _ => maybeFn

const flatMap = arr => (arr && arr.length) ? arr.reduce((a, b) => a.concat(b)) : []

const createEvents = ({type, path, isListenOnlyOnDelta}) => {
    switch (type) {

        case 'value':
            return [{name: 'value', path}]

        case 'once':
            return [{name: 'once', path}]

        case 'all':
            return [
                //{name: 'first_child', path},
                {name: 'child_added', path, isListenOnlyOnDelta},
                {name: 'child_removed', path, isListenOnlyOnDelta},
                {name: 'child_moved', path, isListenOnlyOnDelta},
                {name: 'child_changed', path, isListenOnlyOnDelta}
            ]

        default:
            return []
    }
}

const transformEvent = event => Object.assign({}, defaultEvent, event)

const getEventsFromDefinition = def => flatMap(def.map(path => {
    if (typeof path === 'string' || path instanceof String) {
        return createEvents(transformEvent({ path }))
    }

    if (typeof path === 'array' || path instanceof Array) { // eslint-disable-line
        return createEvents(transformEvent({ type: 'all', path: path[0] }))
    }

    if (typeof path === 'object' || path instanceof Object) {
        const type = path.type || 'value'
        switch (type) {
            case 'value':
                return createEvents(transformEvent({ path: path.path }))

            case 'once':
                return createEvents(transformEvent({ type: 'once', path: path.path }))

            case 'array':
            case 'all':
                return createEvents(transformEvent({ type: 'all', path: path.path, isListenOnlyOnDelta:!!path.isListenOnlyOnDelta }))
        }
    }

    return []
}))

export default (dataOrFn = []) => WrappedComponent => {
    class FirebaseConnect extends Component {

        constructor (props, context) {
            super(props, context)
            this._firebaseEvents = []
            this._pathsToListen = undefined;
            this.firebase = null
        }

        static contextTypes = {
            store: PropTypes.object.isRequired
        };

        componentWillMount () {
            const {firebase, dispatch} = this.context.store

            const linkFn = ensureCallable(dataOrFn)
            this._pathsToListen = linkFn(this.props, firebase)

            const {ref, helpers, storage, database, auth} = firebase
            this.firebase = {ref, storage, database, auth, ...helpers}

            this._firebaseEvents = getEventsFromDefinition(this._pathsToListen)
            watchEvents(firebase, dispatch, this._firebaseEvents)
        }

        componentWillReceiveProps(nextProps) {
            const {firebase, dispatch} = this.context.store

            const linkFn = ensureCallable(dataOrFn)
            const newPathsToListen = linkFn(nextProps, firebase)

            if (!isEqual(newPathsToListen, this._pathsToListen)) {
                this._pathsToListen = newPathsToListen;

                unWatchEvents(firebase, dispatch, this._firebaseEvents, nextProps.isNeedToClean!=undefined ? nextProps.isNeedToClean : false);

                this._firebaseEvents = getEventsFromDefinition(this._pathsToListen)
                watchEvents(firebase, dispatch, this._firebaseEvents)
            }
        }

        componentWillUnmount () {
            const {firebase, dispatch} = this.context.store
            unWatchEvents(firebase, dispatch, this._firebaseEvents, true)
        }

        render () {
            return (
                <WrappedComponent
            {...this.props}
            {...this.state}
            firebase={this.firebase}
        />
        )
        }
    }
    return FirebaseConnect
}
<commit_msg>no message<commit_after>import React, {Component, PropTypes} from 'react'
import {watchEvents, unWatchEvents} from './actions'
import { isEqual } from 'lodash'

const defaultEvent = {
    path: '',
    type: 'value',
    isListenOnlyOnDelta: false
}

const fixPath = (path) =>  ((path.substring(0,1) == '/') ? '': '/') + path

const ensureCallable = maybeFn =>
    typeof maybeFn === 'function' ? maybeFn : _ => maybeFn

const flatMap = arr => (arr && arr.length) ? arr.reduce((a, b) => a.concat(b)) : []

const createEvents = ({type, path, isListenOnlyOnDelta}) => {
    switch (type) {

        case 'value':
            return [{name: 'value', path}]

        case 'once':
            return [{name: 'once', path}]

        case 'all':
            return [
                //{name: 'first_child', path},
                {name: 'child_added', path, isListenOnlyOnDelta},
                {name: 'child_removed', path, isListenOnlyOnDelta},
                {name: 'child_moved', path, isListenOnlyOnDelta},
                {name: 'child_changed', path, isListenOnlyOnDelta}
            ]

        default:
            return []
    }
}

const transformEvent = event => Object.assign({}, defaultEvent, event)

const getEventsFromDefinition = def => flatMap(def.map(path => {
    if (typeof path === 'string' || path instanceof String) {
        return createEvents(transformEvent({ path }))
    }

    if (typeof path === 'array' || path instanceof Array) { // eslint-disable-line
        return createEvents(transformEvent({ type: 'all', path: path[0] }))
    }

    if (typeof path === 'object' || path instanceof Object) {
        const type = path.type || 'value'
        switch (type) {
            case 'value':
                return createEvents(transformEvent({ path: path.path }))

            case 'once':
                return createEvents(transformEvent({ type: 'once', path: path.path }))

            case 'array':
            case 'all':
                return createEvents(transformEvent({ type: 'all', path: path.path, isListenOnlyOnDelta:!!path.isListenOnlyOnDelta }))
        }
    }

    return []
}))

export default (dataOrFn = []) => WrappedComponent => {
    class FirebaseConnect extends Component {

        constructor (props, context) {
            super(props, context)
            this._firebaseEvents = []
            this._pathsToListen = undefined;
            this.firebase = null
        }

        static contextTypes = {
            store: PropTypes.object.isRequired
        };

        componentWillMount () {
            const {firebase, dispatch} = this.context.store

            const linkFn = ensureCallable(dataOrFn)
            this._pathsToListen = linkFn(this.props, firebase)

            const {ref, helpers, storage, database, auth} = firebase
            this.firebase = {ref, storage, database, auth, ...helpers}

            this._firebaseEvents = getEventsFromDefinition(this._pathsToListen)
            watchEvents(firebase, dispatch, this._firebaseEvents)
        }

        componentWillReceiveProps(nextProps) {
            const {firebase, dispatch} = this.context.store

            const linkFn = ensureCallable(dataOrFn)
            const newPathsToListen = linkFn(nextProps, firebase)

            if (!isEqual(newPathsToListen, this._pathsToListen)) {
                this._pathsToListen = newPathsToListen;

                unWatchEvents(firebase, dispatch, this._firebaseEvents, false);

                this._firebaseEvents = getEventsFromDefinition(this._pathsToListen)
                watchEvents(firebase, dispatch, this._firebaseEvents)
            }
        }

        componentWillUnmount () {
            const {firebase, dispatch} = this.context.store
            unWatchEvents(firebase, dispatch, this._firebaseEvents, true)
        }

        render () {
            return (
                <WrappedComponent
            {...this.props}
            {...this.state}
            firebase={this.firebase}
        />
        )
        }
    }
    return FirebaseConnect
}
<|endoftext|>


<commit_before>import React from 'react'
import { connect } from 'react-redux'
import { List, ListItem } from 'material-ui/List'

class App extends React.PureComponent {
  render() {
    return (
      <List>
        {this.renderComicBooks()}
      </List>
    )
  }

  renderComicBooks() {
    return this.props.comicBooks.map(comicBook => (
      <ListItem
        key={comicBook.get('id')}
        primaryText={comicBook.get('id')}
      />
    ))
  }
}

const mapStateToProps = state => ({
  comicBooks: state.get('comicBooks'),
})

export default connect(mapStateToProps)(App)
<commit_msg>Add app bar<commit_after>import React from 'react'
import { connect } from 'react-redux'
import { List, ListItem } from 'material-ui/List'
import AppBar from 'material-ui/AppBar'

class App extends React.PureComponent {
  render() {
    return (
      <div>
        <AppBar />
        <List>
          {this.renderComicBooks()}
        </List>
      </div>
    )
  }

  renderComicBooks() {
    return this.props.comicBooks.map(comicBook => (
      <ListItem
        key={comicBook.get('id')}
        primaryText={comicBook.get('id')}
      />
    ))
  }
}

const mapStateToProps = state => ({
  comicBooks: state.get('comicBooks'),
})

export default connect(mapStateToProps)(App)
<|endoftext|>


<commit_before>var hotkeys = (function () {

var exports = {};

var directional_hotkeys = {
    40:  rows.next_visible,  // down arrow
    106: rows.next_visible,  // 'j'
    38:  rows.prev_visible,  // up arrow
    107: rows.prev_visible,  // 'k'
    36:  rows.first_visible, // Home
    35:  rows.last_visible   // End
};

var narrow_hotkeys = {
    115: narrow.by_recipient,           // 's'
    83:  narrow.by_subject,             // 'S'
    118: narrow.all_private_messages    // 'v'
};

// Process a keydown or keypress event.
//
// Returns true if we handled it, false if the browser should.
function process_hotkey(e) {
    var code = e.which;
    var next_message;

    // Disable hotkeys on settings page etc., and when a modal pop-up
    // is visible.
    if (ui.home_tab_obscured())
        return false;

    // Process hotkeys specially when in an input, textarea, or send button
    if ($('input:focus,textarea:focus,#compose-send-button:focus').length > 0) {
        if (code === 27) {
            // If one of our typeaheads is open, do nothing so that the Esc
            // will go to close it
            if ($("#subject").data().typeahead.shown ||
                $("#stream").data().typeahead.shown ||
                $("#private_message_recipient").data().typeahead.shown) {
                return false;
            } else {
                // If the user hit the escape key, cancel the current compose
                compose.cancel();
            }
        }
        // Keycode 13 is Return.
        if ((code === 13) && $("#search_query").is(":focus")) {
            // Pass it along to the search up button.
            $("#search_up").focus();
        }
        // Let the browser handle the key normally.
        return false;
    }

    if (directional_hotkeys.hasOwnProperty(code)) {
        next_message = directional_hotkeys[code](selected_message);
        if (next_message.length !== 0) {
            select_message(next_message, {then_scroll: true});
        }
        if ((next_message.length === 0) && (code === 40 || code === 106)) {
            // At the last message, scroll to the bottom so we have
            // lots of nice whitespace for new messages coming in.
            //
            // FIXME: this doesn't work for End because rows.last_visible()
            // always returns a message.
            viewport.scrollTop($("#main_div").outerHeight(true));
        }
        return true;
    }

    if (narrow_hotkeys.hasOwnProperty(code)) {
        narrow.target(selected_message_id);
        narrow_hotkeys[code]();
        return true;
    }

    // We're in the middle of a combo; stop processing because
    // we want the browser to handle it (to avoid breaking
    // things like Ctrl-C or Command-C for copy).
    if (e.metaKey || e.ctrlKey) {
        return false;
    }

    switch (code) {
    case 33: // Page Up
        if (at_top_of_viewport()) {
            select_message(rows.first_visible(), {then_scroll: false});
        }
        return false; // We want the browser to actually page up and down
    case 32: // Spacebar
    case 34: // Page Down
        if (at_bottom_of_viewport()) {
            select_message(rows.last_visible(), {then_scroll: false});
        }
        return false;
    case 27: // Esc: close userinfo popup, cancel compose, or un-narrow
        if (ui.userinfo_currently_popped()) {
            ui.hide_userinfo_popover();
        } else if (compose.composing()) {
            compose.cancel();
        } else {
            narrow.show_all_messages();
        }
        return true;
    case 99: // 'c': compose
        compose.start('stream');
        return true;
    case 67: // 'C': compose private message
        compose.start('private');
        return true;
    case  13: // Enter: respond to message (unless we need to do something else)
        if (search.keyboard_currently_finding()) {
            // Pass through to our searchbox (to advance to next result)
            return false;
        } else {
            respond_to_message();
            return true;
        }
    case 114: // 'r': respond to message
        respond_to_message();
        return true;
    case 82: // 'R': respond to author
        respond_to_message("personal");
        return true;
    case 47: // '/': initiate search
        search.initiate_search();
        return true;
    case 63: // '?': Show keyboard shortcuts page
        $('#keyboard-shortcuts').modal('show');
        return true;
    }

    return false;
}

/* We register both a keydown and a keypress function because
   we want to intercept pgup/pgdn, escape, etc, and process them
   as they happen on the keyboard. However, if we processed
   letters/numbers in keydown, we wouldn't know what the case of
   the letters were.

   We want case-sensitive hotkeys (such as in the case of r vs R)
   so we bail in .keydown if the event is a letter or number and
   instead just let keypress go for it. */

$(document).keydown(function (e) {
    // Restrict to non-alphanumeric keys
    if (48 > e.which || 90 < e.which) {
        if (process_hotkey(e))
            e.preventDefault();
    }
});

$(document).keypress(function (e) {
    // What exactly triggers .keypress may vary by browser.
    // Welcome to compatability hell.
    //
    // In particular, when you press tab in Firefox, it fires a
    // keypress event with keycode 0 after processing the original
    // event.
    if (e.which !== 0 && e.charCode !== 0) {
        if (process_hotkey(e))
            e.preventDefault();
    }
});

return exports;

}());
<commit_msg>Allow 'Esc' to clear a keyboard-driven Find.<commit_after>var hotkeys = (function () {

var exports = {};

var directional_hotkeys = {
    40:  rows.next_visible,  // down arrow
    106: rows.next_visible,  // 'j'
    38:  rows.prev_visible,  // up arrow
    107: rows.prev_visible,  // 'k'
    36:  rows.first_visible, // Home
    35:  rows.last_visible   // End
};

var narrow_hotkeys = {
    115: narrow.by_recipient,           // 's'
    83:  narrow.by_subject,             // 'S'
    118: narrow.all_private_messages    // 'v'
};

// Process a keydown or keypress event.
//
// Returns true if we handled it, false if the browser should.
function process_hotkey(e) {
    var code = e.which;
    var next_message;

    // Disable hotkeys on settings page etc., and when a modal pop-up
    // is visible.
    if (ui.home_tab_obscured())
        return false;

    // Process hotkeys specially when in an input, textarea, or send button
    if ($('input:focus,textarea:focus,#compose-send-button:focus').length > 0) {
        if (code === 27) {
            // If one of our typeaheads is open, do nothing so that the Esc
            // will go to close it
            if ($("#subject").data().typeahead.shown ||
                $("#stream").data().typeahead.shown ||
                $("#private_message_recipient").data().typeahead.shown) {
                return false;
            } else {
                // If the user hit the escape key, cancel the current compose
                compose.cancel();
            }
        }
        // Keycode 13 is Return.
        if ((code === 13) && $("#search_query").is(":focus")) {
            // Pass it along to the search up button.
            $("#search_up").focus();
        }
        // Let the browser handle the key normally.
        return false;
    }

    if (directional_hotkeys.hasOwnProperty(code)) {
        next_message = directional_hotkeys[code](selected_message);
        if (next_message.length !== 0) {
            select_message(next_message, {then_scroll: true});
        }
        if ((next_message.length === 0) && (code === 40 || code === 106)) {
            // At the last message, scroll to the bottom so we have
            // lots of nice whitespace for new messages coming in.
            //
            // FIXME: this doesn't work for End because rows.last_visible()
            // always returns a message.
            viewport.scrollTop($("#main_div").outerHeight(true));
        }
        return true;
    }

    if (narrow_hotkeys.hasOwnProperty(code)) {
        narrow.target(selected_message_id);
        narrow_hotkeys[code]();
        return true;
    }

    // We're in the middle of a combo; stop processing because
    // we want the browser to handle it (to avoid breaking
    // things like Ctrl-C or Command-C for copy).
    if (e.metaKey || e.ctrlKey) {
        return false;
    }

    switch (code) {
    case 33: // Page Up
        if (at_top_of_viewport()) {
            select_message(rows.first_visible(), {then_scroll: false});
        }
        return false; // We want the browser to actually page up and down
    case 32: // Spacebar
    case 34: // Page Down
        if (at_bottom_of_viewport()) {
            select_message(rows.last_visible(), {then_scroll: false});
        }
        return false;
    case 27: // Esc: close userinfo popup, cancel compose, clear a find, or un-narrow
        if (ui.userinfo_currently_popped()) {
            ui.hide_userinfo_popover();
        } else if (compose.composing()) {
            compose.cancel();
        } else if (search.keyboard_currently_finding()) {
            search.clear_search();
        } else {
            narrow.show_all_messages();
        }
        return true;
    case 99: // 'c': compose
        compose.start('stream');
        return true;
    case 67: // 'C': compose private message
        compose.start('private');
        return true;
    case  13: // Enter: respond to message (unless we need to do something else)
        if (search.keyboard_currently_finding()) {
            // Pass through to our searchbox (to advance to next result)
            return false;
        } else {
            respond_to_message();
            return true;
        }
    case 114: // 'r': respond to message
        respond_to_message();
        return true;
    case 82: // 'R': respond to author
        respond_to_message("personal");
        return true;
    case 47: // '/': initiate search
        search.initiate_search();
        return true;
    case 63: // '?': Show keyboard shortcuts page
        $('#keyboard-shortcuts').modal('show');
        return true;
    }

    return false;
}

/* We register both a keydown and a keypress function because
   we want to intercept pgup/pgdn, escape, etc, and process them
   as they happen on the keyboard. However, if we processed
   letters/numbers in keydown, we wouldn't know what the case of
   the letters were.

   We want case-sensitive hotkeys (such as in the case of r vs R)
   so we bail in .keydown if the event is a letter or number and
   instead just let keypress go for it. */

$(document).keydown(function (e) {
    // Restrict to non-alphanumeric keys
    if (48 > e.which || 90 < e.which) {
        if (process_hotkey(e))
            e.preventDefault();
    }
});

$(document).keypress(function (e) {
    // What exactly triggers .keypress may vary by browser.
    // Welcome to compatability hell.
    //
    // In particular, when you press tab in Firefox, it fires a
    // keypress event with keycode 0 after processing the original
    // event.
    if (e.which !== 0 && e.charCode !== 0) {
        if (process_hotkey(e))
            e.preventDefault();
    }
});

return exports;

}());
<|endoftext|>