diff --git a/.travis.yml b/.travis.yml index 48adac0..07848dd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,8 +27,6 @@ branches: jobs: fail_fast: true - allow_failures: - - env: EMBER_TRY_SCENARIO=ember-canary include: # runs linting and tests with current locked deps diff --git a/index.js b/index.js index 879851d..4f203c7 100644 --- a/index.js +++ b/index.js @@ -1,9 +1,14 @@ 'use strict'; +const EMBER_VERSION_WITH_JQUERY_DEPRECATION = '3.9.0-alpha.1'; + module.exports = { name: require('./package').name, included() { this._super.included.apply(this, arguments); + + const VersionChecker = require('ember-cli-version-checker'); + let app = this._findHost(); let optionalFeatures = app.project.findAddonByName("@ember/optional-features"); @@ -13,6 +18,13 @@ module.exports = { app.import('vendor/shims/jquery.js'); + let checker = new VersionChecker(this); + let ember = checker.forEmber(); + + if (ember.gte(EMBER_VERSION_WITH_JQUERY_DEPRECATION)) { + app.import('vendor/jquery/component.dollar.js'); + } + if (optionalFeatures && !optionalFeatures.isFeatureEnabled('jquery-integration')) { app.project.ui.writeDeprecateLine('You have disabled the `jquery-integration` optional feature. You now have to delete `@ember/jquery` from your package.json'); } @@ -24,20 +36,27 @@ module.exports = { const resolve = require('resolve'); const path = require('path'); - var jqueryPath; + let jqueryPath; try { jqueryPath = path.dirname( resolve.sync('jquery/package.json', { basedir: this.project.root }) ); - } catch (error) { + } catch(error) { jqueryPath = path.dirname(require.resolve('jquery/package.json')); } - var jquery = new Funnel(jqueryPath + '/dist', { + let jquery = new Funnel(jqueryPath + '/dist', { destDir: 'jquery', files: ['jquery.js'], }); - return new BroccoliMergeTrees([jquery, tree]); + let babelAddon = this.project.findAddonByName('ember-cli-babel'); + let transpiledTree = babelAddon.transpileTree(tree, { + 'ember-cli-babel': { + compileModules: false + } + }); + + return new BroccoliMergeTrees([jquery, transpiledTree]); }, }; diff --git a/package.json b/package.json index 97d0324..eb49844 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "broccoli-funnel": "^2.0.1", "broccoli-merge-trees": "^3.0.2", "ember-cli-babel": "^7.4.0", + "ember-cli-version-checker": "^3.0.0", "jquery": "^3.3.1", "resolve": "^1.10.0" }, diff --git a/tests/integration/.gitkeep b/tests/integration/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/tests/integration/components/component-dot-dollar-test.js b/tests/integration/components/component-dot-dollar-test.js new file mode 100644 index 0000000..8f6e223 --- /dev/null +++ b/tests/integration/components/component-dot-dollar-test.js @@ -0,0 +1,39 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render } from '@ember/test-helpers'; +import hbs from 'htmlbars-inline-precompile'; +import Component from '@ember/component'; +import jQuery from 'jquery'; + +const component = Component.extend({ + didInsertElement() { + this.setJQueryElement(this.$(this.get('selector'))); + } +}); + +module('Integration | Component | component-dot-dollar', function(hooks) { + setupRenderingTest(hooks); + hooks.beforeEach(function() { + this.owner.register('component:jquery-component', component); + this.$element = null; + this.setJQueryElement = ($) => this.$element = $; + }); + + test('it implements Component.$()', function(assert) { + return assert.noDeprecations(async () => { + await render(hbs`{{jquery-component id="jq" setJQueryElement=setJQueryElement}}`); + + assert.ok(this.$element, 'Component.$() is available'); + assert.ok(this.$element instanceof jQuery, 'Component.$() returns a jQuery object'); + assert.equal(this.$element.get(0), this.element.querySelector('#jq'), 'Component.$() is a jQuery wrapper around Component.element'); + }); + }); + + test('it implements Component.$(selector)', function(assert) { + return assert.noDeprecations(async () => { + await render(hbs`{{#jquery-component id="jq" selector="div" setJQueryElement=setJQueryElement}}
{{/jquery-component}}`); + + assert.equal(this.$element.get(0), this.element.querySelector('#child'), 'Component.$(selector) is a jQuery object of the child elements matching selector'); + }); + }); +}); diff --git a/tests/test-helper.js b/tests/test-helper.js index 0382a84..7ca1458 100644 --- a/tests/test-helper.js +++ b/tests/test-helper.js @@ -1,8 +1,36 @@ +import QUnit from 'qunit'; +import { registerDeprecationHandler } from '@ember/debug'; import Application from '../app'; import config from '../config/environment'; import { setApplication } from '@ember/test-helpers'; import { start } from 'ember-qunit'; +let deprecations; + +registerDeprecationHandler((message, options, next) => { + // in case a deprecation is issued before a test is started + if (!deprecations) { + deprecations = []; + } + + deprecations.push(message); + next(message, options); +}); + +QUnit.testStart(function() { + deprecations = []; +}); + +QUnit.assert.noDeprecations = async function(callback) { + let originalDeprecations = deprecations; + deprecations = []; + + await callback(); + this.deepEqual(deprecations, [], 'Expected no deprecations during test.'); + + deprecations = originalDeprecations; +}; + setApplication(Application.create(config.APP)); start(); diff --git a/vendor/jquery/component.dollar.js b/vendor/jquery/component.dollar.js new file mode 100644 index 0000000..a049637 --- /dev/null +++ b/vendor/jquery/component.dollar.js @@ -0,0 +1,16 @@ +import { assert } from '@ember/debug'; + +(function() { + Ember.Component.reopen({ + $(sel) { + assert( + "You cannot access this.$() on a component with `tagName: ''` specified.", + this.tagName !== '' + ); + + if (this.element) { + return sel ? jQuery(sel, this.element) : jQuery(this.element); + } + } + }); +})();