text:
const assert = require('assert');
const crypto = require('crypto');
const fs = require('fs');

const fse = require('fs-extra');

const electricity = require('../lib/index');

describe('electricity.static', function() {
    it('should default to "public" if a directory isn't specified', function(done) {
        const middleware = electricity.static();

        const req = {
            method: 'GET',
            path: '/robots.txt'
        };

        const next = function() {
            done();
        };

        middleware(req, null, next);
    });

    it('should return a function', function() {
        const middleware = electricity.static('test/public');
        assert.strictEqual(typeof middleware, 'function');
    });

    it('should call next middleware when the specified file can not be found', function(done) {
        const middleware = electricity.static('test/public');

        const req = {
            method: 'GET',
            path: '/not-found.txt'
        };

        const next = function(err) {
            assert.ifError(err);
            done();
        };

        middleware(req, null, next);
    });

    it('should call next middleware when the specified URL is a directory', function(done) {
        const middleware = electricity.static('test/public');

        const req = {
            method: 'GET',
            path: '/scripts'
        };

        const next = function(err) {
            assert.ifError(err);
            done();
        };

        middleware(req, null, next);
    });

    it('should call next middleware with an error if the specified URL is too long', function(done) {
        const middleware = electricity.static('test/public');

        const req = {
            method: 'GET',
            path: crypto.randomBytes(256).toString('hex')
        };

        const next = function(err) {
            assert(err);
            done();
        };

        middleware(req, null, next);
    });

    describe('babel', function() {
        describe('preset-react', function() {
            it('should transform JSX files', function(done) {
                const middleware = electricity.static('test/public', {
                    babel: {},
                    uglifyjs: { enabled: false }
                });

                const req = {
                    method: 'GET',
                    path: '/scripts/babel/preset-react.js'
                };

                const res = {
                    redirect: function(path) {
                        assert.strictEqual(path, '/scripts/babel/preset-react-b43ebe041bbcac2c692f07cae0b9e8d83e058de1.js');

                        const req = {
                            get: function() {},
                            method: 'GET',
                            path
                        };

                        const res = {
                            send: function(body) {
                                assert.strictEqual(body, 'React.render( /*#__PURE__*/React.createElement("h1", null, "Hello World"), document.body);');
                                done();
                            },
                            set: function() {}
                        };

                        middleware(req, res);
                    },
                    set: function() {}
                };

                middleware(req, res);
            });

            describe('errors', function() {
                let consoleWarn = console.warn;

                before(function() {
                    console.warn = function() {};
                });

                it('should return file without transformation on an error', function(done) {
                    const middleware = electricity.static('test/public');

                    const req = {
                        get: function() {},
                        method: 'GET',
                        path: '/scripts/babel/invalid-50c332596d0947cd2cc8d126317bbbde753182d2.js'
                    };

                    const res = {
                        send: function(body) {
                            fs.readFile('test/public/scripts/babel/invalid.js', function(err, expected) {
                                assert.ifError(err);
                                assert.strictEqual(body, expected.toString());
                                done();
                            });
                        },
                        set: function() {}
                    };

                    middleware(req, res);
                });

                after(function() {
                    console.warn = consoleWarn;
                });
            });
        });
    });

    describe('css', function() {
        it('should read .css files direcly from disk', function(done) {
            const middleware = electricity.static('test/public', {
                uglifycss: {
                    enabled: false
                }
            });

            const req = {
                method: 'GET',
                path: '/styles/css/test.css'
            };

            const res = {
                redirect: function(path) {
                    assert.strictEqual(path, '/styles/css/test-566c7e6edb86a4700f7f971fef877db61ffc4b43.css');

                    const req = {
                        get: function() {},
                        method: 'GET',
                        path
                    };

                    const res = {
                        send: function(body) {
                            fs.readFile('test/public/styles/css/test.css', function(err, expected) {
                                assert.strictEqual(body, expected.toString());
                                done();
                            });
                        },
                        set: function() {}
                    };

                    middleware(req, res);
                },
                set: function() {}
            };

            middleware(req, res);
        });

        it('should call next middleware with an error if the specified URL is too long', function(done) {
            const middleware = electricity.static('test/public');

            const req = {
                method: 'GET',
                path: `${crypto.randomBytes(256).toString('hex')}.css`
            };

            const next = function(err) {
                assert(err);
                done();
            };

            middleware(req, null, next);
        });

        it('should update URLs', function(done) {
            const middleware = electricity.static('test/public', {
                uglifycss: {
                    enabled: false
                }
            });

            const req = {
                method: 'GET',
                path: '/styles/urls/urls.css'
            };

            const res = {
                redirect: function(path) {
                    assert.strictEqual(path, '/styles/urls/urls-1099c397162ab5919b081f5f87482f0d76a11893.css');

                    const req = {
                        get: function() {},
                        method: 'GET',
                        path
                    };

                    const res = {
                        send: function(body) {
                            fs.readFile('test/public/styles/urls/urls-expected.css', function(err, expected) {
                                assert.strictEqual(body, expected.toString());
                                done();
                            });
                        },
                        set: function() {}
                    };

                    middleware(req, res);
                },
                set: function() {}
            };

            middleware(req, res);
        });

        it('should update URLs and use a CDN', function(done) {
            const middleware = electricity.static('test/public', {
                hostname: 'cdn.example.com',
                uglifycss: {
                    enabled: false
                }
            });

            const req = {
                method: 'GET',
                path: '/styles/urls/urls.css'
            };

            const res = {
                redirect: function(path) {
                    assert.strictEqual(path, '/styles/urls/urls-bfa1387489627e7e4798da8d3b83939b8d20dc91.css');

                    const req = {
                        get: function() {},
                        method: 'GET',
                        path
                    };

                    const res = {
                        send: function(body) {
                            fs.readFile('test/public/styles/urls/urls-expected-cdn.css', function(err, expected) {
                                assert.strictEqual(body, expected.toString());
                                done();
                            });
                        },
                        set: function() {}
                    };

                    middleware(req, res);
                },
                set: function() {}
            };

            middleware(req, res);
        });

        it('should call next middleware when the specified file can not be found', function(done) {
            const middleware = electricity.static('test/public');

            const req = {
                method: 'GET',
                path: '/not-found.css'
            };

            const next = function(err) {
                assert.ifError(err);
                done();
            };

            middleware(req, null, next);
        });
    });

    describe('gzip', function() {
        it('should gzip TXT files for clients that accept gzip', function(done) {
            const middleware = electricity.static('test/public');

            const req = {
                get: function() {},
                headers: {
                    'accept-encoding': 'gzip, deflate'
                },
                method: 'GET',
                path: '/lorem-ipsum-1866425c51a663f0e9c1b8214c2ba186f6c827e4.txt'
            };

            const res = {
                send: function() {},
                set: function(field, value) {
                    if (field === 'content-encoding' && value === 'gzip') {
                        done();
                    }
                }
            };

            middleware(req, res);
        });

        it('should not gzip TXT files for clients that do not accept gzip', function(done) {
            const middleware = electricity.static('test/public');

            const req = {
                get: function() {},
                headers: {},
                method: 'GET',
                path: '/lorem-ipsum-1866425c51a663f0e9c1b8214c2ba186f6c827e4.txt'
            };

            const res = {
                send: function() {
                    done();
                },
                set: function(field, value) {
                    if (field === 'content-encoding' && value === 'gzip') {
                        assert.fail();
                    }
                }
            };

            middleware(req, res);
        });

        it('should not gzip PNG files', function(done) {
            const middleware = electricity.static('test/public');

            const req = {
                get: function() {},
                method: 'GET',
                path: '/apple-touch-icon-precomposed-217316d510b3122f64bd75f2dc0dcdba6c4786d5.png'
            };

            const res = {
                send: function() {
                    done();
                },
                set: function(field, value) {
                    if (field === 'content-encoding' && value === 'gzip') {
                        assert.fail();
                    }
                }
            };

            middleware(req, res);
        });

        it('should not gzip when disabled', function(done) {
            const middleware = electricity.static('test/public', {
                gzip: {
                    enabled: false
                }
            });

            const req = {
                get: function() {},
                headers: {
                    'accept-encoding': 'gzip, deflate'
                },
                method: 'GET',
                path: '/lorem-ipsum-1866425c51a663f0e9c1b8214c2ba186f6c827e4.txt'
            };

            const res = {
                send: function() {
                    done();
                },
                set: function(field, value) {
                    if (field === 'content-encoding' && value === 'gzip') {
                        assert.fail();
                    }
                }
            };

            middleware(req, res);
        });
    });

    describe('hashify', function() {
        it('should hashify by default', function(done) {
            const middleware = electricity.static('test/public');

            const req = {
                method: 'GET',
                path: '/robots.txt'
            };

            const res = {
                redirect: function(path) {
                    assert.strictEqual(path, '/robots-423251d722a53966eb9368c65bfd14b39649105d.txt');

                    const req = {
                        get: function() {},
                        method: 'GET',
                        path
                    };

                    const res = {
                        send: function(body) {
                            fs.readFile('test/public/robots.txt', function(err, expected) {
                                assert(Buffer.compare(body, expected) === 0);
                                done();
                            });
                        },
                        set: function() {}
                    };

                    middleware(req, res);
                },
                set: function() {}
            };

            middleware(req, res);
        });

        it('should not hashify if disabled', function(done) {
            const middleware = electricity.static('test/public', {
                hashify: false
            });

            const req = {
                get: function() {},
                method: 'GET',
                path: '/robots.txt'
            };

            const res = {
                set: function() {},
                status: function(code) {
                    assert.strictEqual(code, 200);
                },
                send: function(body) {
                    fs.readFile('test/public/robots.txt', function(err, expected) {
                        assert(Buffer.compare(body, expected) === 0);
                        done();
                    });
                }
            };

            middleware(req, res);
        });

        it('should not hashify if enabled', function(done) {
            const middleware = electricity.static('test/public', {
                hashify: true
            });

            const req = {
                method: 'GET',
                path: '/robots.txt'
            };

            const res = {
                redirect: function(path) {
                    assert.strictEqual(path, '/robots-423251d722a53966eb9368c65bfd14b39649105d.txt');
                    done();
                },
                set: function() {}
            };

            middleware(req, res);
        });

        it('should hashify files without extensions', function(done) {
            const middleware = electricity.static('test/public');

            const req = {
                method: 'GET',
                path: '/no-extension'
            };

            const res = {
                redirect: function(path) {
                    assert.strictEqual(path, '/no-extension-2aae6c35c94fcfb415dbe95f408b9ce91ee846ed');
                    done();
                },
                set: function() {}
            };

            middleware(req, res);
        });
    });

    describe('HTTP headers', function() {
        it('should allow additional HTTP headers', function(done) {
            const middleware = electricity.static('test/public', {
                headers: {
                    'access-control-allow-origin': 'https://example.com'
                }
            });

            const req = {
                get: function() {},
                method: 'GET',
                path: '/robots-423251d722a53966eb9368c65bfd14b39649105d.txt'
            };

            const res = {
                send: function() {},
                set: function(value) {
                    if (value['access-control-allow-origin'] === 'https://example.com') {
                        done();
                    }
                }
            };

            middleware(req, res);
        });

        it('should return a 304 for a valid if-none-match header', function(done) {
            const middleware = electricity.static('test/public');

            const req = {
                get: function(field) {
                    if (field === 'if-none-match') {
                        return '"423251d722a53966eb9368c65bfd14b39649105d"';
                    }
                },
                method: 'GET',
                path: '/robots-423251d722a53966eb9368c65bfd14b39649105d.txt'
            };

            const res = {
                set: function() {},
                sendStatus: function(code) {
                    assert.strictEqual(code, 304);
                    done();
                }
            };

            middleware(req, res);
        });

        it('should return etag header for invalid if-none-match header', function(done) {
            const middleware = electricity.static('test/public');

            const req = {
                get: function(field) {
                    if (field === 'if-none-match') {
                        return '"invalid"';
                    }
                },
                method: 'GET',
                path: '/robots-423251d722a53966eb9368c65bfd14b39649105d.txt'
            };

            const res = {
                set: function(headers) {
                    if (headers.etag === '423251d722a53966eb9368c65bfd14b39649105d') {
                        done();
                    }
                },
                send: function() {}
            };

            middleware(req, res);
        });
    });

    describe('HTTP methods', function() {
        it('should handle HEAD requests', function(done) {
            const middleware = electricity.static('test/public');

            const req = {
                get: function() {},
                method: 'HEAD',
                path: '/robots-423251d722a53966eb9368c65bfd14b39649105d.txt'
            };

            const res = {
                sendStatus: function(code) {
                    assert.strictEqual(code, 200);
                    done();
                },
                set: function() {}
            };

            middleware(req, res);
        });

        it('should not handle POST requests', function(done) {
            const middleware = electricity.static('test/public');

            const req = {
                method: 'POST',
                path: '/robots.txt'
            };

            const next = function() {
                done();
            };

            middleware(req, null, next);
        });
    });

    describe('locals', function() {
        it('should register a helper function to generate URLs', function(done) {
            const middleware = electricity.static('test/public');

            const req = {
                app: {
                    locals: {}
                },
                get: function() {},
                method: 'GET',
                path: '/robots-423251d722a53966eb9368c65bfd14b39649105d.txt'
            };

            const res = {
                set: function() {},
                send: function() {
                    assert.strictEqual(typeof req.app.locals.electricity.url, 'function');
                    done();
                }
            };

            middleware(req, res);
        });

        it('should return a hashified URL for a file that was previously requested', function(done) {
            const middleware = electricity.static('test/public');

            const req = {
                app: {
                    locals: {}
                },
                get: function() {},
                method: 'GET',
                path: '/robots-423251d722a53966eb9368c65bfd14b39649105d.txt'
            };

            const res = {
                set: function() {},
                send: function() {
                    assert.strictEqual(req.app.locals.electricity.url('/robots.txt'), '/robots-423251d722a53966eb9368c65bfd14b39649105d.txt');
                    done();
                }
            };

            middleware(req, res);
        });

        it('should return original URL path when hashify is disabled', function(done) {
            const middleware = electricity.static('test/public', {
                hashify: false
            });

            const req = {
                app: {
                    locals: {}
                },
                get: function() {},
                method: 'GET',
                path: '/robots.txt'
            };

            const res = {
                set: function() {},
                send: function() {
                    assert.strictEqual(req.app.locals.electricity.url('/robots.txt'), '/robots.txt');
                    done();
                }
            };

            middleware(req, res);
        });

        it('should return original URL path when the file could not be found', function(done) {
            const middleware = electricity.static('test/public');

            const next = function() {
                assert.strictEqual(req.app.locals.electricity.url('/not-found.txt'), '/not-found.txt');
                done();
            };

            const req = {
                app: {
                    locals: {}
                },
                get: function() {},
                method: 'GET',
                path: '/not-found.txt'
            };

            middleware(req, null, next);
        });

        it('should return an absolute URL when the hostname option is specified', function(done) {
            const middleware = electricity.static('test/public', {
                hostname: 'cdn.example.com'
            });

            const req = {
                app: {
                    locals: {}
                },
                get: function() {},
                method: 'GET',
                path: '/robots-423251d722a53966eb9368c65bfd14b39649105d.txt'
            };

            const res = {
                set: function() {},
                send: function() {
                    assert.strictEqual(req.app.locals.electricity.url('/robots.txt'), 'https://cdn.example.com/robots-423251d722a53966eb9368c65bfd14b39649105d.txt');
                    done();
                }
            };

            middleware(req, res);
        });
    });

    describe('sass', function() {
        it('should read .scss files', function(done) {
            const middleware = electricity.static('test/public', {
                sass: {},
                uglifycss: {
                    enabled: false
                }
            });

            const req = {
                method: 'GET',
                path: '/styles/sass/sass.css'
            };

            const res = {
                redirect: function(path) {
                    assert.strictEqual(path, '/styles/sass/sass-72298afd35d449aa2d9a4b4acc6acf66ab14d91a.css');

                    const req = {
                        get: function() {},
                        method: 'GET',
                        path
                    };

                    const res = {
                        send: function(body) {
                            fs.readFile('test/public/styles/sass/sass-expected.css', function(err, expected) {
                                assert.strictEqual(body, expected.toString());
                                done();
                            });
                        },
                        set: function() {}
                    };

                    middleware(req, res);
                },
                set: function() {}
            };

            middleware(req, res);
        });
    });

    describe('snockets', function() {
        it('should concatenate files', function(done) {
            const middleware = electricity.static('test/public', {
                snockets: {
                    async: true
                },
                uglifyjs: {
                    enabled: false
                }
            });

            const req = {
                method: 'GET',
                path: '/scripts/snockets/main.js'
            };

            const res = {
                redirect: function(path) {
                    assert.strictEqual(path, '/scripts/snockets/main-c5418687251da9326c7b3c1e7ad7a8ac5d20943c.js');

                    const req = {
                        get: function() {},
                        method: 'GET',
                        path
                    };

                    const res = {
                        send: function(body) {
                            fs.readFile('test/public/scripts/snockets/main-expected.js', function(err, expected) {
                                assert.ifError(err);
                                assert.strictEqual(body, expected.toString());
                                done();
                            });
                        },
                        set: function() {}
                    };

                    middleware(req, res);
                },
                set: function() {}
            };

            middleware(req, res);
        });

        describe('errors', function() {
            let consoleWarn = console.warn;

            before(function() {
                console.warn = function() {};
            });

            it('should return file without concatenation on an error', function(done) {
                const middleware = electricity.static('test/public', {
                    uglifyjs: { enabled: false },
                    watch: { enabled: true }
                });

                const req = {
                    get: function() {},
                    method: 'GET',
                    path: '/scripts/snockets/invalid-71f16629fe6cf3e982d38e87ab81c421e4956c8d.js'
                };

                const res = {
                    send: function(body) {
                        fs.readFile('test/public/scripts/snockets/invalid.js', function(err, expected) {
                            assert.ifError(err);
                            assert.strictEqual(body, expected.toString());
                            done();
                        });
                    },
                    set: function() {}
                };

                middleware(req, res);
            });

            it('should call next middleware with an error if the specified URL is too long', function(done) {
                const middleware = electricity.static('test/public');

                const req = {
                    method: 'GET',
                    path: `${crypto.randomBytes(256).toString('hex')}.js`
                };

                const next = function(err) {
                    assert(err);
                    done();
                };

                middleware(req, null, next);
            });

            after(function() {
                console.warn = consoleWarn;
            });
        });
    });

    describe('uglifycss', function() {
        it('should uglify files', function(done) {
            const middleware = electricity.static('test/public');

            const req = {
                method: 'GET',
                path: '/styles/uglifycss/test.css'
            };

            const res = {
                redirect: function(path) {
                    assert.strictEqual(path, '/styles/uglifycss/test-c08394f9bdad595e2e3a7c5e7851b41bd153204f.css');

                    const req = {
                        get: function() {},
                        method: 'GET',
                        path
                    };

                    const res = {
                        send: function(body) {
                            fs.readFile('test/public/styles/uglifycss/test-expected.css', function(err, expected) {
                                assert.ifError(err);
                                assert.strictEqual(body, expected.toString());
                                done();
                            });
                        },
                        set: function() {}
                    };

                    middleware(req, res);
                },
                set: function() {}
            };

            middleware(req, res);
        });
    });

    describe('uglifyjs', function() {
        it('should uglify files', function(done) {
            const middleware = electricity.static('test/public');

            const req = {
                method: 'GET',
                path: '/scripts/uglifyjs/test.js'
            };

            const res = {
                redirect: function(path) {
                    assert.strictEqual(path, '/scripts/uglifyjs/test-bd0e73d5c4845f2f4c39219ae7e4248d122f0c5c.js');

                    const req = {
                        get: function() {},
                        method: 'GET',
                        path
                    };

                    const res = {
                        send: function(body) {
                            fs.readFile('test/public/scripts/uglifyjs/test-expected.js', function(err, expected) {
                                assert.ifError(err);
                                assert.strictEqual(body, expected.toString());
                                done();
                            });
                        },
                        set: function() {}
                    };

                    middleware(req, res);
                },
                set: function() {}
            };

            middleware(req, res);
        });
    });

    describe('watch', function() {
        before(function(done) {
            fs.rm('test/public/watch', { recursive: true, force: true }, done);
        });

        it('should watch for file changes', function(done) {
            this.timeout(3000);

            const middleware = electricity.static('test/public', {
                watch: { enabled: true }
            });

            fse.outputFile('test/public/watch/foo', 'bar', function() {
                setTimeout(function() {
                    const req = {
                        method: 'GET',
                        path: '/watch/foo'
                    };

                    const res = {
                        redirect: function(path) {
                            assert.strictEqual(path, '/watch/foo-62cdb7020ff920e5aa642c3d4066950dd1f01f4d');

                            const req = {
                                get: function() {},
                                method: 'GET',
                                path
                            };

                            const res = {
                                send: function(body) {
                                    assert.strictEqual(body.toString(), 'bar');

                                    fse.outputFile('test/public/watch/foo', 'baz', function() {
                                        setTimeout(function() {
                                            const req = {
                                                method: 'GET',
                                                path: '/watch/foo'
                                            };

                                            const res = {
                                                redirect: function(path) {
                                                    assert.strictEqual(path, '/watch/foo-bbe960a25ea311d21d40669e93df2003ba9b90a2');

                                                    const req = {
                                                        get: function() {},
                                                        method: 'GET',
                                                        path
                                                    };

                                                    const res = {
                                                        send: function(body) {
                                                            assert.strictEqual(body.toString(), 'baz');
                                                            done();
                                                        },
                                                        set: function() {}
                                                    };

                                                    middleware(req, res);
                                                },
                                                set: function() {}
                                            };

                                            middleware(req, res);
                                        }, 1000);
                                    });
                                },
                                set: function() {}
                            };

                            middleware(req, res);
                        },
                        set: function() {}
                    };

                    middleware(req, res);
                }, 1000);
            });
        });

        it('should watch for CSS file changes', function(done) {
            this.timeout(3000);

            const middleware = electricity.static('test/public', {
                uglifyjs: { enabled: false },
                watch: { enabled: true }
            });

            fse.outputFile('test/public/watch/2.scss', 'p{color:red}', function() {
                fse.outputFile('test/public/watch/1.scss', '@import \'2\';', function() {
                    fse.outputFile('test/public/watch/main.scss', '@import \'1\';', function() {
                        setTimeout(function() {
                            const req = {
                                method: 'GET',
                                path: '/watch/main.css'
                            };

                            const res = {
                                redirect: function(path) {
                                    assert.strictEqual(path, '/watch/main-6f8c504c70c088a326b9973c5e543784625c1a1d.css');

                                    const req = {
                                        get: function() {},
                                        method: 'GET',
                                        path
                                    };

                                    const res = {
                                        send: function(body) {
                                            assert.strictEqual(body.toString(), 'p{color:red}');

                                            fse.outputFile('test/public/watch/2.scss', 'p{color:green}', function() {
                                                setTimeout(function() {
                                                    const req = {
                                                        method: 'GET',
                                                        path: '/watch/main.css'
                                                    };

                                                    const res = {
                                                        redirect: function(path) {
                                                            assert.strictEqual(path, '/watch/main-4746a8638dcba3d5afe18eef995e31623eb19d4c.css');

                                                            const req = {
                                                                get: function() {},
                                                                method: 'GET',
                                                                path
                                                            };

                                                            const res = {
                                                                send: function(body) {
                                                                    assert.strictEqual(body.toString(), 'p{color:green}');
                                                                    done();
                                                                },
                                                                set: function() {}
                                                            };

                                                            middleware(req, res);
                                                        },
                                                        set: function() {}
                                                    };

                                                    middleware(req, res);
                                                }, 1000);
                                            });
                                        },
                                        set: function() {}
                                    };

                                    middleware(req, res);
                                },
                                set: function() {}
                            };

                            middleware(req, res);
                        }, 1000);
                    });
                });
            });
        });

        it('should handle CSS file deletions', function(done) {
            this.timeout(3000);

            const middleware = electricity.static('test/public', {
                uglifyjs: { enabled: false },
                watch: { enabled: true }
            });

            fse.outputFile('test/public/watch/to-be-deleted.scss', 'p{color:red}', function() {
                setTimeout(function() {
                    const req = {
                        method: 'GET',
                        path: '/watch/to-be-deleted.css'
                    };

                    const res = {
                        redirect: function(path) {
                            assert.strictEqual(path, '/watch/to-be-deleted-6f8c504c70c088a326b9973c5e543784625c1a1d.css');

                            const req = {
                                get: function() {},
                                method: 'GET',
                                path
                            };

                            const res = {
                                send: function(body) {
                                    assert.strictEqual(body.toString(), 'p{color:red}');

                                    fs.rm('test/public/watch/to-be-deleted.scss', function() {
                                        setTimeout(function() {
                                            const req = {
                                                method: 'GET',
                                                path: '/watch/to-be-deleted.css'
                                            };

                                            const next = function(err) {
                                                assert.ifError(err);
                                                done();
                                            };

                                            middleware(req, null, next);
                                        }, 1000);
                                    });
                                },
                                set: function() {}
                            };

                            middleware(req, res);
                        },
                        set: function() {}
                    };

                    middleware(req, res);
                }, 1000);
            });
        });

        it('should watch for JavaScript file changes', function(done) {
            this.timeout(3000);

            const middleware = electricity.static('test/public', {
                uglifyjs: { enabled: false },
                watch: { enabled: true }
            });

            fse.outputFile('test/public/watch/2.js', 'console.log(\'foo\');', function() {
                fse.outputFile('test/public/watch/1.js', '//= require 2.js', function() {
                    fse.outputFile('test/public/watch/main.js', '//= require 1.js', function() {
                        setTimeout(function() {
                            const req = {
                                method: 'GET',
                                path: '/watch/main.js'
                            };

                            const res = {
                                redirect: function(path) {
                                    assert.strictEqual(path, '/watch/main-8c6a79ed3718fbe45d7e0d438ec5a2bb767ff8c8.js');

                                    const req = {
                                        get: function() {},
                                        method: 'GET',
                                        path
                                    };

                                    const res = {
                                        send: function(body) {
                                            assert.strictEqual(body.toString(), 'console.log(\'foo\'); //= require 2.js\n//= require 1.js');

                                            fse.outputFile('test/public/watch/2.js', 'console.log(\'bar\');', function() {
                                                setTimeout(function() {
                                                    const req = {
                                                        method: 'GET',
                                                        path: '/watch/main.js'
                                                    };

                                                    const res = {
                                                        redirect: function(path) {
                                                            assert.strictEqual(path, '/watch/main-fa387bf84db36e790f09529c19cedf9a24897159.js');

                                                            const req = {
                                                                get: function() {},
                                                                method: 'GET',
                                                                path
                                                            };

                                                            const res = {
                                                                send: function(body) {
                                                                    assert.strictEqual(body.toString(), 'console.log(\'bar\'); //= require 2.js\n//= require 1.js');
                                                                    done();
                                                                },
                                                                set: function() {}
                                                            };

                                                            middleware(req, res);
                                                        },
                                                        set: function() {}
                                                    };

                                                    middleware(req, res);
                                                }, 1000);
                                            });
                                        },
                                        set: function() {}
                                    };

                                    middleware(req, res);
                                },
                                set: function() {}
                            };

                            middleware(req, res);
                        }, 1000);
                    });
                });
            });
        });

        after(function(done) {
            fs.rm('test/public/watch', { recursive: true, force: true }, done);
        });
    });
});


