From 43106236cce7c78061fbd6a198269fc9d7beb782 Mon Sep 17 00:00:00 2001 From: xzyfer Date: Tue, 31 Jan 2017 20:06:40 +1100 Subject: [PATCH 1/2] Restore behaviour of cwd in include path Traditionally Sass has added the cwd as the first include path. This behaviour was remove in Sass 3.4, and recently in LibSass 3.5.0.beta.2. People depend on this behaviour and as a result a lot of compilations are now failing. This PR restores the expected behaviour and adds a test to boot. Fixes #1876 --- lib/index.js | 5 +++++ test/api.js | 17 +++++++++++++++++ test/fixtures/cwd-include-path/expected.css | 2 ++ test/fixtures/cwd-include-path/outside.scss | 3 +++ test/fixtures/cwd-include-path/root/index.scss | 1 + 5 files changed, 28 insertions(+) create mode 100644 test/fixtures/cwd-include-path/expected.css create mode 100644 test/fixtures/cwd-include-path/outside.scss create mode 100644 test/fixtures/cwd-include-path/root/index.scss diff --git a/lib/index.js b/lib/index.js index 4d880a8f5..fafbe55f2 100644 --- a/lib/index.js +++ b/lib/index.js @@ -171,6 +171,11 @@ function buildIncludePaths(options) { ); } + // Preserve the behaviour people have come to expect. + // This behaviour was removed from Sass in 3.4 and + // LibSass in 3.5. + options.includePaths.unshift(process.cwd()); + return options.includePaths.join(path.delimiter); } diff --git a/test/api.js b/test/api.js index 8ff5a972d..67a53ccb3 100644 --- a/test/api.js +++ b/test/api.js @@ -142,6 +142,23 @@ describe('api', function() { }); }); + it('should add cwd to the front on include paths', function(done) { + var src = fixture('cwd-include-path/root/index.scss'); + var expected = read(fixture('cwd-include-path/expected.css'), 'utf8').trim(); + var cwd = process.cwd(); + + process.chdir(fixture('cwd-include-path')); + sass.render({ + file: src, + includePaths: [] + }, function(error, result) { + assert.equal(result.css.toString().trim(), expected.replace(/\r\n/g, '\n')); + + process.chdir(cwd); + done(); + }); + }); + it('should check SASS_PATH in the specified order', function(done) { var src = read(fixture('sass-path/index.scss'), 'utf8'); var expectedRed = read(fixture('sass-path/expected-red.css'), 'utf8').trim(); diff --git a/test/fixtures/cwd-include-path/expected.css b/test/fixtures/cwd-include-path/expected.css new file mode 100644 index 000000000..1cfd35a4a --- /dev/null +++ b/test/fixtures/cwd-include-path/expected.css @@ -0,0 +1,2 @@ +.outside { + color: red; } diff --git a/test/fixtures/cwd-include-path/outside.scss b/test/fixtures/cwd-include-path/outside.scss new file mode 100644 index 000000000..956862381 --- /dev/null +++ b/test/fixtures/cwd-include-path/outside.scss @@ -0,0 +1,3 @@ +.outside { + color: red; +} diff --git a/test/fixtures/cwd-include-path/root/index.scss b/test/fixtures/cwd-include-path/root/index.scss new file mode 100644 index 000000000..0279f783b --- /dev/null +++ b/test/fixtures/cwd-include-path/root/index.scss @@ -0,0 +1 @@ +@import 'outside'; From 203f8d6627067b1004bad0599989c5849f72f6a0 Mon Sep 17 00:00:00 2001 From: xzyfer Date: Tue, 31 Jan 2017 20:42:38 +1100 Subject: [PATCH 2/2] Mirror render and renderSync tests --- test/api.js | 167 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 152 insertions(+), 15 deletions(-) diff --git a/test/api.js b/test/api.js index 67a53ccb3..e082c9714 100644 --- a/test/api.js +++ b/test/api.js @@ -87,6 +87,19 @@ describe('api', function() { }); }); + 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 + }, function(error, result) { + assert.equal(result.css.toString().trim(), expected.replace(/\r\n/g, '\n')); + done(); + }); + }); + it('should NOT compile empty data string', function(done) { sass.render({ data: '' @@ -96,27 +109,14 @@ describe('api', function() { }); }); - it('should NOT compile without parameters', function(done) { + it('should NOT compile without any input', function(done) { sass.render({ }, function(error) { assert.equal(error.message, 'No input specified: provide a file name or a source string to process'); 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 - }, function(error, result) { - assert.equal(result.css.toString().trim(), expected.replace(/\r\n/g, '\n')); - done(); - }); - }); - - it('should throw error status 1 for bad input', function(done) { + it('should returnn error status 1 for bad input', function(done) { sass.render({ data: '#navbar width 80%;' }, function(error) { @@ -1406,6 +1406,143 @@ describe('api', function() { 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(); + var result = sass.renderSync({ + data: src, + includePaths: [ + fixture('include-path/functions'), + fixture('include-path/lib') + ] + }); + + assert.equal(result.css.toString().trim(), expected.replace(/\r\n/g, '\n')); + done(); + }); + + it('should add cwd to the front on include paths', function(done) { + var src = fixture('cwd-include-path/root/index.scss'); + var expected = read(fixture('cwd-include-path/expected.css'), 'utf8').trim(); + var cwd = process.cwd(); + + process.chdir(fixture('cwd-include-path')); + var result = sass.renderSync({ + file: src, + includePaths: [ + fixture('include-path/functions'), + fixture('include-path/lib') + ] + }); + process.chdir(cwd); + + assert.equal(result.css.toString().trim(), expected.replace(/\r\n/g, '\n')); + done(); + }); + + it('should check SASS_PATH in the specified order', function(done) { + var src = read(fixture('sass-path/index.scss'), 'utf8'); + var expectedRed = read(fixture('sass-path/expected-red.css'), 'utf8').trim(); + var expectedOrange = read(fixture('sass-path/expected-orange.css'), 'utf8').trim(); + + var envIncludes = [ + fixture('sass-path/red'), + fixture('sass-path/orange') + ]; + + process.env.SASS_PATH = envIncludes.join(path.delimiter); + var result = sass.renderSync({ + data: src, + includePaths: [] + }); + + assert.equal(result.css.toString().trim(), expectedRed.replace(/\r\n/g, '\n')); + + process.env.SASS_PATH = envIncludes.reverse().join(path.delimiter); + result = sass.renderSync({ + data: src, + includePaths: [] + }); + + assert.equal(result.css.toString().trim(), expectedOrange.replace(/\r\n/g, '\n')); + done(); + }); + + it('should prefer include path over SASS_PATH', function(done) { + var src = read(fixture('sass-path/index.scss'), 'utf8'); + var expectedRed = read(fixture('sass-path/expected-red.css'), 'utf8').trim(); + var expectedOrange = read(fixture('sass-path/expected-orange.css'), 'utf8').trim(); + + var envIncludes = [ + fixture('sass-path/red') + ]; + process.env.SASS_PATH = envIncludes.join(path.delimiter); + + var result = sass.renderSync({ + data: src, + includePaths: [] + }); + + assert.equal(result.css.toString().trim(), expectedRed.replace(/\r\n/g, '\n')); + + result = sass.renderSync({ + data: src, + includePaths: [fixture('sass-path/orange')] + }); + + assert.equal(result.css.toString().trim(), expectedOrange.replace(/\r\n/g, '\n')); + 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(); + var result = sass.renderSync({ + data: src, + precision: 10 + }); + + assert.equal(result.css.toString().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, '/') + ]; + + var result = sass.renderSync({ + data: src, + includePaths: [fixture('include-files')] + }); + + assert.deepEqual(result.stats.includedFiles, expected); + done(); + }); + + it('should render with indentWidth and indentType options', function(done) { + var result = sass.renderSync({ + data: 'div { color: transparent; }', + indentWidth: 7, + indentType: 'tab' + }); + + assert.equal(result.css.toString().trim(), 'div {\n\t\t\t\t\t\t\tcolor: transparent; }'); + done(); + }); + + it('should render with linefeed option', function(done) { + var result = sass.renderSync({ + data: 'div { color: transparent; }', + linefeed: 'lfcr' + }); + + assert.equal(result.css.toString().trim(), 'div {\n\r color: transparent; }'); + done(); + }); }); describe('.renderSync(importer)', function() {