From 60e4ca132a66b04807bd098887f0cb1f24ddeb4a Mon Sep 17 00:00:00 2001 From: Carlos Jimenez <=> Date: Wed, 7 Mar 2018 12:24:47 +0100 Subject: [PATCH 01/10] #155 web access functionality completed --- client/client/src/web-access/web-access.html | 4 +- client/client/src/web-access/web-access.js | 11 ++++ .../common/methods/client/isValidClient.js | 50 +++++++++++++++++++ services/loopback/common/models/client.js | 1 + 4 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 services/loopback/common/methods/client/isValidClient.js diff --git a/client/client/src/web-access/web-access.html b/client/client/src/web-access/web-access.html index aaeffa5ba..cd615720c 100644 --- a/client/client/src/web-access/web-access.html +++ b/client/client/src/web-access/web-access.html @@ -12,7 +12,9 @@ + field="$ctrl.account.active" + vn-acl="employee" + acl-conditional-to-employee="{{$ctrl.canEnableCheckBox}}"> diff --git a/client/client/src/web-access/web-access.js b/client/client/src/web-access/web-access.js index 41aefc0bf..00595bff4 100644 --- a/client/client/src/web-access/web-access.js +++ b/client/client/src/web-access/web-access.js @@ -6,11 +6,14 @@ export default class Controller { this.$http = $http; this.vnApp = vnApp; this.canChangePassword = false; + this.canEnableCheckBox = true; } + $onChanges() { if (this.client) { this.account = this.client.account; this.isCustomer(); + this.checkConditions(); } } @@ -24,6 +27,14 @@ export default class Controller { } } + checkConditions() { + if (this.client && this.client.id) { + this.$http.get(`/client/api/Clients/${this.client.id}/isValidClient`).then(res => { + this.canEnableCheckBox = res.data; + }); + } + } + onPassOpen() { this.newPassword = ''; this.repeatPassword = ''; diff --git a/services/loopback/common/methods/client/isValidClient.js b/services/loopback/common/methods/client/isValidClient.js new file mode 100644 index 000000000..583efa299 --- /dev/null +++ b/services/loopback/common/methods/client/isValidClient.js @@ -0,0 +1,50 @@ +module.exports = Self => { + Self.remoteMethod('isValidClient', { + description: 'Checks if the user havent got the role employee, is active and has verified data', + accessType: 'READ', + accepts: [ + { + arg: 'id', + type: 'string', + required: true, + description: 'The user id', + http: {source: 'path'} + }, { + arg: 'context', + type: 'object', + required: true, + description: 'Filter defining where', + http: function(context) { + return context.req.query; + } + } + ], + returns: { + type: 'boolean', + root: true + }, + http: { + path: `/:id/isValidClient`, + verb: 'GET' + } + }); + + Self.isValidClient = async function(id) { + let query = + `SELECT r.name + FROM salix.Account A + JOIN vn.client C ON A.id = C.id + JOIN salix.RoleMapping rm ON rm.principalId = A.id + JOIN salix.Role r ON r.id = rm.roleId + WHERE A.id = ? AND C.isActive AND C.isTaxDataChecked`; + + let roleNames = await Self.rawSql(query, [id]); + if (!roleNames.length) return false; + + roleNames.forEach(role => { + if (role.name === 'employee') + return false; + }); + return true; + }; +}; diff --git a/services/loopback/common/models/client.js b/services/loopback/common/models/client.js index 7a26ce6ff..e5202c5bf 100644 --- a/services/loopback/common/models/client.js +++ b/services/loopback/common/models/client.js @@ -12,6 +12,7 @@ module.exports = function(Self) { require('../methods/client/listWorkers')(Self); require('../methods/client/filter')(Self); require('../methods/client/hasCustomerRole')(Self); + require('../methods/client/isValidClient')(Self); require('../methods/client/activeSalesPerson')(Self); require('../methods/client/addressesPropagateRe')(Self); From a95f2c3adaf70da343d6aee6560541ea739d6e9a Mon Sep 17 00:00:00 2001 From: Carlos Jimenez <=> Date: Wed, 7 Mar 2018 12:25:23 +0100 Subject: [PATCH 02/10] #155 back end unit tests for webaccess new functionality --- .../client/specs/isValidClient.spec.js | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 services/loopback/common/methods/client/specs/isValidClient.spec.js diff --git a/services/loopback/common/methods/client/specs/isValidClient.spec.js b/services/loopback/common/methods/client/specs/isValidClient.spec.js new file mode 100644 index 000000000..35c9264d7 --- /dev/null +++ b/services/loopback/common/methods/client/specs/isValidClient.spec.js @@ -0,0 +1,57 @@ +const app = require('../../../../../client/server/server'); + +describe('Client isValidClient', () => { + it('should call the isValidClient() method with a client id and receive true', done => { + let id = 101; + app.models.Client.isValidClient(id) + .then(result => { + expect(result).toBeTruthy(); + done(); + }); + }); + + it('should call the isValidClient() method with a employee id and receive false', done => { + let id = 1; + app.models.Client.isValidClient(id) + .then(result => { + expect(result).toBeFalsy(); + done(); + }); + }); + + it('should call the isValidClient() method with a unexistant id and receive false', done => { + let id = 999999; + app.models.Client.isValidClient(id) + .then(result => { + expect(result).toBeFalsy(); + done(); + }); + }); + + it('should call the isValidClient() method with a invalid id and receive false', done => { + let id = 'Pepinillos'; + app.models.Client.isValidClient(id) + .then(result => { + expect(result).toBeFalsy(); + done(); + }); + }); + + it('should call the isValidClient() method with a customer id which isnt active and return false', done => { + let id = '106'; + app.models.Client.isValidClient(id) + .then(result => { + expect(result).toBeFalsy(); + done(); + }); + }); + + it('should call the isValidClient() method with a customer id which his data isnt verified and return false', done => { + let id = '110'; + app.models.Client.isValidClient(id) + .then(result => { + expect(result).toBeFalsy(); + done(); + }); + }); +}); From 6eaaa6dde52897214efeff43f32e3d1d9fe7f165 Mon Sep 17 00:00:00 2001 From: Carlos Jimenez <=> Date: Wed, 7 Mar 2018 15:05:09 +0100 Subject: [PATCH 03/10] #148 client web-access task --- client/client/src/web-access/web-access.html | 6 ++--- client/client/src/web-access/web-access.js | 10 ++++---- client/core/src/components/dialog/dialog.js | 14 ++++++----- client/core/src/components/dialog/style.scss | 10 ++++++-- .../core/src/components/snackbar/snackbar.js | 23 ++++++++++--------- 5 files changed, 35 insertions(+), 28 deletions(-) diff --git a/client/client/src/web-access/web-access.html b/client/client/src/web-access/web-access.html index cd615720c..47e05759a 100644 --- a/client/client/src/web-access/web-access.html +++ b/client/client/src/web-access/web-access.html @@ -19,11 +19,11 @@ + field="$ctrl.account.name"> @@ -49,7 +49,7 @@ - + diff --git a/client/client/src/web-access/web-access.js b/client/client/src/web-access/web-access.js index 00595bff4..5545b96f8 100644 --- a/client/client/src/web-access/web-access.js +++ b/client/client/src/web-access/web-access.js @@ -18,17 +18,15 @@ export default class Controller { } isCustomer() { - if (this.client && this.client.id) { + if (this.client.id) { this.$http.get(`/client/api/Clients/${this.client.id}/hasCustomerRole`).then(res => { - this.canChangePassword = (res.data) ? res.data.isCustomer : false; + this.canChangePassword = res.data && res.data.isCustomer; }); - } else { - this.canChangePassword = false; } } checkConditions() { - if (this.client && this.client.id) { + if (this.client.id) { this.$http.get(`/client/api/Clients/${this.client.id}/isValidClient`).then(res => { this.canEnableCheckBox = res.data; }); @@ -42,7 +40,7 @@ export default class Controller { } onPassChange(response) { - if (response == 'ACCEPT' && this.canChangePassword) + if (response == 'ACCEPT') try { if (!this.newPassword) throw new Error(`Passwords can't be empty`); diff --git a/client/core/src/components/dialog/dialog.js b/client/core/src/components/dialog/dialog.js index 602acfe45..401a13e11 100644 --- a/client/core/src/components/dialog/dialog.js +++ b/client/core/src/components/dialog/dialog.js @@ -37,14 +37,16 @@ export default class Dialog extends Component { show() { if (this.shown) return; this.shown = true; - this.keypressHandler = e => this.onKeypress(e); - this.document.addEventListener('keypress', this.keypressHandler); + this.keyDownHandler = e => this.onkeyDown(e); + this.document.addEventListener('keydown', this.keyDownHandler); this.element.style.display = 'flex'; - this.transitionTimeout = - setTimeout(() => this.$element.addClass('shown'), 30); + this.transitionTimeout = setTimeout(() => this.$element.addClass('shown'), 30); if (this.onOpen) this.onOpen(); + + let firstFocusable = this.element.querySelector('input, textarea'); + if (firstFocusable) firstFocusable.focus(); } /** * Hides the dialog calling the response handler. @@ -68,7 +70,7 @@ export default class Dialog extends Component { realHide() { if (!this.shown) return; this.element.style.display = 'none'; - this.document.removeEventListener('keypress', this.keypressHandler); + this.document.removeEventListener('keydown', this.keyDownHandler); this.lastEvent = null; this.shown = false; this.transitionTimeout = @@ -94,7 +96,7 @@ export default class Dialog extends Component { if (event != this.lastEvent) this.hide(); } - onKeypress(event) { + onkeyDown(event) { if (event.keyCode == 27) // Esc this.hide(); } diff --git a/client/core/src/components/dialog/style.scss b/client/core/src/components/dialog/style.scss index 12477a037..de13f0f7c 100644 --- a/client/core/src/components/dialog/style.scss +++ b/client/core/src/components/dialog/style.scss @@ -28,7 +28,10 @@ display: block; width: 20em; } - button { + button, + input[type="button"], + input[type="submit"], + input[type="reset"] { text-transform: uppercase; background-color: transparent; border: none; @@ -55,7 +58,10 @@ margin-top: 1.5em; text-align: right; - button { + button, + input[type="button"], + input[type="submit"], + input[type="reset"] { color: #ffa410; font-family: vn-font-bold; padding: .7em; diff --git a/client/core/src/components/snackbar/snackbar.js b/client/core/src/components/snackbar/snackbar.js index 18a4b516f..387442f83 100644 --- a/client/core/src/components/snackbar/snackbar.js +++ b/client/core/src/components/snackbar/snackbar.js @@ -15,6 +15,7 @@ export default class Controller extends Component { this.button = $element[0].querySelector('button'); this.textNode = this.snackbar.querySelector('.text'); } + /** * Shows a notification. * @@ -29,14 +30,13 @@ export default class Controller extends Component { this.button.textContent = data.actionText || this.$translate.instant('Hide'); - this.documentClickHandler = e => this.onDocumentClick(e); - document.addEventListener('click', this.documentClickHandler); - this.timeoutId = setTimeout(() => this.hide(), - data.timeout || 6000); + this.timeoutId = setTimeout(() => + this.hide(), data.timeout || 6000); - this.transitionTimeout = - setTimeout(() => this.$snackbar.addClass('shown'), 30); + this.transitionTimeout = setTimeout(() => + this.$snackbar.addClass('shown'), 30); } + /** * Shows an error. * @@ -46,38 +46,38 @@ export default class Controller extends Component { this.$snackbar.addClass('error'); this.show(data); } + /** * Hides the snackbar. */ hide() { if (!this.shown) return; clearTimeout(this.timeoutId); - document.removeEventListener('click', this.documentClickHandler); this.shown = false; this.hideTimeout = setTimeout(() => this.onTransitionEnd(), 250); this.transitionTimeout = setTimeout(() => this.$snackbar.removeClass('shown'), 30); } + onTransitionEnd() { this.$snackbar.removeClass('error'); this.textNode.textContent = ''; this.button.textContent = ''; this.actionHandler = null; } - onDocumentClick(event) { - if (event === this.event) return; - this.hide(); - } + onSnackbarClick(event) { this.event = event; } + onButtonClick() { if (this.actionHandler) this.actionHandler(); else this.hide(); } + clearTimeouts() { clearTimeout(this.timeoutId); clearTimeout(this.hideTimeout); @@ -86,6 +86,7 @@ export default class Controller extends Component { this.hideTimeout = null; this.transitionTimeout = null; } + $onDestroy() { this.clearTimeouts(); } From 94bbbef2d08c913347123cb0a718f6391d0338dc Mon Sep 17 00:00:00 2001 From: Daniel Herrero Date: Thu, 8 Mar 2018 08:14:49 +0100 Subject: [PATCH 04/10] Bug fixed address observations --- client/client/src/address-edit/address-edit.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/client/src/address-edit/address-edit.js b/client/client/src/address-edit/address-edit.js index 4d73dc215..a715dc8a4 100644 --- a/client/client/src/address-edit/address-edit.js +++ b/client/client/src/address-edit/address-edit.js @@ -41,6 +41,9 @@ export default class Controller { this._setDirtyForm(); } } + if (this.observations.length === 0 && Object.keys(this.observationsOld).length === 0) { + this._unsetDirtyForm(); + } } _submitObservations(objectObservations) { return this.$http.post(`/client/api/AddressObservations/crudAddressObservations`, objectObservations); From 80b22a4e7dd1160e9c9cc71df01dcb13715cc629 Mon Sep 17 00:00:00 2001 From: Daniel Herrero Date: Thu, 8 Mar 2018 09:47:56 +0100 Subject: [PATCH 05/10] Bug #157 Sumario de item mostrar iva --- client/item/src/summary/item-summary.html | 12 +++++++++--- client/item/src/summary/item-summary.js | 20 ++++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/client/item/src/summary/item-summary.html b/client/item/src/summary/item-summary.html index 71c5c720b..7ad31fd9d 100644 --- a/client/item/src/summary/item-summary.html +++ b/client/item/src/summary/item-summary.html @@ -32,14 +32,20 @@ -
Tags
-

