Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix windows bugs & tests #1965

Merged
merged 24 commits into from Sep 22, 2018
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 0 additions & 6 deletions appveyor.yml
Expand Up @@ -3,7 +3,6 @@ environment:
matrix:
- nodejs_version: "6"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Travis already tests Node 6 compatibility and the tests that break on windows that don't break on Travis are usually related to the filesystem, which is the same on Node 8.

Removing this would make it as fast as Travis, this way we don't have to wait hours before AppVeyor catches up

- nodejs_version: "8"
- nodejs_version: "10"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why don't we test on nodejs 10 ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it takes too long to run all platforms and node 10 should generally work if node 8 works.

Travis is fine, cuz it runs the builds in parallel, AppVeyor runs one platform after another taking ages to finish.

Besides node specific issues should be caught by Travis anyways, Appveyor is just to catch windows errors which should be the same on pretty much every node version (unless there is a bug inside node or some native package we use (which we try to avoid))

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, that makes sense. Hopefully, there won't rise any node-specific windows errors like that edge case.


# Install scripts. (runs after repo cloning)
install:
Expand All @@ -20,11 +19,6 @@ install:
- rustc -Vv
- cargo -V

# Restore symlinks from git
# https://github.com/appveyor/ci/issues/650
- cmd: git config core.symlinks true
- cmd: git reset --hard

# Post-install test scripts.
test_script:
# Output useful info for debugging.
Expand Down
2 changes: 1 addition & 1 deletion src/Bundler.js
Expand Up @@ -19,7 +19,7 @@ const installPackage = require('./utils/installPackage');
const bundleReport = require('./utils/bundleReport');
const prettifyTime = require('./utils/prettifyTime');
const getRootDir = require('./utils/getRootDir');
const glob = require('fast-glob');
const {glob} = require('./utils/glob');

