merge conflict

This commit is contained in:
Daniel Herrero 2018-01-16 13:56:09 +01:00
commit 7503179cb8
20 changed files with 260 additions and 84 deletions

View File

@ -1,53 +1,67 @@
# Project Title
One Paragraph of project description goes here
Salix is an Enterprise resource planning (ERP) integrated management of core business processes, in real-time and mediated by software and technology developed with the stack listed below.
Salix is also the scientific name of a beautifull tree! :)
### Prerequisites
For testing purposes you will need to install globally the following items:
npm install -g karma
npm install -g karma-cli
## Getting Started // ### Installing
Pull from repo.
install nodejs v6 or above.
You will need to install globally the following items:
$ npm install -g karma
$ npm install -g karma-cli
$ npm install -g gulp
$ npm install -g webpack
$ npm install -g nodemon
install nginx globally.
Ask a senior dev for the datasources.development.json files required to run the project.
## Getting Started // ### Installing
Pull from repository.
install nodejs v6.
Ask a senior developer for the datasources.development.json files required to run the project.
on root run:
npm install
gulp install
$ npm install
$ gulp install
lauching nginx:
./dev.sh
$ ./dev.sh
launching frontend:
gulp client
$ gulp client
or start nginx before client on sequence
$ gulp clientDev
launching backend:
gulp services
$ gulp services
or start the local database before services on sequence
$ gulp serivcesDev
Manually reset local fixtures:
$ gulp docker
to check docker images and containers status:
$ docker images
$ docker ps -a
## Running the tests
for client-side unit tests run from project's root:
karma start
$ karma start
for server-side unit tests run from project's root:
npm run testWatch or test for single run
$ npm run test
### Break down into end to end tests
on root run:
Run local database plus e2e paths:
$ gulp e2e
gulp docker
wait 10 secs for db to be ready
npm run e2e
Just the e2e paths as the fixtures are untainted:
$ npm run e2e
## Built With

View File

@ -5,6 +5,7 @@
form="form"
save="post">
</vn-watcher>
<form pad-medium name="form" ng-submit="$ctrl.onSubmit()">
<vn-card>
<vn-vertical pad-medium>

View File

@ -0,0 +1,39 @@
import './greuge-create.js';
describe('Client', () => {
describe('Component vnClientGreugeCreate', () => {
let $componentController;
let $scope;
let $state;
let controller;
beforeEach(() => {
angular.mock.module('client');
});
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$state_) => {
$componentController = _$componentController_;
$scope = $rootScope.$new();
$state = _$state_;
$scope.watcher = {
submit: () => {
return {
then: callback => {
callback();
}
};
}
};
controller = $componentController('vnClientGreugeCreate', {$scope: $scope});
}));
describe('onSubmit()', () => {
it('should call the function go() on $state to go to the greuges list', () => {
spyOn($state, 'go');
controller.onSubmit();
expect(controller.$state.go).toHaveBeenCalledWith('clientCard.greuge.list');
});
});
});
});

View File

