text: var assert = require('assert'),
      fs = require('fs'),
      path = require('path'),
      read = fs.readFileSync,
      sass = process.env.NODESASS_COV ? require('../lib-cov') : require('../lib'),
      fixture = path.join.bind(null, __dirname, 'fixtures'),
      resolveFixture = path.resolve.bind(null, __dirname, 'fixtures');
  
  describe('api', function() {
    describe('.render(options)', function() {
      it('should compile sass to css with file', function(done) {
        var expected = read(fixture('simple/expected.css'), 'utf8').trim();
  
        sass.render({
          file: fixture('simple/index.scss'),
          success: function(result) {
            assert.equal(result.css.trim(), expected.replace(/\r\n/g, '\n'));
            done();
          }
        });
      });
  
      it('should compile sass to css with outFile set to absolute url', function(done) {
        sass.render({
          file: fixture('simple/index.scss'),
          sourceMap: true,
          outFile: fixture('simple/index-test.css'),
  
          success: function(result) {
            assert.equal(JSON.parse(result.map).file, 'index-test.css');
            done();
          }
        });
      });
  
      it('should compile sass to css with outFile set to relative url', function(done) {
        sass.render({
          file: fixture('simple/index.scss'),
          sourceMap: true,
          outFile: './index-test.css',
  
          success: function(result) {
            assert.equal(JSON.parse(result.map).file, 'index-test.css');
            done();
          }
        });
      });
  
      it('should compile sass to css with outFile and sourceMap set to relative url', function(done) {
        sass.render({
          file: fixture('simple/index.scss'),
          sourceMap: './deep/nested/index.map',
          outFile: './index-test.css',
  
          success: function(result) {
            assert.equal(JSON.parse(result.map).file, '../../index-test.css');
            done();
          }
        });
      });
  
      it('should compile sass to css with data', function(done) {
        var src = read(fixture('simple/index.scss'), 'utf8');
        var expected = read(fixture('simple/expected.css'), 'utf8').trim();
  
        sass.render({
          data: src,
          success: function(result) {
            assert.equal(result.css.trim(), expected.replace(/\r\n/g, '\n'));
            done();
          }
        });
      });
  
      it('should compile sass to css using indented syntax', function(done) {
        var src = read(fixture('indent/index.sass'), 'utf8');
        var expected = read(fixture('indent/expected.css'), 'utf8').trim();
  
        sass.render({
          data: src,
          indentedSyntax: true,
          success: function(result) {
            assert.equal(result.css.trim(), expected.replace(/\r\n/g, '\n'));
            done();
          }
        });
      });
  
      it('should throw error status 1 for bad input', function(done) {
        sass.render({
          data: '#navbar width 80%;',
          error: function(error) {
            assert(error.message);
            assert.equal(error.status, 1);
            done();
          }
        });
      });
  
      it('should compile with include paths', function(done) {
        var src = read(fixture('include-path/index.scss'), 'utf8');
        var expected = read(fixture('include-path/expected.css'), 'utf8').trim();
  
        sass.render({
          data: src,
          includePaths: [
            fixture('include-path/functions'),
            fixture('include-path/lib')
          ],
          success: function(result) {
            assert.equal(result.css.trim(), expected.replace(/\r\n/g, '\n'));
            done();
          }
        });
      });
  
      it('should compile with image path', function(done) {
        var src = read(fixture('image-path/index.scss'), 'utf8');
        var expected = read(fixture('image-path/expected.css'), 'utf8').trim();
  
        sass.render({
          data: src,
          imagePath: '/path/to/images',
          success: function(result) {
            assert.equal(result.css.trim(), expected.replace(/\r\n/g, '\n'));
            done();
          }
        });
      });
  
      it('should throw error with non-string image path', function(done) {
        var src = read(fixture('image-path/index.scss'), 'utf8');
  
        assert.throws(function() {
          sass.render({
            data: src,
            imagePath: ['/path/to/images']
          });
        });
  
        done();
      });
  
      it('should render with --precision option', function(done) {
        var src = read(fixture('precision/index.scss'), 'utf8');
        var expected = read(fixture('precision/expected.css'), 'utf8').trim();
  
        sass.render({
          data: src,
          precision: 10,
          success: function(result) {
            assert.equal(result.css.trim(), expected.replace(/\r\n/g, '\n'));
            done();
          }
        });
      });
  
      it('should contain all included files in stats when data is passed', function(done) {
        var src = read(fixture('include-files/index.scss'), 'utf8');
        var expected = [
          fixture('include-files/bar.scss').replace(/\\/g, '/'),
          fixture('include-files/foo.scss').replace(/\\/g, '/')
        ];
  
        sass.render({
          data: src,
          includePaths: [fixture('include-files')],
          success: function(result) {
            assert.deepEqual(result.stats.includedFiles, expected);
            done();
          }
        });
      });
    });
  
    describe('.render(importer)', function() {
      var src = read(fixture('include-files/index.scss'), 'utf8');
  
      it('should override imports with "data" as input and fires callback with file and contents', function(done) {
        sass.render({
          data: src,
          success: function(result) {
            assert.equal(result.css.trim(), 'div {\n  color: yellow; }\n\ndiv {\n  color: yellow; }');
            done();
          },
          importer: function(url, prev, done) {
            done({
              file: '/some/other/path.scss',
              contents: 'div {color: yellow;}'
            });
          }
        });
      });
  
      it('should override imports with "file" as input and fires callback with file and contents', function(done) {
        sass.render({
          file: fixture('include-files/index.scss'),
          success: function(result) {
            assert.equal(result.css.trim(), 'div {\n  color: yellow; }\n\ndiv {\n  color: yellow; }');
            done();
          },
          importer: function(url, prev, done) {
            done({
              file: '/some/other/path.scss',
              contents: 'div {color: yellow;}'
            });
          }
        });
      });
  
      it('should override imports with "data" as input and returns file and contents', function(done) {
        sass.render({
          data: src,
          success: function(result) {
            assert.equal(result.css.trim(), 'div {\n  color: yellow; }\n\ndiv {\n  color: yellow; }');
            done();
          },
          importer: function(url, prev) {
            return {
              file: prev + url,
              contents: 'div {color: yellow;}'
            };
          }
        });
      });
  
      it('should override imports with "file" as input and returns file and contents', function(done) {
        sass.render({
          file: fixture('include-files/index.scss'),
          success: function(result) {
            assert.equal(result.css.trim(), 'div {\n  color: yellow; }\n\ndiv {\n  color: yellow; }');
            done();
          },
          importer: function(url, prev) {
            return {
              file: prev + url,
              contents: 'div {color: yellow;}'
            };
          }
        });
      });
  
      it('should override imports with "data" as input and fires callback with file', function(done) {
        sass.render({
          data: src,
          success: function(result) {
            assert.equal(result.css.trim(), '');
            done();
          },
          importer: function(url, /* jshint unused:false */ prev, done) {
            done({
              file: path.resolve(path.dirname(fixture('include-files/index.scss')), url + (path.extname(url) ? '' : '.scss'))
            });
          }
        });
      });
  
      it('should override imports with "file" as input and fires callback with file', function(done) {
        sass.render({
          file: fixture('include-files/index.scss'),
          success: function(result) {
            assert.equal(result.css.trim(), '');
            done();
          },
          importer: function(url, prev, done) {
            done({
              file: path.resolve(path.dirname(prev), url + (path.extname(url) ? '' : '.scss'))
            });
          }
        });
      });
  
      it('should override imports with "data" as input and returns file', function(done) {
        sass.render({
          data: src,
          success: function(result) {
            assert.equal(result.css.trim(), '');
            done();
          },
          importer: function(url, /* jshint unused:false */ prev) {
            return {
              file: path.resolve(path.dirname(fixture('include-files/index.scss')), url + (path.extname(url) ? '' : '.scss'))
            };
          }
        });
      });
  
      it('should override imports with "file" as input and returns file', function(done) {
        sass.render({
          file: fixture('include-files/index.scss'),
          success: function(result) {
            assert.equal(result.css.trim(), '');
            done();
          },
          importer: function(url, prev) {
            return {
              file: path.resolve(path.dirname(prev), url + (path.extname(url) ? '' : '.scss'))
            };
          }
        });
      });
  	
      it('should override imports with "data" as input and fires callback with contents', function(done) {
        sass.render({
          data: src,
          success: function(result) {
            assert.equal(result.css.trim(), 'div {\n  color: yellow; }\n\ndiv {\n  color: yellow; }');
            done();
          },
          importer: function(url, prev, done) {
            done({
              contents: 'div {color: yellow;}'
            });
          }
        });
      });
  
      it('should override imports with "file" as input and fires callback with contents', function(done) {
        sass.render({
          file: fixture('include-files/index.scss'),
          success: function(result) {
            assert.equal(result.css.trim(), 'div {\n  color: yellow; }\n\ndiv {\n  color: yellow; }');
            done();
          },
          importer: function(url, prev, done) {
            done({
              contents: 'div {color: yellow;}'
            });
          }
        });
      });
  
      it('should override imports with "data" as input and returns contents', function(done) {
        sass.render({
          data: src,
          success: function(result) {
            assert.equal(result.css.trim(), 'div {\n  color: yellow; }\n\ndiv {\n  color: yellow; }');
            done();
          },
          importer: function() {
            return {
              contents: 'div {color: yellow;}'
            };
          }
        });
      });
  
      it('should override imports with "file" as input and returns contents', function(done) {
        sass.render({
          file: fixture('include-files/index.scss'),
          success: function(result) {
            assert.equal(result.css.trim(), 'div {\n  color: yellow; }\n\ndiv {\n  color: yellow; }');
            done();
          },
          importer: function() {
            return {
              contents: 'div {color: yellow;}'
            };
          }
        });
      });
    });
  
    describe('.renderSync(options)', function() {
      it('should compile sass to css with file', function(done) {
        var expected = read(fixture('simple/expected.css'), 'utf8').trim();
        var result = sass.renderSync({file: fixture('simple/index.scss')});
  
        assert.equal(result.css.trim(), expected.replace(/\r\n/g, '\n'));
        done();
      });
  
      it('should compile sass to css with outFile set to absolute url', function(done) {
        var result = sass.renderSync({
          file: fixture('simple/index.scss'),
          sourceMap: true,
          outFile: fixture('simple/index-test.css')
        });
  
        assert.equal(JSON.parse(result.map).file, 'index-test.css');
        done();
      });
  
      it('should compile sass to css with outFile set to relative url', function(done) {
        var result = sass.renderSync({
          file: fixture('simple/index.scss'),
          sourceMap: true,
          outFile: './index-test.css'
        });
  
        assert.equal(JSON.parse(result.map).file, 'index-test.css');
        done();
      });
  
      it('should compile sass to css with outFile and sourceMap set to relative url', function(done) {
        var result = sass.renderSync({
          file: fixture('simple/index.scss'),
          sourceMap: './deep/nested/index.map',
          outFile: './index-test.css'
        });
  
        assert.equal(JSON.parse(result.map).file, '../../index-test.css');
        done();
      });
  
      it('should compile sass to css with data', function(done) {
        var src = read(fixture('simple/index.scss'), 'utf8');
        var expected = read(fixture('simple/expected.css'), 'utf8').trim();
        var result = sass.renderSync({data: src});
  
        assert.equal(result.css.trim(), expected.replace(/\r\n/g, '\n'));
        done();
      });
  
      it('should compile sass to css using indented syntax', function(done) {
        var src = read(fixture('indent/index.sass'), 'utf8');
        var expected = read(fixture('indent/expected.css'), 'utf8').trim();
        var css = sass.renderSync({
          data: src,
          indentedSyntax: true
        }).css.trim();
  
        assert.equal(css, expected.replace(/\r\n/g, '\n'));
        done();
      });
  
      it('should throw error for bad input', function(done) {
        assert.throws(function() {
          sass.renderSync({data: '#navbar width 80%;'});
        });
  
        done();
      });
    });
  
    describe('.renderSync(importer)', function() {
      var src = read(fixture('include-files/index.scss'), 'utf8');
  
      it('should override imports with "data" as input and returns file and contents', function(done) {
        var result = sass.renderSync({
          data: src,
          importer: function(url, prev) {
            return {
              file: prev + url,
              contents: 'div {color: yellow;}'
            };
          }
        });
  
        assert.equal(result.css.trim(), 'div {\n  color: yellow; }\n\ndiv {\n  color: yellow; }');
        done();
      });
  
      it('should override imports with "file" as input and returns file and contents', function(done) {
        var result = sass.renderSync({
          file: fixture('include-files/index.scss'),
          importer: function(url, prev) {
            return {
              file: prev + url,
              contents: 'div {color: yellow;}'
            };
          }
        });
  
        assert.equal(result.css.trim(), 'div {\n  color: yellow; }\n\ndiv {\n  color: yellow; }');
        done();
      });
  
      it('should override imports with "data" as input and returns file', function(done) {
        var result = sass.renderSync({
          data: src,
          importer: function(url, /* jshint unused:false */ prev) {
            return {
              file: path.resolve(path.dirname(fixture('include-files/index.scss')), url + (path.extname(url) ? '' : '.scss'))
            };
          }
        });
  
        assert.equal(result.css.trim(), '');
        done();
      });
  
      it('should override imports with "file" as input and returns file', function(done) {
        var result = sass.renderSync({
          file: fixture('include-files/index.scss'),
          importer: function(url, prev) {
            return {
              file: path.resolve(path.dirname(prev), url + (path.extname(url) ? '' : '.scss'))
            };
          }
        });
  
        assert.equal(result.css.trim(), '');
        done();
      });
  	
      it('should override imports with "data" as input and returns contents', function(done) {
        var result = sass.renderSync({
          data: src,
          importer: function() {
            return {
              contents: 'div {color: yellow;}'
            };
          }
        });
  
        assert.equal(result.css.trim(), 'div {\n  color: yellow; }\n\ndiv {\n  color: yellow; }');
        done();
      });
  
      it('should override imports with "file" as input and returns contents', function(done) {
        var result = sass.renderSync({
          file: fixture('include-files/index.scss'),
          importer: function() {
            return {
              contents: 'div {color: yellow;}'
            };
          }
        });
  
        assert.equal(result.css.trim(), 'div {\n  color: yellow; }\n\ndiv {\n  color: yellow; }');
        done();
      });
    });
  
    describe('.render({stats: {}})', function() {
      var start = Date.now();
  
      it('should provide a start timestamp', function(done) {
        sass.render({
          file: fixture('include-files/index.scss'),
          success: function(result) {
            assert(typeof result.stats.start === 'number');
            assert(result.stats.start >= start);
            done();
          },
          error: function(err) {
            assert(!err);
            done();
          }
        });
      });
  
      it('should provide an end timestamp', function(done) {
        sass.render({
          file: fixture('include-files/index.scss'),
          success: function(result) {
            assert(typeof result.stats.end === 'number');
            assert(result.stats.end >= result.stats.start);
            done();
          },
          error: function(err) {
            assert(!err);
            done();
          }
        });
      });
  
      it('should provide a duration', function(done) {
        sass.render({
          file: fixture('include-files/index.scss'),
          success: function(result) {
            assert(typeof result.stats.duration === 'number');
            assert.equal(result.stats.end - result.stats.start, result.stats.duration);
            done();
          },
          error: function(err) {
            assert(!err);
            done();
          }
        });
      });
  
      it('should contain the given entry file', function(done) {
        sass.render({
          file: fixture('include-files/index.scss'),
          success: function(result) {
            assert.equal(result.stats.entry, fixture('include-files/index.scss'));
            done();
          },
          error: function(err) {
            assert(!err);
            done();
          }
        });
      });
  
      it('should contain an array of all included files', function(done) {
        var expected = [
          fixture('include-files/bar.scss').replace(/\\/g, '/'),
          fixture('include-files/foo.scss').replace(/\\/g, '/'),
          fixture('include-files/index.scss').replace(/\\/g, '/')
        ];
  
        sass.render({
          file: fixture('include-files/index.scss'),
          success: function(result) {
            assert.deepEqual(result.stats.includedFiles, expected);
            done();
          },
          error: function(err) {
            assert(!err);
            done();
          }
        });
      });
  
      it('should contain array with the entry if there are no import statements', function(done) {
        var expected = fixture('simple/index.scss').replace(/\\/g, '/');
  
        sass.render({
          file: fixture('simple/index.scss'),
          success: function(result) {
            assert.deepEqual(result.stats.includedFiles, [expected]);
            done();
          }
        });
      });
  
      it('should state `data` as entry file', function(done) {
        sass.render({
          data: read(fixture('simple/index.scss'), 'utf8'),
          success: function(result) {
            assert.equal(result.stats.entry, 'data');
            done();
          }
        });
      });
  
      it('should contain an empty array as includedFiles', function(done) {
        sass.render({
          data: read(fixture('simple/index.scss'), 'utf8'),
          success: function(result) {
            assert.deepEqual(result.stats.includedFiles, []);
            done();
          }
        });
      });
    });
  
    describe('.renderSync({stats: {}})', function() {
      var start = Date.now();
      var result = sass.renderSync({
        file: fixture('include-files/index.scss')
      });
  
      it('should provide a start timestamp', function(done) {
        assert(typeof result.stats.start === 'number');
        assert(result.stats.start >= start);
        done();
      });
  
      it('should provide an end timestamp', function(done) {
        assert(typeof result.stats.end === 'number');
        assert(result.stats.end >= result.stats.start);
        done();
      });
  
      it('should provide a duration', function(done) {
        assert(typeof result.stats.duration === 'number');
        assert.equal(result.stats.end - result.stats.start, result.stats.duration);
        done();
      });
  
      it('should contain the given entry file', function(done) {
        assert.equal(result.stats.entry, resolveFixture('include-files/index.scss'));
        done();
      });
  
      it('should contain an array of all included files', function(done) {
        var expected = [
          fixture('include-files/bar.scss').replace(/\\/g, '/'),
          fixture('include-files/foo.scss').replace(/\\/g, '/'),
          fixture('include-files/index.scss').replace(/\\/g, '/')
        ];
  
        assert.equal(result.stats.includedFiles[0], expected[0]);
        assert.equal(result.stats.includedFiles[1], expected[1]);
        assert.equal(result.stats.includedFiles[2], expected[2]);
        done();
      });
  
      it('should contain array with the entry if there are no import statements', function(done) {
        var expected = fixture('simple/index.scss').replace(/\\/g, '/');
  
        var result = sass.renderSync({
          file: fixture('simple/index.scss')
        });
  
        assert.deepEqual(result.stats.includedFiles, [expected]);
        done();
      });
  
      it('should state `data` as entry file', function(done) {
        var result = sass.renderSync({
          data: read(fixture('simple/index.scss'), 'utf8')
        });
  
        assert.equal(result.stats.entry, 'data');
        done();
      });
  
      it('should contain an empty array as includedFiles', function(done) {
        var result = sass.renderSync({
          data: read(fixture('simple/index.scss'), 'utf8')
        });
  
        assert.deepEqual(result.stats.includedFiles, []);
        done();
      });
    });
  
    describe('.info()', function() {
      it('should return a correct version info', function(done) {
        assert.equal(sass.info(), [
          'node-sass version: ' + require('../package.json').version, 
          'libsass version: ' + require('../package.json').libsass 
        ].join('\n'));
  
        done();
      });
    });
  });
  