text:
/* vi: set sw=4 ts=4: */
/*
 * password utility routines.
 *
 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
 *
 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
 */

#include "libbb.h"

#define assert(x) ((void)0)

/* internal function for bb_getpwuid and bb_getgrgid */
/* Hacked by Tito Ragusa (c) 2004 <farmatito@tiscali.it> to make it more
 * flexible:
 *
 * bufsize > 0:      If idname is not NULL it is copied to buffer,
 *                   and buffer is returned. Else id as string is written
 *                   to buffer, and NULL is returned.
 *
 * bufsize == 0:     idname is returned.
 *
 * bufsize < 0:      If idname is not NULL it is returned.
 *                   Else an error message is printed and the program exits.
 */
static char* bb_getug(char *buffer, int bufsize, char *idname, long id, char prefix)
{
	if (bufsize > 0) {
		assert(buffer != NULL);
		if (idname) {
			return safe_strncpy(buffer, idname, bufsize);
		}
		snprintf(buffer, bufsize, "%ld", id);
	} else if (bufsize < 0 && !idname) {
		bb_error_msg_and_die("unknown %cid %ld", prefix, id);
	}
	return idname;
}

/* bb_getpwuid, bb_getgrgid:
 * bb_getXXXid(buf, bufsz, id) - copy user/group name or id
 *               as a string to buf, return user/group name or NULL
 * bb_getXXXid(NULL, 0, id) - return user/group name or NULL
 * bb_getXXXid(NULL, -1, id) - return user/group name or exit
 */
