Commit 44c4eade authored by Pedro Eduardo Trujillo's avatar Pedro Eduardo Trujillo
Browse files

Corrige detalles de testeo

Mejora tests de perfil de usuario y de navegación mediante sidebar, para
que sean válidos y no dependan de otros tests.

Mejora la detección de carga de la app y las esperas a que termine,
eliminando restos arcaicos de contadores extraños. En su lugar, fija
timeouts configurables de tiempo predecible.

Documenta nuevo ejemplo de testeo.
parent fbbd4144
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -160,3 +160,15 @@ grunt test-functional-remote \
  --suitesGroups="common" \
  --browser=chrome
```

También es posible lanzar estos tests bajo un usuario concreto. Por ejemplo, para lanzar tests funcionales del grupo de suites `common` sobre el servicio arrancado en el host (escuchando en el puerto 80) con rol de administrador, usando el usuario `test@redmic.es` con password `changeMe`, en navegador Mozilla Firefox (con interfaz):

```sh
grunt test-functional-remote \
  --serverUrl="http://172.17.0.1" \
  --role=administrator \
  --user="test@redmic.es" \
  --pass="changeMe" \
  --suitesGroups="common" \
  --browser=firefox
```
+43 −7
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ define([
	, LoginPage
	, Utils
) {

	var indexPage,

		userImageContainerSelector = 'div.infoContainer div.imageContainerEdit span',
@@ -150,7 +151,7 @@ define([
				var editButtonSelector = 'div.infoContainer :nth-child(2) div.rowsContainer :first-child i.fa-edit',
					textInputSelector = 'div[data-redmic-model="firstName"] div.dijitInputContainer input',
					valuesObj = {
						newValue: 'Benancio'
						newValue: Date.now().toString()
					};

				return goToProfile()
@@ -190,21 +191,57 @@ define([
				var _sectorRowSelector = 'div.infoContainer :nth-child(2) div.rowsContainer :nth-child(3) ',
					editButtonSelector = _sectorRowSelector + 'i.fa-edit',
					sectorSpanSelector = _sectorRowSelector + 'span.spanTemplate span.name',
					inputElementSelector = 'div[data-redmic-model="sector"] div.containerFilteringSelect input:nth-child(2)',
					selectInputSelector = 'div[data-redmic-model="sector"] div.buttonSearch',
					selectInputValueSelector = 'span[data-redmic-id="10"]',
					selectInputAltValueSelector = 'span[data-redmic-id="11"]',
					valuesObj = {};

				return goToProfile()
					.then(Utils.clickElement(editButtonSelector))
					.then(Utils.checkLoadingIsGone())
					// obtiene el valor actual
					.findByCssSelector(inputElementSelector)
						.then(lang.partial(function(values) {

							this.getProperty('value')
								.then(lang.partial(function(innerValues, inputValue) {

									innerValues.oldValue = inputValue;
								}, values));
						}, valuesObj))
						.end()
					// cambia el valor a una opción diferente
					.then(Utils.clickElement(selectInputSelector))
					.sleep(Config.timeout.shortSleep)
					.findByCssSelector(selectInputValueSelector)
						.getVisibleText()
						.then(lang.partial(function(values, text) {
						.then(lang.partial(function(values, text, setContext) {

							// usa el nuevo valor alternativo si ya estaba en el nuevo valor predefinido
							if (values.oldValue === text) {
								return this.parent
									.end()
									.sleep(Config.timeout.shortSleep)
									.findByCssSelector(selectInputAltValueSelector)
										.getVisibleText()
										.then(lang.partial(function(args, innerText) {

											args.values.newValue = innerText;
										}, {
											values,
											setContext
										}))
										.click()
										.end(2);
							}

							// usa el nuevo valor predefinido
							values.newValue = text;

							return this.parent
								.click();
						}, valuesObj))
						.click()
						.end()
					.then(Utils.clickElement(Config.selector.saveButton))
					.then(Utils.checkLoadingIsGone())
@@ -216,7 +253,7 @@ define([
							assert.strictEqual(text, values.newValue, 'El nuevo valor no coincide con el seleccionado');
						}, valuesObj))
						.end()
					// restaura el valor original
					// guarda el valor a vacío y lo comprueba
					.then(Utils.clickElement(editButtonSelector))
					.then(Utils.checkLoadingIsGone())
					.then(Utils.clickElement(Config.selector.clearButton))
@@ -226,7 +263,6 @@ define([

			'Should_UpdateUserPassword_When_EditUserPassword': function() {

				// TODO falla en chrome salvo en modo headless (parece problema del driver, navegador o leadfoot)
				var _sectorRowSelector = 'div.infoContainer :nth-child(2) div.rowsContainer :nth-child(4) ',
					editButtonSelector = _sectorRowSelector + 'i.fa-edit',
					newPasswordInputSelector = 'div[data-redmic-model="password"] div.dijitInputContainer input',
+44 −14
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ define([
		};
	}

	function testSidebarEntries() {
	function testSidebarEntries(/*Boolean*/ secondaryEntriesFlag) {

		return function(allowedModules) {

@@ -82,39 +82,69 @@ define([
				context = context
					.then(Utils.checkLoadingIsGone());

				if (path) {
				if (!secondaryEntriesFlag) {
					if (!path) {
						continue;
					}
					context = context
						.then(testPrimaryEntry(name));
				} else if (innerModules) {
					context = context
						.then(testSecondaryEntries(name, innerModules));

					continue;
				}

				if (!innerModules) {
					continue;
				}

				context = context
					.then(Utils.checkLoadingIsGone());
					.then(testSecondaryEntries(name, innerModules));
			}

			return context;
		};
	}

	var registerSuite = intern.getInterface('object').registerSuite;
	function readLocalStorage() {

		return this.session.getLocalStorageItem(allowedModulesKey);
	}

	function clearLocalStorage() {

		return this.session.clearLocalStorage();
	}

	var registerSuite = intern.getInterface('object').registerSuite,
		assert = intern.getPlugin('chai').assert;

	registerSuite(suiteName, {
		Should_BeAbleToNavigateToAllModules_When_ReceiveAllowedModules: function() {
		Should_BeAbleToNavigateToSidebarPrimaryModules_When_ReceiveAllowedModules: function() {

			indexPage = new LoginPage(this);

			return indexPage
				.login()
				.then(lang.partial(function(itemKey) {
				.then(readLocalStorage)
				.then(testSidebarEntries(false))
				.then(clearLocalStorage, function() {

					return this.session.getLocalStorageItem(itemKey);
				}, allowedModulesKey))
				.then(testSidebarEntries())
				.then(function() {
					lang.hitch(this, clearLocalStorage)();
					assert.fail('No se pudo recorrer todos los módulos con entrada primaria');
				});
		},

					return this.session.clearLocalStorage();
		Should_BeAbleToNavigateToSidebarSecondaryModules_When_ReceiveAllowedModules: function() {

			indexPage = new LoginPage(this);

			return indexPage
				.login()
				.then(readLocalStorage)
				.then(testSidebarEntries(true))
				.then(clearLocalStorage, function() {

					lang.hitch(this, clearLocalStorage)();
					assert.fail('No se pudo recorrer todos los módulos con entrada secundaria');
				});
		}
	});
+6 −8
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@ define([], function() {
			, map: 'div.map.leaflet-container'
			, fileUploadInput: 'input.dz-hidden-input'
			, notLoading: ':not([loading="true"])'
			, loading: '[loading="true"]'
			, loading: '*[loading="true"]'
			, pdfViewer: 'div.windowContent object[data]'
			, okAlertify: 'div.alertify div.ajs-footer button.ajs-ok'
			, cancelAlertify: 'div.alertify div.ajs-footer button.ajs-cancel'
@@ -38,17 +38,15 @@ define([], function() {
			, feedback: '/feedback'
		},
		timeout: {
			veryLongFindElement: 70000,
			longFindElement: 30000,
			findElement: 5000,
			shortFindElement: 500,
			findElement: 5000,
			longFindElement: 30000,
			veryLongFindElement: 70000,
			veryShortSleep: 250,
			shortSleep: 500,
			longSleep: 1000,
			veryLongSleep: 5000
		},
		counter: {
			findLoading: 300
			veryLongSleep: 5000,
			loading: 20000
		}
	};
});
+31 −20
Original line number Diff line number Diff line
@@ -110,11 +110,11 @@ define([
			//	summary:
			//		Busca el elemento correspondiente al selector especificado y clickea sobre él.

			return lang.partial(function(self, elementSelector) {
			return lang.partial(function(self, selector) {

				return this.parent
					.then(self.checkLoadingIsGone())
					.findByCssSelector(elementSelector)
					.findByCssSelector(selector)
						.click();
			}, this, elementSelector);
		},
@@ -123,11 +123,11 @@ define([
			//	summary:
			//		Busca el elemento mostrado correspondiente al selector especificado y clickea sobre él.

			return lang.partial(function(self, elementSelector) {
			return lang.partial(function(self, selector) {

				return this.parent
					.then(self.checkLoadingIsGone())
					.findDisplayedByCssSelector(elementSelector)
					.findDisplayedByCssSelector(selector)
						.click();
			}, this, elementSelector);
		},
@@ -773,40 +773,51 @@ define([

		checkLoadingIsGone: function() {
			//	summary:
			//		Comprueba que no exista ningún cargando en la aplicación.
			//		Comprueba que no exista ningún "cargando" en la aplicación.
			//		Si encuentra alguno, espera hasta que se elimine.
			//		Si supera el limite de carga devuelve un error.

			function onLoadingItemFound(args, elements) {

				args.loadingItemsFound++;
			function onLoadingGone() {

				return this
					.then(lang.hitch(this, seekLoadingItems, args));
				// Captura error para continuar cuando el "cargando" se ha ido
			}

			function seekLoadingItems(args) {

				if (args.loadingItemsFound >= Config.counter.findLoading) {
				var endTimestamp = args.endTimestamp;

					this.setFindTimeout(Config.timeout.findElement);
					throw new Error('Limite de tiempo de carga superado');
				if (Date.now() >= endTimestamp) {
					args.timeoutReached = true;
					return this;
				}

				return this
					.sleep(Config.timeout.veryShortSleep)
					.findByCssSelector('*' + Config.selector.loading)
					.then(lang.hitch(this, onLoadingItemFound, args), function() {});
					.findByCssSelector(Config.selector.loading)
					.then(
						lang.hitch(this, seekLoadingItems, args),
						lang.hitch(this, onLoadingGone)
					);
			}

			function afterSoughtLoadingItems(args) {

				if (args.timeoutReached) {
					assert.fail('Limite de tiempo de carga superado');
				}
			}

			return function() {

				var args = {
					endTimestamp: Date.now() + Config.timeout.loading,
					timeoutReached: false
				};

				return this.parent
					.setFindTimeout(Config.timeout.shortFindElement)
					.then(lang.hitch(this.parent, seekLoadingItems, {
						loadingItemsFound: 0
					}))
					.setFindTimeout(Config.timeout.findElement);
					.then(lang.hitch(this.parent, seekLoadingItems, args))
					.setFindTimeout(Config.timeout.findElement)
					.then(lang.hitch(this.parent, afterSoughtLoadingItems, args));
			};
		},

Loading