- {{tag.tag.name}}: {{tag.value}} +

Tax
+

+ {{tax.country.country}}: {{tax.taxClass.description}}

+ +
Tags
+

+ {{tag.tag.name}}: {{tag.value}} +

+
Nicho
diff --git a/client/item/src/summary/item-summary.js b/client/item/src/summary/item-summary.js index 054a5d0f3..401d70f0a 100644 --- a/client/item/src/summary/item-summary.js +++ b/client/item/src/summary/item-summary.js @@ -17,6 +17,25 @@ class ItemSummary { }); } + _getTaxes() { + let filter = { + fields: ['id', 'countryFk', 'taxClassFk'], + include: [{ + relation: 'country', + scope: {fields: ['country']} + }, { + relation: 'taxClass', + scope: {fields: ['id', 'description']} + }] + }; + + let urlFilter = encodeURIComponent(JSON.stringify(filter)); + let url = `/item/api/Items/${this.item.id}/taxes?filter=${urlFilter}`; + this.$http.get(url).then(json => { + this.taxes = json.data; + }); + } + _getBotanical() { let filter = { where: {itemFk: this.item.id}, @@ -58,6 +77,7 @@ class ItemSummary { this._getTags(); this._getBarcodes(); this._getNiches(); + this._getTaxes(); if (!this.item.botanical) this._getBotanical(); } From 8ef0814fccee350813270e6479d76c465d164c4e Mon Sep 17 00:00:00 2001 From: Carlos Jimenez <=> Date: Thu, 8 Mar 2018 12:23:51 +0100 Subject: [PATCH 06/10] back end unit test fixes plus small refactors --- .../client-module/05_add_address.spec.js | 2 +- .../auth/server/boot/specs/routes.spec.js | 44 +++++++------- services/db/04-fixtures.sql | 39 +++++++------ services/db/testing_fixtures.js | 29 +++++----- .../client/specs/addressesPropagateRe.spec.js | 55 +++--------------- .../common/methods/client/specs/card.spec.js | 4 +- .../client/specs/createWithUser.spec.js | 58 +++---------------- .../client/specs/hasCustomerRole.spec.js | 2 +- .../methods/client/specs/listWorkers.spec.js | 2 +- 9 files changed, 76 insertions(+), 159 deletions(-) diff --git a/e2e/paths/client-module/05_add_address.spec.js b/e2e/paths/client-module/05_add_address.spec.js index 97117bf8c..e765aea72 100644 --- a/e2e/paths/client-module/05_add_address.spec.js +++ b/e2e/paths/client-module/05_add_address.spec.js @@ -122,7 +122,7 @@ describe('Add address path', () => { .waitToClick(selectors.clientAddresses.saveButton) .waitForSnackbar() .then(result => { - expect(result).toContain('Some fields are invalid'); + expect(result).toContain('Error:'); }); }); }); diff --git a/services/auth/server/boot/specs/routes.spec.js b/services/auth/server/boot/specs/routes.spec.js index 6f5deb1d3..20b41b489 100644 --- a/services/auth/server/boot/specs/routes.spec.js +++ b/services/auth/server/boot/specs/routes.spec.js @@ -3,18 +3,16 @@ const routes = require('../routes'); const restoreFixtures = require('../../../../../services/db/testing_fixtures'); describe('Auth routes', () => { - let fixturesToApply = {tables: ['`salix`.`user`'], inserts: [ - `INSERT INTO salix.user(id,username,password,email) - VALUES - (10, 'JessicaJones', 'ac754a330530832ba1bf7687f577da91', 'JessicaJones@verdnatura.es');` - ]}; + let sqlStatements = {deletes: ` + DELETE FROM salix.user WHERE id = 102; + `, inserts: ``, updates: ``}; - beforeEach(done => { - restoreFixtures(fixturesToApply, done); + beforeEach(() => { + restoreFixtures(sqlStatements); }); - afterAll(done => { - restoreFixtures(fixturesToApply, done); + afterAll(() => { + restoreFixtures(sqlStatements); }); let User = app.models.User; @@ -33,6 +31,20 @@ describe('Auth routes', () => { req = {body: {}}; }); + describe('when the user doesnt exist but the client does and the password is correct', () => { + it('should create the user login and return the token', done => { + spyOn(User, 'upsertWithWhere').and.callThrough(); + req.body.user = 'PetterParker'; + req.body.password = 'nightmare'; + res.json = response => { + expect(User.upsertWithWhere).toHaveBeenCalledWith(jasmine.any(Object), jasmine.any(Object), jasmine.any(Function)); + expect(response.token).toBeDefined(); + done(); + }; + loginFunction(req, res); + }); + }); + describe('when the user exists and the password is correct', () => { it('should login and return the token', done => { req.body.user = 'developer'; @@ -44,20 +56,6 @@ describe('Auth routes', () => { loginFunction(req, res); }); - describe('when the user doesnt exist but the client does and the password is correct', () => { - it('should create the user login and return the token', done => { - spyOn(User, 'upsertWithWhere').and.callThrough(); - req.body.user = 'PetterParker'; - req.body.password = 'nightmare'; - res.json = response => { - expect(User.upsertWithWhere).toHaveBeenCalledWith(jasmine.any(Object), jasmine.any(Object), jasmine.any(Function)); - expect(response.token).toBeDefined(); - done(); - }; - loginFunction(req, res); - }); - }); - it('should define the url to continue upon login', done => { req.body.user = 'developer'; req.body.password = 'nightmare'; diff --git a/services/db/04-fixtures.sql b/services/db/04-fixtures.sql index c63c9f616..bcb82cef5 100644 --- a/services/db/04-fixtures.sql +++ b/services/db/04-fixtures.sql @@ -152,25 +152,26 @@ INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `pr (107, '07', 'Somewhere in Valencia', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), (108, '08', 'Somewhere in Silla', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), (109, '09', 'Somewhere in London', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), - (110, '10', 'Somewhere in Algemesi', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), - (111, '11', 'Somewhere in Carlet', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), - (112, '12', 'Somewhere in Campanar', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), - (113, '13', 'Somewhere in Malilla', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), - (114, '14', 'Somewhere in France', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), - (115, '15', 'Somewhere in Birmingham', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), - (116, '16', 'Somewhere in Scotland', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), - (117, '17', 'Somewhere in nowhere', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), - (118, '18', 'Somewhere over the rainbow', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), - (119, '19', 'Somewhere in Alberic', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), - (120, '20', 'Somewhere in Montortal', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), - (121, 'my other address', 'NY roofs', 'Silla', 46460, 1, NULL, NULL, 1, 0, 102, 2, NULL, NULL, 0), - (122, 'my other address', 'The phone box', 'Silla', 46460, 1, NULL, NULL, 1, 0, 103, 2, NULL, NULL, 0), - (123, 'my other address', 'Stark tower', 'Silla', 46460, 1, NULL, NULL, 1, 0, 104, 2, NULL, NULL, 0), - (124, 'my other address', 'The plastic cell', 'Silla', 46460, 1, NULL, NULL, 1, 0, 105, 2, NULL, NULL, 0), - (125, 'my other address', 'Many places', 'Silla', 46460, 1, NULL, NULL, 1, 0, 106, 2, NULL, NULL, 0), - (126, 'my other address', 'Your pocket', 'Silla', 46460, 1, NULL, NULL, 1, 0, 107, 2, NULL, NULL, 0), - (127, 'my other address', 'Cerebro', 'Silla', 46460, 1, NULL, NULL, 1, 0, 108, 2, NULL, NULL, 0), - (128, 'my other address', 'Luke Cages Bar', 'Silla', 46460, 1, NULL, NULL, 1, 0, 110, 2, NULL, NULL, 0); + (110, '10', 'Somewhere in Algemesi', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), + (111, '11', 'Somewhere in Carlet', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), + (112, '12', 'Somewhere in Campanar', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), + (113, '13', 'Somewhere in Malilla', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), + (114, '14', 'Somewhere in France', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), + (115, '15', 'Somewhere in Birmingham', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), + (116, '16', 'Somewhere in Scotland', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), + (117, '17', 'Somewhere in nowhere', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), + (118, '18', 'Somewhere over the rainbow', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), + (119, '19', 'Somewhere in Alberic', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), + (120, '20', 'Somewhere in Montortal', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), + (121, 'my other address', 'the bat cave', 'Silla', 46460, 1, NULL, NULL, 1, 0, 101, 2, NULL, NULL, 0), + (122, 'my other address', 'NY roofs', 'Silla', 46460, 1, NULL, NULL, 1, 0, 102, 2, NULL, NULL, 0), + (123, 'my other address', 'The phone box', 'Silla', 46460, 1, NULL, NULL, 1, 0, 103, 2, NULL, NULL, 0), + (124, 'my other address', 'Stark tower', 'Silla', 46460, 1, NULL, NULL, 1, 0, 104, 2, NULL, NULL, 0), + (125, 'my other address', 'The plastic cell', 'Silla', 46460, 1, NULL, NULL, 1, 0, 105, 2, NULL, NULL, 0), + (126, 'my other address', 'Many places', 'Silla', 46460, 1, NULL, NULL, 1, 0, 106, 2, NULL, NULL, 0), + (127, 'my other address', 'Your pocket', 'Silla', 46460, 1, NULL, NULL, 1, 0, 107, 2, NULL, NULL, 0), + (128, 'my other address', 'Cerebro', 'Silla', 46460, 1, NULL, NULL, 1, 0, 108, 2, NULL, NULL, 0), + (129, 'my other address', 'Luke Cages Bar', 'Silla', 46460, 1, NULL, NULL, 1, 0, 110, 2, NULL, NULL, 0); INSERT INTO `vn`.`clientCredit`(`id`, `clientFk`, `workerFk`, `amount`, `created`) VALUES diff --git a/services/db/testing_fixtures.js b/services/db/testing_fixtures.js index 7563e0103..ca525ccb1 100644 --- a/services/db/testing_fixtures.js +++ b/services/db/testing_fixtures.js @@ -16,26 +16,23 @@ let errorHandler = callback => { }; }; -let insertFixtures = (inserts, callback) => { - connection.query(inserts[0], errorHandler(callback)); - // connection.query('SET FOREIGN_KEY_CHECKS = 1'); -}; - -let truncate = (tables, callback) => { - let truncatesSQL = tables.reduce((accumulator, currentValue, i) => { - let sql = 'TRUNCATE TABLE ' + currentValue + '; '; - return (`${accumulator}${sql}`); - }, ''); - - connection.query(truncatesSQL.slice(0, -2), errorHandler(callback)); +let insertFixtures = async function(sqlStatements) { + try { + if (sqlStatements.deletes.length) + await connection.query(sqlStatements.deletes); + if (sqlStatements.inserts.length) + await connection.query(sqlStatements.inserts); + if (sqlStatements.updates.length) + await connection.query(sqlStatements.updates); + } catch (error) { + errorHandler(error); + } }; connection.connect(); -module.exports = function restoreFixtures(fixturesToApply, callback) { +module.exports = function restoreFixtures(sqlStatements) { connection.query('SET FOREIGN_KEY_CHECKS = 0', () => { - truncate(fixturesToApply.tables, () => { - insertFixtures(fixturesToApply.inserts, callback); - }); + insertFixtures(sqlStatements); }); }; diff --git a/services/loopback/common/methods/client/specs/addressesPropagateRe.spec.js b/services/loopback/common/methods/client/specs/addressesPropagateRe.spec.js index 5034e3f57..47cef837e 100644 --- a/services/loopback/common/methods/client/specs/addressesPropagateRe.spec.js +++ b/services/loopback/common/methods/client/specs/addressesPropagateRe.spec.js @@ -3,58 +3,19 @@ const catchErrors = require('../../../../../../services/utils/jasmineHelpers').c const restoreFixtures = require('../../../../../../services/db/testing_fixtures'); describe('Client addressesPropagateRe', () => { - let fixturesToApply = {tables: ['`account`.`user`', '`vn2008`.`Clientes`', '`vn2008`.`Consignatarios`'], inserts: [ - `INSERT INTO account.user(id,name,password,role,active,email) - VALUES - (1, 'BruceWayne', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'BruceWayne@verdnatura.es'), - (2, 'PetterParker', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'PetterParker@verdnatura.es'), - (3, 'ClarkKent', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'ClarkKent@verdnatura.es'), - (4, 'TonyStark', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'TonyStark@verdnatura.es'), - (5, 'MaxEisenhardt', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'MaxEisenhardt@verdnatura.es'), - (6, 'DavidCharlesHaller', 'ac754a330530832ba1bf7687f577da91', 18, 1, 'DavidCharlesHaller@verdnatura.es'), - (7, 'HankPym', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'HankPym@verdnatura.es'), - (8, 'CharlesXavier', 'ac754a330530832ba1bf7687f577da91', 18, 1, 'CharlesXavier@verdnatura.es'), - (9, 'BruceBanner', 'ac754a330530832ba1bf7687f577da91', 18, 1, 'BruceBanner@verdnatura.es'), - (10, 'JessicaJones', 'ac754a330530832ba1bf7687f577da91', 9, 1, 'JessicaJones@verdnatura.es'), - (11, 'Cyborg', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'cyborg@verdnatura.es'); - - INSERT INTO salix.Address(id, consignee, street, city, postcode, provinceFk, phone, mobile, isEnabled, isDefaultAddress, clientFk, defaultAgencyFk, longitude, latitude, isEqualizated) - VALUES - (1, 'Bruce Wayne', 'The Bat cave', 'Silla', 46460, 1, NULL, NULL, 1, 1, 1, 2, NULL, NULL, 0), - (2, 'Petter Parker', 'NY roofs', 'Silla', 46460, 1, NULL, NULL, 1, 1, 2, 2, NULL, NULL, 0), - (3, 'Clark Kenn', 'The phone box', 'Silla', 46460, 1, NULL, NULL, 1, 1, 3, 2, NULL, NULL, 0), - (4, 'Tony Stark', 'Stark tower', 'Silla', 46460, 1, NULL, NULL, 1, 1, 4, 2, NULL, NULL, 0), - (5, 'Max Eisenhardt', 'The plastic cell', 'Silla', 46460, 1, NULL, NULL, 1, 1, 5, 2, NULL, NULL, 0), - (6, 'David Charles Haller', 'Many places', 'Silla', 46460, 1, NULL, NULL, 1, 1, 6, 2, NULL, NULL, 0), - (7, 'Hank Pym', 'Your pocket', 'Silla', 46460, 1, NULL, NULL, 1, 1, 7, 2, NULL, NULL, 0), - (8, 'Charles Xavier', 'Cerebro', 'Silla', 46460, 1, NULL, NULL, 1, 1, 8, 2, NULL, NULL, 0), - (9, 'Bruce Banner', 'Somewhere in Thailand', 'Silla', 46460, 1, NULL, NULL, 1, 1, 9, 2, NULL, NULL, 0), - (10,'Jessica Jones', 'Luke Cages Bar', 'Silla', 46460, 1, NULL, NULL, 1, 1, 10, 2, NULL, NULL, 0); - - INSERT INTO vn.client(id,name,fi,socialName,contact,street,city,postcode,phone,mobile,fax,isRelevant,email,iban,dueDay,accountingAccount,isEqualizated,provinceFk,hasToInvoice,credit,countryFk,isActive,gestdocFk,quality,payMethodFk,created,isToBeMailed,contactChannelFk,hasSepaVnl,hasCoreVnl,hasCoreVnh,riskCalculated,clientTypeFk,mailAddress,cplusTerIdNifFk,hasToInvoiceByAddress,isTaxDataChecked,isFreezed,creditInsurance,isCreatedAsServed,hasInvoiceSimplified,salesPersonFk,isVies,eypbc) - VALUES - (1, 'Bruce Wayne', '74451390E', 'Batman', 'Alfred', '1007 Mountain Drive, Gotham', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'BruceWayne@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 1, 0, 1), - (2, 'Petter Parker', '87945234L', 'Spider-Man', 'Aunt May', '20 Ingram Street', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'PetterParker@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 1, 0, 1), - (3, 'Clark Kent', '06815934E', 'Super-Man', 'lois lane', '344 Clinton Street', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'ClarkKent@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 1, 0, 1), - (4, 'Tony Stark', '06089160W', 'Iron-Man', 'Pepper Potts', '10880 Malibu Point', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'TonyStark@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 1, 0, 1), - (5, 'Max Eisenhardt', '39182496H', 'Magneto', 'Rogue', 'Unknown Whereabouts', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'MaxEisenhardt@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 3, 0, 1), - (6, 'DavidCharlesHaller', '53136686Q', 'Legion', 'Charles Xavier', 'Evil hideout', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'DavidCharlesHaller@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 3, 0, 1), - (7, 'Hank Pym', '09854837G', 'Ant-Man', 'Hawk', 'Anthill', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'HankPym@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 3, 0, 1), - (8, 'Charles Xavier', '22641921P', 'Professor X', 'Beast', '3800 Victory Pkwy, Cincinnati, OH 45207, USA', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'CharlesXavier@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 4, 0, 1), - (9, 'Bruce Banner', '16104829E', 'Hulk', 'Black widow', 'Somewhere in New York', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'BruceBanner@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 4, 0, 1), - (10, 'Jessica Jones', '58282869H', 'Jessica Jones', 'Luke Cage', 'NYCC 2015 Poster', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'JessicaJones@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 4, 0, 1);` - ]}; - - beforeEach(done => { - restoreFixtures(fixturesToApply, done); + let sqlStatements = {deletes: ``, inserts: ``, updates: + `UPDATE vn.address SET isEqualizated = 0 WHERE clientFk = 101;` + }; + beforeEach(() => { + restoreFixtures(sqlStatements); }); - afterAll(done => { - restoreFixtures(fixturesToApply, done); + afterAll(() => { + restoreFixtures(sqlStatements); }); it('should propagate the isEqualizated on both addresses of Mr Wayne', done => { - let id = 1; + let id = 101; let data = { isEqualizated: true }; diff --git a/services/loopback/common/methods/client/specs/card.spec.js b/services/loopback/common/methods/client/specs/card.spec.js index 1d0697f88..1737dd957 100644 --- a/services/loopback/common/methods/client/specs/card.spec.js +++ b/services/loopback/common/methods/client/specs/card.spec.js @@ -3,13 +3,13 @@ const catchErrors = require('../../../../../../services/utils/jasmineHelpers').c describe('Client card', () => { it('should call the card() method to receive a formated card of Bruce Wayne', done => { - let id = 1; + let id = 101; let callback = (error, result) => { if (error) return catchErrors(done)(error); expect(result).toEqual(jasmine.objectContaining({ - id: 1, + id: 101, name: 'Bruce Wayne' })); done(); diff --git a/services/loopback/common/methods/client/specs/createWithUser.spec.js b/services/loopback/common/methods/client/specs/createWithUser.spec.js index 34b8c0db8..eb41d0873 100644 --- a/services/loopback/common/methods/client/specs/createWithUser.spec.js +++ b/services/loopback/common/methods/client/specs/createWithUser.spec.js @@ -3,58 +3,18 @@ const catchErrors = require('../../../../../../services/utils/jasmineHelpers').c const restoreFixtures = require('../../../../../../services/db/testing_fixtures'); describe('Client Create', () => { - let fixturesToApply = {tables: ['`account`.`user`', '`vn2008`.`Clientes`', '`vn2008`.`Consignatarios`'], inserts: [ - `INSERT INTO account.user(id,name,password,role,active,email) - VALUES - (1, 'BruceWayne', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'BruceWayne@verdnatura.es'), - (2, 'PetterParker', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'PetterParker@verdnatura.es'), - (3, 'ClarkKent', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'ClarkKent@verdnatura.es'), - (4, 'TonyStark', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'TonyStark@verdnatura.es'), - (5, 'MaxEisenhardt', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'MaxEisenhardt@verdnatura.es'), - (6, 'DavidCharlesHaller', 'ac754a330530832ba1bf7687f577da91', 18, 1, 'DavidCharlesHaller@verdnatura.es'), - (7, 'HankPym', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'HankPym@verdnatura.es'), - (8, 'CharlesXavier', 'ac754a330530832ba1bf7687f577da91', 18, 1, 'CharlesXavier@verdnatura.es'), - (9, 'BruceBanner', 'ac754a330530832ba1bf7687f577da91', 18, 1, 'BruceBanner@verdnatura.es'), - (10, 'JessicaJones', 'ac754a330530832ba1bf7687f577da91', 9, 1, 'JessicaJones@verdnatura.es'), - (11, 'Cyborg', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'cyborg@verdnatura.es'); - - INSERT INTO account.user(name, password, role, active, email) - SELECT name, MD5('nightmare'), id, 1, CONCAT(name, '@verdnatura.es') - FROM account.role; + let sqlStatements = {deletes: ` + DELETE FROM vn.address WHERE nickname = "Wade"; + DELETE FROM vn.client WHERE name = "Wade"; + DELETE FROM account.user WHERE name = "Deadpool"; + `, inserts: ``, updates: ``}; - INSERT INTO salix.Address(id, consignee, street, city, postcode, provinceFk, phone, mobile, isEnabled, isDefaultAddress, clientFk, defaultAgencyFk, longitude, latitude, isEqualizated) - VALUES - (1, 'Bruce Wayne', 'The Bat cave', 'Silla', 46460, 1, NULL, NULL, 1, 1, 1, 2, NULL, NULL, 0), - (2, 'Petter Parker', 'NY roofs', 'Silla', 46460, 1, NULL, NULL, 1, 1, 2, 2, NULL, NULL, 0), - (3, 'Clark Kenn', 'The phone box', 'Silla', 46460, 1, NULL, NULL, 1, 1, 3, 2, NULL, NULL, 0), - (4, 'Tony Stark', 'Stark tower', 'Silla', 46460, 1, NULL, NULL, 1, 1, 4, 2, NULL, NULL, 0), - (5, 'Max Eisenhardt', 'The plastic cell', 'Silla', 46460, 1, NULL, NULL, 1, 1, 5, 2, NULL, NULL, 0), - (6, 'David Charles Haller', 'Many places', 'Silla', 46460, 1, NULL, NULL, 1, 1, 6, 2, NULL, NULL, 0), - (7, 'Hank Pym', 'Your pocket', 'Silla', 46460, 1, NULL, NULL, 1, 1, 7, 2, NULL, NULL, 0), - (8, 'Charles Xavier', 'Cerebro', 'Silla', 46460, 1, NULL, NULL, 1, 1, 8, 2, NULL, NULL, 0), - (9, 'Bruce Banner', 'Somewhere in Thailand', 'Silla', 46460, 1, NULL, NULL, 1, 1, 9, 2, NULL, NULL, 0), - (10,'Jessica Jones', 'Luke Cages Bar', 'Silla', 46460, 1, NULL, NULL, 1, 1, 10, 2, NULL, NULL, 0); - - INSERT INTO vn.client(id,name,fi,socialName,contact,street,city,postcode,phone,mobile,fax,isRelevant,email,iban,dueDay,accountingAccount,isEqualizated,provinceFk,hasToInvoice,credit,countryFk,isActive,gestdocFk,quality,payMethodFk,created,isToBeMailed,contactChannelFk,hasSepaVnl,hasCoreVnl,hasCoreVnh,riskCalculated,clientTypeFk,mailAddress,cplusTerIdNifFk,hasToInvoiceByAddress,isTaxDataChecked,isFreezed,creditInsurance,isCreatedAsServed,hasInvoiceSimplified,salesPersonFk,isVies,eypbc) - VALUES - (1, 'Bruce Wayne', '74451390E', 'Batman', 'Alfred', '1007 Mountain Drive, Gotham', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'BruceWayne@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 1, 0, 1), - (2, 'Petter Parker', '87945234L', 'Spider-Man', 'Aunt May', '20 Ingram Street', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'PetterParker@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 1, 0, 1), - (3, 'Clark Kent', '06815934E', 'Super-Man', 'lois lane', '344 Clinton Street', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'ClarkKent@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 1, 0, 1), - (4, 'Tony Stark', '06089160W', 'Iron-Man', 'Pepper Potts', '10880 Malibu Point', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'TonyStark@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 1, 0, 1), - (5, 'Max Eisenhardt', '39182496H', 'Magneto', 'Rogue', 'Unknown Whereabouts', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'MaxEisenhardt@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 3, 0, 1), - (6, 'DavidCharlesHaller', '53136686Q', 'Legion', 'Charles Xavier', 'Evil hideout', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'DavidCharlesHaller@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 3, 0, 1), - (7, 'Hank Pym', '09854837G', 'Ant-Man', 'Hawk', 'Anthill', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'HankPym@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 3, 0, 1), - (8, 'Charles Xavier', '22641921P', 'Professor X', 'Beast', '3800 Victory Pkwy, Cincinnati, OH 45207, USA', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'CharlesXavier@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 4, 0, 1), - (9, 'Bruce Banner', '16104829E', 'Hulk', 'Black widow', 'Somewhere in New York', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'BruceBanner@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 4, 0, 1), - (10, 'Jessica Jones', '58282869H', 'Jessica Jones', 'Luke Cage', 'NYCC 2015 Poster', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'JessicaJones@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 4, 0, 1);` - ]}; - - beforeEach(done => { - restoreFixtures(fixturesToApply, done); + beforeAll(() => { + restoreFixtures(sqlStatements); }); - afterAll(done => { - restoreFixtures(fixturesToApply, done); + afterAll(() => { + restoreFixtures(sqlStatements); }); let newAccountData = { diff --git a/services/loopback/common/methods/client/specs/hasCustomerRole.spec.js b/services/loopback/common/methods/client/specs/hasCustomerRole.spec.js index 32773e25e..c1b25f8a9 100644 --- a/services/loopback/common/methods/client/specs/hasCustomerRole.spec.js +++ b/services/loopback/common/methods/client/specs/hasCustomerRole.spec.js @@ -3,7 +3,7 @@ const catchErrors = require('../../../../../../services/utils/jasmineHelpers').c describe('Client hasCustomerRole', () => { it('should call the hasCustomerRole() method with a customer id', done => { - let id = 1; + let id = 101; let params = {}; let callback = (error, result) => { diff --git a/services/loopback/common/methods/client/specs/listWorkers.spec.js b/services/loopback/common/methods/client/specs/listWorkers.spec.js index 170975d6f..52bd5f3b7 100644 --- a/services/loopback/common/methods/client/specs/listWorkers.spec.js +++ b/services/loopback/common/methods/client/specs/listWorkers.spec.js @@ -7,7 +7,7 @@ describe('Client listWorkers', () => { .then(result => { let amountOfEmployees = Object.keys(result).length; - expect(amountOfEmployees).toEqual(32); + expect(amountOfEmployees).toEqual(37); done(); }) .catch(catchErrors(done)); From 4497b00bab04779521fe34739e39a8f9959368bb Mon Sep 17 00:00:00 2001 From: Daniel Herrero Date: Thu, 8 Mar 2018 13:38:55 +0100 Subject: [PATCH 07/10] arreglado e2e item summary --- e2e/helpers/selectors.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index e592c8e87..dd337df03 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -256,9 +256,10 @@ export default { }, itemSummary: { basicData: `${components.vnItemSummary} > vn-horizontal:nth-child(1) > vn-one:nth-child(2) > vn-vertical > p:nth-child(2)`, - tags: `${components.vnItemSummary} > vn-horizontal:nth-child(1) > vn-one:nth-child(3) > vn-vertical > p`, - niche: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(1) > vn-vertical > p:nth-child(2)`, - botanical: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(2) > vn-vertical > p`, - barcode: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(3) > vn-vertical > p` + vat: `${components.vnItemSummary} > vn-horizontal:nth-child(1) > vn-one:nth-child(3) > vn-vertical > p`, + tags: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(1) > p`, + niche: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(2) > vn-vertical > p:nth-child(2)`, + botanical: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(3) > vn-vertical > p`, + barcode: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(4) > vn-vertical > p` } }; From bbcd39f30daade7e0e419cd5e8b12349afeb34ba Mon Sep 17 00:00:00 2001 From: Juan Date: Fri, 9 Mar 2018 14:15:30 +0100 Subject: [PATCH 08/10] #135 Refactor vnAutocomplete --- .../components/autocomplete/autocomplete.html | 43 +- .../components/autocomplete/autocomplete.js | 482 ++++++-------- .../autocomplete/autocomplete.spec.js | 216 ++----- .../src/components/autocomplete/style.scss | 69 +- .../src/components/drop-down/drop-down.html | 62 +- .../src/components/drop-down/drop-down.js | 592 +++++++++++------- .../components/drop-down/drop-down.spec.js | 339 +--------- client/core/src/components/drop-down/model.js | 107 ++++ .../core/src/components/drop-down/style.scss | 160 ++--- e2e/helpers/selectors.js | 136 ++-- 10 files changed, 975 insertions(+), 1231 deletions(-) mode change 100644 => 100755 client/core/src/components/autocomplete/autocomplete.html mode change 100644 => 100755 client/core/src/components/autocomplete/autocomplete.js mode change 100644 => 100755 client/core/src/components/autocomplete/style.scss mode change 100644 => 100755 client/core/src/components/drop-down/drop-down.html mode change 100644 => 100755 client/core/src/components/drop-down/drop-down.js create mode 100644 client/core/src/components/drop-down/model.js mode change 100644 => 100755 client/core/src/components/drop-down/style.scss diff --git a/client/core/src/components/autocomplete/autocomplete.html b/client/core/src/components/autocomplete/autocomplete.html old mode 100644 new mode 100755 index 6dd9b3ab7..0ee10c5ae --- a/client/core/src/components/autocomplete/autocomplete.html +++ b/client/core/src/components/autocomplete/autocomplete.html @@ -1,22 +1,23 @@ - - - - - {{$parent.item[$ctrl.showField]}} +
+
+ + +
+ + +
+ +
+ - \ No newline at end of file +
\ No newline at end of file diff --git a/client/core/src/components/autocomplete/autocomplete.js b/client/core/src/components/autocomplete/autocomplete.js old mode 100644 new mode 100755 index 2dc37b659..5c216d21d --- a/client/core/src/components/autocomplete/autocomplete.js +++ b/client/core/src/components/autocomplete/autocomplete.js @@ -1,381 +1,255 @@ import ngModule from '../../module'; import Component from '../../lib/component'; -import copyObject from '../../lib/copy'; import './style.scss'; -class Autocomplete extends Component { - constructor($element, $scope, $http, $timeout, $filter) { - super($element); - this.$element = $element; - this.$scope = $scope; +/** + * Input with option selector. + * + * @property {String} valueField The data field name that should be shown + * @property {String} showFiled The data field name that should be used as value + * @property {Array} data Static data for the autocomplete + * @property {Object} intialData A initial data to avoid the server request used to get the selection + * @property {Boolean} multiple Wether to allow multiple selection + */ +export default class Autocomplete extends Component { + constructor($element, $scope, $http, $transclude) { + super($element, $scope); this.$http = $http; - this.$timeout = $timeout; - this.$filter = $filter; + this.$transclude = $transclude; - this._showDropDown = false; - this.finding = false; - this.findMore = false; - this._value = null; - this._field = null; - this._preLoad = false; - this.maxRow = 10; - this.showField = 'name'; + this._field = undefined; + this._selection = null; this.valueField = 'id'; - this.items = copyObject(this.data) || []; - this.displayValueMultiCheck = []; + this.showField = 'name'; this._multiField = []; this.readonly = true; - this.removeLoadMore = false; this.form = null; - this.findForm = false; - } - - get showDropDown() { - return this._showDropDown; - } - - set showDropDown(value) { - if (value && this.url && !this._preLoad) { - this._preLoad = true; - this.getItems(); - } - if (value && !this.width) { - let rectangle = this.$element[0].getBoundingClientRect(); - this.width = Math.round(rectangle.width) - 10; - } - this._showDropDown = value; - } - - get displayValue() { - return this._value; - } - - set displayValue(value) { - let val = (value === undefined || value === '') ? null : value; - if (this.multiple && val) { - let index = this.displayValueMultiCheck.indexOf(val); - if (index === -1) - this.displayValueMultiCheck.push(val); - else - this.displayValueMultiCheck.splice(index, 1); - - this._value = this.displayValueMultiCheck.join(', '); - } else { - this._value = val; - } - - if (value === null) { - this.field = null; - if (this.multiple && this.items.length) { - this.displayValueMultiCheck = []; - this.items.map(item => { - item.checked = false; - return item; - }); - } - } + this.input = this.element.querySelector('.mdl-textfield__input'); + + componentHandler.upgradeElement( + this.element.querySelector('.mdl-textfield')); } + /** + * @type {any} The autocomplete value. + */ get field() { - return this.multiple ? this._multiField : this._field; + return this._field; } set field(value) { - if (!angular.equals(value, this.field)) { - this.finding = true; - if (value && value.hasOwnProperty(this.valueField)) { - this._field = value[this.valueField]; - if (this.multiple) { - this.setMultiField(value[this.valueField]); - } - this.setDirtyForm(); - } else { - this.setValue(value); - } + if (angular.equals(value, this._field)) + return; - if (value && value.hasOwnProperty(this.showField)) - this.displayValue = value[this.showField]; + this._field = value; + this.refreshSelection(); - this.finding = false; - - if (this.onChange) - this.onChange({item: this._field}); - } + if (this.onChange) + this.onChange(value); } - set initialData(value) { - if (value && value.hasOwnProperty(this.valueField)) { - this._field = value[this.valueField]; - if (this.multiple) { - this._multiField = [value[this.valueField]]; - } - if (value.hasOwnProperty(this.showField)) { - this.displayValue = value[this.showField]; - } - } + /** + * @type {Object} The selected data object, you can use this property + * to prevent requests to display the initial value. + */ + get selection() { + return this._selection; } - setMultiField(val) { - if (val && typeof val === 'object' && val[this.valueField]) { - val = val[this.valueField]; - } - if (val === null) { - this._multiField = []; - } else { - let index = this._multiField.indexOf(val); - if (index === -1) { - this._multiField.push(val); - } else { - this._multiField.splice(index, 1); - } - } + set selection(value) { + this._selection = value; + this.refreshDisplayed(); } - setValue(value) { - if (value) { - let data = this.items; + selectionIsValid(selection) { + return selection + && selection[this.valueField] == this._field + && selection[this.showField] != null; + } - if (data && data.length) + refreshSelection() { + if (this.selectionIsValid(this._selection)) + return; + + let value = this._field; + + if (value && this.valueField && this.showField) { + if (this.selectionIsValid(this.initialData)) { + this.selection = this.initialData; + return; + } + + let data = this.data; + + if (!data && this.$.dropDown) + data = this.$.dropDown.$.model.data; + + if (data) for (let i = 0; i < data.length; i++) if (data[i][this.valueField] === value) { - this.showItem(data[i]); + this.selection = data[i]; return; } - this.requestItem(value); - } else { - this._field = null; - this.setMultiField(null); - this.displayValue = ''; - } + if (this.url) { + this.requestSelection(value); + return; + } + } else + this.selection = null; } - requestItem(value) { - if (!value) return; - + requestSelection(value) { let where = {}; - where[this.valueField] = value; + + if (this.multiple) + where[this.valueField] = {inq: this.field}; + else + where[this.valueField] = value; let filter = { - fields: this.getRequestFields(), + fields: this.getFields(), where: where }; - let json = JSON.stringify(filter); - + let json = encodeURIComponent(JSON.stringify(filter)); this.$http.get(`${this.url}?filter=${json}`).then( - json => this.onItemRequest(json.data), - json => this.onItemRequest(null) + json => this.onSelectionRequest(json.data), + () => this.onSelectionRequest(null) ); } - onItemRequest(data) { - if (data && data.length > 0) - this.showItem(data[0]); - else - this.showItem(null); + onSelectionRequest(data) { + if (data && data.length > 0) { + if (this.multiple) + this.selection = data; + else + this.selection = data[0]; + } else + this.selection = null; } - showItem(item) { - this.displayValue = item ? item[this.showField] : ''; - this.field = item; + refreshDisplayed() { + let display = ''; + + if (this._selection && this.showField) { + if (this.multiple && Array.isArray(this._selection)) { + for (var item of this._selection) { + if (display.length > 0) display += ', '; + display += item[this.showField]; + } + } else { + display = this._selection[this.showField]; + } + } + + this.input.value = display; + this.mdlUpdate(); } - getRequestFields() { - let fields = {}; - fields[this.valueField] = true; - fields[this.showField] = true; + getFields() { + let fields = []; + fields.push(this.valueField); + fields.push(this.showField); - if (this._selectFields) - for (let field of this._selectFields) - fields[field] = true; + if (this.selectFields) + for (let field of this.selectFields) + fields.push(field); return fields; } - getOrder() { - return this.order ? this.order : `${this.showField} ASC`; + mdlUpdate() { + let field = this.element.querySelector('.mdl-textfield'); + let mdlField = field.MaterialTextfield; + if (mdlField) mdlField.updateClasses_(); } - findItems(search) { - if (this.url && search && !this.finding) { - this.maxRow = false; - let filter = {}; - if (this.filterSearch) { - let toSearch = this.filterSearch.replace(/search/g, search); - filter = this.$scope.$eval(toSearch); - } else { - filter = {where: {name: {regexp: search}}}; - if (this.filter && this.filter.where) { - Object.assign(filter.where, this.filter.where); - } - } - filter.order = this.getOrder(); - let json = JSON.stringify(filter); - this.finding = true; - this.$http.get(`${this.url}?filter=${json}`).then( - json => { - this.items = []; - json.data.forEach( - el => { - if (this.multiple) { - el.checked = this.field.indexOf(el[this.valueField]) !== -1; - } - this.items.push(el); - } - ); - this.finding = false; - }, - () => { - this.finding = false; - } - ); - } else if (search && !this.url && this.data) { - this.items = this.$filter('filter')(this.data, search); - } else if (!search && !this.finding) { - this.maxRow = 10; - this.items = []; - this.getItems(); - } + setValue(value) { + this.field = value; + if (this.form) this.form.$setDirty(); } - getItems() { - if (this.url === undefined) { - this.items = copyObject(this.data); - this.maxRow = false; - this.removeLoadMore = true; - } else { - let filter = {}; - if (!this.finding) { - this.finding = true; - - if (this.maxRow) { - if (this.items) { - filter.skip = this.items.length; - } - filter.limit = this.maxRow; - filter.order = this.getOrder(); - } - if (this.filter) { - Object.assign(filter, this.filter); - } - - let json = JSON.stringify(filter); - - this.removeLoadMore = false; - - this.$http.get(`${this.url}?filter=${json}`).then( - json => { - if (json.data.length) { - json.data.forEach( - el => { - if (this.multiple) { - el.checked = this.field.indexOf(el[this.valueField]) !== -1; - } - this.items.push(el); - } - ); - if (filter.skip === 0 && this.maxRow && json.data.length < this.maxRow) { - this.removeLoadMore = true; - } - } else { - this.maxRow = false; - } - this.finding = false; - }, - () => { - this.finding = false; - } - ); - } - } - } - _parentForm() { - this.findForm = true; - let formScope = this.$scope; - while (formScope && !formScope.form && formScope.$id > 1) { - formScope = formScope.$parent; - } - this.form = formScope ? formScope.form || null : null; - } - setDirtyForm() { - if (!this.form && !this.findForm) { - this._parentForm(); - } - if (this.form) { - this.form.$setDirty(); - } + onDropDownSelect(value) { + this.setValue(value); + this.field = value; } - $onInit() { - this.findMore = this.url && this.maxRow; - this.mouseFocus = false; - this.focused = false; + onClearClick(event) { + event.preventDefault(); + this.setValue(null); + } - this.$element.bind('mouseover', e => { - this.$timeout(() => { - this.mouseFocus = true; - this.showDropDown = this.focused; - }); + onKeyDown(event) { + if (event.defaultPrevented) return; + + switch (event.keyCode) { + case 38: // Up + case 40: // Down + case 13: // Enter + this.showDropDown(); + break; + default: + if (event.key.length == 1) + this.showDropDown(event.key); + else + return; + } + + event.preventDefault(); + } + + onMouseDown(event) { + event.preventDefault(); + this.showDropDown(); + } + + showDropDown(search) { + Object.assign(this.$.dropDown.$.model, { + url: this.url, + staticData: this.data }); - this.$element.bind('mouseout', () => { - this.$timeout(() => { - this.mouseFocus = false; - this.showDropDown = this.focused; - }); - }); - this.$element.bind('focusin', e => { - this.$timeout(() => { - this.focused = true; - this.showDropDown = true; - }); - }); - this.$element.bind('focusout', e => { - this.$timeout(() => { - this.focused = false; - this.showDropDown = this.mouseFocus; - }); + Object.assign(this.$.dropDown, { + valueField: this.valueField, + showField: this.showField, + selectFields: this.getFields(), + where: this.where, + order: this.order, + parent: this.input, + multiple: this.multiple, + limit: this.limit, + $transclude: this.$transclude }); + this.$.dropDown.show(search); } - - $onDestroy() { - this.$element.unbind('mouseover'); - this.$element.unbind('mouseout'); - this.$element.unbind('focusin'); - this.$element.unbind('focusout'); - } - - $onChanges(objectChange) { - if (objectChange.data && objectChange.data.currentValue && objectChange.data.currentValue.length) { - this.items = copyObject(objectChange.data.currentValue); - this.maxRow = false; - this.removeLoadMore = true; - } - } - } -Autocomplete.$inject = ['$element', '$scope', '$http', '$timeout', '$filter']; +Autocomplete.$inject = ['$element', '$scope', '$http', '$transclude']; ngModule.component('vnAutocomplete', { template: require('./autocomplete.html'), controller: Autocomplete, bindings: { url: '@?', + data: ' { - let $componentController; + let $element; let $scope; let $httpBackend; - let $timeout; - let $element; let controller; + let data = {id: 1, name: 'Bruce Wayne'}; + beforeEach(() => { angular.mock.module('client'); }); beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_, _$timeout_) => { - $componentController = _$componentController_; $scope = $rootScope.$new(); + $element = angular.element(`
${template}
`); $httpBackend = _$httpBackend_; $httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({}); - $timeout = _$timeout_; - $element = angular.element('
'); - controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout}); + controller = _$componentController_('vnAutocomplete', {$element, $scope, $httpBackend, $transclude: null}); })); - describe('showDropDown() setter', () => { - it(`should set _showDropDown value`, () => { - controller._showDropDown = ''; - controller.showDropDown = 'some value'; + describe('field() setter/getter', () => { + it(`should set field controllers property`, () => { + controller.field = data.id; - expect(controller._showDropDown).toEqual('some value'); + expect(controller.field).toEqual(data.id); }); - it(`should set _showDropDown value`, () => { - controller._showDropDown = ''; - controller.showDropDown = 'some value'; + it(`should set selection finding an existing item in the initialData property`, () => { + controller.valueField = 'id'; + controller.showField = 'name'; + controller.initialData = data; + controller.field = data.id; - expect(controller._showDropDown).toEqual('some value'); - }); - }); - - describe('displayValue() setter', () => { - it(`should display value in a formated way`, () => { - let value = 'some value'; - controller.displayValue = value; - - expect(controller._value).toEqual(value); + expect(controller.selection).toEqual(data); }); - describe('when the autocomeplete is multiple', () => { - it(`should display values separated with commas`, () => { - controller.multiple = true; - controller.displayValue = 'some value'; - controller.displayValue = 'another value'; + it(`should set selection finding an existing item in the data property`, () => { + controller.valueField = 'id'; + controller.showField = 'name'; + controller.data = [data]; + controller.field = data.id; - expect(controller._value).toEqual('some value, another value'); - }); - }); - }); - - describe('field() setter', () => { - describe('when value is an object', () => { - it(`should set _field controllers property`, () => { - controller.field = {id: 1, name: 'Bruce Wayne'}; - - expect(controller._field).toEqual(1); - }); - - it(`should set _multifield controllers property `, () => { - controller.multiple = true; - controller.field = {id: 1, name: 'Bruce Wayne'}; - - expect(controller._field).toEqual(1); - expect(controller._multiField[0]).toEqual(1); - - controller.field = {id: 1, name: 'Bruce Wayne'}; - - expect(controller._multiField).toEqual([]); - expect(controller._field).toEqual(1); - }); - - it(`should set _multifield value and remove it if called a second type with same value`, () => { - controller.multiple = true; - controller.field = {id: 1, name: 'Bruce Wayne'}; - - expect(controller._field).toEqual(1); - expect(controller._multiField[0]).toEqual(1); - - controller.field = {id: 1, name: 'Bruce Wayne'}; - - expect(controller._multiField).toEqual([]); - expect(controller._field).toEqual(1); - }); - - it(`should set displayValue finding an existing item in the controller.items property`, () => { - controller.items = [{id: 1, name: 'test1'}, {id: 2, name: 'Bruce Wayne'}]; - controller.field = {id: 2, name: 'Bruce Wayne'}; - - expect(controller.displayValue).toEqual('Bruce Wayne'); - }); + expect(controller.selection).toEqual(data); }); - describe('when value is a number', () => { - it(`should set _field controller property finding an existing item in the controller.items property`, () => { - controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}]; - controller.field = 2; + it(`should set selection to null when can't find an existing item in the data property`, () => { + controller.valueField = 'id'; + controller.showField = 'name'; + controller.field = data.id; - expect(controller._field).toEqual(2); - }); - - it(`should set _multifield value and remove it if called a second type with same value finding an existing item in the controller.items property`, () => { - controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}]; - controller.multiple = true; - controller.field = 2; - - expect(controller._multiField[0]).toEqual(2); - - controller.field = 2; - - expect(controller._multiField).toEqual([]); - }); - - it(`should perform a query if the item id isn't present in the controller.items property`, () => { - controller.url = 'test.com'; - $httpBackend.expectGET(`${controller.url}?filter={"fields":{"id":true,"name":true},"where":{"id":3}}`); - controller.items = [{id: 1, name: 'test1'}, {id: 2, name: 'Bruce Wayne'}]; - controller.field = 3; - $httpBackend.flush(); - }); - - it(`should set displayValue finding an existing item in the controller.items property`, () => { - controller.items = [{id: 1, name: 'test1'}, {id: 2, name: 'Bruce Wayne'}]; - controller.field = 2; - - expect(controller.displayValue).toEqual('Bruce Wayne'); - }); - - it(`should set field performing a query as the item id isn't present in the controller.items property`, () => { - controller.url = 'test.com'; - $httpBackend.expectGET(`${controller.url}?filter={"fields":{"id":true,"name":true},"where":{"id":3}}`); - controller.items = [{id: 1, name: 'test1'}, {id: 2, name: 'Bruce Wayne'}]; - controller.field = 3; - $httpBackend.flush(); - }); + expect(controller.selection).toEqual(null); }); - }); - describe('findItems()', () => { - it(`should perform a search and store the result in controller items`, () => { - let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout}); - controller.url = 'test.com'; - let search = 'The Joker'; - let json = JSON.stringify({where: {name: {regexp: search}}, order: controller.getOrder()}); - $httpBackend.whenGET(`${controller.url}?filter=${json}`).respond([{id: 3, name: 'The Joker'}]); - $httpBackend.expectGET(`${controller.url}?filter=${json}`); - controller.findItems(search); + it(`should perform a query if the item id isn't present in the data property`, () => { + controller.valueField = 'id'; + controller.showField = 'name'; + controller.url = 'localhost'; + controller.field = data.id; + + let filter = { + fields: ['id', 'name'], + where: {id: data.id} + }; + let json = encodeURIComponent(JSON.stringify(filter)); + + $httpBackend.expectGET(`localhost?filter=${json}`); + controller.field = data.id; $httpBackend.flush(); - - expect(controller.items[0]).toEqual({id: 3, name: 'The Joker'}); - }); - - it(`should perform a search and store the result in controller items with filterSearch`, () => { - let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout}); - controller.url = 'test.com'; - let search = 'The Joker'; - controller.filterSearch = "{where: {name: {regexp: 'search'}}}"; - let json = JSON.stringify({where: {name: {regexp: search}}, order: controller.getOrder()}); - $httpBackend.whenGET(`${controller.url}?filter=${json}`).respond([{id: 3, name: 'The Joker'}]); - $httpBackend.expectGET(`${controller.url}?filter=${json}`); - controller.findItems(search); - $httpBackend.flush(); - - expect(controller.items[0]).toEqual({id: 3, name: 'The Joker'}); - }); - - it(`should perform a search with multiple true and store the result in controller items with the checked property defined`, () => { - controller.url = 'test.com'; - let search = 'Joker'; - controller.multiple = true; - let json = JSON.stringify({where: {name: {regexp: search}}, order: controller.getOrder()}); - $httpBackend.whenGET(`${controller.url}?filter=${json}`).respond([{id: 3, name: 'The Joker'}, {id: 4, name: 'Joker'}]); - $httpBackend.expectGET(`${controller.url}?filter=${json}`); - controller.findItems(search); - $httpBackend.flush(); - - expect(controller.items).toEqual([{id: 3, name: 'The Joker', checked: false}, {id: 4, name: 'Joker', checked: false}]); - }); - - it(`should call getItems function if there's no search value`, () => { - controller.url = 'test.com'; - spyOn(controller, 'getItems'); - controller.findItems(); - - expect(controller.getItems).toHaveBeenCalledWith(); - }); - }); - - describe('getItems()', () => { - it(`should perfom a query to fill the items without filter`, () => { - controller.url = 'test.com'; - $httpBackend.whenGET(`${controller.url}?filter={"skip":0,"limit":10,"order":"name ASC"}`).respond([{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}]); - $httpBackend.expectGET(`${controller.url}?filter={"skip":0,"limit":10,"order":"name ASC"}`); - controller.getItems(); - $httpBackend.flush(); - - expect(controller.items).toEqual([{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}]); }); }); }); diff --git a/client/core/src/components/autocomplete/style.scss b/client/core/src/components/autocomplete/style.scss old mode 100644 new mode 100755 index 15e59d4d3..26143c035 --- a/client/core/src/components/autocomplete/style.scss +++ b/client/core/src/components/autocomplete/style.scss @@ -1,3 +1,47 @@ + +vn-autocomplete > div > .mdl-textfield { + position: relative; + width: 100%; + + & > input { + cursor: pointer; + height: 26px; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + + &:focus { + outline: none; + } + &::-moz-focus-inner { + border: 0; + } + } + & > .icons { + display: none; + position: absolute; + right: 0; + top: 1.3em; + height: 1em; + color: #888; + border-radius: .2em; + background-color: rgba(255, 255, 255, .8); + + & > vn-icon { + cursor: pointer; + font-size: 18px; + + &:hover { + color: #333; + } + } + } + &:hover > .icons, + & > input:focus + .icons { + display: block; + } +} + ul.vn-autocomplete { list-style-type: none; padding: 1em; @@ -14,7 +58,7 @@ ul.vn-autocomplete { &.active, &:hover { - background-color: rgba(1,1,1,.1); + background-color: rgba(1, 1, 1, .1); } &.load-more { color: #ffa410; @@ -22,27 +66,4 @@ ul.vn-autocomplete { padding: .4em .8em; } } -} -vn-autocomplete { - position: relative; - vn-vertical { - outline:none; - } - - .mdl-chip__action { - position: absolute; - top: 0px; - right: -6px; - margin: 22px 0px; - background: transparent; - } - .material-icons { - font-size: 18px; - } - vn-drop-down{ - margin-top: 47px; - } - vn-drop-down .dropdown-body .filter vn-icon { - margin-left: -26px; - } } \ No newline at end of file diff --git a/client/core/src/components/drop-down/drop-down.html b/client/core/src/components/drop-down/drop-down.html old mode 100644 new mode 100755 index e155c67af..2855da84c --- a/client/core/src/components/drop-down/drop-down.html +++ b/client/core/src/components/drop-down/drop-down.html @@ -1,28 +1,36 @@ - - - - - - - - -