/* gets a username given a uid */
char* bb_getpwuid(char *name, int bufsize, long uid)
{
	struct passwd *myuser = getpwuid(uid);

	return bb_getug(name, bufsize,
			(myuser ? myuser->pw_name : (char*)myuser),
			uid, 'u');
}
/* gets a groupname given a gid */
char* bb_getgrgid(char *group, int bufsize, long gid)
{
	struct group *mygroup = getgrgid(gid);

	return bb_getug(group, bufsize,
			(mygroup ? mygroup->gr_name : (char*)mygroup),
			gid, 'g');
}

/* returns a gid given a group name */
long xgroup2gid(const char *name)
{
	struct group *mygroup;

	mygroup = getgrnam(name);
	if (mygroup == NULL)
		bb_error_msg_and_die("unknown group name: %s", name);

	return mygroup->gr_gid;
}

/* returns a uid given a username */
long xuname2uid(const char *name)
{
	struct passwd *myuser;

	myuser = getpwnam(name);
	if (myuser == NULL)
		bb_error_msg_and_die("unknown user name: %s", name);

	return myuser->pw_uid;
}

unsigned long get_ug_id(const char *s,
		long (*xname2id)(const char *))
{
	unsigned long r;

	r = bb_strtoul(s, NULL, 10);
	if (errno)
		return xname2id(s);
	return r;
}

