diff --git a/app/serializers/gist.js b/app/serializers/gist.js index 6242a107..7276d868 100644 --- a/app/serializers/gist.js +++ b/app/serializers/gist.js @@ -18,7 +18,7 @@ export default ApplicationSerializer.extend({ }, normalizeArrayResponse(store, primaryModelClass, payload) { - payload.forEach((hash)=> this.normalizeGist(hash, true)); + payload.forEach(hash => this.normalizeGist(hash, true)); return this._super(...arguments); }, diff --git a/app/services/ember-cli.js b/app/services/ember-cli.js index 63db69d8..409bb71f 100644 --- a/app/services/ember-cli.js +++ b/app/services/ember-cli.js @@ -265,11 +265,6 @@ export default Ember.Service.extend({ // avoids security error appJS += "window.history.pushState = function() {}; window.history.replaceState = function() {}; window.sessionStorage = undefined;"; - // Use parent's version of QUnit in Ember.testing mode - if (testing) { - appJS += "window.QUnit = window.parent.QUnit;"; - } - // Hide toolbar since it is not working appCSS += `\n#qunit-testrunner-toolbar, #qunit-tests a[href] { display: none; }\n`; @@ -307,6 +302,10 @@ export default Ember.Service.extend({ let EmberENV = twiddleJSON.EmberENV || {}; const isTestingEnabled = testingEnabled(twiddleJSON); + if (testing && !isTestingEnabled) { + depScriptTags += ``; + } + depScriptTags += ``; depScriptTags += ``; @@ -324,6 +323,41 @@ export default Ember.Service.extend({ } }); + if (isTestingEnabled) { + testStuff += ` + `; + } + depScriptTags += ``; if (isTestingEnabled) { @@ -355,7 +389,7 @@ export default Ember.Service.extend({ testJSFiles.forEach(jsFile => { depScriptTags += ``; }); - + testStuff += ``; diff --git a/bower.json b/bower.json index c2e707ed..8f48bcee 100644 --- a/bower.json +++ b/bower.json @@ -7,7 +7,6 @@ "bootstrap-sass": "~3.3.5", "dom-ruler": "~0.2.4", "pretender": "~1.4.1", - "ember-inflector": "~1.3.1", "lodash": "~3.10.1", "Faker": "~3.1.0", "file-saver": "1.3.4", diff --git a/ember-cli-build.js b/ember-cli-build.js index 8a47d490..73b0e30b 100644 --- a/ember-cli-build.js +++ b/ember-cli-build.js @@ -74,14 +74,7 @@ module.exports = function(defaults) { }, tests: true, - hinting: process.env.EMBER_CLI_TEST_COMMAND || !isProductionLikeBuild, - - vendorFiles: { - 'ember.js': { - staging: 'bower_components/ember/ember.prod.js' - }, - 'ember-testing.js': [] - } + hinting: process.env.EMBER_CLI_TEST_COMMAND || !isProductionLikeBuild }); if (isFastboot) { @@ -99,10 +92,6 @@ module.exports = function(defaults) { app.import('vendor/shims/path.js'); app.import('bower_components/file-saver/FileSaver.js'); - if (env === "test") { - app.import('bower_components/ember/ember-testing.js', { type: 'test' }); - } - if (!isFastboot) { app.import('vendor/drags.js'); } diff --git a/tests/acceptance/acceptance-application-test.js b/tests/acceptance/acceptance-application-test.js new file mode 100644 index 00000000..a5fed342 --- /dev/null +++ b/tests/acceptance/acceptance-application-test.js @@ -0,0 +1,171 @@ +import { test } from 'qunit'; +import moduleForAcceptance from 'ember-twiddle/tests/helpers/module-for-acceptance'; +import { timeout } from 'ember-concurrency'; + +moduleForAcceptance('Acceptance | acceptance-application-test', { + beforeEach: function() { + this.cachePrompt = window.prompt; + window.prompt = (text, defaultResponse) => defaultResponse; + }, + + afterEach: function() { + window.prompt = this.cachePrompt; + } +}); + +test('An acceptance test for an application works', function(assert) { + + const files = [ + { + filename: "application.template.hbs", + content: `Welcome to {{appName}}` + }, + { + filename: "application.controller.js", + content: `import Ember from "ember"; + export default Ember.Controller.extend({ + appName: 'Ember Twiddle' + });` + }, + { + filename: "twiddle.json", + content: `{ + "version": "0.13.0", + "EmberENV": { + "FEATURES": {} + }, + "options": { + "use_pods": false, + "enable-testing": true + }, + "dependencies": { + "jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js" + } + }` + }, + { + filename: "components/my-component.js", + content: `import Ember from 'ember'; + + export default Ember.Component.extend({ + });` + }, + { + filename: "templates/components/my-component.hbs", + content: `{{yield}}` + }, + { + filename: "tests/test-helper.js", + content: `import resolver from './helpers/resolver'; + import { + setResolver + } from 'ember-qunit'; + import jQuery from 'jquery'; + + setResolver(resolver); + + window.testModule = 'twiddle/tests/acceptance/application-test'; + ` + }, + { + filename: "tests/helpers/resolver.js", + content: `import Resolver from '../../resolver'; + import config from '../../config/environment'; + + const resolver = Resolver.create(); + + resolver.namespace = { + modulePrefix: config.modulePrefix, + podModulePrefix: config.podModulePrefix + }; + + export default resolver;` + }, + { + filename: "tests/helpers/module-for-acceptance.js", + content: `import { module } from 'qunit'; + import Ember from 'ember'; + import startApp from '../helpers/start-app'; + import destroyApp from '../helpers/destroy-app'; + + const { RSVP: { Promise } } = Ember; + + export default function(name, options = {}) { + module(name, { + beforeEach() { + this.application = startApp(); + + if (options.beforeEach) { + return options.beforeEach.apply(this, arguments); + } + }, + + afterEach() { + let afterEach = options.afterEach && options.afterEach.apply(this, arguments); + return Promise.resolve(afterEach).then(() => destroyApp(this.application)); + } + }); + }` + }, + { + filename: "tests/helpers/start-app.js", + content: `import Ember from 'ember'; + import Application from '../../app'; + import config from '../../config/environment'; + + const { run } = Ember; + const assign = Ember.assign || Ember.merge; + + export default function startApp(attrs) { + let application; + + let attributes = assign({rootElement: "#test-root"}, config.APP); + attributes = assign(attributes, attrs); // use defaults, but you can override; + + run(() => { + application = Application.create(attributes); + application.setupForTesting(); + application.injectTestHelpers(); + }); + + return application; + } + ` + }, + { + filename: "tests/helpers/destroy-app.js", + content: `import Ember from 'ember'; + + export default function destroyApp(application) { + Ember.run(application, 'destroy'); + }` + }, + { + filename: "tests/acceptance/application-test.js", + content: `import { test } from 'qunit'; + import moduleForAcceptance from '../../tests/helpers/module-for-acceptance'; + + moduleForAcceptance('TODO: put something here'); + + test('visiting /application', function(assert) { + visit('/'); + + andThen(function() { + assert.equal(currentURL(), '/', 'route loaded correctly'); + }); + });` + } + ]; + + runGist(files); + + andThen(function() { + return timeout(500); // TODO: fix and remove this timing hack + }); + + andThen(function() { + const outputSpan = 'div#qunit-testresult-display > span.passed'; + + assert.equal(outputPane().$(outputSpan).text(), '1', 'acceptance test passed'); + }); +}); diff --git a/tests/acceptance/integration-component-test.js b/tests/acceptance/integration-component-test.js new file mode 100644 index 00000000..65e7363f --- /dev/null +++ b/tests/acceptance/integration-component-test.js @@ -0,0 +1,125 @@ +import { test } from 'qunit'; +import moduleForAcceptance from 'ember-twiddle/tests/helpers/module-for-acceptance'; +import { timeout } from 'ember-concurrency'; + +moduleForAcceptance('Acceptance | integration-component-test', { + beforeEach: function() { + this.cachePrompt = window.prompt; + window.prompt = (text, defaultResponse) => defaultResponse; + }, + + afterEach: function() { + window.prompt = this.cachePrompt; + } +}); + +test('An integration test for a component works', function(assert) { + + const files = [ + { + filename: "application.template.hbs", + content: `Welcome to {{appName}}` + }, + { + filename: "application.controller.js", + content: `import Ember from "ember"; + export default Ember.Controller.extend({ + appName: 'Ember Twiddle' + });` + }, + { + filename: "twiddle.json", + content: `{ + "version": "0.13.0", + "EmberENV": { + "FEATURES": {} + }, + "options": { + "use_pods": false, + "enable-testing": true + }, + "dependencies": { + "jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js" + } + }` + }, + { + filename: "components/my-component.js", + content: `import Ember from 'ember'; + + export default Ember.Component.extend({ + });` + }, + { + filename: "templates/components/my-component.hbs", + content: `{{yield}}` + }, + { + filename: "tests/test-helper.js", + content: `import resolver from './helpers/resolver'; + import { + setResolver + } from 'ember-qunit'; + import jQuery from 'jquery'; + + setResolver(resolver); + + window.testModule = 'twiddle/tests/integration/components/my-component-test'; + ` + }, + { + filename: "tests/helpers/resolver.js", + content: `import Resolver from '../../resolver'; + import config from '../../config/environment'; + + const resolver = Resolver.create(); + + resolver.namespace = { + modulePrefix: config.modulePrefix, + podModulePrefix: config.podModulePrefix + }; + + export default resolver;` + }, + { + filename: "tests/integration/components/my-component-test.js", + content: `import { moduleForComponent, test } from 'ember-qunit'; + import hbs from 'htmlbars-inline-precompile'; + + moduleForComponent('my-component', 'TODO: put something here', { + integration: true + }); + + test('it renders', function(assert) { + + // Set any properties with this.set('myProperty', 'value'); + // Handle any actions with this.on('myAction', function(val) { ... }); + + this.render(hbs\`{{my-component}}\`); + + assert.equal(this.$().text().trim(), ''); + + // Template block usage: + this.render(hbs\` + {{#my-component}} + template block text + {{/my-component}} + \`); + + assert.equal(this.$().text().trim(), 'template block text'); + });` + } + ]; + + runGist(files); + + andThen(function() { + return timeout(500); // TODO: fix and remove this timing hack + }); + + andThen(function() { + const outputSpan = 'div#qunit-testresult-display > span.passed'; + + assert.equal(outputPane().$(outputSpan).text(), '2', 'integration test passed'); + }); +}); diff --git a/tests/acceptance/unit-controller-test.js b/tests/acceptance/unit-controller-test.js new file mode 100644 index 00000000..5462e1a4 --- /dev/null +++ b/tests/acceptance/unit-controller-test.js @@ -0,0 +1,99 @@ +import { test } from 'qunit'; +import moduleForAcceptance from 'ember-twiddle/tests/helpers/module-for-acceptance'; +import { timeout } from 'ember-concurrency'; + +moduleForAcceptance('Acceptance | unit-controller-test', { + beforeEach: function() { + this.cachePrompt = window.prompt; + window.prompt = (text, defaultResponse) => defaultResponse; + }, + + afterEach: function() { + window.prompt = this.cachePrompt; + } +}); + +test('A unit test for controllers works', function(assert) { + + const files = [ + { + filename: "application.template.hbs", + content: `Welcome to {{appName}}` + }, + { + filename: "application.controller.js", + content: `import Ember from "ember"; + export default Ember.Controller.extend({ + appName: 'Ember Twiddle' + });` + }, + { + filename: "twiddle.json", + content: `{ + "version": "0.13.0", + "EmberENV": { + "FEATURES": {} + }, + "options": { + "use_pods": false, + "enable-testing": true + }, + "dependencies": { + "jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js" + } + }` + }, + { + filename: "tests/test-helper.js", + content: `import resolver from './helpers/resolver'; + import { + setResolver + } from 'ember-qunit'; + + setResolver(resolver); + + window.testModule = 'twiddle/tests/unit/controllers/application-test';` + }, + { + filename: "tests/helpers/resolver.js", + content: `import Resolver from '../../resolver'; + import config from '../../config/environment'; + + const resolver = Resolver.create(); + + resolver.namespace = { + modulePrefix: config.modulePrefix, + podModulePrefix: config.podModulePrefix + }; + + export default resolver;` + }, + { + filename: "tests/unit/controllers/application-test.js", + content: `import { moduleFor, test } from 'ember-qunit'; + + moduleFor('controller:application', 'TODO: put something here', { + // Specify the other units that are required for this test. + // needs: ['controller:foo'] + }); + + // Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.subject(); + assert.ok(controller); + });` + } + ]; + + runGist(files); + + andThen(function() { + return timeout(250); // TODO: fix and remove this timing hack + }); + + andThen(function() { + const outputSpan = 'div#qunit-testresult-display > span.passed'; + + assert.equal(outputPane().$(outputSpan).text(), '1', 'unit test passed'); + }); +}); diff --git a/tests/helpers/wait-for-loaded-iframe.js b/tests/helpers/wait-for-loaded-iframe.js index 0464b1c4..995e96fd 100644 --- a/tests/helpers/wait-for-loaded-iframe.js +++ b/tests/helpers/wait-for-loaded-iframe.js @@ -1,9 +1,9 @@ import Ember from "ember"; -const { RSVP, run, warn } = Ember; +const { RSVP, run } = Ember; export default function(app, url) { - let iframe_window; + let iframeWindow; andThen(function() { @@ -13,30 +13,40 @@ export default function(app, url) { run.schedule('afterRender', function waitForRender() { function onWindowLoad() { - iframe_window.document.removeEventListener('DOMContentLoaded', onWindowLoad); + iframeWindow.document.removeEventListener('DOMContentLoaded', onWindowLoad); resolve(); } if (times++ >= 10) { - warn('Timeout: Twiddle has failed to load'); + // eslint-disable-next-line no-console + console.warn('Timeout: Twiddle has failed to load'); run.cancelTimers(); - } else if (app.testHelpers.find('iframe').length === 0) { + } else if (app.testHelpers.find('iframe#dummy-content-iframe').length === 0) { run.later(waitForRender, 10); return; } - iframe_window = outputPane(); - let readyState = iframe_window.document.readyState; + iframeWindow = outputPane(); + let readyState = iframeWindow.document.readyState; if (readyState === 'complete' || readyState === 'interactive') { resolve(); } else { - iframe_window.document.addEventListener('DOMContentLoaded', onWindowLoad); + iframeWindow.document.addEventListener('DOMContentLoaded', onWindowLoad); } }); }); }); - return andThen(function() { + let times = 0; + + return andThen(function tryVisit() { url = url || "/"; - iframe_window.visit(url); + + if (times++ >= 10) { + run.cancelTimers(); + } else if (iframeWindow.visit) { + return iframeWindow.visit(url); + } else { + run.later(tryVisit, 10) + } }); } diff --git a/tests/test-helper.js b/tests/test-helper.js index bf20ab7b..4263311a 100644 --- a/tests/test-helper.js +++ b/tests/test-helper.js @@ -11,7 +11,7 @@ import waitForUnloadedIFrame from './helpers/wait-for-unloaded-iframe'; setResolver(resolver); -const iframe = "#dummy-content-iframe"; +const iframe = "iframe#dummy-content-iframe"; Ember.Test.registerHelper('outputPane', function(app) { return app.testHelpers.find(iframe)[0].contentWindow;