From 9196acfe09820753db151dff7e696c7cc03f31ea Mon Sep 17 00:00:00 2001
From: bertrand <bpinel@ippon.fr>
Date: Thu, 3 Jan 2019 18:30:51 +0100
Subject: [PATCH] add sample application with todo + handling of S3 storage

---
 README.md                                     |   2 +
 app/adapters/application.js                   |   1 -
 blueprints/ember-aws-ehipster/index.js        |   2 +-
 .../files/__root__/adapters/__name__.js       |   6 +-
 jdl/jhipster-jdl.jh                           |  31 ++
 jdl/user.jh                                   |  23 ++
 mirage/scenarios/default.js                   |   1 +
 package.json                                  |   2 +-
 tests/dummy/app/components/todo-item.js       |  49 +++
 tests/dummy/app/components/todo-list.js       |  27 ++
 tests/dummy/app/controllers/active.js         |   6 +
 tests/dummy/app/controllers/application.js    |  20 +
 tests/dummy/app/controllers/completed.js      |   6 +
 tests/dummy/app/controllers/entity-factory.js |  16 +
 .../controllers/entity-factory/authority.js   |  51 +++
 .../app/controllers/entity-factory/todo.js    |  56 +++
 .../app/controllers/entity-factory/user.js    | 105 +++++
 tests/dummy/app/helpers/pluralize.js          |   8 +
 tests/dummy/app/models/authority.js           |   6 +
 tests/dummy/app/models/todo.js                |   7 +
 tests/dummy/app/models/user.js                |  17 +
 tests/dummy/app/router.js                     |   8 +-
 tests/dummy/app/routes/application.js         |   7 +
 .../app/routes/entity-factory/authority.js    |  15 +
 tests/dummy/app/routes/entity-factory/todo.js |  15 +
 tests/dummy/app/routes/entity-factory/user.js |  16 +
 tests/dummy/app/styles/app.css                |  11 +
 tests/dummy/app/styles/ember-aws-ehipster.css |  39 ++
 tests/dummy/app/styles/todo-base.css          | 141 +++++++
 tests/dummy/app/styles/todo-index.css         | 382 ++++++++++++++++++
 tests/dummy/app/templates/active.hbs          |   1 +
 tests/dummy/app/templates/application.hbs     |  35 +-
 tests/dummy/app/templates/completed.hbs       |   1 +
 .../app/templates/components/todo-item.hbs    |   6 +
 .../app/templates/components/todo-list.hbs    |  10 +
 tests/dummy/app/templates/entity-factory.hbs  |   9 +
 .../templates/entity-factory/authority.hbs    |  32 ++
 .../app/templates/entity-factory/todo.hbs     |  33 ++
 .../app/templates/entity-factory/user.hbs     |  49 +++
 tests/dummy/app/templates/index.hbs           |   3 +
 tests/dummy/app/validations/authority.js      |   5 +
 tests/dummy/app/validations/todo.js           |   5 +
 tests/dummy/app/validations/user.js           |   6 +
 tests/dummy/config/environment.js             |  49 +++
 tests/dummy/mirage/config.js                  |  20 +
 tests/dummy/mirage/factories/authority.js     |  11 +
 tests/dummy/mirage/factories/todo.js          |  14 +
 tests/dummy/mirage/factories/user.js          |  41 ++
 tests/dummy/mirage/models/authority.js        |   5 +
 tests/dummy/mirage/models/todo.js             |   5 +
 tests/dummy/mirage/models/user.js             |   6 +
 tests/dummy/mirage/scenarios/default.js       |   6 +
 tests/dummy/mirage/scenarios/tobedeleted.txt  |   1 +
 .../dummy/mirage/serializers/tobedeleted.txt  |   1 +
 tests/unit/adapters/application-test.js       |  12 -
 55 files changed, 1421 insertions(+), 21 deletions(-)
 delete mode 100644 app/adapters/application.js
 rename addon/adapters/application.js => blueprints/entity-factory/files/__root__/adapters/__name__.js (63%)
 create mode 100644 jdl/jhipster-jdl.jh
 create mode 100644 jdl/user.jh
 create mode 100644 tests/dummy/app/components/todo-item.js
 create mode 100644 tests/dummy/app/components/todo-list.js
 create mode 100644 tests/dummy/app/controllers/active.js
 create mode 100644 tests/dummy/app/controllers/application.js
 create mode 100644 tests/dummy/app/controllers/completed.js
 create mode 100644 tests/dummy/app/controllers/entity-factory.js
 create mode 100644 tests/dummy/app/controllers/entity-factory/authority.js
 create mode 100644 tests/dummy/app/controllers/entity-factory/todo.js
 create mode 100644 tests/dummy/app/controllers/entity-factory/user.js
 create mode 100644 tests/dummy/app/helpers/pluralize.js
 create mode 100644 tests/dummy/app/models/authority.js
 create mode 100644 tests/dummy/app/models/todo.js
 create mode 100644 tests/dummy/app/models/user.js
 create mode 100644 tests/dummy/app/routes/application.js
 create mode 100644 tests/dummy/app/routes/entity-factory/authority.js
 create mode 100644 tests/dummy/app/routes/entity-factory/todo.js
 create mode 100644 tests/dummy/app/routes/entity-factory/user.js
 create mode 100644 tests/dummy/app/styles/ember-aws-ehipster.css
 create mode 100644 tests/dummy/app/styles/todo-base.css
 create mode 100644 tests/dummy/app/styles/todo-index.css
 create mode 100644 tests/dummy/app/templates/active.hbs
 create mode 100644 tests/dummy/app/templates/completed.hbs
 create mode 100644 tests/dummy/app/templates/components/todo-item.hbs
 create mode 100644 tests/dummy/app/templates/components/todo-list.hbs
 create mode 100644 tests/dummy/app/templates/entity-factory.hbs
 create mode 100644 tests/dummy/app/templates/entity-factory/authority.hbs
 create mode 100644 tests/dummy/app/templates/entity-factory/todo.hbs
 create mode 100644 tests/dummy/app/templates/entity-factory/user.hbs
 create mode 100644 tests/dummy/app/templates/index.hbs
 create mode 100644 tests/dummy/app/validations/authority.js
 create mode 100644 tests/dummy/app/validations/todo.js
 create mode 100644 tests/dummy/app/validations/user.js
 create mode 100644 tests/dummy/mirage/factories/authority.js
 create mode 100644 tests/dummy/mirage/factories/todo.js
 create mode 100644 tests/dummy/mirage/factories/user.js
 create mode 100644 tests/dummy/mirage/models/authority.js
 create mode 100644 tests/dummy/mirage/models/todo.js
 create mode 100644 tests/dummy/mirage/models/user.js
 create mode 100644 tests/dummy/mirage/scenarios/tobedeleted.txt
 create mode 100644 tests/dummy/mirage/serializers/tobedeleted.txt
 delete mode 100644 tests/unit/adapters/application-test.js

diff --git a/README.md b/README.md
index 8b0239a..4da211b 100644
--- a/README.md
+++ b/README.md
@@ -6,6 +6,8 @@ It also guide you to set up a JSON-API server on top of AWS API Gateway, Lambda
 
 It could also be seen as a starter for setting up Mirage, allowing the developper to build a full working application (using mock data) entirely running on the client. Once the development is over, the persistance can be delegated to an AWS API Gateway using a lambda function storing objects in DynamoDB.
 
+Complete code is available at https://gitlab.ippon.fr/bpinel/ember-aws-ehipster
+
 Installation
 ------------------------------------------------------------------------------
 