redpajama_set_name: RedPajamaGithub


text:
package we.sharediary.base;

import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

import com.umeng.analytics.MobclickAgent;
import com.zhuge.analysis.stat.ZhugeSDK;

/**
 * Created by Jayden on 2016/1/10.
 */
public class BaseFragmentActivity extends FragmentActivity {
    //在BaseActivity或BaseFragment中添加字段
    protected final String HTTP_TASK_KEY = "HttpTaskKey_" + hashCode();

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ZhugeSDK.getInstance().flush(getApplicationContext());
    }

    @Override
    protected void onResume() {
        super.onResume();
        MobclickAgent.onResume(this);
        ZhugeSDK.getInstance().init(getApplicationContext());
    }

    @Override
    protected void onPause() {
        super.onPause();
        MobclickAgent.onPause(this);
    }

    /**
     *写入sharedPreferences
     * @param key
     * @param value
     */
    public void writePreferences(String key, Object value){
        SharedPreferences preferences = getSharedPreferences(Constants.KEY_PRERERENCES, MODE_PRIVATE);
        SharedPreferences.Editor editor = preferences.edit();
        if (value instanceof String){
            editor.putString(key, (String) value);
        }else if (value instanceof Integer){
            editor.putInt(key, (Integer) value);
        }else if (value instanceof Boolean){
            editor.putBoolean(key, (Boolean) value);
        }
        editor.commit();
    }

    /**
     * 读取sharedPreferences
     * @param key
     * @param flag 0:string 1:int 2:boolean
     * @return
     */
    public Object readPreferences(String key, int flag){
        SharedPreferences preferences = getSharedPreferences(Constants.KEY_PRERERENCES, MODE_PRIVATE);
        Object o = null;
        if (flag == 0){
            o = preferences.getString(key, "");
        }else if (flag == 1){
            o = preferences.getInt(key, -1);
        }else if (flag == 2){
            o = preferences.getBoolean(key, false);
        }
        return o;
    }

    public void goNextActivitiy(Class<?> clazz){
        Intent intent = new Intent();
        intent.setClass(this, clazz);
        startActivity(intent);
    }

    public void goNextActivitiyForResult(Class<?> clazz, int requestCode){
        Intent intent = new Intent();
        intent.setClass(this, clazz);
        startActivityForResult(intent, requestCode);
    }
    public void goNextActivitiyForResult(Class<?> clazz, int requestCode, String key, Bundle bundle){
        Intent intent = new Intent();
        intent.setClass(this, clazz);
        intent.putExtra(key, bundle);
        startActivityForResult(intent, requestCode);
    }
}