@ -29,7 +29,6 @@ export function directive(interpolate, compile, $window) {
throw new Error(`vnValidation: Entity '${entityName}' doesn't exist`);
let validations = entity.validations[fieldName];
if (!validations || validations.length == 0)
return;

View File

@ -2,7 +2,7 @@ import {validator} from 'vendor';
export const validators = {
presence: value => {
if (validator.isEmpty(value))
if (validator.isEmpty(value ? String(value) : ''))
throw new Error(`Value can't be empty`);
},
absence: value => {
@ -74,7 +74,7 @@ export function validate(value, conf) {
try {
checkNull(value, conf);
if (validator && value != null)
if (validator) // && value != null ??
validator(value, conf);
} catch (e) {
let message = conf.message ? conf.message : e.message;

View File

@ -4,11 +4,11 @@ import Nightmare from 'nightmare';
export default function createNightmare(width = 1280, height = 720) {
const nightmare = new Nightmare({show: true, typeInterval: 10, x: 0, y: 0}).viewport(width, height);
nightmare.on('page', function(type, message, error) {
nightmare.on('page', (type, message, error) => {
fail(error);
});
nightmare.on('console', function(type, message) {
nightmare.on('console', (type, message) => {
if (type === 'error') {
fail(message);
}

View File

@ -128,11 +128,15 @@ export default {
greuge: {
greugeButton: `${components.vnMenuItem}[ui-sref="clientCard.greuge.list"]`,
addGreugeFloatButton: `${components.vnFloatButton}`,
amountInput: `${components.vnTextfield}[name="Amount"]`,
descriptionInput: `${components.vnTextfield}[name="Description"]`,
amountInput: `${components.vnTextfield}[name="amount"]`,
descriptionInput: `${components.vnTextfield}[name="description"]`,
typeInput: `${components.vnAutocomplete}[field="$ctrl.greuge.greugeTypeFk"] > vn-vertical > ${components.vnTextfield}`,
typeSecondOption: `${components.vnAutocomplete}[field="$ctrl.greuge.greugeTypeFk"] > vn-vertical > vn-drop-down > vn-vertical > vn-auto:nth-child(2) > ul > li`,
saveButton: `${components.vnSubmit}`
// firstGreugeText: ''
saveButton: `${components.vnSubmit}`,
firstGreugeText: 'body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > ui-view > vn-client-greuge-list > vn-card > div > vn-vertical > vn-one > vn-horizontal'
},
mandate: {
mandateButton: `${components.vnMenuItem}[ui-sref="clientCard.mandate"]`,
firstMandateText: 'body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > vn-client-mandate > vn-card > div > vn-vertical > vn-one > vn-horizontal'
}
};

View File

@ -86,7 +86,7 @@ describe('create client path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('No changes to save');
expect(result).toEqual('Some fields are invalid');
done();
})
.catch(catchErrors(done));
@ -100,7 +100,7 @@ describe('create client path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
expect(result).toContain('Some fields are invalid');
done();
})
.catch(catchErrors(done));
@ -115,7 +115,7 @@ describe('create client path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
expect(result).toContain('Some fields are invalid');
done();
})
.catch(catchErrors(done));
@ -130,7 +130,7 @@ describe('create client path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
expect(result).toContain('Some fields are invalid');
done();
})
.catch(catchErrors(done));
@ -145,7 +145,7 @@ describe('create client path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
expect(result).toContain('Some fields are invalid');
done();
})
.catch(catchErrors(done));
@ -175,7 +175,7 @@ describe('create client path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
expect(result).toContain('Some fields are invalid');
done();
})
.catch(catchErrors(done));
@ -190,7 +190,7 @@ describe('create client path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
expect(result).toContain('Some fields are invalid');
done();
})
.catch(catchErrors(done));

View File

@ -103,7 +103,7 @@ describe('Edit addresses path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
expect(result).toContain('Some fields are invalid');
done();
})
.catch(catchErrors(done));
@ -117,7 +117,7 @@ describe('Edit addresses path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
expect(result).toContain('Some fields are invalid');
done();
})
.catch(catchErrors(done));
@ -132,7 +132,7 @@ describe('Edit addresses path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
expect(result).toContain('Some fields are invalid');
done();
})
.catch(catchErrors(done));
@ -147,7 +147,7 @@ describe('Edit addresses path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
expect(result).toContain('Some fields are invalid');
done();
})
.catch(catchErrors(done));
@ -162,7 +162,7 @@ describe('Edit addresses path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
expect(result).toContain('Some fields are invalid');
done();
})
.catch(catchErrors(done));
@ -178,7 +178,7 @@ describe('Edit addresses path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
expect(result).toContain('Some fields are invalid');
done();
})
.catch(catchErrors(done));
@ -193,7 +193,7 @@ describe('Edit addresses path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
expect(result).toContain('Some fields are invalid');
done();
})
.catch(catchErrors(done));
@ -207,7 +207,7 @@ describe('Edit addresses path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
expect(result).toContain('Some fields are invalid');
done();
})
.catch(catchErrors(done));
@ -222,7 +222,7 @@ describe('Edit addresses path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
expect(result).toContain('Some fields are invalid');
done();
})
.catch(catchErrors(done));

View File