diff --git a/app/adapters/application.js b/app/adapters/application.js
deleted file mode 100644
index 3fc80e2..0000000
--- a/app/adapters/application.js
+++ /dev/null
@@ -1 +0,0 @@
-export { default } from 'ember-aws-ehipster/adapters/application';
diff --git a/blueprints/ember-aws-ehipster/index.js b/blueprints/ember-aws-ehipster/index.js
index f651c31..d5c3204 100644
--- a/blueprints/ember-aws-ehipster/index.js
+++ b/blueprints/ember-aws-ehipster/index.js
@@ -51,7 +51,7 @@ module.exports = {
                               '\t\t\t\tlabel: "col-form-label",\n\t\t\t\thelp: "small form-text text-danger",'+
                               '\n\t\t\t\thint: "small form-text text-muted",\n\t\t\t\tcheckbox: "checkbox",\n\t\t\t\tbutton: "btn btn-default",'+
                               '\n\t\t\t\tsubmit: "btn btn-primary",\n\t\t\t\tloading: "loading",\n\t\t\t\tvalid: "is-valid",'+
-                              '\n\t\t\t\terror: "is-invalid"\n\t\t\t}\n\t\t},\n';
+                              '\n\t\t\t\terror: "is-invalid"\n\t\t\t}\n\t\t},\n\t\tgatewayURL: "",\n';
     addLineToFile(this, configPath, /let ENV = {/, validatedFormConfig);
 
     // Add import of ember_aws_ehipster.css to apps.css
diff --git a/addon/adapters/application.js b/blueprints/entity-factory/files/__root__/adapters/__name__.js
similarity index 63%
rename from addon/adapters/application.js
rename to blueprints/entity-factory/files/__root__/adapters/__name__.js
index 098a237..afc48ba 100644
--- a/addon/adapters/application.js
+++ b/blueprints/entity-factory/files/__root__/adapters/__name__.js
@@ -1,7 +1,9 @@
 import DS from 'ember-data';
+import config from '../config/environment';
 
 export default DS.JSONAPIAdapter.extend({
     headers: {
         "Content-Type": "application/json; charset=utf-8"
-      }
-});
+      },
+  host: config.gatewayURL
+});
\ No newline at end of file
diff --git a/jdl/jhipster-jdl.jh b/jdl/jhipster-jdl.jh
new file mode 100644
index 0000000..a7bfd9b
--- /dev/null
+++ b/jdl/jhipster-jdl.jh
@@ -0,0 +1,31 @@
+entity User {
+ login String required minlength(4),
+ passwordHash String required minlength(8),
+ firstName String,
+ lastName String,
+ email String,
+ imageUrl String,
+ activated Boolean,
+ createdBy String,
+ createdDate LocalDate,
+ lastModifiedBy String,
+ lastModifiedDate Instant 
+}
+
+entity Authority {
+ name String required
+}
+
+entity Todo {
+	title String required,
+    completed Boolean
+}
+
+relationship ManyToMany {
+	User{user(login)} to Authority{authority(name)}
+}
+
+relationship OneToMany {
+ 	User{user(login)} to Todo{todo}
+}
+
diff --git a/jdl/user.jh b/jdl/user.jh
new file mode 100644
index 0000000..aa93534
--- /dev/null
+++ b/jdl/user.jh
@@ -0,0 +1,23 @@
+entity User {
+ login String required,
+ passwordHash String required minlength(8),
+ firstName String,
+ lastName String,
+ email String,
+ imageUrl String,
+ activated Boolean,
+ createdBy String,
+ createdDate LocalDate,
+ lastModifiedBy String,
+ lastModifiedDate Instant 
+}
+
+entity Authority {
+ name String required
+}
+
+relationship ManyToMany {
+	User{user(id)} to Authority{authorityName}
+}
+
+
diff --git a/mirage/scenarios/default.js b/mirage/scenarios/default.js
index 1b5dd13..c0ed642 100644
--- a/mirage/scenarios/default.js
+++ b/mirage/scenarios/default.js
@@ -1,2 +1,3 @@
 export default function(server) {
+
 }