text:
RSpec.describe RuboCop::Cop::Style::RedundantArgument, :config do
  let(:cop_config) do
    { 'Methods' => { 'join' => '', 'split' => ' ', 'chomp' => "\n", 'chomp!' => "\n" } }
  end

  it 'registers an offense and corrects when method called on variable' do
    expect_offense(<<~'RUBY')
      foo.join('')
      ^^^^^^^^^^^^ Argument '' is redundant because it is implied by default.
      foo.split(' ')
      ^^^^^^^^^^^^^^ Argument ' ' is redundant because it is implied by default.
      foo.chomp("\n")
      ^^^^^^^^^^^^^^^ Argument "\n" is redundant because it is implied by default.
      foo.chomp!("\n")
      ^^^^^^^^^^^^^^^^ Argument "\n" is redundant because it is implied by default.
    RUBY

    expect_correction(<<~RUBY)
      foo.join
      foo.split
      foo.chomp
      foo.chomp!
    RUBY
  end

  it 'registers an offense and corrects when method called without parenthesis on variable' do
    expect_offense(<<~RUBY)
      foo.join ''
      ^^^^^^^^^^^ Argument '' is redundant because it is implied by default.
      foo.split ' '
      ^^^^^^^^^^^^^ Argument ' ' is redundant because it is implied by default.
    RUBY

    expect_correction(<<~RUBY)
      foo.join
      foo.split
    RUBY
  end

  it 'registers an offense and corrects when method called on literals' do
    expect_offense(<<~RUBY)
      [1, 2, 3].join('')
      ^^^^^^^^^^^^^^^^^^ Argument '' is redundant because it is implied by default.
      "first second".split(' ')
      ^^^^^^^^^^^^^^^^^^^^^^^^^ Argument ' ' is redundant because it is implied by default.
    RUBY

    expect_correction(<<~RUBY)
      [1, 2, 3].join
      "first second".split
    RUBY
  end

  it 'registers an offense and corrects when method called without parenthesis on literals' do
    expect_offense(<<~RUBY)
      [1, 2, 3].join ''
      ^^^^^^^^^^^^^^^^^ Argument '' is redundant because it is implied by default.
    RUBY

    expect_correction(<<~RUBY)
      [1, 2, 3].join
    RUBY
  end

  it 'works with double-quoted strings when configuration is single-quotes' do
    expect_offense(<<~RUBY)
      foo.join("")
      ^^^^^^^^^^^^ Argument "" is redundant because it is implied by default.
      "first second".split(" ")
      ^^^^^^^^^^^^^^^^^^^^^^^^^ Argument " " is redundant because it is implied by default.
    RUBY

    expect_correction(<<~RUBY)
      foo.join
      "first second".split
    RUBY
  end

  it 'does not register an offense when method called with no arguments' do
    expect_no_offenses(<<~RUBY)
      foo.join
      "first second".split
    RUBY
  end

  it 'does not register an offense when method called with more than one arguments' do
    expect_no_offenses(<<~RUBY)
      foo.join('', 2)
      [1, 2, 3].split(" ", true, {})
    RUBY
  end

  it 'does not register an offense when method called with different argument' do
    expect_no_offenses(<<~RUBY)
      foo.join(',')
      foo.split(',')
    RUBY
  end

  it 'does not register an offense when method called with no receiver' do
    expect_no_offenses(<<~RUBY)
      join('')
      split(' ')
    RUBY
  end

  context 'non-builtin method' do
    let(:cop_config) { { 'Methods' => { 'foo' => 2 } } }

    it 'registers an offense and corrects with configured argument' do
      expect_offense(<<~RUBY)
        A.foo(2)
        ^^^^^^^^ Argument 2 is redundant because it is implied by default.
      RUBY

      expect_correction(<<~RUBY)
        A.foo
      RUBY
    end

    it 'does not register an offense with other argument' do
      expect_no_offenses(<<~RUBY)
        A.foo(5)
      RUBY
    end
  end
