Skip to content

Commit

Permalink
Make configuration work in engines
Browse files Browse the repository at this point in the history
This makes sure that all nested dependencies use the correct 
application configuration, and that the import/configuration works in 
nested addons, especially in engines.
  • Loading branch information
Francesco Novy committed Nov 27, 2018
1 parent 1c7ff64 commit 3506873
Show file tree
Hide file tree
Showing 2 changed files with 205 additions and 24 deletions.
49 changes: 26 additions & 23 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,35 +63,19 @@ module.exports = {
* which allows us to use the `import()` method to tell it to include a file
* from our `vendor` tree into the final built app.
*/
included: function(app) {
included: function() {
this._super.included.apply(this, arguments);

let target = app;
let app = this._findApp();
let importTarget = app;

if (typeof this.import === 'function') {
target = this;
} else {
// If the addon has the _findHost() method (in ember-cli >= 2.7.0), we'll just
// use that.
if (typeof this._findHost === 'function') {
target = this._findHost();
} else {
// Otherwise, we'll use this implementation borrowed from the _findHost()
// method in ember-cli.
// Keep iterating upward until we don't have a grandparent.
// Has to do this grandparent check because at some point we hit the project.
let current = this;
do {
target = current.app || app;
} while (current.parent.parent && (current = current.parent));
}
// If this.import is not a function, app and target should point to the same EmberApp
app = target;
importTarget = this;
}

this.buildConfig = app.options['ember-fetch'] || { preferNative: false };
app._fetchBuildConfig = app.options['ember-fetch'] || { preferNative: false };

target.import('vendor/ember-fetch.js', {
importTarget.import('vendor/ember-fetch.js', {
exports: {
default: [
'default',
Expand Down Expand Up @@ -128,7 +112,8 @@ module.exports = {
this.ui.writeWarnLine('[ember-fetch] Could not find `ember-cli-babel` addon, opting out of transpilation!')
}

const preferNative = this.buildConfig.preferNative;
const app = this._findApp();
const preferNative = app._fetchBuildConfig.preferNative;

return debug(map(browserTree, (content) => `if (typeof FastBoot === 'undefined') {
var preferNative = ${preferNative};
Expand Down Expand Up @@ -181,4 +166,22 @@ module.exports = {
};
}), 'browser-fetch');
},

_findApp() {
if (typeof this._findHost === 'function') {
return this._findHost();
} else {
// Otherwise, we'll use this implementation borrowed from the _findHost()
// method in ember-cli.
// Keep iterating upward until we don't have a grandparent.
// Has to do this grandparent check because at some point we hit the project.
let app;
let current = this;
do {
app = current.app || this;
} while (current.parent && current.parent.parent && (current = current.parent));

return app;
}
},
};
180 changes: 179 additions & 1 deletion test/prefer-native-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ require('fetch-test');
addon = Object.create(AddonFactory);
Object.assign(addon, {
addons: [],
buildConfig: {
_fetchBuildConfig: {
preferNative
},
ui: {
Expand Down Expand Up @@ -95,4 +95,182 @@ require('fetch-test');
}))
}
});

describe(`Build browser assets with preferNative = ${preferNative} in nested dependencies`, function() {
let output, subject, addon;

beforeEach(function() {
addon = Object.create(AddonFactory);

let app = {
_fetchBuildConfig: {
preferNative
}
};

Object.assign(addon, {
addons: [],
_findHost() {
return app;
},
ui: {
writeWarnLine() {},
},
});
subject = addon.treeForVendor();
output = helpers.createBuilder(subject);
});

afterEach(co.wrap(function* () {
yield output.dispose();
}));

it('preferNative is built into vendor file', co.wrap(function*() {
yield output.build();
let files = output.read();
expect(files).to.have.all.keys('ember-fetch.js');
expect(files['ember-fetch.js']).to.include(`var preferNative = ${preferNative}`);
}));

it(`${
preferNative ? 'Prefers' : "Doesn't prefer"
} native fetch as specified`, co.wrap(function*() {
yield output.build();
let emberFetchCode = output.read()['ember-fetch.js'];
const amdLoaderCode = fs.readFileSync(require.resolve('loader.js'));
const sandbox = {
__result: false,
window: {
fetch: function() {
sandbox.__result = true;
},
Ember: { RSVP }
}
};
vm.createContext(sandbox);
const code = amdLoaderCode + emberFetchCode + testCode;
vm.runInContext(code, sandbox);
expect(sandbox.__result).to.equal(preferNative);
}));

if (preferNative === true) {
it('Has fetch poly fill even if fetch is not there', co.wrap(function*() {
yield output.build();
let emberFetchCode = output.read()['ember-fetch.js'];
const amdLoaderCode = fs.readFileSync(require.resolve('loader.js'));
const sandbox = {
console,
window: {
__result: false,
// no fetch here
// fetch: function() {},
Ember: { RSVP }
}
};
vm.createContext(sandbox);
const testCodeForNonFetch = `
define('fetch-test', ['fetch'], function(_fetch) {
if (_fetch.default.polyfill) {
window.__result = true
}
});
require('fetch-test');
`;
const code = amdLoaderCode + emberFetchCode + testCodeForNonFetch;
vm.runInContext(code, sandbox);
expect(sandbox.window.__result).to.equal(true);
}))
}
});

describe(`Build browser assets with preferNative = ${preferNative} in nested dependencies without _findHost`, function() {
let output, subject, addon;

beforeEach(function() {
addon = Object.create(AddonFactory);

let app = {
_fetchBuildConfig: {
preferNative
}
};

Object.assign(addon, {
addons: [],
app: this,
parent: {
parent: {
app,
parent: {}
}
},
ui: {
writeWarnLine() {},
},
});
subject = addon.treeForVendor();
output = helpers.createBuilder(subject);
});

afterEach(co.wrap(function* () {
yield output.dispose();
}));

it('preferNative is built into vendor file', co.wrap(function*() {
yield output.build();
let files = output.read();
expect(files).to.have.all.keys('ember-fetch.js');
expect(files['ember-fetch.js']).to.include(`var preferNative = ${preferNative}`);
}));

it(`${
preferNative ? 'Prefers' : "Doesn't prefer"
} native fetch as specified`, co.wrap(function*() {
yield output.build();
let emberFetchCode = output.read()['ember-fetch.js'];
const amdLoaderCode = fs.readFileSync(require.resolve('loader.js'));
const sandbox = {
__result: false,
window: {
fetch: function() {
sandbox.__result = true;
},
Ember: { RSVP }
}
};
vm.createContext(sandbox);
const code = amdLoaderCode + emberFetchCode + testCode;
vm.runInContext(code, sandbox);
expect(sandbox.__result).to.equal(preferNative);
}));

if (preferNative === true) {
it('Has fetch poly fill even if fetch is not there', co.wrap(function*() {
yield output.build();
let emberFetchCode = output.read()['ember-fetch.js'];
const amdLoaderCode = fs.readFileSync(require.resolve('loader.js'));
const sandbox = {
console,
window: {
__result: false,
// no fetch here
// fetch: function() {},
Ember: { RSVP }
}
};
vm.createContext(sandbox);
const testCodeForNonFetch = `
define('fetch-test', ['fetch'], function(_fetch) {
if (_fetch.default.polyfill) {
window.__result = true
}
});
require('fetch-test');
`;
const code = amdLoaderCode + emberFetchCode + testCodeForNonFetch;
vm.runInContext(code, sandbox);
expect(sandbox.window.__result).to.equal(true);
}))
}
});
});

0 comments on commit 3506873

Please sign in to comment.