diff --git a/.eslintrc.json b/.eslintrc.json index 99af1fe5342..d3c9e011a87 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -13,5 +13,8 @@ "globals": { "parcelRequire": true, "define": true + }, + "rules": { + "no-return-await": "error" } } diff --git a/CHANGELOG.md b/CHANGELOG.md index ce7d382d42e..7e904a13617 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ and parcel adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). - Add support for HMR with elm-hot [Details](https://github.com/parcel-bundler/parcel/pull/2388) - Log dev server access for log level verbose or more [Details](https://github.com/parcel-bundler/parcel/pull/2402) - Process array of assets for JSON-LD [Details](https://github.com/parcel-bundler/parcel/pull/2319) -- Extract workerfarm into seperate package [Details](https://github.com/parcel-bundler/parcel/pull/2162) +- Extract workerfarm into separate package [Details](https://github.com/parcel-bundler/parcel/pull/2162) - Extract Logger into its own package [Details](https://github.com/parcel-bundler/parcel/pull/2165) - Extract watcher into its own package [Details](https://github.com/parcel-bundler/parcel/pull/2176) - Merge fs-watcher-child into Parcel's monorepo [Details](https://github.com/parcel-bundler/parcel/pull/2197) @@ -538,7 +538,7 @@ and parcel adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). - Opencollective [Details](https://github.com/parcel-bundler/parcel/commit/0f554dc2f5c8f2557ec84eee5301b90ffb279764) - Use `JSON5` to parse config files [Details](https://github.com/parcel-bundler/parcel/commit/bd458660ce38e7a1d25bd9758084acc24418e054) -- Move JSAsset options gathering into seperate function [Details](https://github.com/parcel-bundler/parcel/commit/333c3aa5d20f98a5f3c52635751032d12854c13c) +- Move JSAsset options gathering into separate function [Details](https://github.com/parcel-bundler/parcel/commit/333c3aa5d20f98a5f3c52635751032d12854c13c) ### Fixed diff --git a/README.md b/README.md index 68c4d2000f0..cbe0d6d3fd2 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ or with npm: npm install -g parcel-bundler ``` -2. Parcel can take any type of file as an entry point, but an HTML or JavaScript file is a good place to start. If you link your main JavaScript file in the HTML using a relative path, Parcel will also process it for you, and replace the reference with a URL to the output file. +2. Parcel can take any type of file as an entry point, but a HTML or JavaScript file is a good place to start. If you link your main JavaScript file in the HTML using a relative path, Parcel will also process it for you, and replace the reference with a URL to the output file. ```html @@ -46,7 +46,7 @@ npm install -g parcel-bundler ``` -3. Parcel has a development server built in, which will automatically rebuild your app as you change files and supports hot module replacement for fast development. Just point it at your entry file: +3. Parcel has a development server built in which will automatically rebuild your app as you change files and supports hot module replacement for fast development. Just point it at your entry file: ```shell parcel index.html diff --git a/packages/core/fs/package.json b/packages/core/fs/package.json index 8c7ae89f88b..05489f28cd7 100644 --- a/packages/core/fs/package.json +++ b/packages/core/fs/package.json @@ -11,6 +11,9 @@ "engines": { "node": ">= 6.0.0" }, + "publishConfig": { + "access": "public" + }, "scripts": { "test": "echo this package has no tests yet", "test-ci": "yarn build && yarn test", diff --git a/packages/core/integration-tests/test/bundler.js b/packages/core/integration-tests/test/bundler.js index 7534f3a5603..3203dcca046 100644 --- a/packages/core/integration-tests/test/bundler.js +++ b/packages/core/integration-tests/test/bundler.js @@ -1,7 +1,12 @@ const assert = require('assert'); const sinon = require('sinon'); const path = require('path'); -const {assertBundleTree, bundle, bundler, nextBundle} = require('./utils'); +const { + assertBundleTree, + bundle, + bundler, + nextBundle +} = require('@parcel/test-utils'); describe('bundler', function() { it('should bundle once before exporting middleware', async function() { diff --git a/packages/core/integration-tests/test/contentHashing.js b/packages/core/integration-tests/test/contentHashing.js index 9dc279db394..584677c07c9 100644 --- a/packages/core/integration-tests/test/contentHashing.js +++ b/packages/core/integration-tests/test/contentHashing.js @@ -1,7 +1,7 @@ const assert = require('assert'); const path = require('path'); const fs = require('@parcel/fs'); -const {bundle, rimraf, ncp} = require('./utils'); +const {bundle, rimraf, ncp} = require('@parcel/test-utils'); describe('content hashing', function() { beforeEach(async function() { diff --git a/packages/core/integration-tests/test/css.js b/packages/core/integration-tests/test/css.js index 44be2354224..d55db7e807f 100644 --- a/packages/core/integration-tests/test/css.js +++ b/packages/core/integration-tests/test/css.js @@ -1,7 +1,13 @@ const assert = require('assert'); const path = require('path'); const fs = require('@parcel/fs'); -const {bundle, run, assertBundleTree, rimraf, ncp} = require('./utils'); +const { + bundle, + run, + assertBundleTree, + rimraf, + ncp +} = require('@parcel/test-utils'); describe('css', function() { it('should produce two bundles when importing a CSS file', async function() { @@ -12,12 +18,16 @@ describe('css', function() { assets: ['index.js', 'index.css', 'local.js', 'local.css'], childBundles: [ { - name: 'index.map' + name: 'index.js.map' }, { name: 'index.css', assets: ['index.css', 'local.css'], - childBundles: [] + childBundles: [ + { + type: 'map' + } + ] } ] }); @@ -44,21 +54,30 @@ describe('css', function() { ], childBundles: [ { + type: 'css', name: 'index.css', assets: ['index.css'], - childBundles: [] + childBundles: [ + { + type: 'map' + } + ] }, { - type: 'map' + name: 'index.js.map' }, { type: 'js', - assets: ['local.js', 'local.css'], + assets: ['local.css', 'local.js'], childBundles: [ { type: 'css', assets: ['local.css'], - childBundles: [] + childBundles: [ + { + type: 'map' + } + ] }, { type: 'map' @@ -85,10 +104,14 @@ describe('css', function() { { name: 'index.css', assets: ['index.css', 'other.css', 'local.css'], - childBundles: [] + childBundles: [ + { + type: 'map' + } + ] }, { - name: 'index.map', + name: 'index.js.map', type: 'map' } ] @@ -118,7 +141,11 @@ describe('css', function() { { name: 'index.css', assets: ['index.css'], - childBundles: [] + childBundles: [ + { + type: 'map' + } + ] }, { type: 'map' @@ -173,7 +200,11 @@ describe('css', function() { { name: 'index.css', assets: ['index.css'], - childBundles: [] + childBundles: [ + { + type: 'map' + } + ] }, { type: 'map' @@ -213,6 +244,54 @@ describe('css', function() { ); }); + it('should support linking to assets in parent folders with url() from CSS', async function() { + let b = await bundle( + [ + path.join(__dirname, '/integration/css-url-relative/src/a/style1.css'), + path.join(__dirname, '/integration/css-url-relative/src/b/style2.css') + ], + { + production: true, + sourceMaps: false + } + ); + + await assertBundleTree(b, [ + { + type: 'css', + assets: ['style1.css'], + childBundles: [ + { + type: 'png' + } + ] + }, + { + type: 'css', + assets: ['style2.css'] + } + ]); + + let css = await fs.readFile( + path.join(__dirname, '/dist/a/style1.css'), + 'utf8' + ); + + assert(css.includes('background-image'), 'includes `background-image`'); + assert(/url\([^)]*\)/.test(css), 'includes url()'); + + assert( + await fs.exists( + path.join( + __dirname, + path.dirname('/dist/a/style1.css'), + css.match(/url\(([^)]*)\)/)[1] + ) + ), + 'path specified in url() exists' + ); + }); + it('should support transforming with postcss', async function() { let b = await bundle(path.join(__dirname, '/integration/postcss/index.js')); @@ -223,7 +302,11 @@ describe('css', function() { { name: 'index.css', assets: ['index.css'], - childBundles: [] + childBundles: [ + { + type: 'map' + } + ] }, { type: 'map' @@ -235,9 +318,9 @@ describe('css', function() { assert.equal(typeof output, 'function'); let value = output(); - assert(/_index_[0-9a-z]+_1/.test(value)); + assert(/_index_[0-9a-z]/.test(value)); - let cssClass = value.match(/(_index_[0-9a-z]+_1)/)[1]; + let cssClass = value.match(/(_index_[0-9a-z]+)/)[1]; let css = await fs.readFile( path.join(__dirname, '/dist/index.css'), @@ -259,6 +342,227 @@ describe('css', function() { assert.equal(run1(), run2()); }); + it('should support postcss composes imports', async function() { + let b = await bundle( + path.join(__dirname, '/integration/postcss-composes/index.js') + ); + + await assertBundleTree(b, { + name: 'index.js', + assets: ['index.js', 'composes-1.css', 'composes-2.css', 'mixins.css'], + childBundles: [ + { + name: 'index.css', + assets: ['composes-1.css', 'composes-2.css', 'mixins.css'], + childBundles: [ + { + type: 'map' + } + ] + }, + { + type: 'map' + } + ] + }); + + let output = await run(b); + assert.equal(typeof output, 'function'); + + let value = output(); + const composes1Classes = value.composes1.split(' '); + const composes2Classes = value.composes2.split(' '); + assert(composes1Classes[0].startsWith('_composes1_')); + assert(composes1Classes[1].startsWith('_test_')); + assert(composes2Classes[0].startsWith('_composes2_')); + assert(composes2Classes[1].startsWith('_test_')); + + let css = await fs.readFile( + path.join(__dirname, '/dist/index.css'), + 'utf8' + ); + let cssClass1 = value.composes1.match(/(_composes1_[0-9a-z]+)/)[1]; + assert(css.includes(`.${cssClass1}`)); + let cssClass2 = value.composes2.match(/(_composes2_[0-9a-z]+)/)[1]; + assert(css.includes(`.${cssClass2}`)); + }); + + it('should not include css twice for postcss composes imports', async function() { + let b = await bundle( + path.join(__dirname, '/integration/postcss-composes/index.js') + ); + + await run(b); + + let css = await fs.readFile( + path.join(__dirname, '/dist/index.css'), + 'utf8' + ); + assert.equal( + css.indexOf('height: 100px;'), + css.lastIndexOf('height: 100px;') + ); + }); + + it('should support postcss composes imports for sass', async function() { + let b = await bundle( + path.join(__dirname, '/integration/postcss-composes/index2.js') + ); + + await assertBundleTree(b, { + name: 'index2.js', + assets: ['index2.js', 'composes-3.css', 'mixins.scss'], + childBundles: [ + { + name: 'index2.css', + assets: ['composes-3.css', 'mixins.scss'], + childBundles: [ + { + type: 'map' + } + ] + }, + { + type: 'map' + } + ] + }); + + let output = await run(b); + assert.equal(typeof output, 'function'); + + let value = output(); + const composes3Classes = value.composes3.split(' '); + assert(composes3Classes[0].startsWith('_composes3_')); + assert(composes3Classes[1].startsWith('_test_')); + + let css = await fs.readFile( + path.join(__dirname, '/dist/index2.css'), + 'utf8' + ); + assert(css.includes('height: 200px;')); + }); + + it('should support postcss composes imports with custom path names', async function() { + let b = await bundle( + path.join(__dirname, '/integration/postcss-composes/index3.js') + ); + + await assertBundleTree(b, { + name: 'index3.js', + assets: ['index3.js', 'composes-4.css', 'mixins.css'], + childBundles: [ + { + name: 'index3.css', + assets: ['composes-4.css', 'mixins.css'], + childBundles: [ + { + type: 'map' + } + ] + }, + { + type: 'map' + } + ] + }); + + let output = await run(b); + assert.equal(typeof output, 'function'); + + let value = output(); + const composes4Classes = value.composes4.split(' '); + assert(composes4Classes[0].startsWith('_composes4_')); + assert(composes4Classes[1].startsWith('_test_')); + + let css = await fs.readFile( + path.join(__dirname, '/dist/index3.css'), + 'utf8' + ); + assert(css.includes('height: 100px;')); + }); + + it('should support deep nested postcss composes imports', async function() { + let b = await bundle( + path.join(__dirname, '/integration/postcss-composes/index4.js') + ); + + await assertBundleTree(b, { + name: 'index4.js', + assets: [ + 'index4.js', + 'composes-5.css', + 'mixins-intermediate.css', + 'mixins.css' + ], + childBundles: [ + { + name: 'index4.css', + assets: ['composes-5.css', 'mixins-intermediate.css', 'mixins.css'], + childBundles: [ + { + type: 'map' + } + ] + }, + { + type: 'map' + } + ] + }); + + let output = await run(b); + assert.equal(typeof output, 'function'); + + let value = output(); + const composes5Classes = value.composes5.split(' '); + assert(composes5Classes[0].startsWith('_composes5_')); + assert(composes5Classes[1].startsWith('_intermediate_')); + assert(composes5Classes[2].startsWith('_test_')); + + let css = await fs.readFile( + path.join(__dirname, '/dist/index4.css'), + 'utf8' + ); + assert(css.includes('height: 100px;')); + assert(css.includes('height: 300px;')); + assert(css.indexOf('._test_') < css.indexOf('._intermediate_')); + }); + + it('should support postcss composes imports for multiple selectors', async function() { + let b = await bundle( + path.join(__dirname, '/integration/postcss-composes/index5.js') + ); + + await assertBundleTree(b, { + name: 'index5.js', + assets: ['index5.js', 'composes-6.css', 'mixins.css'], + childBundles: [ + { + name: 'index5.css', + assets: ['composes-6.css', 'mixins.css'], + childBundles: [ + { + type: 'map' + } + ] + }, + { + type: 'map' + } + ] + }); + + let output = await run(b); + assert.equal(typeof output, 'function'); + + let value = output(); + const composes6Classes = value.composes6.split(' '); + assert(composes6Classes[0].startsWith('_composes6_')); + assert(composes6Classes[1].startsWith('_test_')); + assert(composes6Classes[2].startsWith('_test-2_')); + }); + it('should minify CSS in production mode', async function() { let b = await bundle( path.join(__dirname, '/integration/cssnano/index.js'), @@ -277,7 +581,7 @@ describe('css', function() { ); assert(css.includes('.local')); assert(css.includes('.index')); - assert(!css.includes('\n')); + assert.equal(css.split('\n').length, 2); // sourceMappingURL }); it('should automatically install postcss plugins with npm if needed', async function() { diff --git a/packages/core/integration-tests/test/elm.js b/packages/core/integration-tests/test/elm.js index 4ab71a716db..972c5a3a4a0 100644 --- a/packages/core/integration-tests/test/elm.js +++ b/packages/core/integration-tests/test/elm.js @@ -1,6 +1,6 @@ const assert = require('assert'); const fs = require('@parcel/fs'); -const {bundle, assertBundleTree, run} = require('./utils'); +const {bundle, assertBundleTree, run} = require('@parcel/test-utils'); describe('elm', function() { it('should produce a basic Elm bundle', async function() { diff --git a/packages/core/integration-tests/test/encodedURI.js b/packages/core/integration-tests/test/encodedURI.js index 8450f167962..4aecc42eff2 100644 --- a/packages/core/integration-tests/test/encodedURI.js +++ b/packages/core/integration-tests/test/encodedURI.js @@ -1,7 +1,7 @@ const assert = require('assert'); const path = require('path'); const fs = require('@parcel/fs'); -const {bundle, assertBundleTree} = require('./utils'); +const {bundle, assertBundleTree} = require('@parcel/test-utils'); describe('encodedURI', function() { it('should support bundling files which names in encoded URI', async function() { diff --git a/packages/core/integration-tests/test/fs.js b/packages/core/integration-tests/test/fs.js index 1bfa96c2721..f466d80218f 100644 --- a/packages/core/integration-tests/test/fs.js +++ b/packages/core/integration-tests/test/fs.js @@ -1,7 +1,7 @@ const assert = require('assert'); const fs = require('@parcel/fs'); const path = require('path'); -const {bundle, run, assertBundleTree} = require('./utils'); +const {bundle, run, assertBundleTree} = require('@parcel/test-utils'); describe('fs', function() { describe('--target=browser', function() { diff --git a/packages/core/integration-tests/test/glob.js b/packages/core/integration-tests/test/glob.js index 9663d7be4b6..96b4582bc29 100644 --- a/packages/core/integration-tests/test/glob.js +++ b/packages/core/integration-tests/test/glob.js @@ -1,7 +1,7 @@ const assert = require('assert'); const fs = require('@parcel/fs'); const path = require('path'); -const {bundle, run, assertBundleTree} = require('./utils'); +const {bundle, run, assertBundleTree} = require('@parcel/test-utils'); describe('glob', function() { it('should require a glob of files', async function() { @@ -54,7 +54,11 @@ describe('glob', function() { { name: 'index.css', assets: ['index.css', 'other.css', 'local.css'], - childBundles: [] + childBundles: [ + { + type: 'map' + } + ] }, { type: 'map' diff --git a/packages/core/integration-tests/test/glsl.js b/packages/core/integration-tests/test/glsl.js index b8b1db9e3db..e16f033f638 100644 --- a/packages/core/integration-tests/test/glsl.js +++ b/packages/core/integration-tests/test/glsl.js @@ -1,7 +1,12 @@ const assert = require('assert'); const path = require('path'); const fs = require('@parcel/fs'); -const {bundle, run, assertBundleTree, normaliseNewlines} = require('./utils'); +const { + bundle, + run, + assertBundleTree, + normaliseNewlines +} = require('@parcel/test-utils'); describe('glsl', function() { it('should support requiring GLSL files via glslify', async function() { diff --git a/packages/core/integration-tests/test/graphql.js b/packages/core/integration-tests/test/graphql.js index 4c890f7b1dc..2a90d4b22ba 100644 --- a/packages/core/integration-tests/test/graphql.js +++ b/packages/core/integration-tests/test/graphql.js @@ -1,7 +1,7 @@ const assert = require('assert'); const path = require('path'); const gql = require('graphql-tag'); -const {bundle, run, assertBundleTree} = require('./utils'); +const {bundle, run, assertBundleTree} = require('@parcel/test-utils'); describe('graphql', function() { it('should support requiring graphql files', async function() { diff --git a/packages/core/integration-tests/test/hmr.js b/packages/core/integration-tests/test/hmr.js index e06276c6e30..0fe734ce817 100644 --- a/packages/core/integration-tests/test/hmr.js +++ b/packages/core/integration-tests/test/hmr.js @@ -1,7 +1,7 @@ const assert = require('assert'); const fs = require('@parcel/fs'); const path = require('path'); -const {bundler, run, rimraf, ncp} = require('./utils'); +const {bundler, run, rimraf, ncp} = require('@parcel/test-utils'); const {sleep} = require('@parcel/test-utils'); const WebSocket = require('ws'); const json5 = require('json5'); @@ -287,6 +287,37 @@ describe('hmr', function() { assert.deepEqual(outputs, [3, 10]); }); + it('should work with circular dependencies', async function() { + await ncp( + path.join(__dirname, '/integration/hmr-circular'), + path.join(__dirname, '/input') + ); + + b = bundler(path.join(__dirname, '/input/index.js'), { + watch: true, + hmr: true + }); + let bundle = await b.bundle(); + let outputs = []; + + await run(bundle, { + output(o) { + outputs.push(o); + } + }); + + assert.deepEqual(outputs, [3]); + + await sleep(100); + fs.writeFile( + path.join(__dirname, '/input/local.js'), + "var other = require('./index.js'); exports.a = 5; exports.b = 5;" + ); + + await nextEvent(b, 'bundled'); + assert.deepEqual(outputs, [3, 10]); + }); + it('should call dispose and accept callbacks', async function() { await ncp( path.join(__dirname, '/integration/hmr-callbacks'), @@ -361,6 +392,45 @@ describe('hmr', function() { assert.deepEqual(outputs, [3, 10]); }); + it('should bubble up HMR events to a page reload', async function() { + await ncp( + path.join(__dirname, '/integration/hmr-reload'), + path.join(__dirname, '/input') + ); + + b = bundler(path.join(__dirname, '/input/index.js'), { + watch: true, + hmr: true + }); + let bundle = await b.bundle(); + + let outputs = []; + let ctx = await run( + bundle, + { + output(o) { + outputs.push(o); + } + }, + {require: false} + ); + let spy = sinon.spy(ctx.location, 'reload'); + + await sleep(50); + assert.deepEqual(outputs, [3]); + assert(spy.notCalled); + + await sleep(100); + fs.writeFile( + path.join(__dirname, '/input/local.js'), + 'exports.a = 5; exports.b = 5;' + ); + + await nextEvent(b, 'bundled'); + assert.deepEqual(outputs, [3]); + assert(spy.calledOnce); + }); + it('should log emitted errors and show an error overlay', async function() { await ncp( path.join(__dirname, '/integration/commonjs'), @@ -529,4 +599,56 @@ describe('hmr', function() { await buildEnd; }); + + it('should watch new dependencies that cause errors', async function() { + await ncp( + path.join(__dirname, '/integration/elm-dep-error'), + path.join(__dirname, '/input') + ); + + b = bundler(path.join(__dirname, '/input/index.js'), { + watch: true, + hmr: true + }); + await b.bundle(); + + ws = new WebSocket('ws://localhost:' + b.options.hmrPort); + + const buildEnd = nextEvent(b, 'buildEnd'); + + await sleep(100); + fs.writeFile( + path.join(__dirname, '/input/src/Main.elm'), + ` +module Main exposing (main) + +import BrokenDep +import Html + +main = + Html.text "Hello, world!" + ` + ); + + let msg = JSON.parse(await nextEvent(ws, 'message')); + assert.equal(msg.type, 'error'); + + await sleep(100); + fs.writeFile( + path.join(__dirname, '/input/src/BrokenDep.elm'), + ` +module BrokenDep exposing (anError) + + +anError : String +anError = + "fixed" + ` + ); + + msg = JSON.parse(await nextEvent(ws, 'message')); + assert.equal(msg.type, 'error-resolved'); + + await buildEnd; + }); }); diff --git a/packages/core/integration-tests/test/html.js b/packages/core/integration-tests/test/html.js index ed3962951e4..30921296ef8 100644 --- a/packages/core/integration-tests/test/html.js +++ b/packages/core/integration-tests/test/html.js @@ -1,6 +1,6 @@ const assert = require('assert'); const fs = require('@parcel/fs'); -const {bundle, assertBundleTree} = require('./utils'); +const {bundle, assertBundleTree} = require('@parcel/test-utils'); const path = require('path'); describe('html', function() { @@ -24,7 +24,11 @@ describe('html', function() { { type: 'css', assets: ['index.css'], - childBundles: [] + childBundles: [ + { + type: 'map' + } + ] }, { type: 'html', @@ -151,7 +155,11 @@ describe('html', function() { { type: 'css', assets: ['index.css'], - childBundles: [] + childBundles: [ + { + type: 'map' + } + ] }, { type: 'map' @@ -185,7 +193,11 @@ describe('html', function() { { type: 'css', assets: ['index.css'], - childBundles: [] + childBundles: [ + { + type: 'map' + } + ] }, { type: 'map' @@ -219,9 +231,6 @@ describe('html', function() { type: 'css', assets: ['index.css'], childBundles: [ - { - type: 'map' - }, { type: 'js', assets: [ @@ -230,7 +239,14 @@ describe('html', function() { 'css-loader.js', 'hmr-runtime.js' ], - childBundles: [] + childBundles: [ + { + type: 'map' + } + ] + }, + { + type: 'map' } ] } @@ -257,7 +273,11 @@ describe('html', function() { { type: 'css', assets: ['index.css'], - childBundles: [] + childBundles: [ + { + type: 'map' + } + ] }, { type: 'map' @@ -280,16 +300,32 @@ describe('html', function() { }); it('should minify HTML in production mode', async function() { - await bundle(path.join(__dirname, '/integration/htmlnano/index.html'), { + let inputFile = path.join(__dirname, '/integration/htmlnano/index.html'); + await bundle(inputFile, { production: true }); - let html = await fs.readFile( - path.join(__dirname, '/dist/index.html'), - 'utf8' - ); + let inputSize = (await fs.stat(inputFile)).size; + + let outputFile = path.join(__dirname, '/dist/index.html'); + let outputSize = (await fs.stat(outputFile)).size; + + assert(inputSize > outputSize); + + let html = await fs.readFile(outputFile, 'utf8'); assert(html.includes('Other page')); - assert(!html.includes('\n')); + }); + + it('should work with an empty html file', async function() { + let inputFile = path.join(__dirname, '/integration/html-empty/index.html'); + await bundle(inputFile, { + minify: false + }); + + let outputFile = path.join(__dirname, '/dist/index.html'); + + let html = await fs.readFile(outputFile, 'utf8'); + assert.equal(html.length, 0); }); it('should read .htmlnanorc and minify HTML in production mode', async function() { @@ -326,19 +362,23 @@ describe('html', function() { }); it('should not minify default values inside HTML in production mode', async function() { - await bundle( - path.join(__dirname, '/integration/htmlnano-defaults-form/index.html'), - { - production: true - } + let inputFile = path.join( + __dirname, + '/integration/htmlnano-defaults-form/index.html' ); + await bundle(inputFile, { + production: true + }); - let html = await fs.readFile( - path.join(__dirname, '/dist/index.html'), - 'utf8' - ); + let inputSize = (await fs.stat(inputFile)).size; + + let outputFile = path.join(__dirname, '/dist/index.html'); + let outputSize = (await fs.stat(outputFile)).size; + + assert(inputSize > outputSize); + + let html = await fs.readFile(outputFile, 'utf8'); assert(html.includes('')); - assert(!html.includes('\n')); }); it('should not prepend the public path to assets with remote URLs', async function() { diff --git a/packages/core/integration-tests/test/integration/css-url-relative/src/a/style1.css b/packages/core/integration-tests/test/integration/css-url-relative/src/a/style1.css new file mode 100644 index 00000000000..8ad6f805d0d --- /dev/null +++ b/packages/core/integration-tests/test/integration/css-url-relative/src/a/style1.css @@ -0,0 +1,3 @@ +body { + background-image: url('../foo.png'); +} diff --git a/packages/core/integration-tests/test/integration/css-url-relative/src/b/style2.css b/packages/core/integration-tests/test/integration/css-url-relative/src/b/style2.css new file mode 100644 index 00000000000..b05faf8ead0 --- /dev/null +++ b/packages/core/integration-tests/test/integration/css-url-relative/src/b/style2.css @@ -0,0 +1,3 @@ +body { + color: red; +} diff --git a/packages/core/integration-tests/test/integration/css-url-relative/src/foo.png b/packages/core/integration-tests/test/integration/css-url-relative/src/foo.png new file mode 100644 index 00000000000..8a1daa0121d Binary files /dev/null and b/packages/core/integration-tests/test/integration/css-url-relative/src/foo.png differ diff --git a/packages/core/integration-tests/test/integration/elm-dep-error/elm.json b/packages/core/integration-tests/test/integration/elm-dep-error/elm.json new file mode 100644 index 00000000000..dd41cae2a31 --- /dev/null +++ b/packages/core/integration-tests/test/integration/elm-dep-error/elm.json @@ -0,0 +1,24 @@ +{ + "type": "application", + "source-directories": [ + "src" + ], + "elm-version": "0.19.0", + "dependencies": { + "direct": { + "elm/browser": "1.0.0", + "elm/core": "1.0.0", + "elm/html": "1.0.0" + }, + "indirect": { + "elm/json": "1.0.0", + "elm/time": "1.0.0", + "elm/url": "1.0.0", + "elm/virtual-dom": "1.0.0" + } + }, + "test-dependencies": { + "direct": {}, + "indirect": {} + } +} \ No newline at end of file diff --git a/packages/core/integration-tests/test/integration/elm-dep-error/index.js b/packages/core/integration-tests/test/integration/elm-dep-error/index.js new file mode 100644 index 00000000000..61906ed5a66 --- /dev/null +++ b/packages/core/integration-tests/test/integration/elm-dep-error/index.js @@ -0,0 +1,5 @@ +var local = require('./src/Main.elm'); + +module.exports = function () { + return local; +}; \ No newline at end of file diff --git a/packages/core/integration-tests/test/integration/elm-dep-error/src/BrokenDep.elm b/packages/core/integration-tests/test/integration/elm-dep-error/src/BrokenDep.elm new file mode 100644 index 00000000000..b52d49738bd --- /dev/null +++ b/packages/core/integration-tests/test/integration/elm-dep-error/src/BrokenDep.elm @@ -0,0 +1,8 @@ +module BrokenDep exposing (anError) + +{- This module causes a compiler error -} + + +anError : String +anError = + 2 diff --git a/packages/core/integration-tests/test/integration/elm-dep-error/src/Main.elm b/packages/core/integration-tests/test/integration/elm-dep-error/src/Main.elm new file mode 100644 index 00000000000..67393aaa654 --- /dev/null +++ b/packages/core/integration-tests/test/integration/elm-dep-error/src/Main.elm @@ -0,0 +1,7 @@ +module Main exposing (main) + +import Html + + +main = + Html.text "Hello, world!" diff --git a/packages/core/integration-tests/test/integration/globals/index.js b/packages/core/integration-tests/test/integration/globals/index.js index fa6f5ff1411..d036bcb5735 100644 --- a/packages/core/integration-tests/test/integration/globals/index.js +++ b/packages/core/integration-tests/test/integration/globals/index.js @@ -2,7 +2,7 @@ module.exports = function () { return { dir: __dirname, file: __filename, - buf: new Buffer(process.title).toString('base64'), + buf: Buffer.from(process.title).toString('base64'), global: !!global.document }; }; diff --git a/packages/core/integration-tests/test/integration/hmr-circular/index.js b/packages/core/integration-tests/test/integration/hmr-circular/index.js new file mode 100644 index 00000000000..d46510716d1 --- /dev/null +++ b/packages/core/integration-tests/test/integration/hmr-circular/index.js @@ -0,0 +1,11 @@ +var local = require('./local'); + +function run() { + output(local.a + local.b); +} + +module.hot.accept(); + +run(); + +module.exports = 'value'; diff --git a/packages/core/integration-tests/test/integration/hmr-circular/local.js b/packages/core/integration-tests/test/integration/hmr-circular/local.js new file mode 100644 index 00000000000..3bb6f4669b5 --- /dev/null +++ b/packages/core/integration-tests/test/integration/hmr-circular/local.js @@ -0,0 +1,4 @@ +var other = require('./index.js'); + +exports.a = 1; +exports.b = 2; diff --git a/packages/core/integration-tests/test/integration/hmr-dynamic/index.js b/packages/core/integration-tests/test/integration/hmr-dynamic/index.js index 37ed6fb597c..ee3c1d451fb 100644 --- a/packages/core/integration-tests/test/integration/hmr-dynamic/index.js +++ b/packages/core/integration-tests/test/integration/hmr-dynamic/index.js @@ -6,4 +6,6 @@ function run() { }); }; +module.hot.accept(); + run(); diff --git a/packages/core/integration-tests/test/integration/hmr-reload/index.js b/packages/core/integration-tests/test/integration/hmr-reload/index.js new file mode 100644 index 00000000000..bd54fc09f6e --- /dev/null +++ b/packages/core/integration-tests/test/integration/hmr-reload/index.js @@ -0,0 +1,7 @@ +var local = require('./local'); + +function run() { + output(local.a + local.b); +} + +run(); diff --git a/packages/core/integration-tests/test/integration/hmr-reload/local.js b/packages/core/integration-tests/test/integration/hmr-reload/local.js new file mode 100644 index 00000000000..59aa6ffd125 --- /dev/null +++ b/packages/core/integration-tests/test/integration/hmr-reload/local.js @@ -0,0 +1,2 @@ +exports.a = 1; +exports.b = 2; diff --git a/packages/core/integration-tests/test/integration/hmr/index.js b/packages/core/integration-tests/test/integration/hmr/index.js index bd54fc09f6e..21178bc0101 100644 --- a/packages/core/integration-tests/test/integration/hmr/index.js +++ b/packages/core/integration-tests/test/integration/hmr/index.js @@ -4,4 +4,6 @@ function run() { output(local.a + local.b); } +module.hot.accept(); + run(); diff --git a/packages/core/integration-tests/test/integration/html-empty/index.html b/packages/core/integration-tests/test/integration/html-empty/index.html new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/core/integration-tests/test/integration/jsx-hyperapp-no-dep/index.js b/packages/core/integration-tests/test/integration/jsx-hyperapp-no-dep/index.js new file mode 100644 index 00000000000..4a97bbe9739 --- /dev/null +++ b/packages/core/integration-tests/test/integration/jsx-hyperapp-no-dep/index.js @@ -0,0 +1,3 @@ +import * as Hyperapp from 'hyperapp' + +module.exports =
; diff --git a/packages/core/integration-tests/test/integration/jsx-hyperapp-no-dep/package.json b/packages/core/integration-tests/test/integration/jsx-hyperapp-no-dep/package.json new file mode 100644 index 00000000000..352055cdf83 --- /dev/null +++ b/packages/core/integration-tests/test/integration/jsx-hyperapp-no-dep/package.json @@ -0,0 +1,3 @@ +{ + "private": true +} diff --git a/packages/core/integration-tests/test/integration/jsx-nervjs-no-dep/index.js b/packages/core/integration-tests/test/integration/jsx-nervjs-no-dep/index.js new file mode 100644 index 00000000000..9c8f2c81f29 --- /dev/null +++ b/packages/core/integration-tests/test/integration/jsx-nervjs-no-dep/index.js @@ -0,0 +1,3 @@ +import * as Nerv from 'nervjs'; + +module.exports = ; diff --git a/packages/core/integration-tests/test/integration/jsx-nervjs-no-dep/package.json b/packages/core/integration-tests/test/integration/jsx-nervjs-no-dep/package.json new file mode 100644 index 00000000000..352055cdf83 --- /dev/null +++ b/packages/core/integration-tests/test/integration/jsx-nervjs-no-dep/package.json @@ -0,0 +1,3 @@ +{ + "private": true +} diff --git a/packages/core/integration-tests/test/integration/jsx-preact-no-dep/index.js b/packages/core/integration-tests/test/integration/jsx-preact-no-dep/index.js new file mode 100644 index 00000000000..9483f2ef3e4 --- /dev/null +++ b/packages/core/integration-tests/test/integration/jsx-preact-no-dep/index.js @@ -0,0 +1,3 @@ +const Preact = require('preact'); + +module.exports = ; diff --git a/packages/core/integration-tests/test/integration/jsx-preact-no-dep/package.json b/packages/core/integration-tests/test/integration/jsx-preact-no-dep/package.json new file mode 100644 index 00000000000..352055cdf83 --- /dev/null +++ b/packages/core/integration-tests/test/integration/jsx-preact-no-dep/package.json @@ -0,0 +1,3 @@ +{ + "private": true +} diff --git a/packages/core/integration-tests/test/integration/jsx-react-no-dep/index.js b/packages/core/integration-tests/test/integration/jsx-react-no-dep/index.js new file mode 100644 index 00000000000..4f5a71615ed --- /dev/null +++ b/packages/core/integration-tests/test/integration/jsx-react-no-dep/index.js @@ -0,0 +1,3 @@ +import * as React from 'react'; + +module.exports = ; diff --git a/packages/core/integration-tests/test/integration/jsx-react-no-dep/package.json b/packages/core/integration-tests/test/integration/jsx-react-no-dep/package.json new file mode 100644 index 00000000000..352055cdf83 --- /dev/null +++ b/packages/core/integration-tests/test/integration/jsx-react-no-dep/package.json @@ -0,0 +1,3 @@ +{ + "private": true +} diff --git a/packages/core/integration-tests/test/integration/markdown/100x100.png b/packages/core/integration-tests/test/integration/markdown/100x100.png new file mode 100644 index 00000000000..8a1daa0121d Binary files /dev/null and b/packages/core/integration-tests/test/integration/markdown/100x100.png differ diff --git a/packages/core/integration-tests/test/integration/markdown/index.md b/packages/core/integration-tests/test/integration/markdown/index.md new file mode 100644 index 00000000000..d1d6628f15c --- /dev/null +++ b/packages/core/integration-tests/test/integration/markdown/index.md @@ -0,0 +1,5 @@ +# heading1 + +content content content + +[image](./100x100.png) diff --git a/packages/core/integration-tests/test/integration/postcss-composes/.postcssrc b/packages/core/integration-tests/test/integration/postcss-composes/.postcssrc new file mode 100644 index 00000000000..050061e1080 --- /dev/null +++ b/packages/core/integration-tests/test/integration/postcss-composes/.postcssrc @@ -0,0 +1,3 @@ +{ + "modules": true +} diff --git a/packages/core/integration-tests/test/integration/postcss-composes/composes-1.css b/packages/core/integration-tests/test/integration/postcss-composes/composes-1.css new file mode 100644 index 00000000000..547498770fc --- /dev/null +++ b/packages/core/integration-tests/test/integration/postcss-composes/composes-1.css @@ -0,0 +1,4 @@ +.composes1 { + composes: test from './mixins.css'; + border: 3px solid orange; +} diff --git a/packages/core/integration-tests/test/integration/postcss-composes/composes-2.css b/packages/core/integration-tests/test/integration/postcss-composes/composes-2.css new file mode 100644 index 00000000000..98163adf124 --- /dev/null +++ b/packages/core/integration-tests/test/integration/postcss-composes/composes-2.css @@ -0,0 +1,4 @@ +.composes2 { + composes: test from './mixins.css'; + border: 3px solid red; +} diff --git a/packages/core/integration-tests/test/integration/postcss-composes/composes-3.css b/packages/core/integration-tests/test/integration/postcss-composes/composes-3.css new file mode 100644 index 00000000000..862fe412920 --- /dev/null +++ b/packages/core/integration-tests/test/integration/postcss-composes/composes-3.css @@ -0,0 +1,4 @@ +.composes3 { + composes: test from './mixins.scss'; + border: 3px solid brown; +} diff --git a/packages/core/integration-tests/test/integration/postcss-composes/composes-4.css b/packages/core/integration-tests/test/integration/postcss-composes/composes-4.css new file mode 100644 index 00000000000..b0f3992251d --- /dev/null +++ b/packages/core/integration-tests/test/integration/postcss-composes/composes-4.css @@ -0,0 +1,4 @@ +.composes4 { + composes: test from '~mixins.css'; + border: 3px solid black; +} diff --git a/packages/core/integration-tests/test/integration/postcss-composes/composes-5.css b/packages/core/integration-tests/test/integration/postcss-composes/composes-5.css new file mode 100644 index 00000000000..4522e2bfdff --- /dev/null +++ b/packages/core/integration-tests/test/integration/postcss-composes/composes-5.css @@ -0,0 +1,4 @@ +.composes5 { + composes: intermediate from './mixins-intermediate.css'; + border: 3px solid yellow; +} diff --git a/packages/core/integration-tests/test/integration/postcss-composes/composes-6.css b/packages/core/integration-tests/test/integration/postcss-composes/composes-6.css new file mode 100644 index 00000000000..780d4fe80b0 --- /dev/null +++ b/packages/core/integration-tests/test/integration/postcss-composes/composes-6.css @@ -0,0 +1,4 @@ +.composes6 { + composes: test test-2 from './mixins.css'; + border: 3px solid orangered; +} diff --git a/packages/core/integration-tests/test/integration/postcss-composes/index.js b/packages/core/integration-tests/test/integration/postcss-composes/index.js new file mode 100644 index 00000000000..19a9be12e73 --- /dev/null +++ b/packages/core/integration-tests/test/integration/postcss-composes/index.js @@ -0,0 +1,6 @@ +var map1 = require('./composes-1.css'); +var map2 = require('./composes-2.css'); + +module.exports = function () { + return Object.assign({}, map1, map2); +}; diff --git a/packages/core/integration-tests/test/integration/postcss-composes/index2.js b/packages/core/integration-tests/test/integration/postcss-composes/index2.js new file mode 100644 index 00000000000..b72aba8c409 --- /dev/null +++ b/packages/core/integration-tests/test/integration/postcss-composes/index2.js @@ -0,0 +1,5 @@ +var map3 = require('./composes-3.css'); + +module.exports = function () { + return map3; +}; diff --git a/packages/core/integration-tests/test/integration/postcss-composes/index3.js b/packages/core/integration-tests/test/integration/postcss-composes/index3.js new file mode 100644 index 00000000000..e1eb241f911 --- /dev/null +++ b/packages/core/integration-tests/test/integration/postcss-composes/index3.js @@ -0,0 +1,5 @@ +var map4 = require('./composes-4.css'); + +module.exports = function () { + return map4; +}; diff --git a/packages/core/integration-tests/test/integration/postcss-composes/index4.js b/packages/core/integration-tests/test/integration/postcss-composes/index4.js new file mode 100644 index 00000000000..315561cbd3b --- /dev/null +++ b/packages/core/integration-tests/test/integration/postcss-composes/index4.js @@ -0,0 +1,5 @@ +var map5 = require('./composes-5.css'); + +module.exports = function () { + return map5; +}; diff --git a/packages/core/integration-tests/test/integration/postcss-composes/index5.js b/packages/core/integration-tests/test/integration/postcss-composes/index5.js new file mode 100644 index 00000000000..31932b14b88 --- /dev/null +++ b/packages/core/integration-tests/test/integration/postcss-composes/index5.js @@ -0,0 +1,5 @@ +var map6 = require('./composes-6.css'); + +module.exports = function () { + return map6; +}; diff --git a/packages/core/integration-tests/test/integration/postcss-composes/mixins-intermediate.css b/packages/core/integration-tests/test/integration/postcss-composes/mixins-intermediate.css new file mode 100644 index 00000000000..ebbbcafc863 --- /dev/null +++ b/packages/core/integration-tests/test/integration/postcss-composes/mixins-intermediate.css @@ -0,0 +1,4 @@ +.intermediate { + composes: test from './mixins.css'; + height: 300px; +} diff --git a/packages/core/integration-tests/test/integration/postcss-composes/mixins.css b/packages/core/integration-tests/test/integration/postcss-composes/mixins.css new file mode 100644 index 00000000000..2de4a887869 --- /dev/null +++ b/packages/core/integration-tests/test/integration/postcss-composes/mixins.css @@ -0,0 +1,8 @@ +.test { + height: 100px; + width: 100px; +} + +.test-2 { + background: red; +} diff --git a/packages/core/integration-tests/test/integration/postcss-composes/mixins.scss b/packages/core/integration-tests/test/integration/postcss-composes/mixins.scss new file mode 100644 index 00000000000..6a801aa790a --- /dev/null +++ b/packages/core/integration-tests/test/integration/postcss-composes/mixins.scss @@ -0,0 +1,6 @@ +$test: 200px; + +.test { + height: $test; + width: $test; +} diff --git a/packages/core/integration-tests/test/integration/process/index.js b/packages/core/integration-tests/test/integration/process/index.js new file mode 100644 index 00000000000..469e248a1e5 --- /dev/null +++ b/packages/core/integration-tests/test/integration/process/index.js @@ -0,0 +1,8 @@ +process.browser = false +module.exports = function () { + return process.browser && test(process.browser); +}; + +function test(val) { + return val; +} diff --git a/packages/core/integration-tests/test/integration/scope-hoisting/es6/dynamic-import-dynamic/a.js b/packages/core/integration-tests/test/integration/scope-hoisting/es6/dynamic-import-dynamic/a.js new file mode 100644 index 00000000000..0888e345bef --- /dev/null +++ b/packages/core/integration-tests/test/integration/scope-hoisting/es6/dynamic-import-dynamic/a.js @@ -0,0 +1 @@ +export default import("./b.js").then(b => b.default); diff --git a/packages/core/integration-tests/test/integration/scope-hoisting/es6/dynamic-import-dynamic/b.js b/packages/core/integration-tests/test/integration/scope-hoisting/es6/dynamic-import-dynamic/b.js new file mode 100644 index 00000000000..30628ea0fbe --- /dev/null +++ b/packages/core/integration-tests/test/integration/scope-hoisting/es6/dynamic-import-dynamic/b.js @@ -0,0 +1 @@ +export default import('./c.js').then(b => b.default + 1); diff --git a/packages/core/integration-tests/test/integration/scope-hoisting/es6/dynamic-import-dynamic/c.js b/packages/core/integration-tests/test/integration/scope-hoisting/es6/dynamic-import-dynamic/c.js new file mode 100644 index 00000000000..67d639a53f2 --- /dev/null +++ b/packages/core/integration-tests/test/integration/scope-hoisting/es6/dynamic-import-dynamic/c.js @@ -0,0 +1 @@ +export default 122; diff --git a/packages/core/integration-tests/test/integration/scope-hoisting/es6/export-undefined/a.js b/packages/core/integration-tests/test/integration/scope-hoisting/es6/export-undefined/a.js new file mode 100644 index 00000000000..eb53777b1b3 --- /dev/null +++ b/packages/core/integration-tests/test/integration/scope-hoisting/es6/export-undefined/a.js @@ -0,0 +1 @@ +export {Test}; diff --git a/packages/core/integration-tests/test/integration/scope-hoisting/es6/re-export-renamed/a.js b/packages/core/integration-tests/test/integration/scope-hoisting/es6/re-export-renamed/a.js new file mode 100644 index 00000000000..1077b636aca --- /dev/null +++ b/packages/core/integration-tests/test/integration/scope-hoisting/es6/re-export-renamed/a.js @@ -0,0 +1,3 @@ +import { x } from './b.js'; + +output = x; diff --git a/packages/core/integration-tests/test/integration/scope-hoisting/es6/re-export-renamed/b.js b/packages/core/integration-tests/test/integration/scope-hoisting/es6/re-export-renamed/b.js new file mode 100644 index 00000000000..154372df193 --- /dev/null +++ b/packages/core/integration-tests/test/integration/scope-hoisting/es6/re-export-renamed/b.js @@ -0,0 +1,3 @@ +export const x = 'foobar'; + +export { x as y } from './c.js' diff --git a/packages/core/integration-tests/test/integration/scope-hoisting/es6/re-export-renamed/c.js b/packages/core/integration-tests/test/integration/scope-hoisting/es6/re-export-renamed/c.js new file mode 100644 index 00000000000..0190dbd267f --- /dev/null +++ b/packages/core/integration-tests/test/integration/scope-hoisting/es6/re-export-renamed/c.js @@ -0,0 +1 @@ +export const x = 'xyz'; diff --git a/packages/core/integration-tests/test/integration/scss-absolute-imports/b.scss b/packages/core/integration-tests/test/integration/scss-absolute-imports/b.scss new file mode 100644 index 00000000000..b28d1ab0817 --- /dev/null +++ b/packages/core/integration-tests/test/integration/scss-absolute-imports/b.scss @@ -0,0 +1,3 @@ +.b { + color: red; +} diff --git a/packages/core/integration-tests/test/integration/scss-absolute-imports/style.scss b/packages/core/integration-tests/test/integration/scss-absolute-imports/style.scss new file mode 100644 index 00000000000..f7caaac8c3b --- /dev/null +++ b/packages/core/integration-tests/test/integration/scss-absolute-imports/style.scss @@ -0,0 +1,5 @@ +@import '/b.scss'; + +.a { + color: blue; +} diff --git a/packages/core/integration-tests/test/integration/sourcemap-css-existing/style.css b/packages/core/integration-tests/test/integration/sourcemap-css-existing/style.css new file mode 100644 index 00000000000..191ad2bf43d --- /dev/null +++ b/packages/core/integration-tests/test/integration/sourcemap-css-existing/style.css @@ -0,0 +1,5 @@ +@import "./test/library.css"; + +main { + display: none; +} diff --git a/packages/core/integration-tests/test/integration/sourcemap-css-existing/test/library.css b/packages/core/integration-tests/test/integration/sourcemap-css-existing/test/library.css new file mode 100644 index 00000000000..b13111e24ed --- /dev/null +++ b/packages/core/integration-tests/test/integration/sourcemap-css-existing/test/library.css @@ -0,0 +1,2 @@ +body{font:100% Helvetica,sans-serif;color:#333}body div{background-color:red;width:100px;height:100px} +/*# sourceMappingURL=library.css.map*/ \ No newline at end of file diff --git a/packages/core/integration-tests/test/integration/sourcemap-css-existing/test/library.css.map b/packages/core/integration-tests/test/integration/sourcemap-css-existing/test/library.css.map new file mode 100644 index 00000000000..579f260dfcf --- /dev/null +++ b/packages/core/integration-tests/test/integration/sourcemap-css-existing/test/library.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["library.scss"],"names":[],"mappings":"AAGA,KACE,+BACA,WAEA,SACC,qBACA,YACA","file":"library.css.map","sourceRoot":".","sourcesContent":["$font-stack: Helvetica, sans-serif;\n$primary-color: #333;\n\nbody {\n font: 100% $font-stack;\n color: $primary-color;\n\n div {\n \tbackground-color: red;\n \twidth: 100px;\n \theight: 100px;\n }\n}"]} \ No newline at end of file diff --git a/packages/core/integration-tests/test/integration/sourcemap-css-existing/test/library.raw.scss b/packages/core/integration-tests/test/integration/sourcemap-css-existing/test/library.raw.scss new file mode 100644 index 00000000000..93097df8f38 --- /dev/null +++ b/packages/core/integration-tests/test/integration/sourcemap-css-existing/test/library.raw.scss @@ -0,0 +1,13 @@ +$font-stack: Helvetica, sans-serif; +$primary-color: #333; + +body { + font: 100% $font-stack; + color: $primary-color; + + div { + background-color: red; + width: 100px; + height: 100px; + } +} \ No newline at end of file diff --git a/packages/core/integration-tests/test/integration/sourcemap-css-import/another-style.css b/packages/core/integration-tests/test/integration/sourcemap-css-import/another-style.css new file mode 100644 index 00000000000..107e9f29b84 --- /dev/null +++ b/packages/core/integration-tests/test/integration/sourcemap-css-import/another-style.css @@ -0,0 +1,3 @@ +main { + font-family: monospace; +} diff --git a/packages/core/integration-tests/test/integration/sourcemap-css-import/other-style.css b/packages/core/integration-tests/test/integration/sourcemap-css-import/other-style.css new file mode 100644 index 00000000000..6d844850414 --- /dev/null +++ b/packages/core/integration-tests/test/integration/sourcemap-css-import/other-style.css @@ -0,0 +1,5 @@ + +div { + width: 100px; + height: 100px; +} diff --git a/packages/core/integration-tests/test/integration/sourcemap-css-import/style.css b/packages/core/integration-tests/test/integration/sourcemap-css-import/style.css new file mode 100644 index 00000000000..01ef4f07c71 --- /dev/null +++ b/packages/core/integration-tests/test/integration/sourcemap-css-import/style.css @@ -0,0 +1,8 @@ + +@import "./other-style.css"; + +body { + background-color: red; +} + +@import "./another-style.css"; diff --git a/packages/core/integration-tests/test/integration/sourcemap-css/style.css b/packages/core/integration-tests/test/integration/sourcemap-css/style.css new file mode 100644 index 00000000000..0ac172751f5 --- /dev/null +++ b/packages/core/integration-tests/test/integration/sourcemap-css/style.css @@ -0,0 +1,4 @@ + +body { + background-color: red; +} diff --git a/packages/core/integration-tests/test/integration/sourcemap-less/style.less b/packages/core/integration-tests/test/integration/sourcemap-less/style.less new file mode 100644 index 00000000000..e1a4d641769 --- /dev/null +++ b/packages/core/integration-tests/test/integration/sourcemap-less/style.less @@ -0,0 +1,5 @@ +@value: 100px * 2; + +div { + width: @value; +} diff --git a/packages/core/integration-tests/test/integration/sourcemap-sass-imported/other.scss b/packages/core/integration-tests/test/integration/sourcemap-sass-imported/other.scss new file mode 100644 index 00000000000..3498c8f2370 --- /dev/null +++ b/packages/core/integration-tests/test/integration/sourcemap-sass-imported/other.scss @@ -0,0 +1,5 @@ +$variable: monospace; + +div { + font-family: $variable; +} diff --git a/packages/core/integration-tests/test/integration/sourcemap-sass-imported/style.css b/packages/core/integration-tests/test/integration/sourcemap-sass-imported/style.css new file mode 100644 index 00000000000..b486b67de91 --- /dev/null +++ b/packages/core/integration-tests/test/integration/sourcemap-sass-imported/style.css @@ -0,0 +1,5 @@ +@import "./other.scss"; + +body { + color: red; +} diff --git a/packages/core/integration-tests/test/integration/sourcemap-sass/style.scss b/packages/core/integration-tests/test/integration/sourcemap-sass/style.scss new file mode 100644 index 00000000000..8ce95c4110e --- /dev/null +++ b/packages/core/integration-tests/test/integration/sourcemap-sass/style.scss @@ -0,0 +1,5 @@ +$variable: #333; + +body { + color: $variable; +} diff --git a/packages/core/integration-tests/test/integration/sourcemap-sourcemappingurl-multiple-entrypoints/a/index.js b/packages/core/integration-tests/test/integration/sourcemap-sourcemappingurl-multiple-entrypoints/a/index.js new file mode 100644 index 00000000000..d6357c10e58 --- /dev/null +++ b/packages/core/integration-tests/test/integration/sourcemap-sourcemappingurl-multiple-entrypoints/a/index.js @@ -0,0 +1 @@ +console.log('hello1'); \ No newline at end of file diff --git a/packages/core/integration-tests/test/integration/sourcemap-sourcemappingurl-multiple-entrypoints/b/index.js b/packages/core/integration-tests/test/integration/sourcemap-sourcemappingurl-multiple-entrypoints/b/index.js new file mode 100644 index 00000000000..a023d214778 --- /dev/null +++ b/packages/core/integration-tests/test/integration/sourcemap-sourcemappingurl-multiple-entrypoints/b/index.js @@ -0,0 +1 @@ +console.log('hello2'); \ No newline at end of file diff --git a/packages/core/integration-tests/test/integration/sourcemap-sourcemappingurl/index.js b/packages/core/integration-tests/test/integration/sourcemap-sourcemappingurl/index.js new file mode 100644 index 00000000000..ea17b22ee52 --- /dev/null +++ b/packages/core/integration-tests/test/integration/sourcemap-sourcemappingurl/index.js @@ -0,0 +1 @@ +console.log('hello'); \ No newline at end of file diff --git a/packages/core/integration-tests/test/javascript.js b/packages/core/integration-tests/test/javascript.js index a0474f8212e..a8b1fdd6c8a 100644 --- a/packages/core/integration-tests/test/javascript.js +++ b/packages/core/integration-tests/test/javascript.js @@ -8,8 +8,9 @@ const { assertBundleTree, deferred, ncp -} = require('./utils'); +} = require('@parcel/test-utils'); const {mkdirp} = require('@parcel/fs'); +const {symlinkPrivilegeWarning} = require('@parcel/test-utils'); const {symlinkSync} = require('fs'); describe('javascript', function() { @@ -802,7 +803,7 @@ describe('javascript', function() { assert.deepEqual(output(), { dir: path.join(__dirname, '/integration/globals'), file: path.join(__dirname, '/integration/globals/index.js'), - buf: new Buffer('browser').toString('base64'), + buf: Buffer.from('browser').toString('base64'), global: true }); }); @@ -855,6 +856,45 @@ describe('javascript', function() { assert.equal(output, 'bartest'); }); + it('should replace process.browser on --target=browser', async function() { + let b = await bundle( + path.join(__dirname, '/integration/process/index.js'), + { + target: 'browser' + } + ); + + let output = await run(b); + assert.ok(output.toString().indexOf('process.browser') === -1); + assert.equal(output(), true); + }); + + it('should not replace process.browser on --target=node', async function() { + let b = await bundle( + path.join(__dirname, '/integration/process/index.js'), + { + target: 'node' + } + ); + + let output = await run(b); + assert.ok(output.toString().indexOf('process.browser') !== -1); + assert.equal(output(), false); + }); + + it('should not replace process.browser on --target=electron', async function() { + let b = await bundle( + path.join(__dirname, '/integration/process/index.js'), + { + target: 'electron' + } + ); + + let output = await run(b); + assert.ok(output.toString().indexOf('process.browser') !== -1); + assert.equal(output(), false); + }); + it('should support adding implicit dependencies', async function() { let b = await bundle(path.join(__dirname, '/integration/json/index.js'), { delegate: { @@ -1290,21 +1330,28 @@ describe('javascript', function() { inputDir ); - // Create the symlink here to prevent cross platform and git issues - symlinkSync( - path.join(inputDir, 'packages/foo'), - path.join(inputDir, 'node_modules/foo'), - 'dir' - ); + try { + // Create the symlink here to prevent cross platform and git issues + symlinkSync( + path.join(inputDir, 'packages/foo'), + path.join(inputDir, 'node_modules/foo'), + 'dir' + ); - await bundle(inputDir + '/index.js'); + await bundle(inputDir + '/index.js'); - let file = await fs.readFile( - path.join(__dirname, '/dist/index.js'), - 'utf8' - ); - assert(file.includes('function Foo')); - assert(file.includes('function Bar')); + let file = await fs.readFile( + path.join(__dirname, '/dist/index.js'), + 'utf8' + ); + assert(file.includes('function Foo')); + assert(file.includes('function Bar')); + } catch (e) { + if (e.perm == 'EPERM') { + symlinkPrivilegeWarning(); + this.skip(); + } + } }); it('should not compile node_modules with a source field in package.json when not symlinked', async function() { @@ -1343,6 +1390,28 @@ describe('javascript', function() { assert(file.includes('React.createElement("div"')); }); + it('should support compiling JSX in JS files with React dependency even if React is not specified as dependency', async function() { + let originalPkg = await fs.readFile( + __dirname + '/integration/jsx-react-no-dep/package.json' + ); + + await bundle( + path.join(__dirname, '/integration/jsx-react-no-dep/index.js') + ); + + let file = await fs.readFile( + path.join(__dirname, '/dist/index.js'), + 'utf8' + ); + + assert(file.includes('React.createElement("div"')); + + await fs.writeFile( + __dirname + '/integration/jsx-react-no-dep/package.json', + originalPkg + ); + }); + it('should support compiling JSX in JS files with Preact dependency', async function() { await bundle(path.join(__dirname, '/integration/jsx-preact/index.js')); @@ -1353,6 +1422,28 @@ describe('javascript', function() { assert(file.includes('h("div"')); }); + it('should support compiling JSX in JS files with Preact dependency even if Preact is not specified as dependency', async function() { + let originalPkg = await fs.readFile( + __dirname + '/integration/jsx-preact-no-dep/package.json' + ); + + await bundle( + path.join(__dirname, '/integration/jsx-preact-no-dep/index.js') + ); + + let file = await fs.readFile( + path.join(__dirname, '/dist/index.js'), + 'utf8' + ); + + assert(file.includes('h("div"')); + + await fs.writeFile( + __dirname + '/integration/jsx-preact-no-dep/package.json', + originalPkg + ); + }); + it('should support compiling JSX in JS files with Nerv dependency', async function() { await bundle(path.join(__dirname, '/integration/jsx-nervjs/index.js')); @@ -1363,6 +1454,28 @@ describe('javascript', function() { assert(file.includes('Nerv.createElement("div"')); }); + it('should support compiling JSX in JS files with Nerv dependency even if Nerv is not specified as dependency', async function() { + let originalPkg = await fs.readFile( + __dirname + '/integration/jsx-nervjs-no-dep/package.json' + ); + + await bundle( + path.join(__dirname, '/integration/jsx-nervjs-no-dep/index.js') + ); + + let file = await fs.readFile( + path.join(__dirname, '/dist/index.js'), + 'utf8' + ); + + assert(file.includes('Nerv.createElement("div"')); + + await fs.writeFile( + __dirname + '/integration/jsx-nervjs-no-dep/package.json', + originalPkg + ); + }); + it('should support compiling JSX in JS files with Hyperapp dependency', async function() { await bundle(path.join(__dirname, '/integration/jsx-hyperapp/index.js')); @@ -1370,7 +1483,30 @@ describe('javascript', function() { path.join(__dirname, '/dist/index.js'), 'utf8' ); + + assert(file.includes('h("div"')); + }); + + it('should support compiling JSX in JS files with Hyperapp dependency even if Hyperapp is not specified as dependency', async function() { + let originalPkg = await fs.readFile( + __dirname + '/integration/jsx-hyperapp-no-dep/package.json' + ); + + await bundle( + path.join(__dirname, '/integration/jsx-hyperapp-no-dep/index.js') + ); + + let file = await fs.readFile( + path.join(__dirname, '/dist/index.js'), + 'utf8' + ); + assert(file.includes('h("div"')); + + await fs.writeFile( + __dirname + '/integration/jsx-hyperapp-no-dep/package.json', + originalPkg + ); }); it('should support optional dependencies in try...catch blocks', async function() { diff --git a/packages/core/integration-tests/test/kotlin.js b/packages/core/integration-tests/test/kotlin.js index 0e62f88133d..43ddbcdc7a9 100644 --- a/packages/core/integration-tests/test/kotlin.js +++ b/packages/core/integration-tests/test/kotlin.js @@ -1,7 +1,16 @@ const assert = require('assert'); -const {bundle, assertBundleTree, run} = require('./utils'); +const {bundle, assertBundleTree, run} = require('@parcel/test-utils'); +const commandExists = require('command-exists'); describe('kotlin', function() { + if (!commandExists.sync('java')) { + // eslint-disable-next-line no-console + console.log( + 'Skipping Kotlin tests. Install https://www.java.com/download/ to run them.' + ); + return; + } + it('should produce a basic kotlin bundle', async function() { let b = await bundle(__dirname + '/integration/kotlin/index.js'); diff --git a/packages/core/integration-tests/test/less.js b/packages/core/integration-tests/test/less.js index da522dd66d0..2a700a0dd33 100644 --- a/packages/core/integration-tests/test/less.js +++ b/packages/core/integration-tests/test/less.js @@ -1,7 +1,7 @@ const assert = require('assert'); const path = require('path'); const fs = require('@parcel/fs'); -const {bundle, run, assertBundleTree} = require('./utils'); +const {bundle, run, assertBundleTree} = require('@parcel/test-utils'); describe('less', function() { it('should support requiring less files', async function() { @@ -17,7 +17,11 @@ describe('less', function() { { name: 'index.css', assets: ['index.less'], - childBundles: [] + childBundles: [ + { + type: 'map' + } + ] } ] }); @@ -48,7 +52,11 @@ describe('less', function() { { name: 'index.css', assets: ['index.less'], - childBundles: [] + childBundles: [ + { + type: 'map' + } + ] } ] }); @@ -80,7 +88,11 @@ describe('less', function() { { name: 'index.css', assets: ['index.less'], - childBundles: [] + childBundles: [ + { + type: 'map' + } + ] } ] }); @@ -112,7 +124,11 @@ describe('less', function() { { name: 'index.css', assets: ['index.less'], - childBundles: [] + childBundles: [ + { + type: 'map' + } + ] } ] }); @@ -125,7 +141,11 @@ describe('less', function() { path.join(__dirname, '/dist/index.css'), 'utf8' ); - assert.equal(css, ''); + assert( + /^\/\*# sourceMappingURL=\/\w*\.css\.map \*\/$/.test( + css.replace('\n', '') + ) + ); }); it('should support linking to assets with url() from less', async function() { @@ -143,7 +163,11 @@ describe('less', function() { { name: 'index.css', assets: ['index.less'], - childBundles: [] + childBundles: [ + { + type: 'map' + } + ] }, { type: 'woff2', @@ -191,19 +215,23 @@ describe('less', function() { { name: 'index.css', assets: ['index.less'], - childBundles: [] + childBundles: [ + { + type: 'map' + } + ] } ] }); let output = await run(b); assert.equal(typeof output, 'function'); - assert.equal(output(), '_index_ku5n8_1'); + assert(output().startsWith('_index_')); let css = await fs.readFile( path.join(__dirname, '/dist/index.css'), 'utf8' ); - assert(css.includes('._index_ku5n8_1')); + assert(css.includes('._index_')); }); }); diff --git a/packages/core/integration-tests/test/markdown.js b/packages/core/integration-tests/test/markdown.js new file mode 100644 index 00000000000..017e8fe9d33 --- /dev/null +++ b/packages/core/integration-tests/test/markdown.js @@ -0,0 +1,33 @@ +const assert = require('assert'); +const path = require('path'); +const fs = require('@parcel/fs'); +const {bundle, run, assertBundleTree} = require('./utils'); + +describe('markdown', function() { + it('should support bundling Markdown', async function() { + let b = await bundle( + path.join(__dirname, '/integration/markdown/index.md') + ); + + await assertBundleTree(b, { + name: 'index.html', + assets: ['index.md'], + childBundles: [ + { + type: 'png', + assets: ['100x100.png'], + childBundles: [] + } + ] + }); + + let files = await fs.readdir(path.join(__dirname, '/dist')); + let html = await fs.readFile(path.join(__dirname, '/dist/index.html')); + for (let file of files) { + let ext = file.match(/\.([0-9a-z]+)(?:[?#]|$)/i)[0]; + if (file !== 'index.html' && ext !== '.map') { + assert(html.includes(file)); + } + } + }); +}); diff --git a/packages/core/integration-tests/test/parser.js b/packages/core/integration-tests/test/parser.js index af10583255a..8ff2d4e3418 100644 --- a/packages/core/integration-tests/test/parser.js +++ b/packages/core/integration-tests/test/parser.js @@ -1,7 +1,7 @@ const assert = require('assert'); const path = require('path'); const fs = require('@parcel/fs'); -const {bundle, assertBundleTree} = require('./utils'); +const {bundle, assertBundleTree} = require('@parcel/test-utils'); describe('parser', function() { it('should support case-insensitive file extension', async function() { @@ -24,7 +24,11 @@ describe('parser', function() { { type: 'css', assets: ['index.cSs'], - childBundles: [] + childBundles: [ + { + type: 'map' + } + ] }, { type: 'html', diff --git a/packages/core/integration-tests/test/pug.js b/packages/core/integration-tests/test/pug.js index 79bc8f0f778..2962fdecac8 100644 --- a/packages/core/integration-tests/test/pug.js +++ b/packages/core/integration-tests/test/pug.js @@ -1,7 +1,7 @@ const assert = require('assert'); const path = require('path'); const fs = require('@parcel/fs'); -const {bundle, assertBundleTree, normaliseNewlines} = require('./utils'); +const {bundle, assertBundleTree} = require('@parcel/test-utils'); describe('pug', function() { it('should support bundling HTML', async function() { @@ -24,7 +24,11 @@ describe('pug', function() { { type: 'css', assets: ['index.css'], - childBundles: [] + childBundles: [ + { + type: 'map' + } + ] }, { type: 'js', @@ -58,17 +62,13 @@ describe('pug', function() { assets: ['index.pug'] }); - const html = normaliseNewlines( - await fs.readFile(path.join(__dirname, '/dist/index.html'), 'utf-8') - ); - const expect = normaliseNewlines( - await fs.readFile( - path.join(__dirname, '/integration/pug-include-extends/expect.html'), - 'utf-8' - ) + const html = await fs.readFile( + path.join(__dirname, '/dist/index.html'), + 'utf-8' ); - assert.equal(html, expect, 'Content mismatch'); + assert(html.includes('')); + assert(html.includes("