end


text:
#import "ANNativeStandardAdResponse.h"
#import "ANGlobal.h"
#import "ANLogging.h"
#import "ANBrowserViewController.h"
#import "ANNativeAdResponse+PrivateMethods.h"
#import "NSTimer+ANCategory.h"
#import "UIView+ANCategory.h"
#import "ANNativeImpressionTrackerManager.h"

@interface ANNativeStandardAdResponse() <ANBrowserViewControllerDelegate>

@property (nonatomic, readwrite, strong) NSDate *dateCreated;
@property (nonatomic, readwrite, assign) ANNativeAdNetworkCode networkCode;
@property (nonatomic, readwrite, assign, getter=hasExpired) BOOL expired;
@property (nonatomic, readwrite, strong) ANBrowserViewController *inAppBrowser;

@property (nonatomic, readwrite, assign) NSUInteger viewabilityValue;
@property (nonatomic, readwrite, assign) NSUInteger targetViewabilityValue;
@property (nonatomic, readwrite, strong) NSTimer *viewabilityTimer;
@property (nonatomic, readwrite, assign) BOOL impressionHasBeenTracked;

@end

@implementation ANNativeStandardAdResponse

@synthesize title = _title;
@synthesize body = _body;
@synthesize callToAction = _callToAction;
@synthesize rating = _rating;
@synthesize mainImage = _mainImage;
@synthesize mainImageURL = _mainImageURL;
@synthesize iconImage = _iconImage;
@synthesize iconImageURL = _iconImageURL;
@synthesize socialContext = _socialContext;
@synthesize customElements = _customElements;
@synthesize networkCode = _networkCode;
@synthesize expired = _expired;

