",
13 | "directories": {
14 | "doc": "doc",
15 | "test": "tests"
16 | },
17 | "repository": "git@github.com:pixelhandler/ember-jsonapi-resources.git",
18 | "scripts": {
19 | "build": "ember build",
20 | "start": "ember server",
21 | "test": "ember try:each",
22 | "nodetest": "mocha node-tests --recursive"
23 | },
24 | "dependencies": {
25 | "ember-cli-babel": "^5.1.7",
26 | "ember-fetchjax": "^0.6.1",
27 | "ember-inflector": "^1.9.1",
28 | "ember-runtime-enumerable-includes-polyfill": "^1.0.2",
29 | "inflection": "~1.7.1",
30 | "lodash": "~3.10.1"
31 | },
32 | "devDependencies": {
33 | "broccoli-asset-rev": "^2.4.5",
34 | "broccoli-es6-concatenator": "^0.1.11",
35 | "broccoli-filter": "^0.1.14",
36 | "broccoli-static-compiler": "^0.2.1",
37 | "ember-buffered-proxy": "^0.5.1",
38 | "ember-cli": "2.10.0",
39 | "ember-cli-app-version": "^2.0.0",
40 | "ember-cli-blueprint-test-helpers": "^0.13.0",
41 | "ember-cli-content-security-policy": "0.4.0",
42 | "ember-cli-dependency-checker": "^1.3.0",
43 | "ember-cli-get-dependency-depth": "^1.0.0",
44 | "ember-cli-htmlbars": "^1.0.10",
45 | "ember-cli-htmlbars-inline-precompile": "^0.3.3",
46 | "ember-cli-inject-live-reload": "^1.4.1",
47 | "ember-cli-jshint": "^2.0.1",
48 | "ember-cli-path-utils": "^1.0.0",
49 | "ember-cli-qunit": "^3.0.1",
50 | "ember-cli-release": "^0.2.9",
51 | "ember-cli-sri": "^2.1.0",
52 | "ember-cli-string-utils": "^1.0.0",
53 | "ember-cli-test-info": "^1.0.0",
54 | "ember-cli-test-loader": "^1.1.0",
55 | "ember-cli-uglify": "^1.2.0",
56 | "ember-disable-prototype-extensions": "^1.1.0",
57 | "ember-export-application-global": "^1.0.5",
58 | "ember-load-initializers": "^0.5.1",
59 | "ember-resolver": "^2.0.3",
60 | "glob": "^4.5.3",
61 | "http-proxy": "^1.12.0",
62 | "loader.js": "^4.0.10",
63 | "mocha": "^2.5.3",
64 | "morgan": "^1.6.1",
65 | "silent-error": "^1.0.0",
66 | "yuidocjs": "^0.7.0"
67 | },
68 | "engines": {
69 | "node": ">= 0.12.0"
70 | },
71 | "ember-addon": {
72 | "configPath": "tests/dummy/config"
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/server/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true
3 | }
4 |
--------------------------------------------------------------------------------
/server/index.js:
--------------------------------------------------------------------------------
1 | /*jshint node:true*/
2 |
3 | // To use it create some files under `mocks/`
4 | // e.g. `server/mocks/ember-hamsters.js`
5 | //
6 | // module.exports = function(app) {
7 | // app.get('/ember-hamsters', function(req, res) {
8 | // res.send('hello');
9 | // });
10 | // };
11 |
12 | module.exports = function(app) {
13 | var globSync = require('glob').sync;
14 | var mocks = globSync('./mocks/**/*.js', { cwd: __dirname }).map(require);
15 | var proxies = globSync('./proxies/**/*.js', { cwd: __dirname }).map(require);
16 |
17 | // Log proxy requests
18 | var morgan = require('morgan');
19 | app.use(morgan('dev'));
20 |
21 | mocks.forEach(function(route) { route(app); });
22 | proxies.forEach(function(route) { route(app); });
23 |
24 | };
25 |
--------------------------------------------------------------------------------
/server/proxies/api.js:
--------------------------------------------------------------------------------
1 | /*jshint node:true*/
2 | var proxyPath = '/api';
3 |
4 | module.exports = function(app) {
5 | // For options, see:
6 | // https://github.com/nodejitsu/node-http-proxy
7 | var proxy = require('http-proxy').createProxyServer({});
8 |
9 | proxy.on('error', function(err, req) {
10 | console.error(err, req.url);
11 | });
12 |
13 | app.use(proxyPath, function(req, res, next){
14 | // include root path in proxied request
15 | req.url = proxyPath + '/' + req.url;
16 | if (process.env.EMBER_ENV == 'development') {
17 | proxy.web(req, res, { target: 'http://localhost:3000' });
18 | } else if (process.env.EMBER_ENV == 'production') {
19 | proxy.web(req, res, { target: 'http://api.pixelhandler.com' });
20 | }
21 | });
22 | };
23 |
--------------------------------------------------------------------------------
/testem.js:
--------------------------------------------------------------------------------
1 | /*jshint node:true*/
2 | module.exports = {
3 | "framework": "qunit",
4 | "test_page": "tests/index.html?hidepassed",
5 | "disable_watching": true,
6 | "launch_in_ci": [
7 | "PhantomJS"
8 | ],
9 | "launch_in_dev": [
10 | "PhantomJS",
11 | "Chrome"
12 | ]
13 | };
14 |
--------------------------------------------------------------------------------
/tests/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "predef": [
3 | "document",
4 | "window",
5 | "location",
6 | "setTimeout",
7 | "$",
8 | "-Promise",
9 | "define",
10 | "console",
11 | "visit",
12 | "exists",
13 | "fillIn",
14 | "click",
15 | "keyEvent",
16 | "triggerEvent",
17 | "find",
18 | "findWithAssert",
19 | "wait",
20 | "QUnit",
21 | "andThen",
22 | "currentURL",
23 | "currentPath",
24 | "currentRouteName"
25 | ],
26 | "node": false,
27 | "browser": false,
28 | "boss": true,
29 | "curly": true,
30 | "debug": false,
31 | "devel": false,
32 | "eqeqeq": true,
33 | "evil": true,
34 | "forin": false,
35 | "immed": false,
36 | "laxbreak": false,
37 | "newcap": true,
38 | "noarg": true,
39 | "noempty": false,
40 | "nonew": false,
41 | "nomen": false,
42 | "onevar": false,
43 | "plusplus": false,
44 | "regexp": false,
45 | "undef": true,
46 | "sub": true,
47 | "strict": false,
48 | "white": false,
49 | "eqnull": true,
50 | "esversion": 6,
51 | "unused": true
52 | }
53 |
--------------------------------------------------------------------------------
/tests/acceptance/polymorphic-test.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import RSVP from 'rsvp';
3 | import { module, test } from 'qunit';
4 | import startApp from '../../tests/helpers/start-app';
5 |
6 | import picturesMock from 'fixtures/api/pictures';
7 | import pictures1Mock from 'fixtures/api/pictures/1';
8 | import pictures1ImageableMock from 'fixtures/api/pictures/1/imageable';
9 | import pictures5Mock from 'fixtures/api/pictures/5';
10 | import pictures5ImageableMock from 'fixtures/api/pictures/5/imageable';
11 |
12 | import config from '../../config/environment';
13 |
14 | module('Acceptance | polymorphic', {
15 | beforeEach: function() {
16 | this.sandbox = window.sinon.sandbox.create();
17 | this.application = startApp();
18 | },
19 |
20 | afterEach: function() {
21 | Ember.run(this.application, 'destroy');
22 | this.sandbox.restore();
23 | }
24 | });
25 |
26 | test('visiting /pictures list', function(assert) {
27 | assert.expect(6);
28 | setupFetchResponses(this.sandbox);
29 |
30 | visit('/pictures');
31 | andThen(function() {
32 | assert.equal(currentURL(), '/pictures', 'Pictures route rendered');
33 | let listItems = document.querySelector('#ember-testing ul').querySelectorAll('li');
34 | let name;
35 | for (let i = 0; i < picturesMock.data.length; i++) {
36 | name = picturesMock.data[i].attributes.name;
37 | assert.equal(listItems[i].innerText, name, 'item rendered: ' + name);
38 | }
39 | });
40 | });
41 |
42 | test('visiting /pictures/1, picture with an (imageable) product relation', function(assert) {
43 | assert.expect(3);
44 | setupFetchResponses(this.sandbox);
45 |
46 | visit('/pictures/1');
47 | andThen(function() {
48 | assert.equal(currentURL(), '/pictures/1', 'Pictures #1 route rendered');
49 | let content = document.querySelectorAll('#ember-testing p');
50 | let name = pictures1Mock.data.attributes.name;
51 | assert.ok(content[0].innerText.trim().match(name) !== null, name + ' rendered in outlet');
52 | let imageableName = pictures1ImageableMock.data.attributes.name;
53 | assert.ok(content[1].innerText.trim().match(imageableName) !== null, imageableName + ' rendered in outlet');
54 | });
55 | });
56 |
57 | test('visiting /pictures/5, picture with an (imageable) employee relation', function(assert) {
58 | assert.expect(3);
59 | setupFetchResponses(this.sandbox);
60 |
61 | visit('/pictures/5');
62 | andThen(function() {
63 | assert.equal(currentURL(), '/pictures/5', 'Pictures #5 route rendered');
64 | let content = document.querySelectorAll('#ember-testing p');
65 | let name = pictures5Mock.data.attributes.name;
66 | assert.ok(content[0].innerText.trim().match(name) !== null, name + ' rendered in outlet');
67 | let imageableName = pictures5ImageableMock.data.attributes.name;
68 | assert.ok(content[1].innerText.trim().match(imageableName) !== null, imageableName + ' rendered in outlet');
69 | });
70 | });
71 |
72 |
73 | function setupFetchResponses(sandbox) {
74 | const apiUrl = [config.APP.API_HOST, config.APP.API_PATH].join('/');
75 | sandbox.stub(window, 'fetch', function (url) {
76 | let resp;
77 | switch(url) {
78 | case [apiUrl, 'pictures?sort=id&include=imageable'].join('/'):
79 | resp = picturesMockResponse();
80 | break;
81 | case [apiUrl, 'pictures/1'].join('/'):
82 | resp = pictures1MockResponse();
83 | break;
84 | case [apiUrl, 'pictures/1/imageable'].join('/'):
85 | case pictures1Mock.data.relationships.imageable.links.related:
86 | resp = pictures1ImageableMockResponse();
87 | break;
88 | case [apiUrl, 'pictures/5'].join('/'):
89 | resp = pictures5MockResponse();
90 | break;
91 | case [apiUrl, 'pictures/5/imageable'].join('/'):
92 | case pictures5Mock.data.relationships.imageable.links.related:
93 | resp = pictures5ImageableMockResponse();
94 | break;
95 | default:
96 | throw('no mocked fetch reponse for request: ' + url);
97 | }
98 | return resp;
99 | });
100 | }
101 |
102 | function picturesMockResponse() {
103 | return RSVP.Promise.resolve({
104 | "status": 200,
105 | "json": function() {
106 | return RSVP.Promise.resolve(picturesMock);
107 | }
108 | });
109 | }
110 |
111 | function pictures1MockResponse() {
112 | return RSVP.Promise.resolve({
113 | "status": 200,
114 | "json": function() {
115 | return RSVP.Promise.resolve(pictures1Mock);
116 | }
117 | });
118 | }
119 |
120 | function pictures1ImageableMockResponse() {
121 | return RSVP.Promise.resolve({
122 | "status": 200,
123 | "json": function() {
124 | return RSVP.Promise.resolve(pictures1ImageableMock);
125 | }
126 | });
127 | }
128 |
129 | function pictures5MockResponse() {
130 | return RSVP.Promise.resolve({
131 | "status": 200,
132 | "json": function() {
133 | return RSVP.Promise.resolve(pictures5Mock);
134 | }
135 | });
136 | }
137 |
138 | function pictures5ImageableMockResponse() {
139 | return RSVP.Promise.resolve({
140 | "status": 200,
141 | "json": function() {
142 | return RSVP.Promise.resolve(pictures5ImageableMock);
143 | }
144 | });
145 | }
146 |
--------------------------------------------------------------------------------
/tests/blanket-options.js:
--------------------------------------------------------------------------------
1 | /* globals blanket, module */
2 |
3 | var options = {
4 | modulePrefix: 'ember-jsonapi-resources',
5 | filter: '//.*ember-jsonapi-resources/.*/',
6 | antifilter: '//.*(tests|template).*/',
7 | loaderExclusions: [],
8 | enableCoverage: true,
9 | cliOptions: {
10 | reporters: ['lcov'],
11 | autostart: true
12 | }
13 | };
14 | if (typeof exports === 'undefined') {
15 | blanket.options(options);
16 | } else {
17 | module.exports = options;
18 | }
19 |
--------------------------------------------------------------------------------
/tests/dummy/app/adapters/author.js:
--------------------------------------------------------------------------------
1 | import ApplicationAdapter from './application';
2 |
3 | export default ApplicationAdapter.extend({
4 | type: 'author'
5 | });
6 |
--------------------------------------------------------------------------------
/tests/dummy/app/adapters/comment.js:
--------------------------------------------------------------------------------
1 | import ApplicationAdapter from './application';
2 |
3 | export default ApplicationAdapter.extend({
4 | type: 'comment'
5 | });
6 |
--------------------------------------------------------------------------------
/tests/dummy/app/adapters/commenter.js:
--------------------------------------------------------------------------------
1 | import ApplicationAdapter from './application';
2 |
3 | export default ApplicationAdapter.extend({
4 | type: 'commenter'
5 | });
6 |
--------------------------------------------------------------------------------
/tests/dummy/app/adapters/employee.js:
--------------------------------------------------------------------------------
1 | import ApplicationAdapter from './application';
2 |
3 | export default ApplicationAdapter.extend({
4 | type: 'employee'
5 | });
6 |
--------------------------------------------------------------------------------
/tests/dummy/app/adapters/imageable.js:
--------------------------------------------------------------------------------
1 | import ApplicationAdapter from './application';
2 |
3 | export default ApplicationAdapter.extend({
4 | type: 'imageable',
5 |
6 | url: null,
7 |
8 | find() {},
9 | findOne() {},
10 | findQuery() {},
11 | cacheUpdate() {},
12 | cacheResource() {},
13 | initEvents() {}
14 | });
15 |
--------------------------------------------------------------------------------
/tests/dummy/app/adapters/picture.js:
--------------------------------------------------------------------------------
1 | import ApplicationAdapter from './application';
2 |
3 | export default ApplicationAdapter.extend({
4 | type: 'picture'
5 | });
6 |
--------------------------------------------------------------------------------
/tests/dummy/app/adapters/post.js:
--------------------------------------------------------------------------------
1 | import ApplicationAdapter from './application';
2 | import AuthorizationMixin from '../mixins/authorization';
3 |
4 | export default ApplicationAdapter.extend(AuthorizationMixin, {
5 | type: 'post'
6 | });
7 |
--------------------------------------------------------------------------------
/tests/dummy/app/adapters/product.js:
--------------------------------------------------------------------------------
1 | import ApplicationAdapter from './application';
2 |
3 | export default ApplicationAdapter.extend({
4 | type: 'product'
5 | });
6 |
--------------------------------------------------------------------------------
/tests/dummy/app/app.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import Resolver from './resolver';
3 | import loadInitializers from 'ember-load-initializers';
4 | import config from './config/environment';
5 |
6 | let App;
7 |
8 | Ember.MODEL_FACTORY_INJECTIONS = true;
9 |
10 | App = Ember.Application.extend({
11 | modulePrefix: config.modulePrefix,
12 | podModulePrefix: config.podModulePrefix,
13 | Resolver
14 | });
15 |
16 | loadInitializers(App, config.modulePrefix);
17 |
18 | export default App;
19 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pixelhandler/ember-jsonapi-resources/9a24b6c6b0f65bff48a45c9154b327b0853e0886/tests/dummy/app/components/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/components/form-post.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import BufferedProxy from 'ember-buffered-proxy/proxy';
3 |
4 | export default Ember.Component.extend({
5 | tagName: 'form',
6 |
7 | resource: Ember.computed('post', function() {
8 | return BufferedProxy.create({ content: this.get('post') });
9 | }).readOnly(),
10 |
11 | isNew: null,
12 | isEditing: true,
13 |
14 | focusOut() {
15 | if (!this.get('isNew')) {
16 | this.get('resource').applyChanges();
17 | this.set('isEditing', false);
18 | this.get('on-edit')(this.get('post')).finally(function() {
19 | this.set('isEditing', true);
20 | }.bind(this));
21 | }
22 | },
23 |
24 | actions: {
25 | edit() {
26 | this.set('isEditing', true);
27 | },
28 | done() {
29 | this.set('isEditing', false);
30 | },
31 | save() {
32 | this.set('isEditing', false);
33 | this.get('resource').applyChanges();
34 | this.sendAction('on-save', this.get('post'));
35 | },
36 | cancel() {
37 | this.set('isEditing', false);
38 | this.get('resource').discardChanges();
39 | this.sendAction('on-cancel');
40 | }
41 | }
42 | });
43 |
--------------------------------------------------------------------------------
/tests/dummy/app/controllers/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pixelhandler/ember-jsonapi-resources/9a24b6c6b0f65bff48a45c9154b327b0853e0886/tests/dummy/app/controllers/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/controllers/admin/edit.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default Ember.Controller.extend({
4 | actions: {
5 | update(model) {
6 | return this.store.updateResource('posts', model).catch(function(err) {
7 | Ember.Logger.error(err);
8 | model.rollback();
9 | });
10 | }
11 | }
12 | });
13 |
--------------------------------------------------------------------------------
/tests/dummy/app/controllers/post/comments.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default Ember.Controller.extend();
4 |
--------------------------------------------------------------------------------
/tests/dummy/app/helpers/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pixelhandler/ember-jsonapi-resources/9a24b6c6b0f65bff48a45c9154b327b0853e0886/tests/dummy/app/helpers/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dummy
7 |
8 |
9 |
10 | {{content-for "head"}}
11 |
12 |
13 |
14 |
15 | {{content-for "head-footer"}}
16 |
17 |
18 | {{content-for "body"}}
19 |
20 |
21 |
22 |
23 | {{content-for "body-footer"}}
24 |
25 |
26 |
--------------------------------------------------------------------------------
/tests/dummy/app/initializers/author.js:
--------------------------------------------------------------------------------
1 | import Author from '../models/author';
2 |
3 | export function initialize() {
4 | let application = arguments[1] || arguments[0];
5 | application.register('model:author', Author, { instantiate: false, singleton: false });
6 | application.inject('service:store', 'authors', 'service:authors');
7 | application.inject('service:authors', 'serializer', 'serializer:author');
8 | }
9 |
10 | export default {
11 | name: 'authors-service',
12 | after: 'store',
13 | initialize: initialize
14 | };
15 |
--------------------------------------------------------------------------------
/tests/dummy/app/initializers/comment.js:
--------------------------------------------------------------------------------
1 | import Comment from '../models/comment';
2 |
3 | export function initialize() {
4 | let application = arguments[1] || arguments[0];
5 | application.register('model:comment', Comment, { instantiate: false, singleton: false });
6 | application.inject('service:store', 'comments', 'service:comments');
7 | application.inject('service:comments', 'serializer', 'serializer:comment');
8 | }
9 |
10 | export default {
11 | name: 'comments-service',
12 | after: 'store',
13 | initialize: initialize
14 | };
15 |
--------------------------------------------------------------------------------
/tests/dummy/app/initializers/commenter.js:
--------------------------------------------------------------------------------
1 | import Commenter from '../models/commenter';
2 |
3 | export function initialize() {
4 | let application = arguments[1] || arguments[0];
5 | application.register('model:commenter', Commenter, { instantiate: false, singleton: false });
6 | application.inject('service:store', 'commenters', 'service:commenters');
7 | application.inject('service:commenters', 'serializer', 'serializer:commenter');
8 | }
9 |
10 | export default {
11 | name: 'commenters-service',
12 | after: 'store',
13 | initialize: initialize
14 | };
15 |
--------------------------------------------------------------------------------
/tests/dummy/app/initializers/employee.js:
--------------------------------------------------------------------------------
1 | import Employee from '../models/employee';
2 |
3 | export function initialize() {
4 | let application = arguments[1] || arguments[0];
5 | application.register('model:employee', Employee, { instantiate: false, singleton: false });
6 | application.inject('service:store', 'employees', 'service:employees');
7 | application.inject('service:employees', 'serializer', 'serializer:employee');
8 | }
9 |
10 | export default {
11 | name: 'employees-service',
12 | after: 'store',
13 | initialize: initialize
14 | };
15 |
--------------------------------------------------------------------------------
/tests/dummy/app/initializers/imageable.js:
--------------------------------------------------------------------------------
1 | export function initialize() {
2 | let application = arguments[1] || arguments[0];
3 | application.inject('service:store', 'imageables', 'service:imageables');
4 | application.inject('service:imageables', 'serializer', 'serializer:imageable');
5 | }
6 |
7 | export default {
8 | name: 'imageables-service',
9 | after: 'store',
10 | initialize: initialize
11 | };
12 |
--------------------------------------------------------------------------------
/tests/dummy/app/initializers/picture.js:
--------------------------------------------------------------------------------
1 | import Picture from '../models/picture';
2 |
3 | export function initialize() {
4 | let application = arguments[1] || arguments[0];
5 | application.register('model:picture', Picture, { instantiate: false, singleton: false });
6 | application.inject('service:store', 'pictures', 'service:pictures');
7 | application.inject('service:pictures', 'serializer', 'serializer:picture');
8 | }
9 |
10 | export default {
11 | name: 'pictures-service',
12 | after: 'store',
13 | initialize: initialize
14 | };
15 |
--------------------------------------------------------------------------------
/tests/dummy/app/initializers/post.js:
--------------------------------------------------------------------------------
1 | import Post from '../models/post';
2 |
3 | export function initialize() {
4 | let application = arguments[1] || arguments[0];
5 | application.register('model:post', Post, { instantiate: false, singleton: false });
6 | application.inject('service:store', 'posts', 'service:posts');
7 | application.inject('service:posts', 'serializer', 'serializer:post');
8 | }
9 |
10 | export default {
11 | name: 'posts-service',
12 | after: 'store',
13 | initialize: initialize
14 | };
15 |
--------------------------------------------------------------------------------
/tests/dummy/app/initializers/product.js:
--------------------------------------------------------------------------------
1 | import Product from '../models/product';
2 |
3 | export function initialize() {
4 | let application = arguments[1] || arguments[0];
5 | application.register('model:product', Product, { instantiate: false, singleton: false });
6 | application.inject('service:store', 'products', 'service:products');
7 | application.inject('service:products', 'serializer', 'serializer:product');
8 | }
9 |
10 | export default {
11 | name: 'products-service',
12 | after: 'store',
13 | initialize: initialize
14 | };
15 |
--------------------------------------------------------------------------------
/tests/dummy/app/models/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pixelhandler/ember-jsonapi-resources/9a24b6c6b0f65bff48a45c9154b327b0853e0886/tests/dummy/app/models/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/models/author.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import Resource from './resource';
3 | import { attr, toMany } from 'ember-jsonapi-resources/models/resource';
4 |
5 | export default Resource.extend({
6 | type: 'authors',
7 | service: Ember.inject.service('authors'),
8 |
9 | name: attr('string'),
10 | email: attr('string'),
11 |
12 | posts: toMany('posts')
13 | });
14 |
--------------------------------------------------------------------------------
/tests/dummy/app/models/comment.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import Resource from './resource';
3 | import { attr, toOne } from 'ember-jsonapi-resources/models/resource';
4 |
5 | export default Resource.extend({
6 | type: 'comments',
7 | service: Ember.inject.service('comments'),
8 |
9 | body: attr('string'),
10 |
11 | date: Ember.computed('attributes', {
12 | get() {
13 | return this.get('attributes.created-at');
14 | }
15 | }),
16 |
17 | commenter: toOne('commenter'),
18 | post: toOne('post')
19 | });
20 |
--------------------------------------------------------------------------------
/tests/dummy/app/models/commenter.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import Resource from './resource';
3 | import { attr, toMany } from 'ember-jsonapi-resources/models/resource';
4 |
5 | export default Resource.extend({
6 | type: 'commenters',
7 | service: Ember.inject.service('commenters'),
8 |
9 | name: attr('string'),
10 | email: attr('string'),
11 | hash: attr(),
12 |
13 | comments: toMany('comments')
14 | });
15 |
--------------------------------------------------------------------------------
/tests/dummy/app/models/employee.js:
--------------------------------------------------------------------------------
1 | import PersonResource from './person';
2 | import { toOne, toMany } from 'ember-jsonapi-resources/models/resource';
3 |
4 | export default PersonResource.extend({
5 | type: 'employees',
6 | pictures: toMany('pictures'),
7 | supervisor: toOne('supervisor')
8 | });
9 |
--------------------------------------------------------------------------------
/tests/dummy/app/models/person.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import Resource from './resource';
3 | import { attr } from 'ember-jsonapi-resources/models/resource';
4 |
5 | export default Resource.extend({
6 | type: 'people',
7 | service: Ember.inject.service('people'),
8 | name: attr() // can use any value type for an attribute
9 | });
10 |
--------------------------------------------------------------------------------
/tests/dummy/app/models/picture.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import Resource from './resource';
3 | import { attr, toOne } from 'ember-jsonapi-resources/models/resource';
4 |
5 | export default Resource.extend({
6 | type: 'pictures',
7 | service: Ember.inject.service('pictures'),
8 |
9 | "name": attr('string'),
10 | "updated-at": attr('date'),
11 | "created-at": attr('date'),
12 |
13 | imageable: toOne('imageable') // polymorphic
14 | });
15 |
--------------------------------------------------------------------------------
/tests/dummy/app/models/post.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import Resource from './resource';
3 | import { attr, toOne, toMany } from 'ember-jsonapi-resources/models/resource';
4 |
5 | export default Resource.extend({
6 | type: 'posts',
7 | service: Ember.inject.service('posts'),
8 |
9 | title: attr('string'),
10 | date: attr(),
11 | excerpt: attr('string'),
12 |
13 | author: toOne('author'),
14 | comments: toMany('comments')
15 | });
16 |
--------------------------------------------------------------------------------
/tests/dummy/app/models/product.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import Resource from './resource';
3 | import { attr, toMany } from 'ember-jsonapi-resources/models/resource';
4 |
5 | export default Resource.extend({
6 | type: 'products',
7 | service: Ember.inject.service('products'),
8 |
9 | name: attr('string'),
10 |
11 | pictures: toMany('pictures')
12 | });
13 |
--------------------------------------------------------------------------------
/tests/dummy/app/models/supervisor.js:
--------------------------------------------------------------------------------
1 | import EmployeeResource from './person';
2 | import { toMany } from 'ember-jsonapi-resources/models/resource';
3 |
4 | export default EmployeeResource.extend({
5 | type: 'supervisors',
6 | directReports: toMany({resource: 'direct-reports', type: 'employees'})
7 | });
8 |
--------------------------------------------------------------------------------
/tests/dummy/app/resolver.js:
--------------------------------------------------------------------------------
1 | import Resolver from 'ember-resolver';
2 |
3 | export default Resolver;
4 |
--------------------------------------------------------------------------------
/tests/dummy/app/router.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import config from './config/environment';
3 |
4 | const Router = Ember.Router.extend({
5 | location: config.locationType,
6 | rootURL: config.rootURL
7 | });
8 |
9 | Router.map(function() {
10 | this.route('index', { path: '/' });
11 | this.route('post', { path: '/:post_id' }, function () {
12 | this.route('detail', { path: '/' });
13 | this.route('comments');
14 | });
15 | this.route('admin', function () {
16 | this.route('index');
17 | this.route('create');
18 | this.route('edit', { path: ':edit_id' });
19 | });
20 | this.route('products', { path: '/products' }, function () {
21 | this.route('detail', { path: '/:product_id' });
22 | });
23 | this.route('employees', { path: '/employees' }, function () {
24 | this.route('detail', { path: '/:employee_id' });
25 | });
26 | this.route('pictures', { path: '/pictures' }, function () {
27 | this.route('detail', { path: '/:picture_id' });
28 | });
29 | });
30 |
31 | export default Router;
32 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pixelhandler/ember-jsonapi-resources/9a24b6c6b0f65bff48a45c9154b327b0853e0886/tests/dummy/app/routes/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/routes/admin/create.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default Ember.Route.extend({
4 | beforeModel() {
5 | return this.store.find('authors').then(function (authors) {
6 | this.set('authors', authors);
7 | }.bind(this));
8 | },
9 |
10 | model() {
11 | let owner = Ember.getOwner(this);
12 | return owner._lookupFactory('model:post').create({
13 | isNew: true,
14 | attributes: { date: new Date() }
15 | });
16 | },
17 |
18 | afterModel(resource) {
19 | const author = this.get('authors.firstObject');
20 | resource.addRelationship('author', author.get('id'));
21 | return resource;
22 | },
23 |
24 | actions: {
25 | save(resource) {
26 | this.store.createResource('posts', resource).then(function(resp) {
27 | let collection = this.modelFor('admin.index');
28 | if (collection) { collection.addObject(resp); }
29 | collection = this.modelFor('index');
30 | if (collection) { collection.addObject(resp); }
31 | this.transitionTo('admin.index');
32 | }.bind(this));
33 | },
34 |
35 | cancel() {
36 | this.transitionTo('admin.index');
37 | }
38 | },
39 |
40 | deactivate() {
41 | this.modelFor('admin.create').destroy();
42 | }
43 | });
44 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/admin/edit.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default Ember.Route.extend({
4 | model(params) {
5 | return this.store.find('posts', params.edit_id);
6 | },
7 |
8 | setupController(controller, model) {
9 | this._super(controller, model);
10 | controller.set('isEditing', true);
11 | }
12 | });
13 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/admin/index.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default Ember.Route.extend({
4 | serviceName: 'posts',
5 |
6 | model() {
7 | return this.store.find('posts', { query: { 'page[limit]': 10, 'sort': '-date' }});
8 | },
9 |
10 | actions: {
11 | destroy(model) {
12 | this.modelFor('admin.index').removeObject(model);
13 | return this.store.deleteResource('posts', model).then(function() {
14 | this.refresh();
15 | }.bind(this)).catch(function(e) {
16 | console.error(e);
17 | });
18 | }
19 | }
20 | });
21 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/employees.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default Ember.Route.extend({
4 | model() {
5 | const options = {
6 | query: {
7 | sort: 'name',
8 | include: 'pictures'
9 | }
10 | };
11 | return this.store.find('employees', options);
12 | },
13 |
14 | actions: {
15 | error(error) {
16 | Ember.Logger.error(error);
17 | }
18 | }
19 | });
20 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/index.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default Ember.Route.extend({
4 |
5 | model() {
6 | const options = {
7 | query: {
8 | sort: '-date',
9 | include: 'author',
10 | 'page[offset]': 0,
11 | 'page[limit]': 5
12 | }
13 | };
14 | return this.store.find('posts', options);
15 | }
16 | });
17 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/pictures.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default Ember.Route.extend({
4 | model() {
5 | const options = {
6 | query: {
7 | sort: 'id',
8 | include: 'imageable'
9 | }
10 | };
11 | return this.store.find('pictures', options);
12 | },
13 |
14 | actions: {
15 | error(error) {
16 | Ember.Logger.error(error);
17 | }
18 | }
19 | });
20 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/post.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import RSVP from 'rsvp';
3 |
4 | export default Ember.Route.extend({
5 | model(params) {
6 | return new RSVP.Promise(function (resolve, reject) {
7 | const found = this.store.all('posts').filter(function (post) {
8 | return post.get('id') === params.post_id;
9 | });
10 | if (found.get('length') > 0) {
11 | resolve(found[0]);
12 | } else {
13 | const options = {
14 | id: params.post_id,
15 | query: { include: 'author,comments' }
16 | };
17 | this.store.find('post', options).then(
18 | function (post) {
19 | resolve(post);
20 | },
21 | function (error) {
22 | reject(error);
23 | }
24 | );
25 | }
26 | }.bind(this));
27 | },
28 |
29 | actions: {
30 | error(error) {
31 | Ember.Logger.error(error);
32 | }
33 | }
34 | });
35 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/post/detail.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default Ember.Route.extend({
4 |
5 | setupController(controller, model) {
6 | this._super(controller, model);
7 | this.controllerFor('post.comments').set('model', model.get('comments'));
8 | },
9 |
10 | renderTemplate(controller, model) {
11 | this._super(controller, model);
12 | this.render('post.comments', {
13 | into: 'post.detail',
14 | outlet: 'comments',
15 | controller: this.controllerFor('post.comments')
16 | });
17 | }
18 | });
19 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/products.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default Ember.Route.extend({
4 | model() {
5 | const options = {
6 | query: {
7 | sort: '-id',
8 | include: 'pictures'
9 | }
10 | };
11 | return this.store.find('products', options);
12 | },
13 |
14 | actions: {
15 | error(error) {
16 | Ember.Logger.error(error);
17 | }
18 | }
19 | });
20 |
--------------------------------------------------------------------------------
/tests/dummy/app/serializers/author.js:
--------------------------------------------------------------------------------
1 | import ApplicationSerializer from './application';
2 |
3 | export default ApplicationSerializer.extend();
4 |
--------------------------------------------------------------------------------
/tests/dummy/app/serializers/comment.js:
--------------------------------------------------------------------------------
1 | import ApplicationSerializer from './application';
2 |
3 | export default ApplicationSerializer.extend();
4 |
--------------------------------------------------------------------------------
/tests/dummy/app/serializers/commenter.js:
--------------------------------------------------------------------------------
1 | import ApplicationSerializer from './application';
2 |
3 | export default ApplicationSerializer.extend();
4 |
--------------------------------------------------------------------------------
/tests/dummy/app/serializers/employee.js:
--------------------------------------------------------------------------------
1 | import ApplicationSerializer from './application';
2 |
3 | export default ApplicationSerializer.extend();
4 |
--------------------------------------------------------------------------------
/tests/dummy/app/serializers/imageable.js:
--------------------------------------------------------------------------------
1 | import ApplicationSerializer from './application';
2 |
3 | export default ApplicationSerializer.extend();
4 |
--------------------------------------------------------------------------------
/tests/dummy/app/serializers/picture.js:
--------------------------------------------------------------------------------
1 | import ApplicationSerializer from './application';
2 |
3 | export default ApplicationSerializer.extend();
4 |
--------------------------------------------------------------------------------
/tests/dummy/app/serializers/post.js:
--------------------------------------------------------------------------------
1 | import ApplicationSerializer from './application';
2 |
3 | export default ApplicationSerializer.extend();
4 |
--------------------------------------------------------------------------------
/tests/dummy/app/serializers/product.js:
--------------------------------------------------------------------------------
1 | import ApplicationSerializer from './application';
2 |
3 | export default ApplicationSerializer.extend();
4 |
--------------------------------------------------------------------------------
/tests/dummy/app/services/authors.js:
--------------------------------------------------------------------------------
1 | import Adapter from '../adapters/author';
2 | import ServiceCache from '../mixins/service-cache';
3 |
4 | Adapter.reopenClass({ isServiceFactory: true });
5 |
6 | export default Adapter.extend(ServiceCache);
7 |
--------------------------------------------------------------------------------
/tests/dummy/app/services/commenters.js:
--------------------------------------------------------------------------------
1 | import Adapter from '../adapters/commenter';
2 | import ServiceCache from '../mixins/service-cache';
3 |
4 | Adapter.reopenClass({ isServiceFactory: true });
5 |
6 | export default Adapter.extend(ServiceCache);
7 |
--------------------------------------------------------------------------------
/tests/dummy/app/services/comments.js:
--------------------------------------------------------------------------------
1 | import Adapter from '../adapters/comment';
2 | import ServiceCache from '../mixins/service-cache';
3 |
4 | Adapter.reopenClass({ isServiceFactory: true });
5 |
6 | export default Adapter.extend(ServiceCache);
7 |
--------------------------------------------------------------------------------
/tests/dummy/app/services/employees.js:
--------------------------------------------------------------------------------
1 | import Adapter from '../adapters/employee';
2 | import ServiceCache from '../mixins/service-cache';
3 |
4 | Adapter.reopenClass({ isServiceFactory: true });
5 |
6 | export default Adapter.extend(ServiceCache);
7 |
--------------------------------------------------------------------------------
/tests/dummy/app/services/imageables.js:
--------------------------------------------------------------------------------
1 | import Adapter from '../adapters/imageable';
2 | import ServiceCache from '../mixins/service-cache';
3 |
4 | Adapter.reopenClass({ isServiceFactory: true });
5 |
6 | export default Adapter.extend(ServiceCache);
7 |
--------------------------------------------------------------------------------
/tests/dummy/app/services/pictures.js:
--------------------------------------------------------------------------------
1 | import Adapter from '../adapters/picture';
2 | import ServiceCache from '../mixins/service-cache';
3 |
4 | Adapter.reopenClass({ isServiceFactory: true });
5 |
6 | export default Adapter.extend(ServiceCache);
7 |
--------------------------------------------------------------------------------
/tests/dummy/app/services/posts.js:
--------------------------------------------------------------------------------
1 | import Adapter from '../adapters/post';
2 | import ServiceCache from '../mixins/service-cache';
3 |
4 | Adapter.reopenClass({ isServiceFactory: true });
5 |
6 | export default Adapter.extend(ServiceCache);
7 |
--------------------------------------------------------------------------------
/tests/dummy/app/services/products.js:
--------------------------------------------------------------------------------
1 | import Adapter from '../adapters/product';
2 | import ServiceCache from '../mixins/service-cache';
3 |
4 | Adapter.reopenClass({ isServiceFactory: true });
5 |
6 | export default Adapter.extend(ServiceCache);
7 |
--------------------------------------------------------------------------------
/tests/dummy/app/styles/app.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pixelhandler/ember-jsonapi-resources/9a24b6c6b0f65bff48a45c9154b327b0853e0886/tests/dummy/app/styles/app.css
--------------------------------------------------------------------------------
/tests/dummy/app/templates/admin/create.hbs:
--------------------------------------------------------------------------------
1 |
2 | Create a Blog Post
3 |
4 | {{form-post post=model isNew=model.isNew on-save="save" on-cancel="cancel"}}
5 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/admin/edit.hbs:
--------------------------------------------------------------------------------
1 |
2 | Edit a Blog Post
3 |
4 | {{form-post post=model isNew=model.isNew on-edit=(action "update")}}
5 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/admin/index.hbs:
--------------------------------------------------------------------------------
1 | Posts Admin
2 |
3 | {{#each model key="@identity" as |post|}}
4 | - {{post.date}}
5 | -
6 | {{post.title}}
7 | {{#link-to "admin.edit" post class="u-button"}}Edit{{/link-to}}
8 |
9 |
10 | {{/each}}
11 |
12 | {{outlet}}
13 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/application.hbs:
--------------------------------------------------------------------------------
1 | Ember JSON API Resources Test App
2 |
3 | {{outlet}}
4 |
5 | Nav
6 |
7 | - {{#link-to 'index'}}Home{{/link-to}}
8 | - {{#link-to 'admin.index'}}Edit{{/link-to}}
9 | - {{#link-to 'admin.create'}}Write{{/link-to}}
10 | - {{#link-to 'products'}}Products{{/link-to}}
11 | - {{#link-to 'employees'}}Employees{{/link-to}}
12 | - {{#link-to 'pictures'}}Pictures{{/link-to}}
13 |
14 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pixelhandler/ember-jsonapi-resources/9a24b6c6b0f65bff48a45c9154b327b0853e0886/tests/dummy/app/templates/components/.gitkeep
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/form-post.hbs:
--------------------------------------------------------------------------------
1 | {{#if isEditing}}
2 | {{#if isNew}}
3 |
4 |
5 | {{else}}
6 |
7 | {{/if}}
8 |
9 | {{! form for editing the resource attributes }}
10 |
29 | {{else}}
30 | {{#if isNew}}
31 |
32 |
33 |
34 | {{else}}
35 |
36 | {{/if}}
37 |
38 | {{! preview of the resource }}
39 | {{resource.title}}
40 |
41 | ({{resource.date}})
42 |
43 |
44 |
45 | {{resource.excerpt}}
46 |
47 |
48 | {{resource.body}}
49 |
50 | {{/if}}
51 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/employees.hbs:
--------------------------------------------------------------------------------
1 |
2 | {{#each model key="@identity" as |employee|}}
3 | - {{#link-to "employees.detail" employee.id}}{{employee.name}}{{/link-to}}
4 | {{/each}}
5 |
6 |
7 | {{outlet}}
8 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/employees/detail.hbs:
--------------------------------------------------------------------------------
1 | Name: {{model.name}}
2 |
3 | {{outlet}}
4 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/index.hbs:
--------------------------------------------------------------------------------
1 |
2 | {{#each model key="@identity" as |post|}}
3 | - {{#link-to "post" post.id}}{{post.title}}{{/link-to}}
4 | {{/each}}
5 |
6 |
7 | {{outlet}}
8 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/pictures.hbs:
--------------------------------------------------------------------------------
1 |
2 | {{#each model key="@identity" as |picture|}}
3 | - {{#link-to "pictures.detail" picture.id}}{{picture.name}}{{/link-to}}
4 | {{/each}}
5 |
6 |
7 | {{outlet}}
8 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/pictures/detail.hbs:
--------------------------------------------------------------------------------
1 |
2 | Name: {{model.name}}
3 | Updated At: {{model.updated-at}}
4 |
5 | Imageable: {{model.imageable.name}}
6 |
7 | {{outlet}}
8 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/post.hbs:
--------------------------------------------------------------------------------
1 | {{outlet}}
2 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/post/comments.hbs:
--------------------------------------------------------------------------------
1 |
2 | Comments
3 |
4 | {{#if model}}
5 |
19 | {{else}}
20 | No comments yet
21 | {{/if}}
22 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/post/detail.hbs:
--------------------------------------------------------------------------------
1 | {{model.title}}
2 |
3 | {{#with model.author as |author|}}
4 | by {{author.name}}
5 | {{/with}}
6 | ({{model.date}})
7 |
8 |
9 |
10 |
11 | {{#if model.excerpt}}
12 | {{model.excerpt}}
13 | {{/if}}
14 |
15 | {{outlet "comments"}}
16 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/products.hbs:
--------------------------------------------------------------------------------
1 |
2 | {{#each model key="@identity" as |product|}}
3 | - {{#link-to "products.detail" product.id}}{{product.name}}{{/link-to}}
4 | {{/each}}
5 |
6 |
7 | {{outlet}}
8 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/products/detail.hbs:
--------------------------------------------------------------------------------
1 | Name: {{model.name}}
2 |
3 | {{outlet}}
4 |
--------------------------------------------------------------------------------
/tests/dummy/config/environment.js:
--------------------------------------------------------------------------------
1 | /* jshint node: true */
2 |
3 | module.exports = function(environment) {
4 | var ENV = {
5 | modulePrefix: 'dummy',
6 | environment: environment,
7 | rootURL: '/',
8 | locationType: 'auto',
9 | EmberENV: {
10 | FEATURES: {
11 | // Here you can enable experimental features on an ember canary build
12 | // e.g. 'with-controller': true
13 | },
14 | MODEL_FACTORY_INJECTIONS: true,
15 | EXTEND_PROTOTYPES: {
16 | // Prevent Ember Data from overriding Date.parse.
17 | Date: false
18 | }
19 | },
20 |
21 | APP: {
22 | // Here you can pass flags/options to your application instance
23 | // when it is created
24 | API_HOST: '',
25 | API_PATH: 'api/v1',
26 | },
27 | contentSecurityPolicy: {
28 | 'script-src': "'self' 'unsafe-inline' 'unsafe-eval' localhost:49152",
29 | 'connect-src': "'self' api.pixelhandler.com localhost:3000 0.0.0.0:3000",
30 | 'img-src': "'self' www.gravatar.com"
31 | }
32 | };
33 |
34 | if (environment === 'development') {
35 | // ENV.APP.LOG_RESOLVER = true;
36 | // ENV.APP.LOG_ACTIVE_GENERATION = true;
37 | // ENV.APP.LOG_TRANSITIONS = true;
38 | // ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
39 | // ENV.APP.LOG_VIEW_LOOKUPS = true;
40 | }
41 |
42 | if (environment === 'test') {
43 | // Testem prefers this...
44 | ENV.locationType = 'none';
45 |
46 | // keep test console output quieter
47 | ENV.APP.LOG_ACTIVE_GENERATION = false;
48 | ENV.APP.LOG_VIEW_LOOKUPS = false;
49 |
50 | ENV.APP.rootElement = '#ember-testing';
51 | }
52 |
53 | if (environment === 'production') {
54 |
55 | }
56 |
57 | return ENV;
58 | };
59 |
--------------------------------------------------------------------------------
/tests/dummy/public/crossdomain.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
15 |
16 |
--------------------------------------------------------------------------------
/tests/dummy/public/robots.txt:
--------------------------------------------------------------------------------
1 | # http://www.robotstxt.org
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/tests/helpers/destroy-app.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default function destroyApp(application) {
4 | Ember.run(application, 'destroy');
5 | }
6 |
--------------------------------------------------------------------------------
/tests/helpers/module-for-acceptance.js:
--------------------------------------------------------------------------------
1 | import { module } from 'qunit';
2 | import Ember from 'ember';
3 | import startApp from '../helpers/start-app';
4 | import destroyApp from '../helpers/destroy-app';
5 |
6 | const { RSVP: { Promise } } = Ember;
7 |
8 | export default function(name, options = {}) {
9 | module(name, {
10 | beforeEach() {
11 | this.application = startApp();
12 |
13 | if (options.beforeEach) {
14 | return options.beforeEach.apply(this, arguments);
15 | }
16 | },
17 |
18 | afterEach() {
19 | let afterEach = options.afterEach && options.afterEach.apply(this, arguments);
20 | return Promise.resolve(afterEach).then(() => destroyApp(this.application));
21 | }
22 | });
23 | }
24 |
--------------------------------------------------------------------------------
/tests/helpers/resolver.js:
--------------------------------------------------------------------------------
1 | import Resolver from '../../resolver';
2 | import config from '../../config/environment';
3 |
4 | const resolver = Resolver.create();
5 |
6 | resolver.namespace = {
7 | modulePrefix: config.modulePrefix,
8 | podModulePrefix: config.podModulePrefix
9 | };
10 |
11 | export default resolver;
12 |
--------------------------------------------------------------------------------
/tests/helpers/resources.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import RSVP from 'rsvp';
3 |
4 | import PostResource from 'dummy/models/post';
5 | import AuthorResource from 'dummy/models/author';
6 | import CommentResource from 'dummy/models/comment';
7 | import CommenterResource from 'dummy/models/commenter';
8 | import PersonResource from 'dummy/models/person';
9 | import EmployeeResource from 'dummy/models/employee';
10 | import SupervisorResource from 'dummy/models/supervisor';
11 | // Even though unused, keep PictureResource here for clarity. (shut up jshint!)
12 | import PictureResource from 'dummy/models/picture'; // jshint ignore:line
13 |
14 | // Remove the service from resources. We're using mock services.
15 | export const Post = PostResource.extend({service: null});
16 | export const Author = AuthorResource.extend({service: null});
17 | export const Comment = CommentResource.extend({service: null});
18 | export const Commenter = CommenterResource.extend({service: null});
19 | export const Person = PersonResource.extend({service: null});
20 | export const Employee = EmployeeResource.extend({service: null});
21 | export const Supervisor = SupervisorResource.extend({service: null});
22 |
23 | export function setup() {
24 | let opts = { instantiate: false, singleton: false };
25 | this.registry.register('model:post', Post, opts);
26 | this.registry.register('model:author', Author, opts);
27 | this.registry.register('model:comment', Comment, opts);
28 | this.registry.register('model:commenter', Commenter, opts);
29 | this.registry.register('model:person', Person, opts);
30 | this.registry.register('model:employee', Employee, opts);
31 | this.registry.register('model:supervisor', Supervisor, opts);
32 | }
33 |
34 | export function mockServices() {
35 | let types = Ember.String.w('posts authors comments commenters people employees supervisors');
36 | let mockService = Ember.Service.extend({
37 | cacheLookup(/*id*/) { return undefined; },
38 | findRelated() { return RSVP.resolve(null); }
39 | });
40 | for (let i = 0; i < types.length; i++) {
41 | this.registry.register('service:' + types[i], mockService);
42 | }
43 | }
44 |
45 | export function teardown() {}
46 |
--------------------------------------------------------------------------------
/tests/helpers/start-app.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import Application from '../../app';
3 | import config from '../../config/environment';
4 |
5 | export default function startApp(attrs) {
6 | let application, attributes;
7 |
8 | // use defaults, but you can override
9 | if (Ember.assign) {
10 | attributes = Ember.assign({}, config.APP, attrs);
11 | } else {
12 | attributes = Ember.merge({}, config.APP);
13 | attributes = Ember.merge(attributes, attrs);
14 | }
15 |
16 | Ember.run(() => {
17 | application = Application.create(attributes);
18 | application.setupForTesting();
19 | application.injectTestHelpers();
20 | });
21 |
22 | return application;
23 | }
24 |
--------------------------------------------------------------------------------
/tests/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dummy Tests
7 |
8 |
9 |
10 | {{content-for "head"}}
11 | {{content-for "test-head"}}
12 |
13 |
14 |
15 |
16 |
17 | {{content-for "head-footer"}}
18 | {{content-for "test-head-footer"}}
19 |
20 |
21 | {{content-for "body"}}
22 | {{content-for "test-body"}}
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | {{content-for "body-footer"}}
33 | {{content-for "test-body-footer"}}
34 |
35 |
36 |
--------------------------------------------------------------------------------
/tests/test-helper.js:
--------------------------------------------------------------------------------
1 | import resolver from './helpers/resolver';
2 | import {
3 | setResolver
4 | } from 'ember-qunit';
5 |
6 | setResolver(resolver);
7 |
--------------------------------------------------------------------------------
/tests/unit/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pixelhandler/ember-jsonapi-resources/9a24b6c6b0f65bff48a45c9154b327b0853e0886/tests/unit/.gitkeep
--------------------------------------------------------------------------------
/tests/unit/initializers/model-setup-test.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import initializer from '../../../initializers/model-setup';
3 | import { module, test } from 'qunit';
4 |
5 | let application, registeredTypeOptions;
6 |
7 | module('Unit | Initializer | model-setup', {
8 | beforeEach() {
9 | Ember.run(function() {
10 | application = Ember.Application.create();
11 | application.deferReadiness();
12 | stub(application);
13 | });
14 | },
15 | afterEach() {
16 | application = null;
17 | registeredTypeOptions = null;
18 | }
19 | });
20 |
21 | test('registers intantiate:false option for model factories', function(assert) {
22 | initializer.initialize(application);
23 | let option = registeredTypeOptions.findBy('name', 'model');
24 | assert.equal(option.name, 'model', 'option for model registered');
25 | assert.equal(option.options.instantiate, false, 'option set to "instantiate:false"');
26 | });
27 |
28 | function stub(app) {
29 | registeredTypeOptions = Ember.A([]);
30 | app.registerOptionsForType = function(name, options) {
31 | registeredTypeOptions.pushObject({name: name, options: options});
32 | };
33 | }
34 |
--------------------------------------------------------------------------------
/tests/unit/initializers/store-test.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import { initialize } from '../../../initializers/store';
3 | import { module, test } from 'qunit';
4 |
5 | let registry, application, factories, injections;
6 |
7 | module('Unit | Initializer | store', {
8 | beforeEach: function() {
9 | Ember.run(function() {
10 | application = Ember.Application.create();
11 | registry = application.registry;
12 | application.deferReadiness();
13 | application = stub(application);
14 | });
15 | },
16 | afterEach: function() {
17 | factories = null;
18 | injections = null;
19 | application = null;
20 | registry = null;
21 | }
22 | });
23 |
24 | test('it registers service and injects into route and controller', function(assert) {
25 | initialize(registry, application);
26 |
27 | let registered = Ember.A(factories.mapBy('name'));
28 | assert.ok(registered.includes('service:store'), 'service:briefs registered');
29 |
30 | let injection = injections.findBy('factory', 'route');
31 | assert.equal(injection.property, 'store', 'store injected into route factory');
32 | assert.equal(injection.injection, 'service:store', 'route.store is service:store');
33 |
34 | injection = injections.findBy('factory', 'controller');
35 | assert.equal(injection.property, 'store', 'store injected into controller factory');
36 | assert.equal(injection.injection, 'service:store', 'controller.store is service:store');
37 | });
38 |
39 | function stub(app) {
40 | factories = Ember.A([]);
41 | injections = Ember.A([]);
42 | app.register = function(name, factory) {
43 | factories.push({name: name, factory: factory});
44 | };
45 | app.inject = function(factory, property, injection) {
46 | injections.push({
47 | factory: factory,
48 | property: property,
49 | injection: injection
50 | });
51 | };
52 | return app;
53 | }
54 |
--------------------------------------------------------------------------------
/tests/unit/mixins/authorization-test.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import AuthorizationMixin from '../../../mixins/authorization';
3 | import { module, test } from 'qunit';
4 |
5 | module('Unit | Mixin | authorization', {
6 | beforeEach() {
7 | window.localStorage.removeItem('AuthorizationHeader');
8 | },
9 | afterEach() {
10 | window.localStorage.removeItem('AuthorizationHeader');
11 | }
12 | });
13 |
14 | test('it uses "Authorization" for a header field', function(assert) {
15 | let AuthorizationObject = Ember.Object.extend(AuthorizationMixin);
16 | let subject = AuthorizationObject.create();
17 | let msg = 'Authorization is the value of the property: authorizationHeaderField';
18 | assert.equal(subject.get('authorizationHeaderField'), 'Authorization', msg);
19 | });
20 |
21 | test('it uses "AuthorizationHeader" for the storage key used to lookup credentials', function(assert) {
22 | let AuthorizationObject = Ember.Object.extend(AuthorizationMixin);
23 | let subject = AuthorizationObject.create();
24 | let msg = 'AuthorizationHeader is the value of the property: authorizationHeaderStorageKey';
25 | assert.equal(subject.get('authorizationHeaderStorageKey'), 'AuthorizationHeader', msg);
26 | });
27 |
28 | test('it has a (private) property _storage set to: "localStorage"', function(assert) {
29 | let AuthorizationObject = Ember.Object.extend(AuthorizationMixin);
30 | let subject = AuthorizationObject.create();
31 | let msg = 'localStorage is the value of the property: _storage';
32 | assert.equal(subject.get('_storage'), 'localStorage', msg);
33 | });
34 |
35 | test('it has a property authorizationCredential that gets and sets a credential/token', function(assert) {
36 | let AuthorizationObject = Ember.Object.extend(AuthorizationMixin);
37 | let subject = AuthorizationObject.create();
38 | assert.ok(!subject.get('authorizationCredential'), 'authorizationCredential is not defined yet.');
39 |
40 | let credential = 'supersecrettokenthatnobodycancrack';
41 | subject.set('authorizationCredential', credential);
42 |
43 | let msg = 'localStorage["AuthorizationHeader"] is set to ' + credential;
44 | assert.equal(window.localStorage.getItem('AuthorizationHeader'), credential, msg);
45 |
46 | msg = 'authorizationCredential is set to ' + credential;
47 | assert.equal(subject.get('authorizationCredential'), credential, msg);
48 | });
49 |
--------------------------------------------------------------------------------
/tests/unit/mixins/resource-operations-test.js:
--------------------------------------------------------------------------------
1 | import RSVP from 'rsvp';
2 | // import ResourceOperationsMixin from 'ember-jsonapi-resources/mixins/resource-operations';
3 | import { module, test } from 'qunit';
4 | import Resource from 'ember-jsonapi-resources/models/resource';
5 | import { attr/*, toOne, toMany*/ } from 'ember-jsonapi-resources/models/resource';
6 |
7 | let promiseResolved = function() { return RSVP.Promise.resolve(); };
8 |
9 | // ResourceOperationsMixin is mixed into Resource so will use Resource for test subject.
10 | module('Unit | Mixin | resource-operations', {
11 | beforeEach() {
12 | this.sandbox = window.sinon.sandbox.create();
13 | let Cowboy = Resource.extend({
14 | type: 'cowboy',
15 | service: {
16 | createResource: this.sandbox.spy(promiseResolved),
17 | updateResource: this.sandbox.spy(promiseResolved),
18 | deleteResource: this.sandbox.spy(promiseResolved),
19 | createRelationship: this.sandbox.spy(promiseResolved),
20 | patchRelationship: this.sandbox.spy(promiseResolved),
21 | deleteRelationship: this.sandbox.spy(promiseResolved),
22 | trigger() {}
23 | },
24 | name: attr('string'),
25 | // mock relationship computed properties
26 | guns: {kind: 'toMany', mapBy() {} }, // toMany('guns')
27 | horse: {kind: 'toOne', get() {} } // toOne('horse')
28 | });
29 | this.subject = Cowboy.create({ id: 1, name:'Lone Ranger'});
30 | // mock payload setup
31 | this.subject.set('relationships', {
32 | guns: { links: { related: 'url' }, data: [] },
33 | horse: { links: { related: 'url' }, data: null }
34 | });
35 | },
36 | afterEach() {
37 | this.sandbox.restore();
38 | delete this.subject;
39 | delete this.sandbox;
40 | }
41 | });
42 |
43 | test('createResource via service/adapter', function(assert) {
44 | let promise = this.subject.createResource();
45 | assert.ok(typeof promise.then === 'function', 'returns a thenable');
46 |
47 | let args = this.subject.get('service').createResource.firstCall.args;
48 | assert.equal( args[0], this.subject,
49 | 'called service.createResource with the resource instance'
50 | );
51 | });
52 |
53 | test('updateResource via service/adapter', function(assert) {
54 | let promise = this.subject.updateResource();
55 | assert.ok(typeof promise.then === 'function', 'returns a thenable');
56 |
57 | let args = this.subject.get('service').updateResource.firstCall.args;
58 | assert.equal( args[0], this.subject,
59 | 'called service.updateResource with the resource instance'
60 | );
61 | });
62 |
63 | test('deleteResource via service/adapter', function(assert) {
64 | let promise = this.subject.deleteResource();
65 | assert.ok(typeof promise.then === 'function', 'returns a thenable');
66 |
67 | let args = this.subject.get('service').deleteResource.firstCall.args;
68 | assert.equal( args[0], this.subject,
69 | 'called service.deleteResource with the resource instance'
70 | );
71 | });
72 |
73 | test('createRelationship for to-many relation', function(assert) {
74 | this.sandbox.stub(this.subject, 'addRelationship');
75 | let promise = this.subject.createRelationship('guns', 1);
76 | assert.ok(typeof promise.then === 'function', 'returns a thenable');
77 | assert.ok(
78 | this.subject.addRelationship.calledWith('guns', 1),
79 | 'called addRelationship'
80 | );
81 |
82 | let args = this.subject.get('service').createRelationship.firstCall.args;
83 | assert.equal( args[0], this.subject,
84 | 'called service.createRelationship with the resource instance'
85 | );
86 | assert.equal( args[1], 'guns',
87 | 'called service.createRelationship with relationship arg: guns'
88 | );
89 | assert.equal( args[2], 1,
90 | 'called service.createRelationship with id arg: 1'
91 | );
92 | });
93 |
94 | test('deleteRelationship for to-many relation', function(assert) {
95 | this.sandbox.stub(this.subject, 'removeRelationship');
96 | let promise = this.subject.deleteRelationship('guns', 2);
97 | assert.ok(typeof promise.then === 'function', 'returns a thenable');
98 | assert.ok(
99 | this.subject.removeRelationship.calledWith('guns', 2),
100 | 'called removeRelationship'
101 | );
102 |
103 | let args = this.subject.get('service').deleteRelationship.firstCall.args;
104 | assert.equal( args[0], this.subject,
105 | 'called service.createRelationship with the resource instance'
106 | );
107 | assert.equal( args[1], 'guns',
108 | 'called service.createRelationship with relationship arg: guns'
109 | );
110 | assert.equal( args[2], 2,
111 | 'called service.createRelationship with id arg: 2'
112 | );
113 | });
114 |
115 |
116 | test('updateRelationship for to-one relation', function(assert) {
117 | this.sandbox.stub(this.subject, '_replaceRelationshipsData');
118 |
119 | let promise = this.subject.updateRelationship('horse', 1);
120 | assert.ok(typeof promise.then === 'function', 'returns a thenable');
121 | assert.ok(
122 | this.subject._replaceRelationshipsData.calledWith('horse', 1),
123 | 'called _replaceRelationshipsData'
124 | );
125 |
126 | let args = this.subject.get('service').patchRelationship.firstCall.args;
127 | assert.equal( args[0], this.subject,
128 | 'called service.patchRelationship with the resource instance'
129 | );
130 | assert.equal( args[1], 'horse',
131 | 'called service.patchRelationship with relationship arg: horse'
132 | );
133 | });
134 |
--------------------------------------------------------------------------------
/tests/unit/mixins/transforms-test.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import TransformsMixin from 'ember-jsonapi-resources/mixins/transforms';
3 | import { module, test } from 'qunit';
4 | import { dateTransform } from 'ember-jsonapi-resources/utils/transforms';
5 |
6 | let sandbox;
7 |
8 | module('Unit | Mixin | transforms', {
9 | beforeEach() {
10 | let Transforms = Ember.Object.extend(TransformsMixin);
11 | this.subject = Transforms.create();
12 | sandbox = window.sinon.sandbox.create();
13 | },
14 | afterEach() {
15 | sandbox.restore();
16 | delete this.subject;
17 | }
18 | });
19 |
20 | test('#serializeDateAttribute', function(assert) {
21 | sandbox.stub(dateTransform, 'serialize');
22 | this.subject.serializeDateAttribute(new Date());
23 | assert.ok(dateTransform.serialize.calledOnce, 'called date transform serialize method');
24 | });
25 |
26 | test('#deserializeDateAttribute', function(assert) {
27 | sandbox.stub(dateTransform, 'deserialize');
28 | this.subject.deserializeDateAttribute( (new Date()).toISOString() );
29 | assert.ok(dateTransform.deserialize.calledOnce, 'called date transform deserialize method');
30 | });
31 |
--------------------------------------------------------------------------------
/tests/unit/services/store-test.js:
--------------------------------------------------------------------------------
1 | import { moduleFor, test } from 'ember-qunit';
2 | import Ember from 'ember';
3 | import { pluralize } from 'ember-inflector';
4 |
5 | let methods = 'find createResource updateResource deleteResource';
6 | methods += ' createRelationship patchRelationship deleteRelationship';
7 | methods = Ember.String.w(methods);
8 |
9 | let mockServices, entities = ['post', 'author', 'comment'];
10 |
11 | const MockService = function (name) {
12 | methods.forEach(function (method) {
13 | this[method] = window.sinon.expectation.create(method);
14 | }.bind(this));
15 | this.cache = { data: Ember.A([{id: '1', type: name}]) };
16 | return this;
17 | };
18 |
19 | moduleFor('service:store', 'Unit | Service | store', {
20 | beforeEach() {
21 | mockServices = {};
22 | entities.forEach(function (entity) {
23 | let serviceName = pluralize(entity);
24 | mockServices[serviceName] = new MockService(serviceName);
25 | });
26 | },
27 | afterEach() {
28 | entities.forEach(function (entity) {
29 | let serviceName = pluralize(entity);
30 | methods.forEach(function(method) {
31 | mockServices[serviceName][method].reset();
32 | });
33 | });
34 | mockServices = null;
35 | }
36 | });
37 |
38 | function methodTest(methodName, assert) {
39 | var store = this.subject(mockServices);
40 | assert.ok(store[methodName], 'service.'+ methodName +' exists');
41 | entities.forEach(function(entity) {
42 | let serviceName = pluralize(entity);
43 | mockServices[serviceName][methodName].once();
44 | store[methodName](entity);
45 | let msg = 'verify store.'+ serviceName +'.'+ methodName +' called through store.'+ methodName;
46 | assert.ok(mockServices[serviceName][methodName].verify(), msg);
47 | });
48 | }
49 |
50 | methods.forEach(function (method) {
51 | test('#' + method, function(assert) {
52 | methodTest.call(this, method, assert);
53 | });
54 | });
55 |
56 | test('#all', function (assert) {
57 | var store = this.subject(mockServices);
58 | entities.forEach(function (entity) {
59 | let resources = store.all(entity);
60 | assert.equal(resources.length, 1, '1 item in the store cache for ' + pluralize(entity));
61 | });
62 | });
63 |
64 | test('singleton service', function (assert) {
65 | var singletonService = new MockService('me');
66 |
67 | var store = this.subject({ 'me': singletonService });
68 | store.find('me', { singleton: true, id: '1' });
69 | assert.ok(singletonService.find.once(), 'singleton service #find called');
70 |
71 | methods.forEach(function(method) {
72 | singletonService[method].reset();
73 | });
74 | });
75 |
--------------------------------------------------------------------------------
/tests/unit/utils/is-test.js:
--------------------------------------------------------------------------------
1 | import { isBlank, isDasherized, isType } from 'ember-jsonapi-resources/utils/is';
2 | import { module, test } from 'qunit';
3 |
4 | module('Unit | Utility | is');
5 |
6 | test('#isBlank null, undefined', function(assert) {
7 | assert.ok(isBlank(null), 'null is blank');
8 | assert.ok(isBlank(undefined), 'undefined is blank');
9 | });
10 |
11 | test('#isBlank primitives: string, number, boolean', function(assert) {
12 | assert.ok(!isBlank('Wild West'), 'A string (with length) is not blank');
13 | assert.ok(!isBlank(''), 'A string (with no length) is not blank');
14 |
15 | assert.ok(!isBlank(1848), 'A (postive) number is not blank');
16 | assert.ok(!isBlank(0), 'A (zero) number is not blank');
17 | assert.ok(!isBlank(-1), 'A (negative) number is not blank');
18 | assert.ok(!isBlank(0.25), 'A (float) number is not blank');
19 |
20 | assert.ok(!isBlank(false), 'A (false) boolean is not blank');
21 | assert.ok(!isBlank(true), 'A (true) boolean is not blank');
22 | });
23 |
24 | test('#isBlank complex: date, object, array', function(assert) {
25 | assert.ok(!isBlank(new Date('1848')), 'A date is not blank');
26 | assert.ok(!isBlank({}), 'An empty object is not blank');
27 | assert.ok(!isBlank({name: 'Joe'}), 'An object (with props) is not blank');
28 | assert.ok(!isBlank(['Sue']), 'An array (with length) is not blank');
29 | });
30 |
31 | test('#isDasherized', function(assert) {
32 | assert.ok(isDasherized('is-dashed'), 'is-dashed is dasherized');
33 | assert.ok(!isDasherized('camelCased'), 'camelCased is not dasherized');
34 | assert.ok(!isDasherized('snake_case'), 'snake_case is not dasherized');
35 | });
36 |
37 | test('#isType - string', function(assert) {
38 | assert.ok(isType('string', 'Los Angeles, CA'), 'value is a string');
39 | });
40 |
41 | test('#isType - number', function(assert) {
42 | assert.ok(isType('number', 1901), 'value is a number');
43 | });
44 |
45 | test('#isType - boolean', function(assert) {
46 | assert.ok(isType('boolean', true), 'value is a boolean');
47 | });
48 |
49 | test('#isType - date', function(assert) {
50 | assert.ok(isType('date', new Date('1848')), 'value is a date');
51 | });
52 |
53 | test('#isType - object', function(assert) {
54 | assert.ok(isType('object', {}), 'value is an object');
55 | });
56 |
57 | test('#isType - array', function(assert) {
58 | assert.ok(isType('array', []), 'value is an array');
59 | });
60 |
--------------------------------------------------------------------------------
/tests/unit/utils/to-many-test.js:
--------------------------------------------------------------------------------
1 | import { moduleFor, test } from 'ember-qunit';
2 | import Ember from 'ember';
3 | import { pluralize } from 'ember-inflector';
4 | import { setup, teardown } from 'dummy/tests/helpers/resources';
5 |
6 | let mockServices;
7 | const mockService = function () {
8 | let sandbox = this.sandbox;
9 | return Ember.Service.extend({
10 | findRelated: sandbox.spy(function () { return Ember.RSVP.Promise.resolve(Ember.A([Ember.Object.create({id: 1})])); }),
11 | cacheLookup: sandbox.spy(function () { return Ember.A([]); })
12 | });
13 | };
14 | let entities = ['post', 'author'];
15 |
16 | moduleFor('model:resource', 'Unit | Utility | toMany', {
17 | beforeEach() {
18 | setup.call(this);
19 | this.sandbox = window.sinon.sandbox.create();
20 | mockServices = {};
21 | entities.forEach(function (entity) {
22 | let serviceName = pluralize(entity);
23 | mockServices[serviceName] = mockService.call(this);
24 | this.registry.register('service:'+serviceName, mockServices[serviceName]);
25 | }.bind(this));
26 | },
27 | afterEach() {
28 | mockServices = null;
29 | teardown.call(this);
30 | this.sandbox.restore();
31 | }
32 | });
33 |
34 | test('toMany() helper sets up a promise proxy to a related resource', function(assert) {
35 | let author = Ember.getOwner(this)._lookupFactory('model:author').create({
36 | id: '1', attributes: { name: 'pixelhandler' },
37 | relationships: {
38 | posts: {
39 | links: {
40 | "self": "http://api.pixelhandler.com/api/v1/authors/1/relationships/posts",
41 | "related": "http://api.pixelhandler.com/api/v1/authors/1/posts"
42 | }
43 | }
44 | }
45 | });
46 | Ember.getOwner(this)._lookupFactory('model:post').create({
47 | id: '2', attributes: { title: 'Wyatt Earp', excerpt: 'Was a gambler.'},
48 | relationships: {
49 | author: {
50 | data: { type: 'authors', id: '1' },
51 | links: {
52 | 'self': 'http://api.pixelhandler.com/api/v1/posts/2/relationships/author',
53 | 'related': 'http://api.pixelhandler.com/api/v1/posts/2/author'
54 | }
55 | },
56 | }
57 | });
58 | let promise = author.get('posts');
59 | assert.ok(promise.toString().match('ArrayProxy').length === 1, 'ArrayProxy used for toMany relation');
60 | });
61 |
--------------------------------------------------------------------------------
/tests/unit/utils/to-one-test.js:
--------------------------------------------------------------------------------
1 | import { moduleFor, test } from 'ember-qunit';
2 | import Ember from 'ember';
3 | import RSVP from 'rsvp';
4 | import { pluralize } from 'ember-inflector';
5 | import { setup, teardown } from 'dummy/tests/helpers/resources';
6 |
7 | let mockServices;
8 | const mockService = function () {
9 | let sandbox = this.sandbox;
10 | return Ember.Service.extend({
11 | findRelated: sandbox.spy(function () { return RSVP.Promise.resolve(Ember.Object.create({id: 1})); }),
12 | cacheLookup: sandbox.spy(function () { return undefined; })
13 | });
14 | };
15 | let entities = ['post', 'author'];
16 |
17 | moduleFor('model:resource', 'Unit | Utility | toOne', {
18 | beforeEach() {
19 | setup.call(this);
20 | this.sandbox = window.sinon.sandbox.create();
21 | mockServices = {};
22 | entities.forEach(function (entity) {
23 | let serviceName = pluralize(entity);
24 | mockServices[serviceName] = mockService.call(this);
25 | this.registry.register('service:'+serviceName, mockServices[serviceName]);
26 | }.bind(this));
27 | },
28 | afterEach() {
29 | mockServices = null;
30 | teardown.call(this);
31 | this.sandbox.restore();
32 | }
33 | });
34 |
35 | test('toOne() helper sets up a promise proxy to a related resource', function(assert) {
36 | let post = Ember.getOwner(this)._lookupFactory('model:post').create({
37 | id: '1', attributes: { title: 'Wyatt Earp', excerpt: 'Was a gambler.'},
38 | relationships: {
39 | author: {
40 | data: { type: 'authors', id: '1' },
41 | links: {
42 | 'self': 'http://api.pixelhandler.com/api/v1/posts/1/relationships/author',
43 | 'related': 'http://api.pixelhandler.com/api/v1/posts/1/author'
44 | }
45 | },
46 | }
47 | });
48 | let promise = post.get('author');
49 | assert.ok(promise.toString().match('ObjectProxy').length === 1, 'ObjectProxy used for toOne relation');
50 | });
51 |
--------------------------------------------------------------------------------
/tests/unit/utils/transform-map-test.js:
--------------------------------------------------------------------------------
1 | import TransformMap from 'ember-jsonapi-resources/utils/transform-map';
2 | import { module, test } from 'qunit';
3 |
4 | module('Unit | Utility | transform map');
5 |
6 | const map = Object.create(null);
7 | map.yes = 'Yes';
8 | map.no = 'No';
9 | Object.freeze(map);
10 |
11 | test('#values', function(assert) {
12 | let subject = new TransformMap(map);
13 | assert.equal(subject.values[0], 'Yes', 'map value[0] is "Yes"');
14 | assert.equal(subject.values[1], 'No', 'map value[1] is "No"');
15 | });
16 |
17 | test('#lookup by key', function(assert) {
18 | let subject = new TransformMap(map);
19 | assert.equal(subject.lookup('yes'), 'Yes', 'lookup "yes" value is "Yes"');
20 | assert.equal(subject.lookup('no', 'keys'), 'No', 'lookup "no" value is "No"');
21 | });
22 |
23 | test('#lookup by value', function(assert) {
24 | let subject = new TransformMap(map);
25 | assert.equal(subject.lookup('Yes', 'values'), 'yes', 'lookup "Yes" value is "yes"');
26 | assert.equal(subject.lookup('No', 'values'), 'no', 'lookup "No" value is "no"');
27 | });
28 |
29 | test('#lookup null', function(assert) {
30 | let subject = new TransformMap(map);
31 | assert.equal(subject.lookup(null), null, 'lookup null value is null');
32 | });
33 |
34 | test('#values', function(assert) {
35 | let subject = new TransformMap(map);
36 | assert.equal(subject.values.toString(), "Yes,No", 'values are "Yes,No"');
37 | });
38 |
39 | test('#keys', function(assert) {
40 | let subject = new TransformMap(map);
41 | assert.equal(subject.keys.toString(), "yes,no", 'keys are "yes,no"');
42 | });
43 |
44 | test('#entries', function(assert) {
45 | let subject = new TransformMap(map);
46 | assert.equal(subject.entries[0].toString(), "yes,Yes", 'first entry is `["yes", "Yes"]`');
47 | assert.equal(subject.entries[1].toString(), "no,No", 'last entry is `["no", "No"]`');
48 | });
49 |
--------------------------------------------------------------------------------
/tests/unit/utils/transforms-test.js:
--------------------------------------------------------------------------------
1 | import { dateTransform } from 'ember-jsonapi-resources/utils/transforms';
2 | import { module, test } from 'qunit';
3 |
4 | module('Unit | Utility | transforms');
5 |
6 | test('dateTransform#serialize - to ISO String', function(assert) {
7 | let date = 'October 26, 1881';
8 | let gunfightAtOKCorral = new Date(date);
9 | let expected = gunfightAtOKCorral.toISOString();
10 | let serialized = dateTransform.serialize(gunfightAtOKCorral);
11 | assert.equal(serialized, expected, 'serialized to ISO String');
12 | });
13 |
14 | test('dateTransform#deserialize - from ISO String', function(assert) {
15 | let date = 'October 26, 1881';
16 | let gunfightAtOKCorral = new Date(date);
17 | let value = gunfightAtOKCorral.toISOString();
18 | let deserialized = dateTransform.deserialize(value);
19 | assert.equal(deserialized.valueOf(), gunfightAtOKCorral.valueOf(), 'deserialized from ISO String');
20 | });
21 |
--------------------------------------------------------------------------------
/vendor/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pixelhandler/ember-jsonapi-resources/9a24b6c6b0f65bff48a45c9154b327b0853e0886/vendor/.gitkeep
--------------------------------------------------------------------------------
/yuidoc.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Ember JSON API Resources",
3 | "description": "Lightweight persistence for an Ember CLI app using the JSON API 1.0 specification.",
4 | "version": "0.2.1",
5 | "url": "https://github.com/pixelhandler/ember-jsonapi-resources",
6 | "options": {
7 | "paths": [
8 | "./addon/*/*.js"
9 | ],
10 | "outdir": "./docs"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
{{comment.body}}
16 |