diff --git a/package.json b/package.json
index 0c653bc..a42cb14 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "ember-aws-ehipster",
-  "version": "0.3.26",
+  "version": "0.4.3",
   "description": "Attempt to build a complete web application using serverless architecture on AWS",
   "keywords": [
     "ember-addon",
diff --git a/tests/dummy/app/components/todo-item.js b/tests/dummy/app/components/todo-item.js
new file mode 100644
index 0000000..b5643e1
--- /dev/null
+++ b/tests/dummy/app/components/todo-item.js
@@ -0,0 +1,49 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+    store: Ember.inject.service(),
+	tagName: 'li',
+	editing: false,
+	classNameBindings: ['todo.completed', 'editing'],
+
+	actions: {
+		startEditing() {
+			this.get('onStartEdit')();
+			this.set('editing', true);
+			Ember.run.scheduleOnce('afterRender', this, 'focusInput');
+		},
+
+		doneEditing(todoTitle) {
+			if (!this.get('editing')) { return; }
+			if (Ember.isBlank(todoTitle)) {
+				this.send('removeTodo');
+			} else {
+				this.set('todo.title', todoTitle.trim());
+				this.set('editing', false);
+                this.get('onEndEdit')();
+                this.get('todo').save();
+			}
+		},
+
+		handleKeydown(e) {
+			if (e.keyCode === 13) {
+				e.target.blur();
+			} else if (e.keyCode === 27) {
+				this.set('editing', false);
+			}
+		},
+
+		toggleCompleted(e) {
+			let todo = this.get('todo');
+			Ember.set(todo, 'completed', e.target.checked);
+			todo.save();
+		},
+		removeTodo() {
+			this.get('store').deleteRecord(this.get('todo'));
+		}
+	},
+
+	focusInput() {
+		this.element.querySelector('input.edit').focus();
+	}
+});
diff --git a/tests/dummy/app/components/todo-list.js b/tests/dummy/app/components/todo-list.js
new file mode 100644
index 0000000..fb2fc08
--- /dev/null
+++ b/tests/dummy/app/components/todo-list.js
@@ -0,0 +1,27 @@
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+	store: Ember.inject.service(),
+	tagName: 'section',
+	elementId: 'main',
+	canToggle: true,
+	allCompleted: Ember.computed('todos.@each.completed', function () {
+		return this.get('todos').isEvery('completed');
+	}),
+
+	actions: {
+		enableToggle() {
+			this.set('canToggle', true);
+		},
+
+		disableToggle() {
+			this.set('canToggle', false);
+		},
+
+		toggleAll() {
+			let allCompleted = this.get('allCompleted');
+			this.get('todos').forEach(todo => Ember.set(todo, 'completed', !allCompleted));
+			this.get('store').save();
+		}
+	}
+});
diff --git a/tests/dummy/app/controllers/active.js b/tests/dummy/app/controllers/active.js
new file mode 100644
index 0000000..4d148bd
--- /dev/null
+++ b/tests/dummy/app/controllers/active.js
@@ -0,0 +1,6 @@
+import Controller from '@ember/controller';
+import { computed } from '@ember/object';
+
+export default Controller.extend({
+    todos: computed.filterBy('model', 'completed', false)
+});
diff --git a/tests/dummy/app/controllers/application.js b/tests/dummy/app/controllers/application.js
new file mode 100644
index 0000000..d31b99e
--- /dev/null
+++ b/tests/dummy/app/controllers/application.js
@@ -0,0 +1,20 @@
+import Controller from '@ember/controller';
+import { computed } from '@ember/object';
+import { isBlank } from '@ember/utils';
+
+export default Controller.extend({
+    remaining: computed.filterBy('model', 'completed', false),
+	completed: computed.filterBy('model', 'completed'),
+	actions: {
+		createTodo(e) {
+			if (e.keyCode === 13 && !isBlank(e.target.value)) {
+                let newEntity = this.store.createRecord('todo',{ title: e.target.value.trim(), completed: false });
+                newEntity.save().then(() => { e.target.value = ''; });
+			}
+		},
+
+		clearCompleted() {
+            this.get('completed').forEach((record) => record.destroyRecord());
+		}
+	}
+});
diff --git a/tests/dummy/app/controllers/completed.js b/tests/dummy/app/controllers/completed.js
new file mode 100644
index 0000000..a8d9933
--- /dev/null
+++ b/tests/dummy/app/controllers/completed.js
@@ -0,0 +1,6 @@
+import Controller from '@ember/controller';
+import { computed } from '@ember/object';
+
+export default Controller.extend({
+    todos: computed.filterBy('model', 'completed', true)
+});
diff --git a/tests/dummy/app/controllers/entity-factory.js b/tests/dummy/app/controllers/entity-factory.js
new file mode 100644
index 0000000..12960fb
--- /dev/null
+++ b/tests/dummy/app/controllers/entity-factory.js
@@ -0,0 +1,16 @@
+import Controller from '@ember/controller';
+
+export default Controller.extend({
+    entities: [
+'todo',
+'authority',
+'user',
+    ],
+    entity: '',
+    actions: {
+        selectEntity(entity) {
+            this.set('entity', entity);
+            this.transitionToRoute('entity-factory.'+entity);
+        }
+    }
+});
\ No newline at end of file
diff --git a/tests/dummy/app/controllers/entity-factory/authority.js b/tests/dummy/app/controllers/entity-factory/authority.js
new file mode 100644
index 0000000..0a1a3ea
--- /dev/null
+++ b/tests/dummy/app/controllers/entity-factory/authority.js
@@ -0,0 +1,51 @@
+import Controller from '@ember/controller';
+import { computed } from '@ember/object';
+import { A } from '@ember/array';
+import EmberObject from '@ember/object';
+import AuthorityValidations from "../../validations/authority";
+import { task } from "ember-concurrency";
+
+export default Controller.extend({
+  isAddingEntry: false,
+  newEntry: EmberObject.create({name: '',users: []}),
+  
+  AuthorityValidations,
+
+	userList: computed('users', function() {
+		this.store.findAll('user');
+	}),
+
+	name: null,
+	users: null,
+authorityTableColumns: computed(function() {
+	var col = A([
+		EmberObject.create({
+			propertyName: "name",
+			title: "name"
+		})]);
+	col.pushObject({
+		title: 'Delete',
+		component: 'delete-row'
+	});
+	return col;	}),
+authorityTableContent: computed(function() {
+	return this.get('authorities');
+}),
+
+  actions: {
+    submit() {
+      console.log("action submit");
+    },
+    deleteRecord (record) {
+      console.log('record is '+ record);
+      record.destroyRecord();
+    }
+  },
+  submitEntry: task(function*(model) {
+    yield model.save();
+    let newEntity = this.store.createRecord('authority',yield model.get('data'));
+    yield newEntity.save();
+    console.log("new entry of id "+newEntity.get('id')+" created");
+    this.set('addEntryModal', false);
+  })
+});
\ No newline at end of file
diff --git a/tests/dummy/app/controllers/entity-factory/todo.js b/tests/dummy/app/controllers/entity-factory/todo.js
new file mode 100644
index 0000000..263aebf
--- /dev/null
+++ b/tests/dummy/app/controllers/entity-factory/todo.js
@@ -0,0 +1,56 @@
+import Controller from '@ember/controller';
+import { computed } from '@ember/object';
+import { A } from '@ember/array';
+import EmberObject from '@ember/object';
+import TodoValidations from "../../validations/todo";
+import { task } from "ember-concurrency";
+
+export default Controller.extend({
+  isAddingEntry: false,
+  newEntry: EmberObject.create({title: '',completed: 'false',user: []}),
+  
+  TodoValidations,
+
+	userList: computed('user', function() {
+		this.store.findAll('user');
+	}),
+
+	title: null,
+	completed: null,
+	user: null,
+todoTableColumns: computed(function() {
+	var col = A([
+		EmberObject.create({
+			propertyName: "title",
+			title: "title"
+		}),
+		EmberObject.create({
+			propertyName: "completed",
+			title: "completed"
+		})]);
+	col.pushObject({
+		title: 'Delete',
+		component: 'delete-row'
+	});
+	return col;	}),
+todoTableContent: computed(function() {
+	return this.get('todos');
+}),
+
+  actions: {
+    submit() {
+      console.log("action submit");
+    },
+    deleteRecord (record) {
+      console.log('record is '+ record);
+      record.destroyRecord();
+    }
+  },
+  submitEntry: task(function*(model) {
+    yield model.save();
+    let newEntity = this.store.createRecord('todo',yield model.get('data'));
+    yield newEntity.save();
+    console.log("new entry of id "+newEntity.get('id')+" created");
+    this.set('addEntryModal', false);
+  })
+});
\ No newline at end of file
diff --git a/tests/dummy/app/controllers/entity-factory/user.js b/tests/dummy/app/controllers/entity-factory/user.js
new file mode 100644
index 0000000..087d198
--- /dev/null
+++ b/tests/dummy/app/controllers/entity-factory/user.js
@@ -0,0 +1,105 @@
+import Controller from '@ember/controller';
+import { computed } from '@ember/object';
+import { A } from '@ember/array';
+import EmberObject from '@ember/object';
+import UserValidations from "../../validations/user";
+import { task } from "ember-concurrency";
+
+export default Controller.extend({
+  isAddingEntry: false,
+  newEntry: EmberObject.create({login: '',passwordHash: '',firstName: '',lastName: '',email: '',imageUrl: '',activated: 'false',createdBy: '',createdDate: new Date(),lastModifiedBy: '',lastModifiedDate: new Date(),authorities: [],todos: []}),
+  
+  UserValidations,
+
+	authorityList: computed('authorities', function() {
+		this.store.findAll('authority');
+	}),
+	todoList: computed('todos', function() {
+		this.store.findAll('todo');
+	}),
+
+	login: null,
+	passwordHash: null,
+	firstName: null,
+	lastName: null,
+	email: null,
+	imageUrl: null,
+	activated: null,
+	createdBy: null,
+	createdDate: null,
+	lastModifiedBy: null,
+	lastModifiedDate: null,
+	authorities: null,
+	todos: null,
+userTableColumns: computed(function() {
+	var col = A([
+		EmberObject.create({
+			propertyName: "login",
+			title: "login"
+		}),
+		EmberObject.create({
+			propertyName: "passwordHash",
+			title: "passwordHash"
+		}),
+		EmberObject.create({
+			propertyName: "firstName",
+			title: "firstName"
+		}),
+		EmberObject.create({
+			propertyName: "lastName",
+			title: "lastName"
+		}),
+		EmberObject.create({
+			propertyName: "email",
+			title: "email"
+		}),
+		EmberObject.create({
+			propertyName: "imageUrl",
+			title: "imageUrl"
+		}),
+		EmberObject.create({
+			propertyName: "activated",
+			title: "activated"
+		}),
+		EmberObject.create({
+			propertyName: "createdBy",
+			title: "createdBy"
+		}),
+		EmberObject.create({
+			propertyName: "createdDate",
+			title: "createdDate"
+		}),
+		EmberObject.create({
+			propertyName: "lastModifiedBy",
+			title: "lastModifiedBy"
+		}),
+		EmberObject.create({
+			propertyName: "lastModifiedDate",
+			title: "lastModifiedDate"
+		})]);
+	col.pushObject({
+		title: 'Delete',
+		component: 'delete-row'
+	});
+	return col;	}),
+userTableContent: computed(function() {
+	return this.get('users');
+}),
+
+  actions: {
+    submit() {
+      console.log("action submit");
+    },
+    deleteRecord (record) {
+      console.log('record is '+ record);
+      record.destroyRecord();
+    }
+  },
+  submitEntry: task(function*(model) {
+    yield model.save();
+    let newEntity = this.store.createRecord('user',yield model.get('data'));
+    yield newEntity.save();
+    console.log("new entry of id "+newEntity.get('id')+" created");
+    this.set('addEntryModal', false);
+  })
+});
\ No newline at end of file
diff --git a/tests/dummy/app/helpers/pluralize.js b/tests/dummy/app/helpers/pluralize.js
new file mode 100644
index 0000000..a4dd59c
--- /dev/null
+++ b/tests/dummy/app/helpers/pluralize.js
@@ -0,0 +1,8 @@
+import Ember from 'ember';
+import { pluralize } from 'ember-inflector';
+
+export function pluralizeHelper([singular, count]/*, hash*/) {
+	return count === 1 ? singular : pluralize(singular);
+}
+
+export default Ember.Helper.helper(pluralizeHelper);
\ No newline at end of file
diff --git a/tests/dummy/app/models/authority.js b/tests/dummy/app/models/authority.js
new file mode 100644
index 0000000..70a5d90
--- /dev/null
+++ b/tests/dummy/app/models/authority.js
@@ -0,0 +1,6 @@
+import DS from 'ember-data';
+
+export default DS.Model.extend({
+	name: DS.attr('string'),
+	users: DS.hasMany('user')
+});
diff --git a/tests/dummy/app/models/todo.js b/tests/dummy/app/models/todo.js
new file mode 100644
index 0000000..d53c584
--- /dev/null
+++ b/tests/dummy/app/models/todo.js
@@ -0,0 +1,7 @@
+import DS from 'ember-data';
+
+export default DS.Model.extend({
+	title: DS.attr('string'),
+	completed: DS.attr('boolean'),
+	user: DS.hasMany('user')
+});
diff --git a/tests/dummy/app/models/user.js b/tests/dummy/app/models/user.js
new file mode 100644
index 0000000..f4f1abb
--- /dev/null
+++ b/tests/dummy/app/models/user.js
@@ -0,0 +1,17 @@
+import DS from 'ember-data';
+
+export default DS.Model.extend({
+	login: DS.attr('string'),
+	passwordHash: DS.attr('string'),
+	firstName: DS.attr('string'),
+	lastName: DS.attr('string'),
+	email: DS.attr('string'),
+	imageUrl: DS.attr('string'),
+	activated: DS.attr('boolean'),
+	createdBy: DS.attr('string'),
+	createdDate: DS.attr('date'),
+	lastModifiedBy: DS.attr('string'),
+	lastModifiedDate: DS.attr('date'),
+	authorities: DS.hasMany('authority'),
+	todos: DS.hasMany('todo')
+});
diff --git a/tests/dummy/app/router.js b/tests/dummy/app/router.js
index 1552e4a..81771fe 100644
--- a/tests/dummy/app/router.js
+++ b/tests/dummy/app/router.js
@@ -7,7 +7,13 @@ const Router = EmberRouter.extend({
 });
 
 Router.map(function() {
-
+	this.route('entity-factory', function() {
+    this.route('todo');
+    this.route('authority');
+    this.route('user');
+    });
+    this.route('active');
+    this.route('completed');
 });
 
 export default Router;