- (instancetype)init {
    if (self = [super init]) {
        _networkCode = ANNativeAdNetworkCodeAppNexus;
        _dateCreated = [NSDate date];
    }
    return self;
}

#pragma mark - Registration

- (BOOL)registerResponseInstanceWithNativeView:(UIView *)view
                            rootViewController:(UIViewController *)controller
                                clickableViews:(NSArray *)clickableViews
                                         error:(NSError *__autoreleasing *)error {
    [self setupViewabilityTracker];
    [self attachGestureRecognizersToNativeView:view
                            withClickableViews:clickableViews];
    return YES;
}

#pragma mark - Unregistration

- (void)unregisterViewFromTracking {
    [super unregisterViewFromTracking];
    [self.viewabilityTimer invalidate];
}

#pragma mark - Impression Tracking

- (void)setupViewabilityTracker {
    __weak ANNativeStandardAdResponse *weakSelf = self;
    NSInteger requiredAmountOfSimultaneousViewableEvents = lround(kAppNexusNativeAdIABShouldBeViewableForTrackingDuration
                                                                  / kAppNexusNativeAdCheckViewabilityForTrackingFrequency) + 1;
    self.targetViewabilityValue = lround(pow(2, requiredAmountOfSimultaneousViewableEvents) - 1);
    self.viewabilityTimer = [NSTimer an_scheduledTimerWithTimeInterval:kAppNexusNativeAdCheckViewabilityForTrackingFrequency
                                                                 block:^ {
                                                                     ANNativeStandardAdResponse *strongSelf = weakSelf;
                                                                     [strongSelf checkViewability];
                                                                 }
                                                               repeats:YES];
}