/**
* The Bundler is the main entry point. It resolves and loads assets,
Expand Down
3 changes: 1 addition & 2 deletions src/FSCache.js
Expand Up @@ -4,8 +4,7 @@ const md5 = require('./utils/md5');
const objectHash = require('./utils/objectHash');
const pkg = require('../package.json');
const logger = require('./Logger');
const glob = require('fast-glob');
const isGlob = require('is-glob');
const {isGlob, glob} = require('./utils/glob');

// These keys can affect the output, so if they differ, the cache should not match
const OPTION_KEYS = ['publicURL', 'minify', 'hmr', 'target', 'scopeHoist'];
Expand Down
2 changes: 1 addition & 1 deletion src/Parser.js
@@ -1,7 +1,7 @@
const path = require('path');
const RawAsset = require('./assets/RawAsset');
const GlobAsset = require('./assets/GlobAsset');
const isGlob = require('is-glob');
const {isGlob} = require('./utils/glob');

class Parser {
constructor(options = {}) {
Expand Down
4 changes: 2 additions & 2 deletions src/Resolver.js
@@ -1,7 +1,7 @@
const builtins = require('./builtins');
const nodeBuiltins = require('node-libs-browser');
const path = require('path');
const isGlob = require('is-glob');
const {isGlob} = require('./utils/glob');
const fs = require('./utils/fs');
const micromatch = require('micromatch');

Expand Down Expand Up @@ -147,7 +147,7 @@ class Resolver {

default:
// Module
return path.normalize(filename);
return filename;
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/assets/GlobAsset.js
@@ -1,7 +1,7 @@
const Asset = require('../Asset');
const glob = require('fast-glob');
const micromatch = require('micromatch');
const path = require('path');
const {glob} = require('../utils/glob');

class GlobAsset extends Asset {
constructor(name, options) {
Expand Down
3 changes: 1 addition & 2 deletions src/assets/StylusAsset.js
Expand Up @@ -4,8 +4,7 @@ const localRequire = require('../utils/localRequire');
const Resolver = require('../Resolver');
const fs = require('../utils/fs');
const {dirname, resolve, relative} = require('path');
const isGlob = require('is-glob');
const glob = require('fast-glob');
const {isGlob, glob} = require('../utils/glob');

const URL_RE = /^(?:url\s*\(\s*)?['"]?(?:[#/]|(?:https?:)?\/\/)/i;

Expand Down
18 changes: 18 additions & 0 deletions src/utils/glob.js
@@ -0,0 +1,18 @@
const isGlob = require('is-glob');
const fastGlob = require('fast-glob');

function normalisePath(p) {
return p.replace(/\\/g, '/');
}

exports.isGlob = function(p) {
return isGlob(normalisePath(p));
};

exports.glob = function(p, options) {
return fastGlob(normalisePath(p), options);
};

exports.glob.sync = function(p, options) {
return fastGlob.sync(normalisePath(p), options);
};
6 changes: 4 additions & 2 deletions test/glsl.js
@@ -1,6 +1,6 @@
const assert = require('assert');
const fs = require('../src/utils/fs');
const {bundle, run, assertBundleTree} = require('./utils');
const {bundle, run, assertBundleTree, normaliseNewlines} = require('./utils');

describe('glsl', function() {
it('should support requiring GLSL files via glslify', async function() {
Expand All @@ -25,7 +25,9 @@ describe('glsl', function() {
assert.equal(typeof output, 'function');
assert.ok(
output().reduce((acc, requiredShader) => {
return acc && shader === requiredShader;
return (
acc && normaliseNewlines(shader) === normaliseNewlines(requiredShader)
);
}, true)
);
});
Expand Down

This file was deleted.

1 change: 0 additions & 1 deletion test/integration/resolver/node_modules/source

This file was deleted.

1 change: 0 additions & 1 deletion test/integration/resolver/node_modules/source-alias

This file was deleted.

1 change: 0 additions & 1 deletion test/integration/resolver/node_modules/source-alias-glob

This file was deleted.

19 changes: 17 additions & 2 deletions test/javascript.js
@@ -1,8 +1,9 @@
const assert = require('assert');
const fs = require('../src/utils/fs');
const path = require('path');
const {bundle, run, assertBundleTree, deferred} = require('./utils');
const {bundle, run, assertBundleTree, deferred, ncp} = require('./utils');
const {mkdirp} = require('../src/utils/fs');
const {symlinkSync} = require('fs');

describe('javascript', function() {
it('should produce a basic JS bundle with CommonJS requires', async function() {
Expand Down Expand Up @@ -1018,7 +1019,21 @@ describe('javascript', function() {
});

it('should compile node_modules when symlinked with a source field in package.json', async function() {
await bundle(__dirname + '/integration/babel-node-modules-source/index.js');
const inputDir = __dirname + '/input';
await mkdirp(path.join(inputDir, 'node_modules'));
await ncp(
path.join(__dirname + '/integration/babel-node-modules-source'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

__dirname + '/integration/babel-node-modules-source' should be __dirname, '/integration/babel-node-modules-source'

inputDir
);

// Create the symlinks 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');

let file = await fs.readFile(__dirname + '/dist/index.js', 'utf8');
assert(file.includes('function Foo'));
Expand Down
14 changes: 9 additions & 5 deletions test/pug.js
@@ -1,6 +1,6 @@
const assert = require('assert');
const fs = require('../src/utils/fs');
const {bundle, assertBundleTree} = require('./utils');
const {bundle, assertBundleTree, normaliseNewlines} = require('./utils');

describe('pug', function() {
it('should support bundling HTML', async function() {
Expand Down Expand Up @@ -57,10 +57,14 @@ describe('pug', function() {
assets: ['index.pug']
});

const html = await fs.readFile(__dirname + '/dist/index.html', 'utf-8');
const expect = await fs.readFile(
__dirname + '/integration/pug-include-extends/expect.html',
'utf-8'
const html = normaliseNewlines(
await fs.readFile(__dirname + '/dist/index.html', 'utf-8')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why no path.join() here?

);
const expect = normaliseNewlines(
await fs.readFile(
__dirname + '/integration/pug-include-extends/expect.html',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also why no path.join() here?

'utf-8'
)
);

assert.equal(html, expect, 'Content mismatch');
Expand Down
44 changes: 36 additions & 8 deletions test/resolver.js
@@ -1,17 +1,45 @@
const Resolver = require('../src/Resolver');
const path = require('path');
const assert = require('assert');
const {rimraf, ncp} = require('./utils');
const {mkdirp} = require('../src/utils/fs');
const {symlinkSync} = require('fs');

const rootDir = path.join(__dirname, 'integration', 'resolver');
const resolver = new Resolver({
rootDir,
extensions: {
'.js': true,
'.json': true
}
});
const rootDir = path.join(__dirname, 'input/resolver');

describe('resolver', function() {
let resolver;
before(async function() {
await rimraf(__dirname + '/input');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be replaced by await rimraf(path.join(__dirname, '/input'))

await mkdirp(rootDir);
await ncp(path.join(__dirname, 'integration/resolver'), rootDir);

// Create the symlinks here to prevent cross platform and git issues
symlinkSync(
path.join(rootDir, 'packages/source'),
path.join(rootDir, 'node_modules/source'),
'dir'
);
symlinkSync(
path.join(rootDir, 'packages/source-alias'),
path.join(rootDir, 'node_modules/source-alias'),
'dir'
);
symlinkSync(
path.join(rootDir, 'packages/source-alias-glob'),
path.join(rootDir, 'node_modules/source-alias-glob'),
'dir'
);

resolver = new Resolver({
rootDir,
extensions: {
'.js': true,
'.json': true
}
});
});

describe('file paths', function() {
it('should resolve a relative path with an extension', async function() {
let resolved = await resolver.resolve(
Expand Down
8 changes: 8 additions & 0 deletions test/scope-hoisting.js
Expand Up @@ -6,6 +6,14 @@ const bundle = (name, opts = {}) =>
_bundle(name, Object.assign({scopeHoist: true}, opts));

describe('scope hoisting', function() {
// TODO: Figure out why these throw permission errors on windows
if (process.platform === 'win32') {
// eslint-disable-next-line no-console
console.warn(`WARNING: Scope hoisting tests are disabled on windows due to filesystem errors.
Feel free to look into this and contribute a fix!`);
return;
}

describe('es6', function() {
it('supports default imports and exports of expressions', async function() {
let b = await bundle(
Expand Down
30 changes: 21 additions & 9 deletions test/utils.js
Expand Up @@ -11,16 +11,23 @@ const promisify = require('../src/utils/promisify');
const rimraf = promisify(require('rimraf'));
const ncp = promisify(require('ncp'));

beforeEach(async function() {
// Test run in a single process, creating and deleting the same file(s)
// Windows needs a delay for the file handles to be released before deleting
// is possible. Without a delay, rimraf fails on `beforeEach` for `/dist`
if (process.platform === 'win32') {
await sleep(50);
async function removeDistDirectory(count = 0) {
try {
await rimraf(path.join(__dirname, 'dist'));
} catch (e) {
if (count > 8) {
// eslint-disable-next-line no-console
console.warn('WARNING: Unable to remove dist directory:', e.message);
return;
}

await sleep(250);
await removeDistDirectory(count + 1);
}
// Unix based systems also need a delay but only half as much as windows
await sleep(50);
await rimraf(path.join(__dirname, 'dist'));
}

beforeEach(async function() {
await removeDistDirectory();
});

function sleep(ms) {
Expand Down Expand Up @@ -251,6 +258,10 @@ function deferred() {
return promise;
}

function normaliseNewlines(text) {
return text.replace(/(\r\n|\n|\r)/g, '\n');
}

exports.sleep = sleep;
exports.bundler = bundler;
exports.bundle = bundle;
Expand All @@ -260,3 +271,4 @@ exports.nextBundle = nextBundle;
exports.deferred = deferred;
exports.rimraf = rimraf;
exports.ncp = ncp;
exports.normaliseNewlines = normaliseNewlines;