diff --git a/tests/dummy/app/routes/application.js b/tests/dummy/app/routes/application.js
new file mode 100644
index 0000000..8ad4539
--- /dev/null
+++ b/tests/dummy/app/routes/application.js
@@ -0,0 +1,7 @@
+import Route from '@ember/routing/route';
+
+export default Route.extend({
+    model() {
+		return this.store.findAll("todo");
+	}
+});
diff --git a/tests/dummy/app/routes/entity-factory/authority.js b/tests/dummy/app/routes/entity-factory/authority.js
new file mode 100644
index 0000000..6b20e2e
--- /dev/null
+++ b/tests/dummy/app/routes/entity-factory/authority.js
@@ -0,0 +1,15 @@
+import Route from '@ember/routing/route';
+
+export default Route.extend({
+   model() {
+    return Ember.RSVP.hash({
+        			authorities: this.store.findAll('authority'),
+			users: this.store.findAll('user')
+      });
+   },
+
+   setupController(controller, models) {
+     controller.setProperties(models);
+   }
+
+});
\ No newline at end of file
diff --git a/tests/dummy/app/routes/entity-factory/todo.js b/tests/dummy/app/routes/entity-factory/todo.js
new file mode 100644
index 0000000..909e42a
--- /dev/null
+++ b/tests/dummy/app/routes/entity-factory/todo.js
@@ -0,0 +1,15 @@
+import Route from '@ember/routing/route';
+
+export default Route.extend({
+   model() {
+    return Ember.RSVP.hash({
+        			todos: this.store.findAll('todo'),
+			users: this.store.findAll('user')
+      });
+   },
+
+   setupController(controller, models) {
+     controller.setProperties(models);
+   }
+
+});
\ No newline at end of file
diff --git a/tests/dummy/app/routes/entity-factory/user.js b/tests/dummy/app/routes/entity-factory/user.js
new file mode 100644
index 0000000..d60c2e8
--- /dev/null
+++ b/tests/dummy/app/routes/entity-factory/user.js
@@ -0,0 +1,16 @@
+import Route from '@ember/routing/route';
+
+export default Route.extend({
+   model() {
+    return Ember.RSVP.hash({
+        			users: this.store.findAll('user'),
+			authorities: this.store.findAll('authority'),
+			todos: this.store.findAll('todo')
+      });
+   },
+
+   setupController(controller, models) {
+     controller.setProperties(models);
+   }
+
+});
\ No newline at end of file
diff --git a/tests/dummy/app/styles/app.css b/tests/dummy/app/styles/app.css
index e69de29..8e35abc 100644
--- a/tests/dummy/app/styles/app.css
+++ b/tests/dummy/app/styles/app.css
@@ -0,0 +1,11 @@
+@import 'ember-aws-ehipster.css';
+@import 'todo-base.css';
+@import 'todo-index.css';
+
+footer p {
+    font-size: 25px;
+  }
+  
+  #new-todo {
+    background-color: #ffffff;
+  }
\ No newline at end of file
diff --git a/tests/dummy/app/styles/ember-aws-ehipster.css b/tests/dummy/app/styles/ember-aws-ehipster.css
new file mode 100644
index 0000000..f344568
--- /dev/null
+++ b/tests/dummy/app/styles/ember-aws-ehipster.css
@@ -0,0 +1,39 @@
+a:hover {
+    text-decoration: none;
+}
+a.active {
+    font-weight: 700;
+}
+pre {
+    text-align: left;
+    white-space: pre-line;
+}
+.table-footer {
+    border: 1px solid #ddd;
+    padding: 5px 0;
+}
+
+.models-table-wrapper {
+    margin-bottom: 20px;
+}
+
+.btn-default {
+    background-image: none !important;
+}
+
+.columns-dropdown {
+    margin-bottom: 20px;
+}
+
+.table-column-options.table > tbody > tr > td {
+    border-top-width: 0;
+}
+
+tr.selected-row>td:not(.grouping-cell), tr.selected-expand>td:not(.grouping-cell) {
+    background: #C6E746;
+}
+
+.navbar-text.gh {
+    margin-top: 13px !important;
+    margin-bottom: 11px !important;
+}
\ No newline at end of file
diff --git a/tests/dummy/app/styles/todo-base.css b/tests/dummy/app/styles/todo-base.css
new file mode 100644
index 0000000..da65968
--- /dev/null
+++ b/tests/dummy/app/styles/todo-base.css
@@ -0,0 +1,141 @@
+hr {
+	margin: 20px 0;
+	border: 0;
+	border-top: 1px dashed #c5c5c5;
+	border-bottom: 1px dashed #f7f7f7;
+}
+
+.learn a {
+	font-weight: normal;
+	text-decoration: none;
+	color: #b83f45;
+}
+
+.learn a:hover {
+	text-decoration: underline;
+	color: #787e7e;
+}
+
+.learn h3,
+.learn h4,
+.learn h5 {
+	margin: 10px 0;
+	font-weight: 500;
+	line-height: 1.2;
+	color: #000;
+}
+
+.learn h3 {
+	font-size: 24px;
+}
+
+.learn h4 {
+	font-size: 18px;
+}
+
+.learn h5 {
+	margin-bottom: 0;
+	font-size: 14px;
+}
+
+.learn ul {
+	padding: 0;
+	margin: 0 0 30px 25px;
+}
+
+.learn li {
+	line-height: 20px;
+}
+
+.learn p {
+	font-size: 15px;
+	font-weight: 300;
+	line-height: 1.3;
+	margin-top: 0;
+	margin-bottom: 0;
+}
+
+#issue-count {
+	display: none;
+}
+
+.quote {
+	border: none;
+	margin: 20px 0 60px 0;
+}
+
+.quote p {
+	font-style: italic;
+}
+
+.quote p:before {
+	content: '“';
+	font-size: 50px;
+	opacity: .15;
+	position: absolute;
+	top: -20px;
+	left: 3px;
+}
+
+.quote p:after {
+	content: '”';
+	font-size: 50px;
+	opacity: .15;
+	position: absolute;
+	bottom: -42px;
+	right: 3px;
+}
+
+.quote footer {
+	position: absolute;
+	bottom: -40px;
+	right: 0;
+}
+
+.quote footer img {
+	border-radius: 3px;
+}
+
+.quote footer a {
+	margin-left: 5px;
+	vertical-align: middle;
+}
+
+.speech-bubble {
+	position: relative;
+	padding: 10px;
+	background: rgba(0, 0, 0, .04);
+	border-radius: 5px;
+}
+
+.speech-bubble:after {
+	content: '';
+	position: absolute;
+	top: 100%;
+	right: 30px;
+	border: 13px solid transparent;
+	border-top-color: rgba(0, 0, 0, .04);
+}
+
+.learn-bar > .learn {
+	position: absolute;
+	width: 272px;
+	top: 8px;
+	left: -300px;
+	padding: 10px;
+	border-radius: 5px;
+	background-color: rgba(255, 255, 255, .6);
+	transition-property: left;
+	transition-duration: 500ms;
+}
+
+@media (min-width: 899px) {
+	.learn-bar {
+		width: auto;
+		padding-left: 300px;
+	}
+
+	.learn-bar > .learn {
+		left: 8px;
+	}
+}
diff --git a/tests/dummy/app/styles/todo-index.css b/tests/dummy/app/styles/todo-index.css
new file mode 100644
index 0000000..0ad8b27
--- /dev/null
+++ b/tests/dummy/app/styles/todo-index.css
@@ -0,0 +1,382 @@
+html,
+body {
+	margin: 0;
+	padding: 0;
+}
+
+button {
+	margin: 0;
+	padding: 0;
+	border: 0;
+	background: none;
+	font-size: 100%;
+	vertical-align: baseline;
+	font-family: inherit;
+	font-weight: inherit;
+	color: inherit;
+	-webkit-appearance: none;
+	appearance: none;
+	-webkit-font-smoothing: antialiased;
+	-moz-font-smoothing: antialiased;
+	font-smoothing: antialiased;
+}
+
+body {
+	font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
+	line-height: 1.4em;
+	background: #f5f5f5;
+	color: #4d4d4d;
+	min-width: 230px;
+	max-width: 550px;
+	margin: 0 auto;
+	-webkit-font-smoothing: antialiased;
+	-moz-font-smoothing: antialiased;
+	font-smoothing: antialiased;
+	font-weight: 300;
+}
+
+button,
+input[type="checkbox"] {
+	outline: none;
+}
+
+.hidden {
+	display: none;
+}
+
+#todoapp {
+	background: #fff;
+	margin: 130px 0 40px 0;
+	position: relative;
+	box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
+	            0 25px 50px 0 rgba(0, 0, 0, 0.1);
+}
+
+#todoapp input::-webkit-input-placeholder {
+	font-style: italic;
+	font-weight: 300;
+	color: #e6e6e6;
+}
+
+#todoapp input::-moz-placeholder {
+	font-style: italic;
+	font-weight: 300;
+	color: #e6e6e6;
+}
+
+#todoapp input::input-placeholder {
+	font-style: italic;
+	font-weight: 300;
+	color: #e6e6e6;
+}
+
+#todoapp h1 {
+	position: absolute;
+	top: -155px;
+	width: 100%;
+	font-size: 100px;
+	font-weight: 100;
+	text-align: center;
+	color: rgba(175, 47, 47, 0.15);
+	-webkit-text-rendering: optimizeLegibility;
+	-moz-text-rendering: optimizeLegibility;
+	text-rendering: optimizeLegibility;
+}
+
+#new-todo,
+.edit {
+	position: relative;
+	margin: 0;
+	width: 100%;
+	font-size: 24px;
+	font-family: inherit;
+	font-weight: inherit;
+	line-height: 1.4em;
+	border: 0;
+	outline: none;
+	color: inherit;
+	padding: 6px;
+	border: 1px solid #999;
+	box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
+	box-sizing: border-box;
+	-webkit-font-smoothing: antialiased;
+	-moz-font-smoothing: antialiased;
+	font-smoothing: antialiased;
+}
+
+#new-todo {
+	padding: 16px 16px 16px 60px;
+	border: none;
+	background: rgba(0, 0, 0, 0.003);
+	box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03);
+}
+
+#main {
+	position: relative;
+	z-index: 2;
+	border-top: 1px solid #e6e6e6;
+}
+
+label[for='toggle-all'] {
+	display: none;
+}
+
+#toggle-all {
+	position: absolute;
+	top: -55px;
+	left: -12px;
+	width: 60px;
+	height: 34px;
+	text-align: center;
+	border: none; /* Mobile Safari */
+}
+
+#toggle-all:before {
+	content: '❯';
+	font-size: 22px;
+	color: #e6e6e6;
+	padding: 10px 27px 10px 27px;
+}
+
+#toggle-all:checked:before {
+	color: #737373;
+}
+
+#todo-list {
+	margin: 0;
+	padding: 0;
+	list-style: none;
+}
+
+#todo-list li {
+	position: relative;
+	font-size: 24px;
+	border-bottom: 1px solid #ededed;
+}
+
+#todo-list li:last-child {
+	border-bottom: none;
+}
+
+#todo-list li.editing {
+	border-bottom: none;
+	padding: 0;
+}
+
+#todo-list li.editing .edit {
+	display: block;
+	width: 506px;
+	padding: 13px 17px 12px 17px;
+	margin: 0 0 0 43px;
+}
+
+#todo-list li.editing .view {
+	display: none;
+}
+
+#todo-list li .toggle {
+	text-align: center;
+	width: 40px;
+	/* auto, since non-WebKit browsers doesn't support input styling */
+	height: auto;
+	position: absolute;
+	top: 0;
+	bottom: 0;
+	margin: auto 0;
+	border: none; /* Mobile Safari */
+	-webkit-appearance: none;
+	appearance: none;
+}
+
+#todo-list li .toggle:after {
+	content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#ededed" stroke-width="3"/></svg>');
+}
+
+#todo-list li .toggle:checked:after {
+	content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#bddad5" stroke-width="3"/><path fill="#5dc2af" d="M72 25L42 71 27 56l-4 4 20 20 34-52z"/></svg>');
+}
+
+#todo-list li label {
+	white-space: pre;
+	word-break: break-word;
+	padding: 15px 60px 15px 15px;
+	margin-left: 45px;
+	display: block;
+	line-height: 1.2;
+	transition: color 0.4s;
+}
+
+#todo-list li.completed label {
+	color: #d9d9d9;
+	text-decoration: line-through;
+}
+
+#todo-list li .destroy {
+	display: none;
+	position: absolute;
+	top: 0;
+	right: 10px;
+	bottom: 0;
+	width: 40px;
+	height: 40px;
+	margin: auto 0;
+	font-size: 30px;
+	color: #cc9a9a;
+	margin-bottom: 11px;
+	transition: color 0.2s ease-out;
+}
+
+#todo-list li .destroy:hover {
+	color: #af5b5e;
+}
+
+#todo-list li .destroy:after {
+	content: '×';
+}
+
+#todo-list li:hover .destroy {
+	display: block;
+}
+
+#todo-list li .edit {
+	display: none;
+}
+
+#todo-list li.editing:last-child {
+	margin-bottom: -1px;
+}
+
+#footer {
+	color: #777;
+	padding: 10px 15px;
+	height: 20px;
+	text-align: center;
+	border-top: 1px solid #e6e6e6;
+}
+
+#footer:before {
+	content: '';
+	position: absolute;
+	right: 0;
+	bottom: 0;
+	left: 0;
+	height: 50px;
+	overflow: hidden;
+	box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2),
+	            0 8px 0 -3px #f6f6f6,
+	            0 9px 1px -3px rgba(0, 0, 0, 0.2),
+	            0 16px 0 -6px #f6f6f6,
+	            0 17px 2px -6px rgba(0, 0, 0, 0.2);
+}
+
+#todo-count {
+	float: left;
+	text-align: left;
+}
+
+#todo-count strong {
+	font-weight: 300;
+}
+
+#filters {
+	margin: 0;
+	padding: 0;
+	list-style: none;
+	position: absolute;
+	right: 0;
+	left: 0;
+}
+
+#filters li {
+	display: inline;
+}
+
+#filters li a {
+	color: inherit;
+	margin: 3px;
+	padding: 3px 7px;
+	text-decoration: none;
+	border: 1px solid transparent;
+	border-radius: 3px;
+}
+
+#filters li a.selected,
+#filters li a:hover {
+	border-color: rgba(175, 47, 47, 0.1);
+}
+
+#filters li a.selected {
+	border-color: rgba(175, 47, 47, 0.2);
+}
+
+#clear-completed,
+html #clear-completed:active {
+	float: right;
+	position: relative;
+	line-height: 20px;
+	text-decoration: none;
+	cursor: pointer;
+	position: relative;
+}
+
+#clear-completed:hover {
+	text-decoration: underline;
+}
+
+#info {
+	margin: 65px auto 0;
+	color: #bfbfbf;
+	font-size: 10px;
+	text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
+	text-align: center;
+}
+
+#info p {
+	line-height: 1;
+}
+
+#info a {
+	color: inherit;
+	text-decoration: none;
+	font-weight: 400;
+}
+
+#info a:hover {
+	text-decoration: underline;
+}
+
+/*
+	Hack to remove background from Mobile Safari.
+	Can't use it globally since it destroys checkboxes in Firefox
+*/
+@media screen and (-webkit-min-device-pixel-ratio:0) {
+	#toggle-all,
+	#todo-list li .toggle {
+		background: none;
+	}
+
+	#todo-list li .toggle {
+		height: 40px;
+	}
+
+	#toggle-all {
+		-webkit-transform: rotate(90deg);
+		transform: rotate(90deg);
+		-webkit-appearance: none;
+		appearance: none;
+    }
+
+    #footer {
+		height: 40px;
+	}
+}
+
+@media (max-width: 430px) {
+	#footer {
+		height: 40px;
+	}
+
+	#filters {
+		bottom: 10px;
+	}
+}
diff --git a/tests/dummy/app/templates/active.hbs b/tests/dummy/app/templates/active.hbs
new file mode 100644
index 0000000..de244f4
--- /dev/null
+++ b/tests/dummy/app/templates/active.hbs
@@ -0,0 +1 @@
+{{todo-list todos=todos}}
\ No newline at end of file
diff --git a/tests/dummy/app/templates/application.hbs b/tests/dummy/app/templates/application.hbs
index 2f57967..10ced9f 100644
--- a/tests/dummy/app/templates/application.hbs
+++ b/tests/dummy/app/templates/application.hbs
@@ -1,3 +1,32 @@
-<h2 id="title">A Guinea Pig in the Cloud</h2>
-
-{{outlet}}
\ No newline at end of file
+<section id="todoapp">
+  <header id="header">
+    <h1>todos</h1>
+    <input type="text" id="new-todo" onkeydown={{action 'createTodo'}} placeholder="What needs to be done?" autofocus>
+  </header>
+    {{outlet}}
+    {{#if (gt model.length 0)}}
+      <footer id="footer">
+        <span id="todo-count"><strong>{{remaining.length}}</strong> {{pluralize 'item' remaining.length}} left</span>
+        <ul id="filters">
+          <li>{{#link-to "index" activeClass="selected"}}All{{/link-to}}</li>
+          <li>{{#link-to "active" activeClass="selected"}}Active{{/link-to}}</li>
+          <li>{{#link-to "completed" activeClass="selected"}}Completed{{/link-to}}</li>
+        </ul>
+        {{#if completed.length}}
+          <button id="clear-completed" onclick={{action 'clearCompleted'}}>Clear completed</button>
+        {{/if}}
+      </footer>
+    {{/if}}
+</section>
+<footer id="info">
+  <p>Double-click to edit a todo</p>
+  <p>
+    Created by
+    <a href="http://github.com/cibernox">Miguel Camba</a>,
+    <a href="http://github.com/addyosmani">Addy Osmani</a>
+  </p>
+  <p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
+  <p>Modified for Ember Data by
+          <a href="https://gitlab.ippon.fr/bpinel">Bertrand Pinel</a>,
+  </p>
+</footer>
\ No newline at end of file
diff --git a/tests/dummy/app/templates/completed.hbs b/tests/dummy/app/templates/completed.hbs
new file mode 100644
index 0000000..de244f4
--- /dev/null
+++ b/tests/dummy/app/templates/completed.hbs
@@ -0,0 +1 @@
+{{todo-list todos=todos}}
\ No newline at end of file
diff --git a/tests/dummy/app/templates/components/todo-item.hbs b/tests/dummy/app/templates/components/todo-item.hbs
new file mode 100644
index 0000000..c06975e
--- /dev/null
+++ b/tests/dummy/app/templates/components/todo-item.hbs
@@ -0,0 +1,6 @@
+<div class="view">
+  <input type="checkbox" class="toggle" checked={{todo.completed}} onchange={{action 'toggleCompleted'}}>
+  <label ondblclick={{action 'startEditing'}}>{{todo.title}}</label>
+  <button onclick={{action 'removeTodo'}} class="destroy"></button>
+</div>
+<input type="text" class="edit" value={{todo.title}} onblur={{action 'doneEditing' value='target.value'}} onkeydown={{action 'handleKeydown'}} autofocus>
\ No newline at end of file
diff --git a/tests/dummy/app/templates/components/todo-list.hbs b/tests/dummy/app/templates/components/todo-list.hbs
new file mode 100644
index 0000000..309d07a
--- /dev/null
+++ b/tests/dummy/app/templates/components/todo-list.hbs
@@ -0,0 +1,10 @@
+{{#if todos.length}}
+  {{#if canToggle}}
+    <input type="checkbox" id="toggle-all" checked={{allCompleted}} onchange={{action 'toggleAll'}}>
+  {{/if}}
+  <ul id="todo-list" class="todo-list">
+    {{#each todos as |todo|}}
+      {{todo-item todo=todo onStartEdit=(action 'disableToggle') onEndEdit=(action 'enableToggle')}}
+    {{/each}}
+  </ul>
+{{/if}}
diff --git a/tests/dummy/app/templates/entity-factory.hbs b/tests/dummy/app/templates/entity-factory.hbs
new file mode 100644
index 0000000..4626840
--- /dev/null
+++ b/tests/dummy/app/templates/entity-factory.hbs
@@ -0,0 +1,9 @@
+<div class="container">
+    Available entities :
+    <select class="ember-select" onchange={{action "selectEntity" value="target.value"}}>
+        {{#each entities as |entityChoice|}}
+            <option value={{entityChoice}} selected={{eq entity entityChoice}}>{{entityChoice}}</option>
+        {{/each}}
+    </select>
+</div>
+{{outlet}}
\ No newline at end of file
diff --git a/tests/dummy/app/templates/entity-factory/authority.hbs b/tests/dummy/app/templates/entity-factory/authority.hbs
new file mode 100644
index 0000000..4335d21
--- /dev/null
+++ b/tests/dummy/app/templates/entity-factory/authority.hbs
@@ -0,0 +1,32 @@
+{{outlet}}
+<div class="container-fluid">
+
+<h3>List of authority entities</h3>
+
+{{#models-table data=authorityTableContent columns=authorityTableColumns delete="deleteRecord" as |mt|}}
+  {{mt.global-filter}}
+  {{mt.table}}
+  {{mt.footer}}
+{{/models-table}}
+
+{{#bs-button onClick=(action (mut addEntryModal) true)}}
+  Add new entry
+{{/bs-button}}
+
+{{#bs-modal open=addEntryModal onSubmit=(action "submit") onHidden=(action (mut addEntryModal) false) as |modal|}}
+  {{#modal.header}}
+    <h4 class="modal-title">
+      Add a new Entry
+    </h4>
+  {{/modal.header}}
+  {{#modal.body}}
+    {{#validated-form model = (changeset newEntry AuthorityValidations) on-submit = (perform submitEntry) as |f|}}
+			{{f.input label="name" name="name" }}
+			{{f.input type="select" label="users" name="users" multiple=true 
+options=users optionLabelPath="name" optionValuePath="id" 
+includeBlank= "Please choose..." promptIsSelectable=false}}
+		{{f.submit class="btn btn-primary" label="Save"}}
+	{{/validated-form}}
+  {{/modal.body}}
+{{/bs-modal}}
+</div>
\ No newline at end of file
diff --git a/tests/dummy/app/templates/entity-factory/todo.hbs b/tests/dummy/app/templates/entity-factory/todo.hbs
new file mode 100644
index 0000000..72f4d84
--- /dev/null
+++ b/tests/dummy/app/templates/entity-factory/todo.hbs
@@ -0,0 +1,33 @@
+{{outlet}}
+<div class="container-fluid">
+
+<h3>List of todo entities</h3>
+
+{{#models-table data=todoTableContent columns=todoTableColumns delete="deleteRecord" as |mt|}}
+  {{mt.global-filter}}
+  {{mt.table}}
+  {{mt.footer}}
+{{/models-table}}
+
+{{#bs-button onClick=(action (mut addEntryModal) true)}}
+  Add new entry
+{{/bs-button}}
+
+{{#bs-modal open=addEntryModal onSubmit=(action "submit") onHidden=(action (mut addEntryModal) false) as |modal|}}
+  {{#modal.header}}
+    <h4 class="modal-title">
+      Add a new Entry
+    </h4>
+  {{/modal.header}}
+  {{#modal.body}}
+    {{#validated-form model = (changeset newEntry TodoValidations) on-submit = (perform submitEntry) as |f|}}
+			{{f.input label="title" name="title" }}
+			{{f.input type="checkbox" label="completed" name="completed" }}
+			{{f.input type="select" label="user" name="user" multiple=true 
+options=users optionLabelPath="id" optionValuePath="id" 
+includeBlank= "Please choose..." promptIsSelectable=false}}
+		{{f.submit class="btn btn-primary" label="Save"}}
+	{{/validated-form}}
+  {{/modal.body}}
+{{/bs-modal}}
+</div>
\ No newline at end of file
diff --git a/tests/dummy/app/templates/entity-factory/user.hbs b/tests/dummy/app/templates/entity-factory/user.hbs
new file mode 100644
index 0000000..ce64e51
--- /dev/null
+++ b/tests/dummy/app/templates/entity-factory/user.hbs
@@ -0,0 +1,49 @@
+{{outlet}}
+<div class="container-fluid">
+
+<h3>List of user entities</h3>
+
+{{#models-table data=userTableContent columns=userTableColumns delete="deleteRecord" as |mt|}}
+  {{mt.global-filter}}
+  {{mt.table}}
+  {{mt.footer}}
+{{/models-table}}
+
+{{#bs-button onClick=(action (mut addEntryModal) true)}}
+  Add new entry
+{{/bs-button}}
+
+{{#bs-modal open=addEntryModal onSubmit=(action "submit") onHidden=(action (mut addEntryModal) false) as |modal|}}
+  {{#modal.header}}
+    <h4 class="modal-title">
+      Add a new Entry
+    </h4>
+  {{/modal.header}}
+  {{#modal.body}}
+    {{#validated-form model = (changeset newEntry UserValidations) on-submit = (perform submitEntry) as |f|}}
+			{{f.input label="login" name="login" }}
+			{{f.input label="passwordHash" name="passwordHash" }}
+			{{f.input label="firstName" name="firstName" }}
+			{{f.input label="lastName" name="lastName" }}
+			{{f.input label="email" name="email" }}
+			{{f.input label="imageUrl" name="imageUrl" }}
+			{{f.input type="checkbox" label="activated" name="activated" }}
+			{{f.input label="createdBy" name="createdBy" }}
+			{{#f.input label="createdDate" name="createdDate" as |fi|}}
+				{{pikaday-input useUTC=true format="DD/MM/YYYY" onSelection=fi.update}}
+			{{/f.input}}
+			{{f.input label="lastModifiedBy" name="lastModifiedBy" }}
+			{{#f.input label="lastModifiedDate" name="lastModifiedDate" as |fi|}}
+				{{pikaday-input useUTC=true format="DD/MM/YYYY" onSelection=fi.update}}
+			{{/f.input}}
+			{{f.input type="select" label="authorities" name="authorities" multiple=true 
+options=authorities optionLabelPath="name" optionValuePath="id" 
+includeBlank= "Please choose..." promptIsSelectable=false}}
+			{{f.input type="select" label="todos" name="todos" multiple=true 
+options=todos optionLabelPath="id" optionValuePath="id" 
+includeBlank= "Please choose..." promptIsSelectable=false}}
+		{{f.submit class="btn btn-primary" label="Save"}}
+	{{/validated-form}}
+  {{/modal.body}}
+{{/bs-modal}}
+</div>
\ No newline at end of file
diff --git a/tests/dummy/app/templates/index.hbs b/tests/dummy/app/templates/index.hbs
new file mode 100644
index 0000000..9694e18
--- /dev/null
+++ b/tests/dummy/app/templates/index.hbs
@@ -0,0 +1,3 @@
+{{#if model.length}}
+  {{todo-list todos=model}}
+{{/if}}
\ No newline at end of file
diff --git a/tests/dummy/app/validations/authority.js b/tests/dummy/app/validations/authority.js
new file mode 100644
index 0000000..4e89422
--- /dev/null
+++ b/tests/dummy/app/validations/authority.js
@@ -0,0 +1,5 @@
+import {validatePresence, validateLength, validateFormat} from 'ember-changeset-validations/validators';
+
+export default {
+	name: [validatePresence(true)],
+}
diff --git a/tests/dummy/app/validations/todo.js b/tests/dummy/app/validations/todo.js
new file mode 100644
index 0000000..c3a5a9b
--- /dev/null
+++ b/tests/dummy/app/validations/todo.js
@@ -0,0 +1,5 @@
+import {validatePresence, validateLength, validateFormat} from 'ember-changeset-validations/validators';
+
+export default {
+	title: [validatePresence(true)],
+}
diff --git a/tests/dummy/app/validations/user.js b/tests/dummy/app/validations/user.js
new file mode 100644
index 0000000..0a3e27b
--- /dev/null
+++ b/tests/dummy/app/validations/user.js
@@ -0,0 +1,6 @@
+import {validatePresence, validateLength, validateFormat} from 'ember-changeset-validations/validators';
+
+export default {
+	login: [validatePresence(true),validateLength({min: 4})],
+	passwordHash: [validatePresence(true),validateLength({min: 8})],
+}
diff --git a/tests/dummy/config/environment.js b/tests/dummy/config/environment.js
index 182d3fc..e4e58f7 100644
--- a/tests/dummy/config/environment.js
+++ b/tests/dummy/config/environment.js
@@ -1,10 +1,57 @@
 'use strict';
 
+function usingProxy() {
+	var usingProxyArg = !!process.argv.filter(function (arg) {
+		return arg.indexOf('--proxy') === 0 || arg.indexOf('-pr') === 0 || arg.indexOf('-pxy') === 0;
+	}).length;
+
+	var hasGeneratedProxies = false;
+	var proxiesDir = process.env.PWD + '/server/proxies';
+	try {
+		fs.lstatSync(proxiesDir);
+		hasGeneratedProxies = true;
+  } catch (e) {}
+  
+	return usingProxyArg || hasGeneratedProxies;
+}
+
+function findGatewayURL() {
+  let gatewayURL='http://localhost';
+  for (var i=0;i<process.argv.length;i++) {
+    if (process.argv[i].indexOf('--proxy') === 0 || process.argv[i].indexOf('-pr') === 0 || process.argv[i].indexOf('-pxy') === 0) {
+      gatewayURL = process.argv[i+1];
+      break;
+    }
+  }
+  return gatewayURL;
+}
+
 module.exports = function(environment) {
   let ENV = {
+		"ember-validated-form": {
+			label: {
+				submit: "label.save"
+			},
+			css: {
+				group: "form-group",
+				radio: "radio",
+				control: "form-control",
+				label: "col-form-label",
+				help: "small form-text text-danger",
+				hint: "small form-text text-muted",
+				checkbox: "checkbox",
+				button: "btn btn-default",
+				submit: "btn btn-primary",
+				loading: "loading",
+				valid: "is-valid",
+				error: "is-invalid"
+			}
+		},
+
     modulePrefix: 'dummy',
     environment,
     rootURL: '/',
+    gatewayURL: findGatewayURL(),
     locationType: 'auto',
     EmberENV: {
       FEATURES: {
@@ -20,6 +67,7 @@ module.exports = function(environment) {
     APP: {
       // Here you can pass flags/options to your application instance
       // when it is created
+		proxy: usingProxy(),
     }
   };
 
@@ -44,6 +92,7 @@ module.exports = function(environment) {
   }
 
   if (environment === 'production') {
+    ENV.gatewayURL = 'https://dcftkivcqe.execute-api.us-east-1.amazonaws.com/staging';
     // here you can enable a production-specific feature
   }
 
diff --git a/tests/dummy/mirage/config.js b/tests/dummy/mirage/config.js
index 16cf48b..a93c7e0 100644
--- a/tests/dummy/mirage/config.js
+++ b/tests/dummy/mirage/config.js
@@ -1,3 +1,23 @@
+import ENV from './../config/environment';
 export default function() {
 	this.namespace = '';
+	if (!ENV.APP.proxy) {
+		this.get('/todos');
+		this.get('/todos/:id');
+		this.delete('/todos/:id');
+		this.patch('/todos/:id');
+		this.post('/todos');
+		this.get('/authorities');
+		this.get('/authorities/:id');
+		this.delete('/authorities/:id');
+		this.patch('/authorities/:id');
+		this.post('/authorities');
+		this.get('/users');
+		this.get('/users/:id');
+		this.delete('/users/:id');
+		this.patch('/users/:id');
+		this.post('/users');
+	} else {
+		this.passthrough();
+	}
 }
diff --git a/tests/dummy/mirage/factories/authority.js b/tests/dummy/mirage/factories/authority.js
new file mode 100644
index 0000000..e55d366
--- /dev/null
+++ b/tests/dummy/mirage/factories/authority.js
@@ -0,0 +1,11 @@
+import {
+	Factory,
+	faker
+	} from 'ember-cli-mirage';
+
+export default Factory.extend({
+	name() {
+		return faker.lorem.word();
+	}
+});
+  
\ No newline at end of file
diff --git a/tests/dummy/mirage/factories/todo.js b/tests/dummy/mirage/factories/todo.js
new file mode 100644
index 0000000..073f89b
--- /dev/null
+++ b/tests/dummy/mirage/factories/todo.js
@@ -0,0 +1,14 @@
+import {
+	Factory,
+	faker
+	} from 'ember-cli-mirage';
+
+export default Factory.extend({
+	title() {
+		return faker.lorem.word();
+	},
+	completed() {
+		return faker.random.boolean();
+	}
+});
+  
\ No newline at end of file
diff --git a/tests/dummy/mirage/factories/user.js b/tests/dummy/mirage/factories/user.js
new file mode 100644
index 0000000..d7d4cb1
--- /dev/null
+++ b/tests/dummy/mirage/factories/user.js
@@ -0,0 +1,41 @@
+import {
+	Factory,
+	faker
+	} from 'ember-cli-mirage';
+
+export default Factory.extend({
+	login() {
+		return faker.lorem.word();
+	},
+	passwordHash() {
+		return faker.lorem.word();
+	},
+	firstName() {
+		return faker.name.firstName();
+	},
+	lastName() {
+		return faker.name.lastName();
+	},
+	email() {
+		return faker.internet.email();
+	},
+	imageUrl() {
+		return faker.lorem.word();
+	},
+	activated() {
+		return faker.random.boolean();
+	},
+	createdBy() {
+		return faker.lorem.word();
+	},
+	createdDate() {
+		return faker.date.past();
+	},
+	lastModifiedBy() {
+		return faker.lorem.word();
+	},
+	lastModifiedDate() {
+		return faker.date.past();
+	}
+});
+  
\ No newline at end of file
diff --git a/tests/dummy/mirage/models/authority.js b/tests/dummy/mirage/models/authority.js
new file mode 100644
index 0000000..9c231ea
--- /dev/null
+++ b/tests/dummy/mirage/models/authority.js
@@ -0,0 +1,5 @@
+import { Model, belongsTo, hasMany} from 'ember-cli-mirage';
+
+export default Model.extend({
+	users: hasMany()
+});
\ No newline at end of file
diff --git a/tests/dummy/mirage/models/todo.js b/tests/dummy/mirage/models/todo.js
new file mode 100644
index 0000000..9629371
--- /dev/null
+++ b/tests/dummy/mirage/models/todo.js
@@ -0,0 +1,5 @@
+import { Model, belongsTo, hasMany} from 'ember-cli-mirage';
+
+export default Model.extend({
+	user: hasMany()
+});
\ No newline at end of file
diff --git a/tests/dummy/mirage/models/user.js b/tests/dummy/mirage/models/user.js
new file mode 100644
index 0000000..9700520
--- /dev/null
+++ b/tests/dummy/mirage/models/user.js
@@ -0,0 +1,6 @@
+import { Model, belongsTo, hasMany} from 'ember-cli-mirage';
+
+export default Model.extend({
+	authorities: hasMany(),
+	todos: hasMany()
+});
\ No newline at end of file
diff --git a/tests/dummy/mirage/scenarios/default.js b/tests/dummy/mirage/scenarios/default.js
index c0ed642..149fe92 100644
--- a/tests/dummy/mirage/scenarios/default.js
+++ b/tests/dummy/mirage/scenarios/default.js
@@ -1,3 +1,9 @@
 export default function(server) {
+	server.createList('todo', 6);
+
+	server.createList('authority', 6);
+
+	server.createList('user', 6);
+
 
 }
diff --git a/tests/dummy/mirage/scenarios/tobedeleted.txt b/tests/dummy/mirage/scenarios/tobedeleted.txt
new file mode 100644
index 0000000..f203f96
--- /dev/null
+++ b/tests/dummy/mirage/scenarios/tobedeleted.txt
@@ -0,0 +1 @@
+To be sure that the directory exists...
\ No newline at end of file
diff --git a/tests/dummy/mirage/serializers/tobedeleted.txt b/tests/dummy/mirage/serializers/tobedeleted.txt
new file mode 100644
index 0000000..f203f96
--- /dev/null
+++ b/tests/dummy/mirage/serializers/tobedeleted.txt
@@ -0,0 +1 @@
+To be sure that the directory exists...
\ No newline at end of file
diff --git a/tests/unit/adapters/application-test.js b/tests/unit/adapters/application-test.js
deleted file mode 100644
index eff23bb..0000000
--- a/tests/unit/adapters/application-test.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import { module, test } from 'qunit';
-import { setupTest } from 'ember-qunit';
-
-module('Unit | Adapter | application', function(hooks) {
-  setupTest(hooks);
-
-  // Replace this with your real tests.
-  test('it exists', function(assert) {
-    let adapter = this.owner.lookup('adapter:application');
-    assert.ok(adapter);
-  });
-});
-- 
GitLab