- (void)checkViewability {
    self.viewabilityValue = (self.viewabilityValue << 1 | [self.viewForTracking an_isAtLeastHalfViewable]) & self.targetViewabilityValue;
    BOOL isIABViewable = (self.viewabilityValue == self.targetViewabilityValue);
    if (isIABViewable) {
        [self trackImpression];
    }
}

- (void)trackImpression {
    if (!self.impressionHasBeenTracked) {
        ANLogDebug(@"Firing impression trackers");
        [self fireImpTrackers];
        [self.viewabilityTimer invalidate];
        self.impressionHasBeenTracked = YES;
    }
}

- (void)fireImpTrackers {
    if (self.impTrackers) {
        [ANNativeImpressionTrackerManager fireImpressionTrackerURLArray:self.impTrackers];
    }
}

#pragma mark - Click handling

- (void)handleClick {
    [self adWasClicked];
    [self fireClickTrackers];

    BOOL successfullyOpenedBrowserWithClickURL = [self openIntendedBrowserWithURL:self.clickURL];
    if (!successfullyOpenedBrowserWithClickURL) {
        ANLogDebug(@"Could not open click URL: %@", self.clickURL);
        BOOL successfullyOpenedBrowserWithFallbackURL = [self openIntendedBrowserWithURL:self.clickFallbackURL];
        if (!successfullyOpenedBrowserWithFallbackURL) {
            ANLogError(@"Could not open click fallback URL: %@", self.clickFallbackURL);
        }
    }
}

- (BOOL)openIntendedBrowserWithURL:(NSURL *)URL {
    if (!self.opensInNativeBrowser && (ANHasHttpPrefix(URL.absoluteString) || ANiTunesIDForURL(URL))) {
        if (!self.inAppBrowser) {
            self.inAppBrowser = [[ANBrowserViewController alloc] initWithURL:URL
                                                                    delegate:self
                                                    delayPresentationForLoad:self.landingPageLoadsInBackground];
        } else {
            self.inAppBrowser.url = URL;
        }
        return YES;
    } else if ([[UIApplication sharedApplication] canOpenURL:URL]) {
        [self willLeaveApplication];
        [[UIApplication sharedApplication] openURL:URL];
        return YES;
    } else {
        return NO;
    }
}

- (void)fireClickTrackers {
    for (NSURL *URL in self.clickTrackers) {
        ANLogDebug(@"Firing click tracker with URL %@", URL);
        [NSURLConnection sendAsynchronousRequest:ANBasicRequestWithURL(URL)
                                           queue:[NSOperationQueue mainQueue]
                               completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {

                               }];
    }
}

#pragma mark - Helper

- (void)dealloc {
    [self.viewabilityTimer invalidate];
}

#pragma mark - ANBrowserViewControllerDelegate

- (UIViewController *)rootViewControllerForDisplayingBrowserViewController:(ANBrowserViewController *)controller {
    return self.rootViewController;
}

- (void)willPresentBrowserViewController:(ANBrowserViewController *)controller {
    [self willPresentAd];
}

- (void)didPresentBrowserViewController:(ANBrowserViewController *)controller {
    [self didPresentAd];
}

- (void)willDismissBrowserViewController:(ANBrowserViewController *)controller {
    [self willCloseAd];
}

- (void)didDismissBrowserViewController:(ANBrowserViewController *)controller {
    self.inAppBrowser = nil;
    [self didCloseAd];
}

- (void)willLeaveApplicationFromBrowserViewController:(ANBrowserViewController *)controller {
    [self willLeaveApplication];
}

@end


text:
<configuration>

    <conversionRule conversionWord="coloredLevel" converterClass="play.api.Logger$ColoredLevel" />

    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
        <file>${application.home}/logs/application.log</file>
        <encoder>
            <pattern>%date %coloredLevel [%X{user}] %X{uri} - %message%n%xException{5}</pattern>
        </encoder>
    </appender>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%date %coloredLevel [%X{user}] %X{uri} - %message%n%xException{5}</pattern>
        </encoder>
    </appender>

    <logger name="play" level="INFO" />
    <logger name="application" level="INFO" />

    <root level="INFO">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="FILE" />
    </root>

</configuration>