From 0124563d46f3f99929127f18eb4202222fc25d57 Mon Sep 17 00:00:00 2001 From: Andrew Kirwin Date: Mon, 10 Aug 2020 14:02:41 +0100 Subject: [PATCH] initial example --- app/adapters/foo.js | 16 ++ app/components/my-component.hbs | 7 + app/components/my-component.js | 24 ++ app/controllers/application.js | 3 + app/models/foo.js | 6 + app/routes/application.js | 22 ++ app/serializers/foo.js | 3 + app/services/foo.js | 18 ++ app/styles/app.css | 3 + app/templates/application.hbs | 8 +- app/utils/errors.js | 1 + app/utils/server.js | 20 ++ package-lock.json | 267 ++++++++++++++++++ package.json | 5 +- tests/acceptance/application-test.js | 48 ++++ .../components/my-component-test.js | 26 ++ tests/unit/adapters/foo-test.js | 12 + tests/unit/controllers/application-test.js | 12 + tests/unit/models/foo-test.js | 13 + tests/unit/routes/application-test.js | 11 + tests/unit/serializers/foo-test.js | 23 ++ tests/unit/services/foo-test.js | 12 + 22 files changed, 555 insertions(+), 5 deletions(-) create mode 100644 app/adapters/foo.js create mode 100644 app/components/my-component.hbs create mode 100644 app/components/my-component.js create mode 100644 app/controllers/application.js create mode 100644 app/models/foo.js create mode 100644 app/routes/application.js create mode 100644 app/serializers/foo.js create mode 100644 app/services/foo.js create mode 100644 app/utils/errors.js create mode 100644 app/utils/server.js create mode 100644 tests/acceptance/application-test.js create mode 100644 tests/integration/components/my-component-test.js create mode 100644 tests/unit/adapters/foo-test.js create mode 100644 tests/unit/controllers/application-test.js create mode 100644 tests/unit/models/foo-test.js create mode 100644 tests/unit/routes/application-test.js create mode 100644 tests/unit/serializers/foo-test.js create mode 100644 tests/unit/services/foo-test.js diff --git a/app/adapters/foo.js b/app/adapters/foo.js new file mode 100644 index 0000000..88c8d99 --- /dev/null +++ b/app/adapters/foo.js @@ -0,0 +1,16 @@ +import RESTAdapter from '@ember-data/adapter/rest'; +import fetch from 'fetch'; +import { AJAXError } from '../utils/errors'; + +export default class FooAdapter extends RESTAdapter { + ajax(path, method) { + return fetch(path, { method }) + .then(response => { + if (response.ok) { + return response.json(); + } else { + throw new AJAXError(response.statusText) + } + }) + } +} diff --git a/app/components/my-component.hbs b/app/components/my-component.hbs new file mode 100644 index 0000000..5ce33f9 --- /dev/null +++ b/app/components/my-component.hbs @@ -0,0 +1,7 @@ +Foo: {{@foo.name}} + +{{#unless this.isSaved}} + +{{/unless}} \ No newline at end of file diff --git a/app/components/my-component.js b/app/components/my-component.js new file mode 100644 index 0000000..0441ca6 --- /dev/null +++ b/app/components/my-component.js @@ -0,0 +1,24 @@ +import Component from '@glimmer/component'; +import { action } from '@ember/object'; +import { tracked } from '@glimmer/tracking'; + +export default class MyComponent extends Component { + @tracked isSaving; + @tracked isSaved; + + @action + save() { + this.isSaving = true; + + this.args.onSave() + .then(() => { + this.isSaved = true; + }) + // .catch(error => { + // No need to catch, because already handled, flash message will be displayed (See services/foo.js) + // }) + .finally(() => { + this.isSaving = false; + }); + } +} diff --git a/app/controllers/application.js b/app/controllers/application.js new file mode 100644 index 0000000..3047079 --- /dev/null +++ b/app/controllers/application.js @@ -0,0 +1,3 @@ +import Controller from '@ember/controller'; + +export default class ApplicationController extends Controller {} diff --git a/app/models/foo.js b/app/models/foo.js new file mode 100644 index 0000000..597200f --- /dev/null +++ b/app/models/foo.js @@ -0,0 +1,6 @@ +import Model from '@ember-data/model'; +import { attr } from '@ember-data/model'; + +export default class FooModel extends Model { + @attr() name; +} diff --git a/app/routes/application.js b/app/routes/application.js new file mode 100644 index 0000000..bfdf104 --- /dev/null +++ b/app/routes/application.js @@ -0,0 +1,22 @@ +import Route from '@ember/routing/route'; +import { inject } from '@ember/service'; +import { action } from '@ember/object'; + +export default class ApplicationRoute extends Route { + @inject store; + @inject('foo') fooService; + + + model() { + return this.store.findRecord('foo', 1); + } + + setupController(controller, model) { + controller.foo = model; + } + + @action + save() { + return this.fooService.saveFoo(this.controller.foo) + } +} diff --git a/app/serializers/foo.js b/app/serializers/foo.js new file mode 100644 index 0000000..30f3a45 --- /dev/null +++ b/app/serializers/foo.js @@ -0,0 +1,3 @@ +import RESTSerializer from '@ember-data/serializer/rest'; + +export default class Fooerializer extends RESTSerializer {} diff --git a/app/services/foo.js b/app/services/foo.js new file mode 100644 index 0000000..1e709b3 --- /dev/null +++ b/app/services/foo.js @@ -0,0 +1,18 @@ +import Service, { inject } from '@ember/service'; + +export default class FooService extends Service { + @inject('flash-message') flashMessageService; + + saveFoo(foo) { + return foo.save().catch(error => { + // 'Handle error' + // Make sure if saving a foo fails, then the user always knows about it. + this.flashMessageService.add('error', error.message); + + // Rethrow error, so that the `saveFoo` promise chain remains in an error + // state. This allows us to determine if `saveFoo` failed or succeeded + // later on in the code... (See my-component.js) + throw error; + }); + } +} diff --git a/app/styles/app.css b/app/styles/app.css index e69de29..0c9a302 100644 --- a/app/styles/app.css +++ b/app/styles/app.css @@ -0,0 +1,3 @@ +.flash-message .message__dismiss { + display: none; +} diff --git a/app/templates/application.hbs b/app/templates/application.hbs index 7b1b104..ab67c84 100644 --- a/app/templates/application.hbs +++ b/app/templates/application.hbs @@ -1,5 +1,5 @@ -{{!-- The following component displays Ember's default welcome message. --}} - -{{!-- Feel free to remove this! --}} + -{{outlet}} \ No newline at end of file +

+ + \ No newline at end of file diff --git a/app/utils/errors.js b/app/utils/errors.js new file mode 100644 index 0000000..b1eb921 --- /dev/null +++ b/app/utils/errors.js @@ -0,0 +1 @@ +export class AJAXError extends Error {} diff --git a/app/utils/server.js b/app/utils/server.js new file mode 100644 index 0000000..f83703e --- /dev/null +++ b/app/utils/server.js @@ -0,0 +1,20 @@ +import Pretender from 'pretender'; + +const server = new Pretender(); + +server.prepareBody = JSON.stringify; + +server.put('/foos/1', () => [500, {}, {}]); + +server.get('/foos/1', () => [ + 200, + {}, + { + foo: { + id: 1, + name: 'Foo 1', + }, + }, +]); + +export default server; diff --git a/package-lock.json b/package-lock.json index e66d604..0a5240a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2563,6 +2563,16 @@ } } }, + "@ember/render-modifiers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@ember/render-modifiers/-/render-modifiers-1.0.2.tgz", + "integrity": "sha512-6tEnHl5+62NTSAG2mwhGMFPhUrJQjoVqV+slsn+rlTknm2Zik+iwxBQEbwaiQOU1FUYxkS8RWcieovRNMR8inQ==", + "dev": true, + "requires": { + "ember-cli-babel": "^7.10.0", + "ember-modifier-manager-polyfill": "^1.1.0" + } + }, "@ember/test-helpers": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/@ember/test-helpers/-/test-helpers-1.7.1.tgz", @@ -3145,6 +3155,19 @@ "integrity": "sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g==", "dev": true }, + "@zestia/ember-messages": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@zestia/ember-messages/-/ember-messages-2.1.6.tgz", + "integrity": "sha512-Llsrt+CIte6ktGVoZbd86WKwF+v7hnETiPgNfL6A3/MZK1z0Mx9y1nWFedAE5IM9c/gEfRRJJ31lyQXpc3jOfw==", + "dev": true, + "requires": { + "@ember/render-modifiers": "^1.0.2", + "@glimmer/component": "^1.0.0", + "@glimmer/tracking": "^1.0.0", + "ember-cli-babel": "^7.21.0", + "ember-cli-htmlbars": "^5.1.2" + } + }, "abab": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.4.tgz", @@ -9464,6 +9487,27 @@ "integrity": "sha512-B7wiurPgsxsSGzJuPFkpBWnaeuCu2PGpG2BjyrfA1VcL7//o+5RSnZqiCEY326y7qmxb2GoCgo0ft03KBU0rRw==", "dev": true }, + "ember-factory-for-polyfill": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/ember-factory-for-polyfill/-/ember-factory-for-polyfill-1.3.1.tgz", + "integrity": "sha512-y3iG2iCzH96lZMTWQw6LWNLAfOmDC4pXKbZP6FxG8lt7GGaNFkZjwsf+Z5GAe7kxfD7UG4lVkF7x37K82rySGA==", + "dev": true, + "requires": { + "ember-cli-version-checker": "^2.1.0" + }, + "dependencies": { + "ember-cli-version-checker": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ember-cli-version-checker/-/ember-cli-version-checker-2.2.0.tgz", + "integrity": "sha512-G+KtYIVlSOWGcNaTFHk76xR4GdzDLzAS4uxZUKdASuFX0KJE43C6DaqL+y3VTpUFLI2FIkAS6HZ4I1YBi+S3hg==", + "dev": true, + "requires": { + "resolve": "^1.3.3", + "semver": "^5.3.0" + } + } + } + }, "ember-fetch": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/ember-fetch/-/ember-fetch-8.0.2.tgz", @@ -9716,6 +9760,28 @@ } } }, + "ember-getowner-polyfill": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ember-getowner-polyfill/-/ember-getowner-polyfill-2.2.0.tgz", + "integrity": "sha512-rwGMJgbGzxIAiWYjdpAh04Abvt0s3HuS/VjHzUFhVyVg2pzAuz45B9AzOxYXzkp88vFC7FPaiA4kE8NxNk4A4Q==", + "dev": true, + "requires": { + "ember-cli-version-checker": "^2.1.0", + "ember-factory-for-polyfill": "^1.3.1" + }, + "dependencies": { + "ember-cli-version-checker": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ember-cli-version-checker/-/ember-cli-version-checker-2.2.0.tgz", + "integrity": "sha512-G+KtYIVlSOWGcNaTFHk76xR4GdzDLzAS4uxZUKdASuFX0KJE43C6DaqL+y3VTpUFLI2FIkAS6HZ4I1YBi+S3hg==", + "dev": true, + "requires": { + "resolve": "^1.3.3", + "semver": "^5.3.0" + } + } + } + }, "ember-inflector": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ember-inflector/-/ember-inflector-3.0.1.tgz", @@ -10295,6 +10361,29 @@ } } }, + "ember-modifier-manager-polyfill": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ember-modifier-manager-polyfill/-/ember-modifier-manager-polyfill-1.2.0.tgz", + "integrity": "sha512-bnaKF1LLKMkBNeDoetvIJ4vhwRPKIIumWr6dbVuW6W6p4QV8ZiO+GdF8J7mxDNlog9CeL9Z/7wam4YS86G8BYA==", + "dev": true, + "requires": { + "ember-cli-babel": "^7.10.0", + "ember-cli-version-checker": "^2.1.2", + "ember-compatibility-helpers": "^1.2.0" + }, + "dependencies": { + "ember-cli-version-checker": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ember-cli-version-checker/-/ember-cli-version-checker-2.2.0.tgz", + "integrity": "sha512-G+KtYIVlSOWGcNaTFHk76xR4GdzDLzAS4uxZUKdASuFX0KJE43C6DaqL+y3VTpUFLI2FIkAS6HZ4I1YBi+S3hg==", + "dev": true, + "requires": { + "resolve": "^1.3.3", + "semver": "^5.3.0" + } + } + } + }, "ember-qunit": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/ember-qunit/-/ember-qunit-4.6.0.tgz", @@ -10461,6 +10550,162 @@ "integrity": "sha512-GPKa7zRDBblRy0orxTXt5yrpp/Pf5CkuRFSIR8qMFDww0CqCKjCRwdZnWYzCM4kAEfZnXRIDDefe1tBaFw7v7w==", "dev": true }, + "ember-route-action-helper": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/ember-route-action-helper/-/ember-route-action-helper-2.0.8.tgz", + "integrity": "sha512-V+4uKwqaYveriVt2rl4e+9mzHJiQOr1B8dCPQQ2TS3iAcmi5RD2giRDFGtCK9d2XY9Arb/f9hJh0obP20iyt3A==", + "dev": true, + "requires": { + "ember-cli-babel": "^6.8.1", + "ember-getowner-polyfill": "^2.0.0" + }, + "dependencies": { + "amd-name-resolver": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/amd-name-resolver/-/amd-name-resolver-1.2.0.tgz", + "integrity": "sha512-hlSTWGS1t6/xq5YCed7YALg7tKZL3rkl7UwEZ/eCIkn8JxmM6fU6Qs/1hwtjQqfuYxlffuUcgYEm0f5xP4YKaA==", + "dev": true, + "requires": { + "ensure-posix-path": "^1.0.1" + } + }, + "babel-plugin-debug-macros": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-debug-macros/-/babel-plugin-debug-macros-0.2.0.tgz", + "integrity": "sha512-Wpmw4TbhR3Eq2t3W51eBAQSdKlr+uAyF0GI4GtPfMCD12Y4cIdpKC9l0RjNTH/P9isFypSqqewMPm7//fnZlNA==", + "dev": true, + "requires": { + "semver": "^5.3.0" + } + }, + "babel-plugin-ember-modules-api-polyfill": { + "version": "2.13.4", + "resolved": "https://registry.npmjs.org/babel-plugin-ember-modules-api-polyfill/-/babel-plugin-ember-modules-api-polyfill-2.13.4.tgz", + "integrity": "sha512-uxQPkEQAzCYdwhZk16O9m1R4xtCRNy4oEUTBrccOPfzlIahRZJic/JeP/ZEL0BC6Mfq6r55eOg6gMF/zdFoCvA==", + "dev": true, + "requires": { + "ember-rfc176-data": "^0.3.13" + } + }, + "broccoli-babel-transpiler": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/broccoli-babel-transpiler/-/broccoli-babel-transpiler-6.5.1.tgz", + "integrity": "sha512-w6GcnkxvHcNCte5FcLGEG1hUdQvlfvSN/6PtGWU/otg69Ugk8rUk51h41R0Ugoc+TNxyeFG1opRt2RlA87XzNw==", + "dev": true, + "requires": { + "babel-core": "^6.26.0", + "broccoli-funnel": "^2.0.1", + "broccoli-merge-trees": "^2.0.0", + "broccoli-persistent-filter": "^1.4.3", + "clone": "^2.0.0", + "hash-for-dep": "^1.2.3", + "heimdalljs-logger": "^0.1.7", + "json-stable-stringify": "^1.0.0", + "rsvp": "^4.8.2", + "workerpool": "^2.3.0" + } + }, + "broccoli-merge-trees": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/broccoli-merge-trees/-/broccoli-merge-trees-2.0.1.tgz", + "integrity": "sha512-WjaexJ+I8BxP5V5RNn6um/qDRSmKoiBC/QkRi79FT9ClHfldxRyCDs9mcV7mmoaPlsshmmPaUz5jdtcKA6DClQ==", + "dev": true, + "requires": { + "broccoli-plugin": "^1.3.0", + "merge-trees": "^1.0.1" + } + }, + "broccoli-persistent-filter": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/broccoli-persistent-filter/-/broccoli-persistent-filter-1.4.6.tgz", + "integrity": "sha512-0RejLwoC95kv4kta8KAa+FmECJCK78Qgm8SRDEK7YyU0N9Cx6KpY3UCDy9WELl3mCXLN8TokNxc7/hp3lL4lfw==", + "dev": true, + "requires": { + "async-disk-cache": "^1.2.1", + "async-promise-queue": "^1.0.3", + "broccoli-plugin": "^1.0.0", + "fs-tree-diff": "^0.5.2", + "hash-for-dep": "^1.0.2", + "heimdalljs": "^0.2.1", + "heimdalljs-logger": "^0.1.7", + "mkdirp": "^0.5.1", + "promise-map-series": "^0.2.1", + "rimraf": "^2.6.1", + "rsvp": "^3.0.18", + "symlink-or-copy": "^1.0.1", + "walk-sync": "^0.3.1" + }, + "dependencies": { + "rsvp": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz", + "integrity": "sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==", + "dev": true + } + } + }, + "ember-cli-babel": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/ember-cli-babel/-/ember-cli-babel-6.18.0.tgz", + "integrity": "sha512-7ceC8joNYxY2wES16iIBlbPSxwKDBhYwC8drU3ZEvuPDMwVv1KzxCNu1fvxyFEBWhwaRNTUxSCsEVoTd9nosGA==", + "dev": true, + "requires": { + "amd-name-resolver": "1.2.0", + "babel-plugin-debug-macros": "^0.2.0-beta.6", + "babel-plugin-ember-modules-api-polyfill": "^2.6.0", + "babel-plugin-transform-es2015-modules-amd": "^6.24.0", + "babel-polyfill": "^6.26.0", + "babel-preset-env": "^1.7.0", + "broccoli-babel-transpiler": "^6.5.0", + "broccoli-debug": "^0.6.4", + "broccoli-funnel": "^2.0.0", + "broccoli-source": "^1.1.0", + "clone": "^2.0.0", + "ember-cli-version-checker": "^2.1.2", + "semver": "^5.5.0" + } + }, + "ember-cli-version-checker": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ember-cli-version-checker/-/ember-cli-version-checker-2.2.0.tgz", + "integrity": "sha512-G+KtYIVlSOWGcNaTFHk76xR4GdzDLzAS4uxZUKdASuFX0KJE43C6DaqL+y3VTpUFLI2FIkAS6HZ4I1YBi+S3hg==", + "dev": true, + "requires": { + "resolve": "^1.3.3", + "semver": "^5.3.0" + } + }, + "merge-trees": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-trees/-/merge-trees-1.0.1.tgz", + "integrity": "sha1-zL5nRWl4f53vF/1G5lJfVwC70j4=", + "dev": true, + "requires": { + "can-symlink": "^1.0.0", + "fs-tree-diff": "^0.5.4", + "heimdalljs": "^0.2.1", + "heimdalljs-logger": "^0.1.7", + "rimraf": "^2.4.3", + "symlink-or-copy": "^1.0.0" + } + }, + "rsvp": { + "version": "4.8.5", + "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz", + "integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==", + "dev": true + }, + "workerpool": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-2.3.3.tgz", + "integrity": "sha512-L1ovlYHp6UObYqElXXpbd214GgbEKDED0d3sj7pRdFXjNkb2+un/AUcCkceHizO0IVI6SOGGncrcjozruCkRgA==", + "dev": true, + "requires": { + "object-assign": "4.1.1" + } + } + } + }, "ember-router-generator": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ember-router-generator/-/ember-router-generator-2.0.0.tgz", @@ -11724,6 +11969,12 @@ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", "dev": true }, + "fake-xml-http-request": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fake-xml-http-request/-/fake-xml-http-request-2.1.1.tgz", + "integrity": "sha512-Kn2WYYS6cDBS5jq/voOfSGCA0TafOYAUPbEp8mUVpD/DVV5bQIDjlq+MLLvNUokkbTpjBVlLDaM5PnX+PwZMlw==", + "dev": true + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -15866,6 +16117,16 @@ "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", "dev": true }, + "pretender": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/pretender/-/pretender-3.4.3.tgz", + "integrity": "sha512-AlbkBly9R8KR+R0sTCJ/ToOeEoUMtt52QVCetui5zoSmeLOU3S8oobFsyPLm1O2txR6t58qDNysqPnA1vVi8Hg==", + "dev": true, + "requires": { + "fake-xml-http-request": "^2.1.1", + "route-recognizer": "^0.3.3" + } + }, "pretty-ms": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-3.2.0.tgz", @@ -16676,6 +16937,12 @@ "estree-walker": "^0.6.1" } }, + "route-recognizer": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/route-recognizer/-/route-recognizer-0.3.4.tgz", + "integrity": "sha512-2+MhsfPhvauN1O8KaXpXAOfR/fwe8dnUXVM+xw7yt40lJRfPVQxV6yryZm0cgRvAj5fMF/mdRZbL2ptwbs5i2g==", + "dev": true + }, "rsvp": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz", diff --git a/package.json b/package.json index b276730..d70b8a1 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "@ember/optional-features": "^1.3.0", "@glimmer/component": "^1.0.0", "@glimmer/tracking": "^1.0.0", + "@zestia/ember-messages": "^2.1.6", "babel-eslint": "^10.1.0", "broccoli-asset-rev": "^3.0.0", "ember-auto-import": "^1.5.3", @@ -36,11 +37,12 @@ "ember-cli-uglify": "^3.0.0", "ember-data": "~3.19.0", "ember-export-application-global": "^2.0.1", - "ember-fetch": "^8.0.1", + "ember-fetch": "^8.0.2", "ember-load-initializers": "^2.1.1", "ember-maybe-import-regenerator": "^0.1.6", "ember-qunit": "^4.6.0", "ember-resolver": "^8.0.0", + "ember-route-action-helper": "^2.0.8", "ember-source": "~3.19.0", "ember-template-lint": "^2.8.0", "ember-welcome-page": "^4.0.0", @@ -49,6 +51,7 @@ "eslint-plugin-node": "^11.1.0", "loader.js": "^4.7.0", "npm-run-all": "^4.1.5", + "pretender": "^3.4.3", "qunit-dom": "^1.2.0" }, "engines": { diff --git a/tests/acceptance/application-test.js b/tests/acceptance/application-test.js new file mode 100644 index 0000000..0b839f7 --- /dev/null +++ b/tests/acceptance/application-test.js @@ -0,0 +1,48 @@ +import { module, test } from 'qunit'; +import { visit, click, setupOnerror, resetOnerror } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import { AJAXError } from 'example/utils/errors'; +import server from 'example/utils/server'; + +module('Acceptance | application', function(hooks) { + setupApplicationTest(hooks); + + hooks.beforeEach(function() { + // Squelch AJAX error to allow us to test failure scenarios + // Note: This only works with RSVP! + // + // setupOnerror(error => { + // if (error instanceof AJAXError) { + // return; + // } + // + // throw error; + // }); + }); + + hooks.afterEach(function() { + resetOnerror() + }); + + test('success', async function(assert) { + await visit('/'); + + server.put('/foos/1', () => [200, {}, {}]); + + await click('button'); + + assert.dom('.message').doesNotExist(); + assert.dom('button').doesNotExist(); + }); + + test('failure', async function(assert) { + await visit('/'); + + server.put('/foos/1', () => [500, {}, {}]); + + await click('button'); + + assert.dom('.message').hasText('Internal Server Error'); + assert.dom('button').exists(); + }); +}); diff --git a/tests/integration/components/my-component-test.js b/tests/integration/components/my-component-test.js new file mode 100644 index 0000000..60f0ac1 --- /dev/null +++ b/tests/integration/components/my-component-test.js @@ -0,0 +1,26 @@ +// import { module, test } from 'qunit'; +// import { setupRenderingTest } from 'ember-qunit'; +// import { render } from '@ember/test-helpers'; +// import { hbs } from 'ember-cli-htmlbars'; +// +// module('Integration | Component | my-component', function(hooks) { +// setupRenderingTest(hooks); +// +// test('it renders', async function(assert) { +// // Set any properties with this.set('myProperty', 'value'); +// // Handle any actions with this.set('myAction', function(val) { ... }); +// +// await render(hbs``); +// +// assert.equal(this.element.textContent.trim(), ''); +// +// // Template block usage: +// await render(hbs` +// +// template block text +// +// `); +// +// assert.equal(this.element.textContent.trim(), 'template block text'); +// }); +// }); diff --git a/tests/unit/adapters/foo-test.js b/tests/unit/adapters/foo-test.js new file mode 100644 index 0000000..61b5526 --- /dev/null +++ b/tests/unit/adapters/foo-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Adapter | foo', function(hooks) { + setupTest(hooks); + + // Replace this with your real tests. + test('it exists', function(assert) { + let adapter = this.owner.lookup('adapter:foo'); + assert.ok(adapter); + }); +}); diff --git a/tests/unit/controllers/application-test.js b/tests/unit/controllers/application-test.js new file mode 100644 index 0000000..e4b814b --- /dev/null +++ b/tests/unit/controllers/application-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Controller | application', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let controller = this.owner.lookup('controller:application'); + assert.ok(controller); + }); +}); diff --git a/tests/unit/models/foo-test.js b/tests/unit/models/foo-test.js new file mode 100644 index 0000000..7d57019 --- /dev/null +++ b/tests/unit/models/foo-test.js @@ -0,0 +1,13 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Model | foo', function(hooks) { + setupTest(hooks); + + // Replace this with your real tests. + test('it exists', function(assert) { + let store = this.owner.lookup('service:store'); + let model = store.createRecord('foo', {}); + assert.ok(model); + }); +}); diff --git a/tests/unit/routes/application-test.js b/tests/unit/routes/application-test.js new file mode 100644 index 0000000..21e9fb3 --- /dev/null +++ b/tests/unit/routes/application-test.js @@ -0,0 +1,11 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | application', function(hooks) { + setupTest(hooks); + + test('it exists', function(assert) { + let route = this.owner.lookup('route:application'); + assert.ok(route); + }); +}); diff --git a/tests/unit/serializers/foo-test.js b/tests/unit/serializers/foo-test.js new file mode 100644 index 0000000..3480555 --- /dev/null +++ b/tests/unit/serializers/foo-test.js @@ -0,0 +1,23 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Serializer | foo', function(hooks) { + setupTest(hooks); + + // Replace this with your real tests. + test('it exists', function(assert) { + let store = this.owner.lookup('service:store'); + let serializer = store.serializerFor('foo'); + + assert.ok(serializer); + }); + + test('it serializes records', function(assert) { + let store = this.owner.lookup('service:store'); + let record = store.createRecord('foo', {}); + + let serializedRecord = record.serialize(); + + assert.ok(serializedRecord); + }); +}); diff --git a/tests/unit/services/foo-test.js b/tests/unit/services/foo-test.js new file mode 100644 index 0000000..9d6efae --- /dev/null +++ b/tests/unit/services/foo-test.js @@ -0,0 +1,12 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Service | foo', function(hooks) { + setupTest(hooks); + + // TODO: Replace this with your real tests. + test('it exists', function(assert) { + let service = this.owner.lookup('service:foo'); + assert.ok(service); + }); +});