@ -102,7 +102,7 @@ describe('Add greuge path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
expect(result).toContain('Some fields are invalid');
done();
})
.catch(catchErrors(done));
@ -111,25 +111,25 @@ describe('Add greuge path', () => {
it(`should receive an error if all fields are empty but date and amount on submit`, done => {
nightmare
.type(selectors.greuge.amountInput, 999)
.click(selectors.credit.saveButton)
.click(selectors.greuge.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
expect(result).toContain('Some fields are invalid');
done();
})
.catch(catchErrors(done));
});
it(`should receive an error if all fields are empty but date and amount on submit`, done => {
it(`should receive an error if all fields are empty but date and description on submit`, done => {
nightmare
.clearInput(selectors.greuge.amountInput)
.type(selectors.greuge.descriptionInput, 'Bat-flying suite with anti-APCR rounds')
.click(selectors.credit.saveButton)
.type(selectors.greuge.descriptionInput, 'new armor for Batman!')
.click(selectors.greuge.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
expect(result).toContain('Some fields are invalid');
done();
})
.catch(catchErrors(done));
@ -140,11 +140,39 @@ describe('Add greuge path', () => {
.clearInput(selectors.greuge.descriptionInput)
.waitToClick(selectors.greuge.typeInput)
.waitToClick(selectors.greuge.typeSecondOption)
.click(selectors.credit.saveButton)
.click(selectors.greuge.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
expect(result).toContain('Some fields are invalid');
done();
})
.catch(catchErrors(done));
});
it(`should create a new greuge with all its data`, done => {
nightmare
.type(selectors.greuge.amountInput, 999)
.type(selectors.greuge.descriptionInput, 'new armor for Batman!')
.click(selectors.greuge.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Data saved!');
done();
})
.catch(catchErrors(done));
});
it('should confirm the greuge was added to the list', done => {
nightmare
.waitForSnackbarReset()
.wait(selectors.greuge.firstGreugeText)
.getInnerText(selectors.greuge.firstGreugeText)
.then(value => {
expect(value).toContain(999);
expect(value).toContain('new armor for Batman!');
expect(value).toContain('Diff');
done();
})
.catch(catchErrors(done));

View File

@ -0,0 +1,99 @@
import config from '../helpers/config.js';
import createNightmare from '../helpers/nightmare';
import selectors from '../helpers/selectors.js';
import {catchErrors} from '../../services/utils/jasmineHelpers';
const nightmare = createNightmare();
const moduleAccessViewHashURL = '#!/';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
describe('mandate path', () => {
describe('warm up', () => {
it('should warm up login and fixtures', done => {
nightmare
.login()
.waitForURL(moduleAccessViewHashURL)
.waitToClick(selectors.globalItems.logOutButton)
.then(() => {
done();
})
.catch(catchErrors(done));
});
});
it('should log in', done => {
nightmare
.login()
.waitForURL(moduleAccessViewHashURL)
.url()
.then(url => {
expect(url).toEqual(config.url + moduleAccessViewHashURL);
done();
})
.catch(catchErrors(done));
});
it('should make sure the language is English', done => {
nightmare
.changeLanguageToEnglish()
.then(() => {
done();
})
.catch(catchErrors(done));
});
it('should click on the Clients button of the top bar menu', done => {
nightmare
.waitToClick(selectors.globalItems.applicationsMenuButton)
.wait(selectors.globalItems.applicationsMenuVisible)
.waitToClick(selectors.globalItems.clientsButton)
.wait(selectors.clientsIndex.createClientButton)
.url()
.then(url => {
expect(url).toEqual(config.url + '#!/clients');
done();
})
.catch(catchErrors(done));
});
it('should search for the user Petter Parker', done => {
nightmare
.wait(selectors.clientsIndex.searchResult)
.type(selectors.clientsIndex.searchClientInput, 'Petter Parker')
.click(selectors.clientsIndex.searchButton)
.waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
.countSearchResults(selectors.clientsIndex.searchResult)
.then(result => {
expect(result).toEqual(1);
done();
})
.catch(catchErrors(done));
});
it(`should click on the search result to access to the client's mandate`, done => {
nightmare
.waitForTextInElement(selectors.clientsIndex.searchResult, 'Petter')
.waitToClick(selectors.clientsIndex.searchResult)
.waitToClick(selectors.mandate.mandateButton)
.waitForURL('mandate')
.url()
.then(url => {
expect(url).toContain('mandate');
done();
})
.catch(catchErrors(done));
});
it('should confirm the client has a mandate of the CORE type', done => {
nightmare
.wait(selectors.mandate.firstMandateText)
.getInnerText(selectors.mandate.firstMandateText)
.then(value => {
expect(value).toContain('1');
expect(value).toContain('WAY');
expect(value).toContain('CORE');
done();
})
.catch(catchErrors(done));
});
});

View File

@ -40,7 +40,7 @@ gulp.task('client', ['clean'], function() {
gulp.task('nginxRestart', callback => {
let isWindows = /^win/.test(process.platform);
let command = isWindows ? './dev.cmd' : './dev.sh';
let command = isWindows ? '.\\dev.cmd' : './dev.sh';
exec(command, (err, stdout, stderr) => {
console.log(stdout);
callback(err);

View File

@ -72,8 +72,7 @@
"build": "webpack --progress --colors",
"dev": "webpack-dev-server --progress --colors",
"lint": "eslint ./ --cache --ignore-pattern .gitignore",
"test": "node services_tests",
"testWatcher": "nodemon -q services_tests.js -w services",
"test": "nodemon -q services_tests.js -w services",
"e2e": "node e2e_tests"
}
}

View File

@ -18,15 +18,9 @@ module.exports = function(Self) {
// Validations
Self.validatesUniquenessOf('name', {
message: 'El nombre debe ser único'
});
Self.validatesUniquenessOf('fi', {
message: 'El NIF/CIF debe ser único'
});
Self.validatesPresenceOf('socialName', {
message: 'Debe especificarse la razón social'
});
Self.validatesUniquenessOf('socialName', {
message: 'La razón social debe ser única'
});

View File

@ -22,7 +22,8 @@
"description": "Fiscal indentifier"
},
"socialName": {
"type": "string"
"type": "string",
"required": true
},
"contact": {
"type": "string"

View File

@ -2,11 +2,8 @@ module.exports = function(Self) {
require('../methods/greuge/filter.js')(Self);
require('../methods/greuge/totalGreuge.js')(Self);
Self.validatesPresenceOf('description', 'amount', 'greugeTypeFk', {
message: 'Importe es un campo obligatorio'
});
Self.validatesLengthOf('description', {
max: 45,
message: 'description es un campo max 45'
message: 'La description debe tener maximo 45 caracteres'
});
};

View File

@ -14,10 +14,12 @@
"description": "Identifier"
},
"description": {
"type": "String"
"type": "String",
"required": true
},
"amount": {
"type": "Number"
"type": "Number",
"required": true
},
"shipped": {
"type": "date"
@ -35,7 +37,8 @@
"greugeType": {
"type": "belongsTo",
"model": "GreugeType",
"foreignKey": "greugeTypeFk"
"foreignKey": "greugeTypeFk",
"required": true
}
}
}

View File

@ -525,5 +525,5 @@ INSERT INTO `vn`.`mandateType`(`id`, `name`)
INSERT INTO `vn`.`mandate`(`id`, `clientFk`, `companyFk`, `code`, `created`, `mandateTypeFk`)
VALUES
(1, 1, 442, '1-1', CURDATE(), 2);
(1, 2, 442, '1-1', CURDATE(), 2);

View File

@ -36,7 +36,7 @@ module.exports = function(app) {
for (let validation of validations[fieldName]) {
let options = validation.options;
if ((options && options.async) ||
if ((options && options.async) ||
(validation.validation == 'custom' && !validation.isExportable))
continue;

View File

@ -17,13 +17,12 @@ var jasmine = new Jasmine();
var SpecReporter = require('jasmine-spec-reporter').SpecReporter;
jasmine.loadConfig({
spec_dir: 'services/',
spec_dir: 'services',
spec_files: [
'**/specs/*[sS]pec.js'
'client/common/**/*[sS]pec.js'
],
helpers: [
// to implement
// '/api/utils/jasmineHelpers.js'
'/services/utils/jasmineHelpers.js'
]
});
@ -36,6 +35,5 @@ jasmine.addReporter(new SpecReporter({
}
}));
exports.start = () => {
jasmine.execute();
};
jasmine.execute();