diff --git a/gpii/configs/review4.production.json b/gpii/configs/review4.production.json new file mode 100644 index 000000000..59d77a72e --- /dev/null +++ b/gpii/configs/review4.production.json @@ -0,0 +1,37 @@ +{ + "typeName": "review4.production", + "options": { + "gradeNames": ["autoInit", "fluid.littleComponent"], + "components": { + "server": { + "type": "kettle.server", + "options": { + "logging": true, + "port": 8081 + } + } + }, + "devUrls": { + "preferences": "http://preferences.gpii.net/preferences/%userToken", + "deviceReporter": "http://localhost:%port/device", + "solutionsRegistry": "file://%root/../../../testData/solutions/%os.json" + }, + "matchMakers": { + "flat": { + "url": "http://localhost:8081" + }, + "Statistical": { + "url": "http://stmm.gpii.net" + }, + "RuleBased": { + "url": "http://rbmm.gpii.net" + } + } + }, + "includes": [ + "../node_modules/deviceReporter/configs/production.json", + "../node_modules/flowManager/configs/development.json", + "../node_modules/solutionsRegistry/configs/development.json", + "../node_modules/flatMatchMaker/configs/development.all.local.json" + ] +} \ No newline at end of file diff --git a/gpii/configs/review4.production.txt b/gpii/configs/review4.production.txt new file mode 100644 index 000000000..ecccb5836 --- /dev/null +++ b/gpii/configs/review4.production.txt @@ -0,0 +1,20 @@ +review4.production +========================== + +This configuration runs the system in production mode, but keeps the logging enabled. It refers to both the remote matchmakers and preferences server and uses the dynamic device reporter. The following services are expected to be available when using this configuration: + +* http://preferences.gpii.net - the preferences server +* http://rbmm.gpii.net - the rule based matchmaker +* http://stmm.gpii.net - the statistical matchmaker + +* The following components are running on the local machine: +** flowManager +** OntologyHandler +** solutionsRegistry (reading registry from file) +** deviceReporter (dynamic mode) +** matchMakerFramework +** flatMatchMaker +** lifecycleManager + +**THIS CONFIGURATION IS NOT REGULARLY TESTED AND CANNOT BE TRUSTED TO WORK** +It has been created for the year 4 reviews of C4A and will be tested in that connection, but it currently does not have any test-coverage via acceptance or integration tests. diff --git a/gpii/node_modules/contextManager/index.js b/gpii/node_modules/contextManager/index.js index f68237a65..d0a5a6edb 100644 --- a/gpii/node_modules/contextManager/index.js +++ b/gpii/node_modules/contextManager/index.js @@ -3,4 +3,5 @@ var fluid = require("infusion"); var loader = fluid.getLoader(__dirname); loader.require("./src/ContextManager.js"); -loader.require("./src/ContextManagerUtilities.js"); \ No newline at end of file +loader.require("./src/ContextManagerUtilities.js"); +loader.require("./src/CASConnector.js"); \ No newline at end of file diff --git a/gpii/node_modules/contextManager/src/CASConnector.js b/gpii/node_modules/contextManager/src/CASConnector.js new file mode 100644 index 000000000..277d0f770 --- /dev/null +++ b/gpii/node_modules/contextManager/src/CASConnector.js @@ -0,0 +1,145 @@ +/* +* Context Manager +* +* Copyright 2015 Raising the Floor - International +* +* Licensed under the New BSD license. You may not use this file except in +* compliance with this License. +* +* The research leading to these results has received funding from the European Union's +* Seventh Framework Programme (FP7/2007-2013) +* under grant agreement no. 289016. +* +* You may obtain a copy of the License at +* https://github.com/GPII/universal/blob/master/LICENSE.txt +*/ + +(function () { + "use strict"; + + var fluid = require("infusion"), + io = require("socket.io-client"), + gpii = fluid.registerNamespace("gpii"); + + fluid.registerNamespace("gpii.contextManager.CASConnector"); + + fluid.defaults("gpii.contextManager.CASConnector", { + gradeNames: ["fluid.eventedComponent", "autoInit"], + members: { + socket: null, + CASUrl: "http://localhost:8888/context-stream" + }, + events: { + onConnectRequest: null, + onEmitRequest: null + }, + listeners: { + onCreate: "gpii.contextManager.CASConnector.connectSocket", + onDestroy: "gpii.contextManager.CASConnector.disconnectSocket" + }, + invokers: { + connectSocket: { + funcName: "gpii.contextManager.CASConnector.connectSocket", + args: [ "{that}", "{contextManager}" ] + }, + handleInput: { + funcName: "gpii.contextManager.CASConnector.handleInput", + args: [ "{contextManager}", "{arguments}.0" ] + } + } + }); + + gpii.contextManager.CASConnector.disconnectSocket = function (that) { + if (that.socket) { + that.socket.disconnect(); + }; + } + gpii.contextManager.CASConnector.connectSocket = function (that) { + var location = [2.194909,41.402455]; + console.log("Connecting to socket at "+that.CASUrl); + that.socket = io.connect(that.CASUrl); + + that.socket.on("connect", function () { + fluid.log("Connected to Context Aware Server"); + + that.socket.emit('location', location); + fluid.log("Location emitted to Contet Aware Server: "+location); + + that.socket.on('new-user', function (id) { + console.log("Got user ID from Context Aware Server: " +id) + that.socket.emit('subscribe', id); + console.log("Subscribed to Context Aware Server") + that.socket.on('fired', function (data) { + // console.log("Retrieved data from Context Aware Server: " + JSON.stringify(i)); + that.handleInput(data); + }); + }); + }); + + that.socket.on("error", function (a) { + console.log("Error: " +JSON.stringify(a)); + }); + + that.socket.on("disconnect", function (a) { + // To avoid multiple listeners being assigned to a socket in case the connection is unstable or + // the CAS is restarted, this hack has been implementedt. This should be adressed before this pull- + // request is ready for master + that.socket.removeAllListeners(); + that.connectSocket(); + }); + }; + + /* Data will be input in the format: + { + "id": "54b942e0fd0f7ad45d3aa585", + "data": [ + { + "at": "2015-01-16T16:57:05.439Z", + "value": 8, + "trigger": { + "_id": "54b92334bad6772c3eb0791c", + "_sensor": { + "_id": "54b91ad9bad6772c3eb07169", + "name": "light", + "type": "Float", + "unit": "%", + "devid": "1", + "__v": 0, + "_last": "54b942e0fd0f7ad45d3aa584" + }, + "type": "threshold", + "operator": "gt", + "threshold": 6, + "__v": 0, + "triggered": true, + "hysteresis": 0 + } + } + ] + } + */ + gpii.contextManager.CASConnector.sensorMap = { + "light": "http://registry.gpii.net/common/environment/visual.luminance", + "noise": "http://registry.gpii.net/common/environment/auditory.noise" + }; + + gpii.contextManager.CASConnector.handleInput = function (contextManager, data) { + if (!data || !data.data || !data.data[0]) { + fluid.log("WARNING: Invalid data received from sensor, so ignoring: "+JSON.stringify(data)); + return; + } + data = data.data[0]; + if (data.value === undefined || !data.trigger || !data.trigger._sensor) { + fluid.log("WARNING: need value and name from sensor - so ignoring: "+data); + return; + } + var contextName = gpii.contextManager.CASConnector.sensorMap[data.trigger._sensor.name]; + if (contextName === undefined) { + fluid.log("Invalid sensor name given - so ignoring: " +data.trigger._sensor.name); + return; + } + var newContext = {}; + newContext[contextName] = data.value; + gpii.contextManager.environmentChanged(contextManager, newContext); + } +})(); diff --git a/gpii/node_modules/contextManager/src/ContextManager.js b/gpii/node_modules/contextManager/src/ContextManager.js index 33ae21efa..ef7fa77f1 100644 --- a/gpii/node_modules/contextManager/src/ContextManager.js +++ b/gpii/node_modules/contextManager/src/ContextManager.js @@ -32,6 +32,9 @@ components: { transformer: { type: "gpii.transformer" + }, + CASConnector: { + type: "gpii.contextManager.CASConnector" } }, invokers: { @@ -145,23 +148,21 @@ * that.model.currentContext) **/ gpii.contextManager.evaluateConditions = function (that, lifecycleManager, context) { - // find logged in users - var activeSessions = lifecycleManager.getActiveSessionTokens(); // if none is logged in, do nothing - if (activeSessions.length === 0) { + if (lifecycleManager.getUserTokens().length === 0) { return; } - var activeSession = lifecycleManager.getSession(activeSessions); - var newActiveContexts = gpii.contextManager.utils.findActiveContexts(context, activeSession.matchMakerOutput); + var session = lifecycleManager.getSession(); + var newActiveContexts = gpii.contextManager.utils.findActiveContexts(context, session.matchMakerOutput); fluid.log("New active contexts: " + newActiveContexts); - if (newActiveContexts[0] === activeSession.activeContextName) { - console.log("Same context as before (" + activeSession.appliedContext + ") so doing nothing"); + if (newActiveContexts[0] === session.activeContextName) { + console.log("Same context as before (" + session.appliedContext + ") so doing nothing"); return; } - var activeConfiguration = activeSession.matchMakerOutput.inferredConfiguration[newActiveContexts[0]]; - var lifecycleInstructions = that.transformer.configurationToSettings(activeConfiguration, activeSession.solutionsRegistryEntries); + var activeConfiguration = session.matchMakerOutput.inferredConfiguration[newActiveContexts[0]]; + var lifecycleInstructions = that.transformer.configurationToSettings(activeConfiguration, session.solutionsRegistryEntries); var finalPayload = { - userToken: activeSession.userToken, + userToken: session.userToken, lifecycleInstructions: lifecycleInstructions, activeContextName: newActiveContexts[0], activeConfiguration: activeConfiguration @@ -174,7 +175,7 @@ // "finalPayload" as instructions on how to configure the system.. once configured, // the applied settings are stored in 'activeConfiguration' delete finalPayload.lifecycleInstructions; - $.extend(true, activeSession, finalPayload); + $.extend(true, session, finalPayload); } fluid.log("Successfully updated configuration triggered by context changes"); }); diff --git a/gpii/node_modules/flowManager/src/FlowManagerUtilities.js b/gpii/node_modules/flowManager/src/FlowManagerUtilities.js index e23bb2255..fd06c12bc 100644 --- a/gpii/node_modules/flowManager/src/FlowManagerUtilities.js +++ b/gpii/node_modules/flowManager/src/FlowManagerUtilities.js @@ -198,9 +198,6 @@ lifecycleManager: "{flowManager}.lifecycleManager" }, invokers: { - getActiveSessionTokens: { - func: "{lifecycleManager}.getActiveSessionTokens" - }, withSession: { funcName: "gpii.request.flowManager.sessionAware.withSession", args: ["{that}", "{flowManager}.lifecycleManager", "{requestProxy}.events", "{arguments}.0", "{arguments}.1"] @@ -209,7 +206,7 @@ }); gpii.request.flowManager.sessionAware.withSession = function (that, lifecycleManager, events, callback, failMessage) { - var userTokens = that.getActiveSessionTokens(); + var userTokens = lifecycleManager.getUserTokens(); if (userTokens.length === 0) { failMessage = failMessage || "Error handling request which required active session, but none was active"; events.onError.fire({ @@ -218,7 +215,7 @@ message: failMessage }); } else { - var session = lifecycleManager.getSession(userTokens); + var session = lifecycleManager.getSession(); callback(session, userTokens); } }; diff --git a/gpii/node_modules/flowManager/src/UserLogonStateChange.js b/gpii/node_modules/flowManager/src/UserLogonStateChange.js index fb96bc0fe..79211cf43 100644 --- a/gpii/node_modules/flowManager/src/UserLogonStateChange.js +++ b/gpii/node_modules/flowManager/src/UserLogonStateChange.js @@ -23,67 +23,89 @@ var gpii = fluid.registerNamespace("gpii"); fluid.registerNamespace("gpii.request.flowManager.userLogonStateChange"); - gpii.request.flowManager.userLogonStateChange.handleResetToken = function (activeToken, that) { - if (activeToken === undefined) { // if no user is logged in + gpii.request.flowManager.userLogonStateChange.handleResetToken = function (activeTokens, that) { + if (activeTokens.length === 0) { // if no user is logged in that.errorResponse("No users currently logged in - nothing to reset", 409); } else { - fluid.log("Logging out the user with token " + activeToken); - that.logoutUser(activeToken); + fluid.log("Retrieved Logging out the user(s) with token " + activeTokens); + that.responseMsg = "Retrieved reset token, so logging out the user(s) " + activeTokens; + that.logoutUser(activeTokens); } }; - /** - * /user/:userToken/logonChange handler - * * If no user is logged in, user will be logged in - * * If is logged in, will be logged out - * * If another user is logged in, nothing happens + /* /user//logonChange: + * * If 0 users are logged in, user will be logged in + * * If is logged in, will be logged out + * * if and one other user are logged in, will be logged out + * * If 2 other users are logged in, nothing happens + * * If "reset" is used as the for any of the above URLs, any currently logged in user will be logged out */ gpii.request.flowManager.userLogonStateChange.logonChangeHandler = function (userToken, lifecycleManager, that) { // find currently logged in user: - var activeTokens = lifecycleManager.getActiveSessionTokens(); + var activeTokens = lifecycleManager.getUserTokens(); if (userToken === "reset") { - gpii.request.flowManager.userLogonStateChange.handleResetToken(activeTokens[0], that); + gpii.request.flowManager.userLogonStateChange.handleResetToken(activeTokens, that); return; } - if (activeTokens.length === 0) { // if no user is logged in + + if (fluid.contains(activeTokens, userToken)) { + that.logoutUser(userToken); + return; + } + + if (activeTokens.length === 0 || activeTokens.length === 1) { that.loginUser(userToken); return; } - if (activeTokens.length === 1) { - if (activeTokens[0] === userToken) { - that.logoutUser(activeTokens[0]); - } else { - that.errorResponse("Got logon change request from user " + userToken + ", but the user " + - activeTokens[0] + " is already logged in. So ignoring request.", 409); - } + if (activeTokens.length === 2) { + that.errorResponse("Two other users are already logged in. Ignoring logon change request", 409); } }; - gpii.request.flowManager.userLogonStateChange.errorResponse = function (request, message, statusCode) { + gpii.request.flowManager.userLogonStateChange.errorResponse = function (that, request, message, statusCode) { request.events.onError.fire({ statusCode: statusCode || 500, message: message || "Unknown error occured on logon change action" }); + that.responseMsg = null; }; - gpii.request.flowManager.userLogonStateChange.startLifecycle = function (lifecycleManager, lifecyclePayload, event) { + gpii.request.flowManager.userLogonStateChange.startLifecycle = function (that, lifecycleManager, lifecyclePayload, event) { console.log("Got final payload " + JSON.stringify(lifecyclePayload, null, 2)); lifecycleManager.start(lifecyclePayload, gpii.request.flowManager.logAndNotify("Lifecycle manager returned: ", event, function () { - return "User with token " + lifecyclePayload.userToken + " was successfully logged in."; + var message = that.responseMsg || "User with token " + lifecyclePayload.userToken + " was successfully logged in."; + that.responseMsg = null; + return message; } )); }; - gpii.request.flowManager.userLogonStateChange.logoutUser = function (requestProxy, lifecycleManager, userToken) { - lifecycleManager.stop({ - userToken: userToken - }, function onSuccess(response) { + gpii.request.flowManager.userLogonStateChange.logoutUser = function (that, requestProxy, lifecycleManager, userToken) { + var activeTokens = lifecycleManager.getUserTokens(); + var remainingToken = null; + var message = "User with token " + userToken + " was successfully logged out."; + if (activeTokens.length === 2 && userToken.length !== 2) { + // if two users are logged in, restore system, then log back in the remaining user: + fluid.each(activeTokens, function (activeToken) { + if (activeToken !== userToken) { + remainingToken = activeToken; + } + }); + } + lifecycleManager.stop({ userToken: userToken }, function onSuccess(response) { fluid.log("Lifecycle manager returned: ", response); - requestProxy.events.onSuccess.fire("User with token " + userToken + - " was successfully logged out."); + if (remainingToken) { + // TODO this should probably be done in a prettier way, since we already have device + // and solution information available. But for simplicity, we will do a regular login + that.responseMsg = message; + that.events.onUserToken.fire(remainingToken); + } else { + requestProxy.events.onSuccess.fire(that.responseMsg || message); + that.responseMsg = null; + } }); }; @@ -108,7 +130,7 @@ invokers: { startLifecycle: { funcName: "gpii.request.flowManager.userLogonStateChange.startLifecycle", - args: [ "{flowManager}.lifecycleManager", "{arguments}.0", "{requestProxy}.events.onSuccess" ] + args: [ "{that}", "{flowManager}.lifecycleManager", "{arguments}.0", "{requestProxy}.events.onSuccess" ] // final payload from matchmaking process }, getDeviceContext: { @@ -117,7 +139,7 @@ }, logoutUser: { funcName: "gpii.request.flowManager.userLogonStateChange.logoutUser", - args: ["{requestProxy}", "{flowManager}.lifecycleManager", "{arguments}.0"], + args: ["{that}", "{requestProxy}", "{flowManager}.lifecycleManager", "{arguments}.0"], dynamic: true }, loginUser: { @@ -127,12 +149,15 @@ }, errorResponse: { funcName: "gpii.request.flowManager.userLogonStateChange.errorResponse", - args: ["{request}", "{arguments}.0", "{arguments}.1"] + args: ["{that}", "{request}", "{arguments}.0", "{arguments}.1"] } }, listeners: { onUserToken: "{that}.getDeviceContext", onMatchDone: "{that}.startLifecycle" + }, + members: { + responseMsg: null } }); @@ -148,21 +173,22 @@ /** * Handler for URL: /user//login: - * * If no user is logged in, will be logged in - * * If another user is logged in, nothing will happen - * * If token is "reset", log out any already logged in user. + * * If 0 users are logged in, will be logged in + * * If 1 other user is logged in, will be logged in as dual-user mode + * * If 2 other users are logged in, nothing happens + * * If token is "reset", log out any already logged in users. */ gpii.request.flowManager.userLogonStateChange.loginHandler = function (userToken, lifecycleManager, that) { - var activeTokens = lifecycleManager.getActiveSessionTokens(); // find currently logged in user: + var activeTokens = lifecycleManager.getUserTokens(); // find currently logged in user: if (userToken === "reset") { - gpii.request.flowManager.userLogonStateChange.handleResetToken(activeTokens[0], that); + gpii.request.flowManager.userLogonStateChange.handleResetToken(activeTokens, that); return; } - if (activeTokens.length === 1) { // if another user is already logged in: - that.errorResponse("Got log in request from user " + userToken + ", but the user " + - activeTokens[0] + " is already logged in. So ignoring login request.", 409); + if (activeTokens.length === 2) { // if another user is already logged in: + that.errorResponse("Got login action from user " + userToken + ", but two users are " + + "already logged in. So ignoring login request action.", 409); return; } @@ -181,31 +207,32 @@ /** * Handler for the URL /user//logout: - * * If no user is logged in, nothing happens - * * if user mytoken is logged in, he will be used out - * * If another user is logged in, nothing will happen - * * If token is "reset", log out any already logged in user. + * * If 0 users are logged in, nothing happens + * * if user is logged in, he will be logged out + * * If and one other user is logged in, will be logged out + * * If 2 other users are logged in, nothing happens */ gpii.request.flowManager.userLogonStateChange.logoutHandler = function (userToken, lifecycleManager, that) { - var activeTokens = lifecycleManager.getActiveSessionTokens(); // find currently logged in user: + var activeTokens = lifecycleManager.getUserTokens(); // find currently logged in user: if (userToken === "reset") { - gpii.request.flowManager.userLogonStateChange.handleResetToken(activeTokens[0], that); + gpii.request.flowManager.userLogonStateChange.handleResetToken(activeTokens, that); return; } if (activeTokens.length === 0) { // if no user is logged in - that.errorResponse("No user logged in, so ignoring logout action.", 409); + that.errorResponse("No users logged in, so ignoring logout action.", 409); return; } - if (activeTokens[0] === userToken) { - that.logoutUser(activeTokens[0]); - } else { - that.errorResponse("Got logout request from user " + userToken + ", but the user " + - activeTokens[0] + " is logged in. So ignoring the request.", 409); + if (fluid.contains(activeTokens, userToken) === false) { + that.errorResponse("Got logout request from user " + userToken + ", but that user " + + "is not logged in. So ignoring request.", 409); + return; } + + that.logoutUser(userToken); }; fluid.defaults("kettle.requests.request.handler.userLogout", { diff --git a/gpii/node_modules/flowManager/test/BrowserChannelTests.js b/gpii/node_modules/flowManager/test/BrowserChannelTests.js index 5a3d34194..5d75b6c3e 100644 --- a/gpii/node_modules/flowManager/test/BrowserChannelTests.js +++ b/gpii/node_modules/flowManager/test/BrowserChannelTests.js @@ -119,7 +119,7 @@ gpii.tests.flowManager.browserChannel.checkSettingsForFirefox = function () { }; gpii.tests.flowManager.browserChannel.checkErrorResponse = function (data) { - var expMsg = "No user logged in, so ignoring logout action."; + var expMsg = "No users logged in, so ignoring logout action."; data = JSON.parse(data); jqUnit.assertTrue("Received error as expected", data.isError); jqUnit.assertEquals("Received message as expected", expMsg, data.message); diff --git a/gpii/node_modules/flowManager/test/UpdateTests.js b/gpii/node_modules/flowManager/test/UpdateTests.js index 7e938797f..ae09ad148 100644 --- a/gpii/node_modules/flowManager/test/UpdateTests.js +++ b/gpii/node_modules/flowManager/test/UpdateTests.js @@ -82,8 +82,8 @@ gpii.tests.flowManager.update.testSecondUpdateRequest = function (data) { testUpdateRequest(gpii.tests.flowManager.update.tokenPrefsUpdate, data); }; -gpii.tests.flowManager.update.clearActiveSessions = function (activeSessions) { - delete activeSessions.testUser1; +gpii.tests.flowManager.update.clearSessions = function (lifecycleManager) { + delete lifecycleManager.session; fluid.pushSoftFailure(function testCondition() { fluid.builtinFail(false, ["This failure is expected (flow manager update tests)."]); }); @@ -172,8 +172,8 @@ var testDefs = [{ event: "{login}.events.onComplete", listener: "gpii.tests.flowManager.update.testLoginResponse" }, { - func: "gpii.tests.flowManager.update.clearActiveSessions", - args: "{tests}.configuration.server.flowManager.lifecycleManager.activeSessions" + func: "gpii.tests.flowManager.update.clearSessions", + args: "{tests}.configuration.server.flowManager.lifecycleManager" }, { func: "{updateRequest}.send", args: gpii.tests.flowManager.update.payload1 diff --git a/gpii/node_modules/lifecycleManager/src/LifecycleManager.js b/gpii/node_modules/lifecycleManager/src/LifecycleManager.js index f65c72db1..86739c930 100644 --- a/gpii/node_modules/lifecycleManager/src/LifecycleManager.js +++ b/gpii/node_modules/lifecycleManager/src/LifecycleManager.js @@ -38,16 +38,16 @@ var gpii = fluid.registerNamespace("gpii"); } }, members: { - activeSessions: {} + session: {} }, invokers: { - getActiveSessionTokens: { - funcName: "gpii.lifecycleManager.getActiveSessionTokens", - args: "{that}.activeSessions" - }, getSession: { funcName: "gpii.lifecycleManager.getSession", - args: ["{that}.activeSessions", "{arguments}.0"] // user token + args: [ "{that}.session" ] + }, + getUserTokens: { + funcName: "gpii.lifecycleManager.getUserTokens", + args: [ "{that}" ] }, // TODO: refactor these three methods so that they return promises stop: { @@ -371,19 +371,12 @@ var gpii = fluid.registerNamespace("gpii"); return fluid.promise.sequence(promises); }; - // Will return one of the users token keys for an active session - // TODO: We need to implement logic to ensure at most one of these is set, or - // to manage logic for superposition of sessions if we permit several (see GPII-102) - gpii.lifecycleManager.getActiveSessionTokens = function (activeSessions) { - return fluid.keys(activeSessions); + gpii.lifecycleManager.getSession = function (session) { + return session; }; - gpii.lifecycleManager.getSession = function (activeSessions, userTokens) { - if (userTokens.length === 0) { - fluid.fail("Attempt to get sessions without keys"); - } else { - return activeSessions[userTokens[0]]; - } + gpii.lifecycleManager.getUserTokens = function (that) { + return (that.session && that.session.userTokens) ? that.session.userTokens : []; }; /** @@ -393,8 +386,7 @@ var gpii = fluid.registerNamespace("gpii"); * settingsHandlers: transformed settings handler blocks */ gpii.lifecycleManager.stop = function (that, requestProxy, options, callback) { - var userToken = options.userToken; - var sessionState = that.activeSessions[userToken]; + var sessionState = that.session; if (!sessionState) { callback(false); return; @@ -407,7 +399,7 @@ var gpii = fluid.registerNamespace("gpii"); // TODO: In theory we could stop all solutions in parallel var sequence = fluid.promise.sequence(fluid.values(promises)); sequence.then(function () { - delete that.activeSessions[userToken]; + delete that.session; callback(true); }, function (error) { requestProxy.events.onError.fire(error); @@ -418,11 +410,10 @@ var gpii = fluid.registerNamespace("gpii"); * Update user preferences. */ gpii.lifecycleManager.update = function (that, requestProxy, finalPayload, callback) { - var userToken = finalPayload.userToken, - lifecycleInstructions = finalPayload.lifecycleInstructions; - var sessionState = that.activeSessions[userToken]; + var lifecycleInstructions = finalPayload.lifecycleInstructions; + var sessionState = that.session; if (!sessionState) { - fluid.fail("User with token ", userToken, " has no active session"); + fluid.fail("There currently is not active session to update"); } var promises = []; @@ -446,16 +437,26 @@ var gpii = fluid.registerNamespace("gpii"); gpii.lifecycleManager.start = function (that, requestProxy, finalPayload, callback) { var userToken = finalPayload.userToken, lifecycleInstructions = finalPayload.lifecycleInstructions; - if (that.activeSessions[userToken]) { - // TODO: develop async architecture to prevent rat's nest of callbacks - that.stop({userToken: userToken}, fluid.identity); + if (that.getUserTokens().length > 0) { + var userTokens = []; + // Generally we should, if we hit this point be in a situation of a double login + // but we double check here - and build the activeUserToken array for later: + if (finalPayload.preferences instanceof Array) { + userTokens = that.getUserTokens(); + } + // Indicate we want to log everyone out + that.stop({ userToken: null }, fluid.identity); + // but remember the currently logged in user (we deleted session on logout): + that.session = { + userTokens: userTokens + } } // TODO: Make global map of all users of session state // activeConfiguration: Assigned in contextManager.evaluateMatch, consumed in UserUpdate // userToken, solutionsRegistryEntries: Assigned in initialPayload, consumed in UserUpdate var sessionState = $.extend(true, { actionResults: {} - }, fluid.filterKeys(finalPayload, ["userToken", "activeContextName", "activeConfiguration", "solutionsRegistryEntries", "matchMakerOutput"])); + }, fluid.filterKeys(finalPayload, ["userToken", "preferences", "activeContextName", "activeConfiguration", "solutionsRegistryEntries", "matchMakerOutput"])); // let the user's token as well as any named action results accumulated // to date be resolvable for any future action @@ -472,6 +473,8 @@ var gpii = fluid.registerNamespace("gpii"); // When "stop" is called this payload will be used to restore the settings back to their // original state. sessionState.originalSettings = {}; + // var tmp = + sessionState.userTokens = that.getUserTokens().concat(sessionState.userToken); var tasks = []; fluid.each(lifecycleInstructions, function (solution, solutionId) { tasks.push(function () { @@ -480,7 +483,7 @@ var gpii = fluid.registerNamespace("gpii"); (solution.active ? [ "configure", "start" ] : [ "configure" ]), true); }); }); - that.activeSessions[userToken] = sessionState; + that.session = sessionState; // Note that these promises are only sequenced for their side-effects (the ones on sessionState within applySolution and on the system at large // via the settings handlers) var sequence = fluid.promise.sequence(tasks); diff --git a/gpii/node_modules/lifecycleManager/test/js/LifecycleManagerTests.js b/gpii/node_modules/lifecycleManager/test/js/LifecycleManagerTests.js index 5b8359c12..a96bc35e1 100644 --- a/gpii/node_modules/lifecycleManager/test/js/LifecycleManagerTests.js +++ b/gpii/node_modules/lifecycleManager/test/js/LifecycleManagerTests.js @@ -186,7 +186,7 @@ var fluid = fluid || require("infusion"); lifecycleInstructions: gpii.tests.lifecycleManager.configurationSpec }); - gpii.tests.lifecycleManager.sampleActiveSession = { + gpii.tests.lifecycleManager.sampleSession = { 123: { userToken: 123 } @@ -290,7 +290,7 @@ var fluid = fluid || require("infusion"); gpii.tests.lifecycleManager.updateTestDefs = [{ name: "Updating with the same prefs as already applied", - activeSessions: gpii.tests.lifecycleManager.sampleActiveSession, + session: gpii.tests.lifecycleManager.sampleSession, startPayload: gpii.tests.lifecycleManager.startPayload, updateSpec: gpii.tests.lifecycleManager.buildLifecycleInstructions("org.gnome.desktop.a11y.magnifier", gpii.tests.lifecycleManager.buildSettingsHandlersEntry({ "cross-hairs-clip": false, "cross-hairs-color": "green" }), @@ -306,7 +306,7 @@ var fluid = fluid || require("infusion"); { "update": [ "settings.myconf" ] }) }, { name: "single pref changed without 'update' directive", - activeSessions: gpii.tests.lifecycleManager.sampleActiveSession, + session: gpii.tests.lifecycleManager.sampleSession, startPayload: $.extend(true, {}, gpii.tests.lifecycleManager.userOptions, { lifecycleInstructions: gpii.tests.lifecycleManager.buildLifecycleInstructions("org.gnome.desktop.a11y.magnifier", gpii.tests.lifecycleManager.buildSettingsHandlersEntry({ "cross-hairs-clip": true, "cross-hairs-color": "red" }), @@ -324,7 +324,7 @@ var fluid = fluid || require("infusion"); gpii.tests.lifecycleManager.noUpdateLifecycle) }, { name: "Updating with normal reference to settingsHandler block, single settings", - activeSessions: gpii.tests.lifecycleManager.sampleActiveSession, + session: gpii.tests.lifecycleManager.sampleSession, startPayload: gpii.tests.lifecycleManager.startPayload, updateSpec: gpii.tests.lifecycleManager.buildLifecycleInstructions("org.gnome.desktop.a11y.magnifier", gpii.tests.lifecycleManager.buildSettingsHandlersEntry({ "cross-hairs-color": "green" }), @@ -340,7 +340,7 @@ var fluid = fluid || require("infusion"); { "update": [ "settings.myconf" ] }) }, { name: "Updating with normal reference to settingsHandler block, multiple settings", - activeSessions: gpii.tests.lifecycleManager.sampleActiveSession, + session: gpii.tests.lifecycleManager.sampleSession, startPayload: gpii.tests.lifecycleManager.startPayload, updateSpec: gpii.tests.lifecycleManager.buildLifecycleInstructions("org.gnome.desktop.a11y.magnifier", gpii.tests.lifecycleManager.buildSettingsHandlersEntry({ "cross-hairs-color": "green", "iamasetting": true }), @@ -356,7 +356,7 @@ var fluid = fluid || require("infusion"); { "update": [ "settings.myconf" ] }) }, { name: "Updating with reference to 'configure' directive, single settings", - activeSessions: gpii.tests.lifecycleManager.sampleActiveSession, + session: gpii.tests.lifecycleManager.sampleSession, startPayload: $.extend(true, {}, gpii.tests.lifecycleManager.userOptions, { lifecycleInstructions: gpii.tests.lifecycleManager.buildLifecycleInstructions("org.gnome.desktop.a11y.magnifier", gpii.tests.lifecycleManager.buildSettingsHandlersEntry({ "cross-hairs-clip": true, "cross-hairs-color": "red" }), @@ -395,12 +395,12 @@ var fluid = fluid || require("infusion"); gpii.tests.lifecycleManager.assertExpectedSettingsHandler(" - on start", gpii.tests.lifecycleManager.settingsHandlerExpectedInputNewSettings); lifecycleManager.update(updatePayload, function () { - var appliedSolutions = lifecycleManager.activeSessions[test.startPayload.userToken].appliedSolutions; - var originalSettings = lifecycleManager.activeSessions[test.startPayload.userToken].originalSettings; + var appliedSolutions = lifecycleManager.session[test.startPayload.userToken].appliedSolutions; + var originalSettings = lifecycleManager.session[test.startPayload.userToken].originalSettings; jqUnit.assertDeepEq("Checking appliedSolutions after Update", appliedSolutions, test.expectedAppliedSolutions); jqUnit.assertDeepEq("Checking originalSettings after Update", originalSettings, test.expectedOriginalSettings); lifecycleManager.stop(gpii.tests.lifecycleManager.userOptions, function () { - jqUnit.assertUndefined("no active sessions running after stop", lifecycleManager.activeSessions[test.startPayload.userToken]); + jqUnit.assertUndefined("no active sessions running after stop", lifecycleManager.session[test.startPayload.userToken]); jqUnit.start(); }); }); @@ -462,7 +462,7 @@ var fluid = fluid || require("infusion"); gpii.tests.lifecycleManager.assertExpectedSettingsHandler(" - on stop", gpii.tests.lifecycleManager.settingsHandlerExpectedInputRestoreSettings); jqUnit.assertEquals("Expected pid has been sent to kill handler", 8839, gpii.tests.lifecycleManager.staticRepository.killHandler.pid); - jqUnit.assertDeepEq("stop: Stop message to lifecycle manager, empty session state", {}, lifecycleManager.activeSessions); + jqUnit.assertDeepEq("stop: Stop message to lifecycle manager, empty session state", {}, lifecycleManager.session); jqUnit.start(); }); }); @@ -533,7 +533,7 @@ var fluid = fluid || require("infusion"); jqUnit.assertEquals("Expected pid has been sent to kill handler", 8839, gpii.tests.lifecycleManager.staticRepository.killHandler.pid); lifecycleManager.stop(gpii.tests.lifecycleManager.userOptions, function () { - jqUnit.assertUndefined("no active sessions running after stop", lifecycleManager.activeSessions[startPayload.userToken]); + jqUnit.assertUndefined("no active sessions running after stop", lifecycleManager.session[startPayload.userToken]); jqUnit.start(); }); }); @@ -567,7 +567,7 @@ var fluid = fluid || require("infusion"); gpii.tests.lifecycleManager.assertExpectedExec(); lifecycleManager.stop(gpii.tests.lifecycleManager.userOptions, function () { - jqUnit.assertUndefined("no active sessions running after stop", lifecycleManager.activeSessions[startPayload.userToken]); + jqUnit.assertUndefined("no active sessions running after stop", lifecycleManager.session[startPayload.userToken]); jqUnit.start(); }); }); diff --git a/gpii/node_modules/matchMakerFramework/src/MatchMakerFramework.js b/gpii/node_modules/matchMakerFramework/src/MatchMakerFramework.js index beae08b1a..d1ec8c894 100644 --- a/gpii/node_modules/matchMakerFramework/src/MatchMakerFramework.js +++ b/gpii/node_modules/matchMakerFramework/src/MatchMakerFramework.js @@ -46,7 +46,7 @@ invokers: { preProcess: { funcName: "gpii.matchMakerFramework.preProcess", - args: ["{that}", "{arguments}.0"] + args: ["{that}", "{flowManager}.lifecycleManager", "{arguments}.0"] }, // initialPayload matchMakerDispatcher: { funcName: "gpii.matchMakerFramework.matchMakerDispatcher", @@ -63,7 +63,22 @@ * initialPayload consists of: * userToken, preferences, deviceContext, solutionsRegistryEntry */ - gpii.matchMakerFramework.preProcess = function (that, initialPayload) { + gpii.matchMakerFramework.preProcess = function (that, lifecycleManager, initialPayload) { + var activeTokens = lifecycleManager.getUserTokens(); + if (activeTokens.length === 1) { + // if a user is already logged in, send a combined NP set; + var currentSession = lifecycleManager.session; + var preferences = [{ + userToken: currentSession.userToken, + contexts: currentSession.preferences.contexts + }, { + userToken: initialPayload.userToken, + contexts: initialPayload.preferences.contexts + }]; + initialPayload.preferences = preferences; + + } + var matchMakerInput = $.extend({ activeContexts: [ // TODO calculate properly "gpii-default" diff --git a/package.json b/package.json index 29cba692f..7f6b60bc6 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "semver": "~1.1.4", "xml-mapping": "~1.2.0", "kettle": "git://github.com/fluid-project/kettle.git#ef796237b7b157df6837a970a8b798370ef14144", - + "socket.io-client": "~1.3.6", "express": "~3.4.3", "body-parser": "^1.9.2", "connect-ensure-login": "^0.1.1", diff --git a/testData/deviceReporter/acceptanceTests/chrome_sst.json b/testData/deviceReporter/acceptanceTests/chrome_sst.json new file mode 100644 index 000000000..7484a4280 --- /dev/null +++ b/testData/deviceReporter/acceptanceTests/chrome_sst.json @@ -0,0 +1,5 @@ +[ + { + "id": "com.certh.service-synthesis" + } +] diff --git a/testData/deviceReporter/installedSolutions.json b/testData/deviceReporter/installedSolutions.json index efd67070b..2ff0a33e8 100644 --- a/testData/deviceReporter/installedSolutions.json +++ b/testData/deviceReporter/installedSolutions.json @@ -89,6 +89,10 @@ { "id": "com.android.settings.system" + }, + + { + "id": "com.certh.service-synthesis" } ] diff --git a/testData/preferences/acceptanceTests/chrome_sst_callwebanywhere.json b/testData/preferences/acceptanceTests/chrome_sst_callwebanywhere.json new file mode 100644 index 000000000..87e08859d --- /dev/null +++ b/testData/preferences/acceptanceTests/chrome_sst_callwebanywhere.json @@ -0,0 +1,18 @@ +{ + "flat": { + "contexts": { + "gpii-default": { + "name": "Default preferences", + "preferences": { + "http://registry.gpii.net/applications/com.certh.service-synthesis": { + "serviceName": "CallWebAnywhere", + "serviceInput": { + "voiceLanguage": "fr", + "inputUrl": "" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/testData/preferences/acceptanceTests/chrome_sst_combined.json b/testData/preferences/acceptanceTests/chrome_sst_combined.json new file mode 100644 index 000000000..fa66f85a4 --- /dev/null +++ b/testData/preferences/acceptanceTests/chrome_sst_combined.json @@ -0,0 +1,42 @@ +{ + "flat": { + "contexts": { + "gpii-default": { + "name": "Default preferences", + "preferences": { + "http://registry.gpii.net/applications/com.certh.service-synthesis": { + "serviceName": "callCombinedServices", + "serviceInput": { + "input": [ + { + "serviceName": "Translatewebpage", + "serviceInput": { + "inputUrl": "", + "targetLanguage": "fr" + } + }, + { + "serviceName": "CallWebAnywhere" + } + ], + "mappedVariables": [ + { + "fromServiceName": "Translatewebpage", + "fromVariableName": "finalUrl", + "toServiceName": "CallWebAnywhere", + "toVariableName": "inputUrl" + }, + { + "fromServiceName": "Translatewebpage", + "fromVariableName": "targetLanguageCode", + "toServiceName": "CallWebAnywhere", + "toVariableName": "voiceLanguage" + } + ] + } + } + } + } + } + } +} \ No newline at end of file diff --git a/testData/preferences/acceptanceTests/chrome_sst_fontconverter.json b/testData/preferences/acceptanceTests/chrome_sst_fontconverter.json new file mode 100644 index 000000000..ad1184639 --- /dev/null +++ b/testData/preferences/acceptanceTests/chrome_sst_fontconverter.json @@ -0,0 +1,21 @@ +{ + "flat": { + "contexts": { + "gpii-default": { + "name": "Default preferences", + "preferences": { + "http://registry.gpii.net/applications/com.certh.service-synthesis": { + "serviceName": "FontConverter", + "serviceInput": { + "targetFontSize": "16", + "inputUrl": "", + "targetFontFamily": "Arial", + "targetBackground": "yellow", + "targetColor": "red" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/testData/preferences/acceptanceTests/chrome_sst_translate.json b/testData/preferences/acceptanceTests/chrome_sst_translate.json new file mode 100644 index 000000000..0b3f92cd4 --- /dev/null +++ b/testData/preferences/acceptanceTests/chrome_sst_translate.json @@ -0,0 +1,17 @@ +{ + "flat": { + "contexts": { + "gpii-default": { + "name": "Default preferences", + "preferences": { + "http://registry.gpii.net/applications/com.certh.service-synthesis": { + "serviceName": "Translatewebpage", + "serviceInput": { + "targetLanguage": "fr" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/testData/preferences/acceptanceTests/multiuser1.json b/testData/preferences/acceptanceTests/multiuser1.json new file mode 100644 index 000000000..cc0d49b45 --- /dev/null +++ b/testData/preferences/acceptanceTests/multiuser1.json @@ -0,0 +1,12 @@ +{ + "flat": { + "contexts": { + "gpii-default": { + "name": "Default preferences", + "preferences": { + "http://registry.gpii.net/common/magnification": 1.5 + } + } + } + } +} \ No newline at end of file diff --git a/testData/preferences/acceptanceTests/multiuser2.json b/testData/preferences/acceptanceTests/multiuser2.json new file mode 100644 index 000000000..c901bd782 --- /dev/null +++ b/testData/preferences/acceptanceTests/multiuser2.json @@ -0,0 +1,12 @@ +{ + "flat": { + "contexts": { + "gpii-default": { + "name": "Default preferences", + "preferences": { + "http://registry.gpii.net/common/volume": 1 + } + } + } + } +} \ No newline at end of file diff --git a/testData/preferences/sst.json b/testData/preferences/sst.json new file mode 100644 index 000000000..36552b34a --- /dev/null +++ b/testData/preferences/sst.json @@ -0,0 +1,18 @@ +{ + "flat": { + "contexts": { + "gpii-default": { + "name": "Default preferences", + "preferences": { + "http://registry.gpii.net/applications/com.certh.service-synthesis": { + "service": "Translatewebpage", + "data": { + "targetLanguage": "fr", + "urlToTranslate": "" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/testData/preferences/sstCall.json b/testData/preferences/sstCall.json new file mode 100644 index 000000000..87e08859d --- /dev/null +++ b/testData/preferences/sstCall.json @@ -0,0 +1,18 @@ +{ + "flat": { + "contexts": { + "gpii-default": { + "name": "Default preferences", + "preferences": { + "http://registry.gpii.net/applications/com.certh.service-synthesis": { + "serviceName": "CallWebAnywhere", + "serviceInput": { + "voiceLanguage": "fr", + "inputUrl": "" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/testData/preferences/sstCombined.json b/testData/preferences/sstCombined.json new file mode 100644 index 000000000..fa66f85a4 --- /dev/null +++ b/testData/preferences/sstCombined.json @@ -0,0 +1,42 @@ +{ + "flat": { + "contexts": { + "gpii-default": { + "name": "Default preferences", + "preferences": { + "http://registry.gpii.net/applications/com.certh.service-synthesis": { + "serviceName": "callCombinedServices", + "serviceInput": { + "input": [ + { + "serviceName": "Translatewebpage", + "serviceInput": { + "inputUrl": "", + "targetLanguage": "fr" + } + }, + { + "serviceName": "CallWebAnywhere" + } + ], + "mappedVariables": [ + { + "fromServiceName": "Translatewebpage", + "fromVariableName": "finalUrl", + "toServiceName": "CallWebAnywhere", + "toVariableName": "inputUrl" + }, + { + "fromServiceName": "Translatewebpage", + "fromVariableName": "targetLanguageCode", + "toServiceName": "CallWebAnywhere", + "toVariableName": "voiceLanguage" + } + ] + } + } + } + } + } + } +} \ No newline at end of file diff --git a/testData/preferences/sstFont.json b/testData/preferences/sstFont.json new file mode 100644 index 000000000..ad1184639 --- /dev/null +++ b/testData/preferences/sstFont.json @@ -0,0 +1,21 @@ +{ + "flat": { + "contexts": { + "gpii-default": { + "name": "Default preferences", + "preferences": { + "http://registry.gpii.net/applications/com.certh.service-synthesis": { + "serviceName": "FontConverter", + "serviceInput": { + "targetFontSize": "16", + "inputUrl": "", + "targetFontFamily": "Arial", + "targetBackground": "yellow", + "targetColor": "red" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/testData/preferences/sstIdentImgWithoutAlt.json b/testData/preferences/sstIdentImgWithoutAlt.json new file mode 100644 index 000000000..ea2843f12 --- /dev/null +++ b/testData/preferences/sstIdentImgWithoutAlt.json @@ -0,0 +1,17 @@ +{ + "flat": { + "contexts": { + "gpii-default": { + "name": "Default preferences", + "preferences": { + "http://registry.gpii.net/applications/com.certh.service-synthesis": { + "serviceName": "Identifyimageswithoutaltattributeinwebpage", + "serviceInput": { + "inputUrl": "" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/testData/preferences/sstTranslate.json b/testData/preferences/sstTranslate.json new file mode 100644 index 000000000..0b3f92cd4 --- /dev/null +++ b/testData/preferences/sstTranslate.json @@ -0,0 +1,17 @@ +{ + "flat": { + "contexts": { + "gpii-default": { + "name": "Default preferences", + "preferences": { + "http://registry.gpii.net/applications/com.certh.service-synthesis": { + "serviceName": "Translatewebpage", + "serviceInput": { + "targetLanguage": "fr" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/testData/solutions/linux.json b/testData/solutions/linux.json index fd83685c4..6d78cafa3 100644 --- a/testData/solutions/linux.json +++ b/testData/solutions/linux.json @@ -1525,5 +1525,34 @@ ], "stop": [ ] + }, + "com.certh.service-synthesis": { + "name": "Service Synthesis Adapter", + "contexts": { + "OS": [{ + "id": "linux", + "version": ">=2.6.26" + }] + }, + "settingsHandlers": { + "sstconf": { + "type": "gpii.settingsHandlers.webSockets", + "capabilities": [ + "applications.com\\.certh\\.service-synthesis.id" + ], + "options": { + "path": "com.certh.service-synthesis", + "SSTURL": "http://160.40.50.183:8080/CLOUD4All_SST_Restful_WS/SST/call_" + } + } + }, + "configure": [ + "settings.sstconf" + ], + "restore": [ + "settings.sstconf" + ], + "start": [], + "stop": [] } } diff --git a/testData/solutions/solutionsDescription/com_certh_service-synthesis.md b/testData/solutions/solutionsDescription/com_certh_service-synthesis.md new file mode 100644 index 000000000..ad151a88f --- /dev/null +++ b/testData/solutions/solutionsDescription/com_certh_service-synthesis.md @@ -0,0 +1,58 @@ +# Service-synthesis + +## Details + +* __Name__: Service-synthesis +* __Id__: com.certh.service-synthesis +* __Platform__: Tested on MS Windows and GNU/Linux (it should also work on Mac OSX) +* __Contact__: José Antonio Gutiérrez Dueñas + +## Description +The Chrome extension for Google Chrome is a component installable in the web browser. This extension establishes a connection with GPII to get the active preferences. These preferences contain configuration parameters used, by the extension, to request to the synthesis service the adaptation of a web page. The extension sends the configuration parameters and the website URL to synthesis service. The synthesis service creates a new version of the web page using the URL and the configuration parameters received. Synthesis service returns to the chrome extension a new URL with the new version of the web page. +The Chrome extension can work autonomously, with cloud-based flowManager, or by local flowManager. + +Useful links: + + * [Chrome extensions developer](https://developer.chrome.com/extensions) + * [Source code at github.com](https://github.com/GutiX/SSTChrome4cloud.git) + +## Integration +To install the chrome extension, make the following steps. + + * Download the zip file from https://github.com/GutiX/SSTChrome4cloud/archive/master.zip + * Extract the zip file in a folder of your choice + * In the Chrome browser, click on the ‘settings’ icon in the upper right corner. + * Once in the ‘settings’ page, go to ‘extensions’ in the left sidebar menu + * Make sure the ‘Developer mode’ checkbox is checked + * Then, click on ‘Load unpacked extension...’ + ** Select the folder where you unzipped the files you downloaded in step 2 + + +## Testing +When using a NP set that makes use of the service-synthesis extension, the Chrome browser should be launched and configured properly by taking into account the settings included in that NP set. +Four user profiles with different sets of Needs & Preferences have been provided in order to properly perform the tests. +These user profiles have as follows: + +### sstCall +NP set located at universal's testData/preferences/sstCall.json + + * When logging in, if Chrome browser is open should recharge the all tabs to adapt the websites with WebAnywhere service. If Chrome browser is closed will get the preferences and will adapt the websites when this open. + * When logging out, default settings will be restored. + +### sstFont +NP set located at universal's testData/preferences/sstFont.json + + * When logging in, if Chrome browser is open should recharge the all tabs to adapt the websites with the Font Converter service. If Chrome browser is closed will get the preferences and will adapt the websites when this open. + * When logging out, default settings will be restored. + +### sstTranslate +NP set located at universal's testData/preferences/sstTranslate.json + + * When logging in, if Chrome browser is open should recharge the all tabs to adapt the websites with the Translate Web Page service. If Chrome browser is closed will get the preferences and will adapt the websites when this open. + * When logging out, default settings will be restored. + +### sstCombined +NP set located at universal's testData/preferences/sstCombined.json + + * When logging in, if Chrome browser is open should recharge the all tabs to adapt the websites with the combine service, using Translate web page and WebAnywhere services. If Chrome browser is closed will get the preferences and will adapt the websites when this open. + * When logging out, default settings will be restored. diff --git a/testData/solutions/solutionsDescription/net_eu_gpii_olb.md b/testData/solutions/solutionsDescription/net_eu_gpii_olb.md index 9606c96e3..5ed57703f 100644 --- a/testData/solutions/solutionsDescription/net_eu_gpii_olb.md +++ b/testData/solutions/solutionsDescription/net_eu_gpii_olb.md @@ -1,31 +1,31 @@ -# Online Banking Demonstrator (OLB) +# Online Banking Prototype (OLB) ## Details -* __Name__: Online Banking Demonstrator (OLB) +* __Name__: Online Banking Prototype (OLB) * __Id__: eu.gpii.olb -* __Platform__: Web +* __Platform__: Win32; Web * __Contact__: Christophe Strobbe ## Description -The __[Online Banking Demonstrator](http://gpii.eu/olb/)__ is a web-based application built to demonstrate +The __[Online Banking Prototype](http://gpii.eu/olb/)__ is a web-based application built to demonstrate auto-personalisation from preference sets across multiple levels: * the application itself, * the browser (through browser extensions such as Cloud4Chrome), * assistive technologies (if any are needed), * the platform (typically a desktop operating system). -The Online Banking Demonstrator uses an adapted version of +The Online Banking Prototype uses an adapted version of [Fluid UI Options](http://wiki.fluidproject.org/display/Infusion14/UI+Options) with added support for sign language videos and pictograms. It will be available in four languages: English, German, Spanish and Greek. -The Online Banking Demonstrator will be released under the Apache License, Version 2.0. +The Online Banking Prototype will be released under the Apache License, Version 2.0. ## Integration -The Online Banking Demonstrator is fully supported by the GPII personalisation framework -in the sense that all settings avaiable through the UIOptions panel are mapped to application-specific terms. +The Online Banking Prototype is fully supported by the GPII personalisation framework +in the sense that all settings avaiable through its control panel are mapped to application-specific terms. -Information about value ranges and some mappings to common terms can be found [in the spreadsheet "SP3 Settings for 2nd pilots"](https://docs.google.com/spreadsheet/ccc?key=0AppduB_JZh5EdDRYT1pmOTc5eUpNbkpMckhacUVxWXc&usp=drive_web#gid=31). -(Find the tabe "eu.gpii.olb".) +Information about value ranges and some mappings to common terms can be found [in the spreadsheet "SP3 Settings for 2nd and 3rd pilots"](https://docs.google.com/spreadsheets/d/1uaZV4mBze4udTlEikT30ApmE7CaO46eM0GLT0HVUESg/edit#gid=31). +(Find the tab "eu.gpii.olb".) Note, however, that some of the application-specific terms for the OLB cannot yet be mapped to common terms, since the corresponding common terms still need to be defined. These acceptance tests will be expanded when all application-specific terms can be mapped to common terms. @@ -37,6 +37,8 @@ Manual testing can be of two kinds: * On a platform where GPII is running: Log in a token at the OS level (through USB, NFC, RFID, ...). After the platform has adapted itself to the preferences corresponding to the token, open a browser, go to the OLB and log in there. Then check that the adaptations at the level of the web app do not conflict with or cancel out the adaptations at the other levels. + * Once the browser extension code has been integrated, GPII installed on a Windows system should pass on + OLB settings from the Local Flow Manager to the OLB. (This information will be updated once that work is complete.) ### olb_Carla @@ -64,6 +66,7 @@ Using this NP set in the OLB should have the following effects: * the sign language videos show a human sign language interpreter, * the interface language changes from English to German. + ### [olb_QinKesheng](https://zh.wikipedia.org/wiki/%E6%AC%BD%E5%8F%AF%E8%81%96) Using this NP set in the OLB should have the following effects: @@ -72,3 +75,13 @@ Using this NP set in the OLB should have the following effects: * the sign language videos use avatars, * the interface language does not change since Chinese (zho) is not supported. +### olb_Alicia_app + +Using this NP set in the OLB should have the following effects: + +* high contrast (white on black) should be enabled, +* a simplified UI should be shown. + +Note: this NP set is not available in the `acceptanceTests` directory. + + diff --git a/testData/solutions/web.json b/testData/solutions/web.json index 8a4d30880..e6391184a 100644 --- a/testData/solutions/web.json +++ b/testData/solutions/web.json @@ -481,7 +481,7 @@ }, "eu.gpii.olb": { - "name": "Online Banking Demonstrator", + "name": "Online Banking Prototype", "contexts": { "OS": [ { @@ -491,7 +491,10 @@ }, "settingsHandlers": { "conf": { - "type": "gpii.settingsHandlers.noSettings", + "type": "gpii.settingsHandlers.webSockets", + "options": { + "path": "eu.gpii.olb" + }, "capabilities": [ "applications.eu\\.gpii\\.olb.id", "display.applications.eu\\.gpii\\.olb.name", diff --git a/testData/solutions/win32.json b/testData/solutions/win32.json index 03cb1e2aa..cd30fb9e1 100644 --- a/testData/solutions/win32.json +++ b/testData/solutions/win32.json @@ -1323,7 +1323,6 @@ } ] }, - "com.ilunion.cloud4chrome": { "name": "Cloud4all Chrome extension", "contexts": { @@ -1400,5 +1399,35 @@ ], "stop": [ ] + }, + "com.certh.service-synthesis": { + "name": "Service Synthesis Adapter", + "contexts": { + "OS": [{ + "id": "win32", + "version": ">=5.0" + }] + }, + "settingsHandlers": { + "sstconf": { + "type": "gpii.settingsHandlers.webSockets", + "capabilities": [ + "applications.com\\.certh\\.service-synthesis.id" + ], + "options": { + "path": "com.certh.service-synthesis", + "SSTURL": "http://160.40.50.183:8080/CLOUD4All_SST_Restful_WS/SST/call_" + } + } + }, + "configure": [ + "settings.sstconf" + ], + "restore": [ + "settings.sstconf" + ], + "start": [], + "stop": [] } } + diff --git a/tests/ContextIntegrationTests.js b/tests/ContextIntegrationTests.js index d1a9de1a6..63196aa74 100644 --- a/tests/ContextIntegrationTests.js +++ b/tests/ContextIntegrationTests.js @@ -63,7 +63,7 @@ gpii.tests.contextIntegration.receiveLifecycleManager = function (testCaseHolder gpii.tests.contextIntegration.checkCurrentContext = function (lifecycleManager, token, expected) { jqUnit.assertEquals("Checking that the activeContextName matches: ", expected, - lifecycleManager.activeSessions[token].activeContextName); + lifecycleManager.session.activeContextName); }; gpii.tests.contextIntegration.changeEnvironmentAndCheck = function (contextName) { diff --git a/tests/MultiUserTests.js b/tests/MultiUserTests.js new file mode 100644 index 000000000..9b137bbb2 --- /dev/null +++ b/tests/MultiUserTests.js @@ -0,0 +1,513 @@ +/** +GPII Multi-user support Tests + +Copyright 2014 Raising the Floor - International + +Licensed under the New BSD license. You may not use this file except in +compliance with this License. + +The research leading to these results has received funding from the European Union's +Seventh Framework Programme (FP7/2007-2013) under grant agreement no. 289016. + +You may obtain a copy of the License at +https://github.com/GPII/universal/blob/master/LICENSE.txt +*/ + + +"use strict"; + +var fluid = require("infusion"), + kettle = fluid.registerNamespace("kettle"), + path = require("path"), + jqUnit = jqUnit || fluid.require("jqUnit"), + gpii = fluid.registerNamespace("gpii"); + +fluid.registerNamespace("gpii.tests.multiUserSupport"); + +require("../index.js"); + +gpii.loadTestingSupport(); + +/* + * Initial function to be called when the user hits the /match URL. Simply calls the + * gpii.flatMatchMaker.match function and fires the 'onSuccess' event when it returns + */ +gpii.tests.multiUserSupport.flatMatchMakerMockMatch = function (ontologyHandler, body) { + // fake a matchmaking process and return a payload dependent on users/preferences: + var responseOptions = { + "multiuser1": { + "inferredConfiguration": { + "gpii-default": { + "applications": { + "org.gnome.desktop.a11y.magnifier": { + "active": true, + "settings": { + "http://registry.gpii.net/common/magnification": 1.5 + } + } + } + } + } + }, + "multiuser2": { + "inferredConfiguration": { + "gpii-default": { + "applications": { + "org.alsa-project": { + "active": true, + "settings": { + "http://registry.gpii.net/common/volume": 1 + } + } + } + } + } + }, + "combinedUser": { + "inferredConfiguration": { + "gpii-default": { + "applications": { + "org.gnome.desktop.a11y.magnifier": { + "active": true, + "settings": { + "http://registry.gpii.net/common/magnification": 1.5 + } + }, + "org.alsa-project": { + "active": true, + "settings": { + "http://registry.gpii.net/common/volume": 1 + } + } + } + } + } + } + }; + return (body.preferences.length === 2) ? responseOptions.combinedUser : responseOptions[body.userToken]; +}; + +fluid.defaults("gpii.tests.multiUserSupport.testCaseHolder.linux", { + gradeNames: [ + "gpii.test.integration.testCaseHolder.linux" + ], + components: { + mockMM: { + type: "fluid.littleComponent", + options: { + invokers: { + match: { + funcName: "gpii.tests.multiUserSupport.flatMatchMakerMockMatch" + } + } + } + }, + resetRequest: { + type: "kettle.test.request.http", + options: { + path: "/user/reset/logonChange", + port: 8081 + } + }, + multi1Keyaction: { + type: "kettle.test.request.http", + options: { + path: "/user/multiuser1/logonChange", + port: 8081 + } + }, + multi2Keyaction: { + type: "kettle.test.request.http", + options: { + path: "/user/multiuser2/logonChange", + port: 8081 + } + }, + extraKeyaction: { + type: "kettle.test.request.http", + options: { + path: "/user/extrauser/logonChange", + port: 8081 + } + }, + multi1Login: { + type: "kettle.test.request.http", + options: { + path: "/user/multiuser1/login", + port: 8081 + } + }, + multi2Login: { + type: "kettle.test.request.http", + options: { + path: "/user/multiuser2/login", + port: 8081 + } + }, + multi1Logout: { + type: "kettle.test.request.http", + options: { + path: "/user/multiuser1/logout", + port: 8081 + } + }, + multi2Logout: { + type: "kettle.test.request.http", + options: { + path: "/user/multiuser2/logout", + port: 8081 + } + }, + extraLogin: { + type: "kettle.test.request.http", + options: { + path: "/user/extrauser/login", + port: 8081 + } + }, + extraLogout: { + type: "kettle.test.request.http", + options: { + path: "/user/extrauser/logout", + port: 8081 + } + } + }, + distributeOptions: [{ + record: { + funcName: null, + func: "{gpii.tests.multiUserSupport.testCaseHolder.linux}.mockMM.match" + }, + target: "{that flatMatchMaker}.options.invokers.match" + }] +}); + +gpii.tests.multiUserSupport.checkCustomResponse = function (expected, actual) { + jqUnit.assertEquals("Checking custom response", expected, actual); +}; + +gpii.tests.multiUserSupport.checkErrorResponse = function (expectedMsg, expectedCode, actual) { + jqUnit.assertDeepEq("Checking custom response", { + isError: true, + message: expectedMsg, + statusCode: expectedCode + }, JSON.parse(actual)); +}; + +gpii.tests.multiUserSupport.data = { + multiuser1: { + "gpii.gsettings": { + "data": [{ + "settings": { + "mag-factor": 1.5 + }, + "options": { + "schema": "org.gnome.desktop.a11y.magnifier" + } + }] + } + }, + multiuser2: { + "gpii.alsa": { + "data": [{ + "settings": { + "masterVolume": 100 + } + }] + } + }, + combinedUser: { + "gpii.gsettings": { + "data": [{ + "settings": { + "mag-factor": 1.5 + }, + "options": { + "schema": "org.gnome.desktop.a11y.magnifier" + } + }] + }, + "gpii.alsa": { + "data": [{ + "settings": { + "masterVolume": 100 + } + }] + } + } +}; + +gpii.tests.multiUserSupport.fixtures = [ + { + name: "Simple login and logout of a single user", + expect: 4, + sequenceSegments: [ + [ + { + "func": "gpii.test.expandSettings", + args: [ "{tests}" ] + }, { + func: "gpii.test.snapshotSettings", + args: ["{tests}.options.data.multiuser1", "{tests}.settingsStore", "{nameResolver}"] + }, { + func: "{multi1Keyaction}.send" + }, { + event: "{multi1Keyaction}.events.onComplete", + listener: "gpii.test.loginRequestListen" + }, { + func: "gpii.test.checkConfiguration", + args: [ "{tests}.options.data.multiuser1", "{nameResolver}" ] + }, { + func: "{multi1Keyaction}.send" + }, { + event: "{multi1Keyaction}.events.onComplete", + listener: "gpii.test.logoutRequestListen" + }, { + func: "gpii.test.checkRestoredConfiguration", + args: ["{tests}.options.data.multiuser1", "{tests}.settingsStore", "{nameResolver}"] + } + ] + ] + }, { + name: "Login and logout of two users", + expect: 8, + sequenceSegments: [ + [ + { + "func": "gpii.test.expandSettings", + args: [ "{tests}" ] + }, { + func: "gpii.test.snapshotSettings", + args: ["{tests}.options.data.combinedUser", "{tests}.settingsStore", "{nameResolver}"] + }, { // log in first user + func: "{multi1Keyaction}.send" + }, { + event: "{multi1Keyaction}.events.onComplete", + listener: "gpii.test.loginRequestListen" + }, { // and check configuration + func: "gpii.test.checkConfiguration", + args: [ "{tests}.options.data.multiuser1", "{nameResolver}" ] + }, { // log in second user + func: "{multi2Keyaction}.send" + }, { + event: "{multi2Keyaction}.events.onComplete", + listener: "gpii.test.loginRequestListen" + }, { // and check configuration + func: "gpii.test.checkConfiguration", + args: [ "{tests}.options.data.combinedUser", "{nameResolver}" ] + }, { //log out user 2 (leaving user 1) + func: "{multi2Keyaction}.send" + }, { + event: "{multi2Keyaction}.events.onComplete", + listener: "gpii.test.logoutRequestListen" + }, { + func: "gpii.test.checkConfiguration", + args: [ "{tests}.options.data.multiuser1", "{nameResolver}" ] + }, { //log out user 1 + func: "{multi1Keyaction}.send" + }, { + event: "{multi1Keyaction}.events.onComplete", + listener: "gpii.test.logoutRequestListen" + }, { + func: "gpii.test.checkRestoredConfiguration", + args: ["{tests}.options.data.combinedUser", "{tests}.settingsStore", "{nameResolver}"] + } + + ] + ] + }, { + name: "Single user login followed by reset", + expect: 4, + sequenceSegments: [ + [ + { + "func": "gpii.test.expandSettings", + args: [ "{tests}" ] + }, { + func: "gpii.test.snapshotSettings", + args: ["{tests}.options.data.multiuser1", "{tests}.settingsStore", "{nameResolver}"] + }, { // log in user + func: "{multi1Keyaction}.send" + }, { + event: "{multi1Keyaction}.events.onComplete", + listener: "gpii.test.loginRequestListen" + }, { // and check configuration + func: "gpii.test.checkConfiguration", + args: [ "{tests}.options.data.multiuser1", "{nameResolver}" ] + }, { // send reset signal + func: "{resetRequest}.send" + }, { + event: "{resetRequest}.events.onComplete", + listener: "gpii.tests.multiUserSupport.checkCustomResponse", + args: [ "Retrieved reset token, so logging out the user(s) multiuser1", "{arguments}.0" ] + }, { + func: "gpii.test.checkRestoredConfiguration", + args: ["{tests}.options.data.multiuser1", "{tests}.settingsStore", "{nameResolver}"] + } + + ] + ] + }, { + name: "Dual user login followed by reset", + expect: 6, + sequenceSegments: [ + [ + { + "func": "gpii.test.expandSettings", + args: [ "{tests}" ] + }, { + func: "gpii.test.snapshotSettings", + args: ["{tests}.options.data.combinedUser", "{tests}.settingsStore", "{nameResolver}"] + }, { // log in user 1 + func: "{multi1Keyaction}.send" + }, { + event: "{multi1Keyaction}.events.onComplete", + listener: "gpii.test.loginRequestListen" + }, { // and check configuration + func: "gpii.test.checkConfiguration", + args: [ "{tests}.options.data.multiuser1", "{nameResolver}" ] + }, { // log in user 2 + func: "{multi2Keyaction}.send" + }, { + event: "{multi2Keyaction}.events.onComplete", + listener: "gpii.test.loginRequestListen" + }, { // and check configuration + func: "gpii.test.checkConfiguration", + args: [ "{tests}.options.data.multiuser2", "{nameResolver}" ] + }, { // send reset signal + func: "{resetRequest}.send" + }, { + event: "{resetRequest}.events.onComplete", + listener: "gpii.tests.multiUserSupport.checkCustomResponse", + args: [ "Retrieved reset token, so logging out the user(s) multiuser1,multiuser2", "{arguments}.0" ] + }, { + func: "gpii.test.checkRestoredConfiguration", + args: ["{tests}.options.data.combinedUser", "{tests}.settingsStore", "{nameResolver}"] + } + ] + ] + }, { + name: "Three users logging in in a row -> error msg", + expect: 6, + sequenceSegments: [ + [ + { + "func": "gpii.test.expandSettings", + args: [ "{tests}" ] + }, { + func: "gpii.test.snapshotSettings", + args: ["{tests}.options.data.combinedUser", "{tests}.settingsStore", "{nameResolver}"] + }, { // log in user 1 + func: "{multi1Keyaction}.send" + }, { + event: "{multi1Keyaction}.events.onComplete", + listener: "gpii.test.loginRequestListen" + }, { // and check configuration + func: "gpii.test.checkConfiguration", + args: [ "{tests}.options.data.multiuser1", "{nameResolver}" ] + }, { // log in user 2 + func: "{multi2Keyaction}.send" + }, { + event: "{multi2Keyaction}.events.onComplete", + listener: "gpii.test.loginRequestListen" + }, { // and check configuration + func: "gpii.test.checkConfiguration", + args: [ "{tests}.options.data.multiuser2", "{nameResolver}" ] + }, { // log in user 3 + func: "{extraKeyaction}.send" + }, { + event: "{extraKeyaction}.events.onComplete", + listener: "gpii.tests.multiUserSupport.checkErrorResponse", + args: [ "Two other users are already logged in. Ignoring logon change request", 409, "{arguments}.0" ] + }, { // and check configuration + func: "gpii.test.checkConfiguration", + args: [ "{tests}.options.data.multiuser2", "{nameResolver}" ] + } + ] + ] + }, { + name: "Login and Logout using standard URLs", + expect: 4, + sequenceSegments: [ + [ + { + "func": "gpii.test.expandSettings", + args: [ "{tests}" ] + }, { + func: "gpii.test.snapshotSettings", + args: ["{tests}.options.data.multiuser1", "{tests}.settingsStore", "{nameResolver}"] + }, { // log in user 1 + func: "{multi1Login}.send" + }, { + event: "{multi1Login}.events.onComplete", + listener: "gpii.test.loginRequestListen" + }, { // and check configuration + func: "gpii.test.checkConfiguration", + args: [ "{tests}.options.data.multiuser1", "{nameResolver}" ] + }, { // log out user 1 + func: "{multi1Logout}.send" + }, { + event: "{multi1Logout}.events.onComplete", + listener: "gpii.test.logoutRequestListen" + }, { // and check configuration + func: "gpii.test.checkRestoredConfiguration", + args: ["{tests}.options.data.multiuser1", "{tests}.settingsStore", "{nameResolver}"] + } + ] + ] + }, { + name: "Login followed by logout of wrong user", + expect: 3, + sequenceSegments: [ + [ + { + "func": "gpii.test.expandSettings", + args: [ "{tests}" ] + }, { + func: "gpii.test.snapshotSettings", + args: ["{tests}.options.data.multiuser1", "{tests}.settingsStore", "{nameResolver}"] + }, { // log in user 1 + func: "{multi1Login}.send" + }, { + event: "{multi1Login}.events.onComplete", + listener: "gpii.test.loginRequestListen" + }, { // and check configuration + func: "gpii.test.checkConfiguration", + args: [ "{tests}.options.data.multiuser1", "{nameResolver}" ] + }, { // log out user 1 + func: "{multi2Logout}.send" + }, { + event: "{multi2Logout}.events.onComplete", + listener: "gpii.tests.multiUserSupport.checkErrorResponse", + args: [ "Got logout request from user multiuser2, but that user is not logged in. So ignoring request.", 409, "{arguments}.0" ] + } + ] + ] + } +]; + + +gpii.tests.multiUserSupport.buildTestFixtures = function (fixtures) { + return fluid.transform(fixtures, function (fixture) { + var testDef = { + name: fixture.name, + userToken: "context1", + expect: fixture.expect, + gradeNames: "gpii.tests.multiUserSupport.testCaseHolder.linux", + config: { + configName: "multiUserTester", + configPath: path.resolve(__dirname, "configs") + }, + sequence: [], + data: gpii.tests.multiUserSupport.data + }; + fluid.each(fixture.sequenceSegments, function (arr) { + testDef.sequence = testDef.sequence.concat(arr); + }); + + return testDef; + }); +}; + +kettle.test.bootstrapServer(gpii.tests.multiUserSupport.buildTestFixtures( + gpii.tests.multiUserSupport.fixtures)); \ No newline at end of file diff --git a/tests/UserLogonStateChangeTests.js b/tests/UserLogonStateChangeTests.js deleted file mode 100644 index 7647ccf24..000000000 --- a/tests/UserLogonStateChangeTests.js +++ /dev/null @@ -1,181 +0,0 @@ -/* - * GPII Flow Manager Development Tests - * - * Copyright 2013 OCAD University - * - * Licensed under the New BSD license. You may not use this file except in - * compliance with this License. - * - * The research leading to these results has received funding from the European Union's - * Seventh Framework Programme (FP7/2007-2013) - * under grant agreement no. 289016. - * - * You may obtain a copy of the License at - * https://github.com/GPII/universal/blob/master/LICENSE.txt - */ - -"use strict"; - -var fluid = require("infusion"), - jqUnit = fluid.require("jqUnit"), - path = require("path"), - configPath = path.resolve(__dirname, "../gpii/configs"), - gpii = fluid.registerNamespace("gpii"), - $ = fluid.registerNamespace("jQuery"), - kettle = fluid.registerNamespace("kettle"); - -require("../index.js"); - -gpii.loadTestingSupport(); - -fluid.defaults("gpii.tests.userLogonStateChange.testCaseHolder", { - gradeNames: ["gpii.test.common.testCaseHolder", "autoInit"], - components: { - resetRequest: { - type: "kettle.test.request.http", - options: { - path: "/user/reset/logonChange", - port: 8081 - } - }, - logonChangeRequest2: { - type: "kettle.test.request.http", - options: { - path: "/user/someotheruser/logonChange", - port: 8081 - } - }, - logoutRequest2: { - type: "kettle.test.request.http", - options: { - path: "/user/someotheruser/logout", - port: 8081 - } - } - } -}); - -fluid.registerNamespace("gpii.tests.userLogonStateChange"); - -gpii.tests.userLogonStateChange.userToken = "testUser1"; - -gpii.tests.userLogonStateChange.testLoginResponse = function (data) { - jqUnit.assertEquals("Response is correct", "User with token " + - gpii.tests.userLogonStateChange.userToken + " was successfully logged in.", data); -}; - -gpii.tests.userLogonStateChange.testLogoutResponse = function (data) { - jqUnit.assertEquals("Response is correct", "User with token " + - gpii.tests.userLogonStateChange.userToken + " was successfully logged out.", data); -}; - -gpii.tests.userLogonStateChange.testErrorResponse = function (expMsg, expCode) { - return function (data) { - data = JSON.parse(data); - jqUnit.assertTrue("Received error as expected", data.isError); - jqUnit.assertEquals("Received message as expected", expMsg, data.message); - jqUnit.assertEquals("Received correct error code", expCode, data.statusCode); - }; -}; - -gpii.tests.userLogonStateChange.buildTestDefs = function (testDefs) { - return fluid.transform(testDefs, function (testDef) { - return $.extend(true, { - config: { - configName: "development.all.local", - configPath: configPath - }, - gradeNames: "gpii.tests.userLogonStateChange.testCaseHolder", - userToken: gpii.tests.userLogonStateChange.userToken - }, testDef); - }); -}; - -gpii.tests.userLogonStateChange.testDefs = [{ - name: "Testing standard logonChange login and logout", - expect: 2, - sequence: [{ // standard login - func: "{logonChangeRequest}.send" - }, { - event: "{logonChangeRequest}.events.onComplete", - listener: "gpii.tests.userLogonStateChange.testLoginResponse" - }, { // standard logout - func: "{logonChangeRequest}.send" - }, { - event: "{logonChangeRequest}.events.onComplete", - listener: "gpii.tests.userLogonStateChange.testLogoutResponse" - }] -}, { - name: "Testing logonChange with 'reset' token", - expect: 5, - sequence: [{ // resetting with no user logged in - func: "{resetRequest}.send" - }, { - event: "{resetRequest}.events.onComplete", - listenerMaker: "gpii.tests.userLogonStateChange.testErrorResponse", - makerArgs: [ "No users currently logged in - nothing to reset", 409 ] - }, { // resetting with user logged in (part 1: login) - func: "{logonChangeRequest}.send" - }, { - event: "{logonChangeRequest}.events.onComplete", - listener: "gpii.tests.userLogonStateChange.testLoginResponse" - }, { // resetting with user logged in (part 2: reset and check that user is logged out) - func: "{resetRequest}.send" - }, { - event: "{resetRequest}.events.onComplete", - listener: "gpii.tests.userLogonStateChange.testLogoutResponse" - }] -}, { - name: "Testing standard logonChange with another user already logged in", - expect: 4, - sequence: [{ // standard login - func: "{logonChangeRequest}.send" - }, { - event: "{logonChangeRequest}.events.onComplete", - listener: "gpii.tests.userLogonStateChange.testLoginResponse" - }, { // logout of different user - func: "{logonChangeRequest2}.send" - }, { - event: "{logonChangeRequest2}.events.onComplete", - // listener: "gpii.tests.userLogonStateChange.testOtherUserLoggedInResponse" - listenerMaker: "gpii.tests.userLogonStateChange.testErrorResponse", - makerArgs: [ "Got logon change request from user someotheruser, but the user testUser1 is " + - "already logged in. So ignoring request.", 409] - }] -}, { - name: "Testing standard user//login and /user//logout URLs", - expect: 11, - sequence: [{ // standard login - func: "{loginRequest}.send" - }, { - event: "{loginRequest}.events.onComplete", - listener: "gpii.tests.userLogonStateChange.testLoginResponse" - }, { // standard login with an already logged in user: - func: "{loginRequest}.send" - }, { - event: "{loginRequest}.events.onComplete", - listenerMaker: "gpii.tests.userLogonStateChange.testErrorResponse", - makerArgs: [ "Got log in request from user testUser1, but the user testUser1 is already " + - "logged in. So ignoring login request.", 409] - }, { // logout of different user - func: "{logoutRequest2}.send" - }, { - event: "{logoutRequest2}.events.onComplete", - listenerMaker: "gpii.tests.userLogonStateChange.testErrorResponse", - makerArgs: [ "Got logout request from user someotheruser, but the user testUser1 is logged " + - "in. So ignoring the request.", 409] - }, { // logout of the correct user - func: "{logoutRequest}.send" - }, { - event: "{logoutRequest}.events.onComplete", - listener: "gpii.tests.userLogonStateChange.testLogoutResponse" - }, { // logout of user when none is logged - func: "{logoutRequest}.send" - }, { - event: "{logoutRequest}.events.onComplete", - listenerMaker: "gpii.tests.userLogonStateChange.testErrorResponse", - makerArgs: [ "No user logged in, so ignoring logout action.", 409] - }] -}]; - -kettle.test.bootstrapServer(gpii.tests.userLogonStateChange.buildTestDefs(gpii.tests.userLogonStateChange.testDefs)); diff --git a/tests/all-tests.js b/tests/all-tests.js index f920b56a9..efda4de03 100644 --- a/tests/all-tests.js +++ b/tests/all-tests.js @@ -38,7 +38,7 @@ var testIncludes = [ "./platform/cloud/AcceptanceTests_tvm.js", "./platform/cloud/AcceptanceTests_olb.js", "./DevelopmentTests.js", - "./UserLogonStateChangeTests.js", + "./MultiUserTests.js", "./IntegrationTests.js", "./ContextIntegrationTests.js", "./DeviceReporterErrorTests.js", diff --git a/tests/configs/multiUserTester.json b/tests/configs/multiUserTester.json new file mode 100644 index 000000000..28b60d606 --- /dev/null +++ b/tests/configs/multiUserTester.json @@ -0,0 +1,26 @@ +{ + "typeName": "multiuserTests.linux.integration", + "options": { + "components": { + "server": { + "options": { + "components": { + "deviceReporter": { + "options": { + "installedSolutionsUrl": "file://%root/../../../testData/deviceReporter/acceptanceTests/linux_builtIn.json" + } + }, + "rawPreferencesServer": { + "options": { + "rawPreferencesSourceUrl": "file://%root/../../../testData/preferences/acceptanceTests/%userToken.json" + } + } + } + } + } + } + }, + "includes": [ + "${universal}/tests/configs/localInstall.json" + ] +} \ No newline at end of file diff --git a/tests/platform/index-windows.js b/tests/platform/index-windows.js index 144122c6c..1741b7c5f 100644 --- a/tests/platform/index-windows.js +++ b/tests/platform/index-windows.js @@ -24,5 +24,6 @@ module.exports = [ "windows/windows-jaws-testSpec.js", "windows/windows-nvda-testSpec.js", "windows/windows-maavis-testSpec.js", - "windows/windows-chrome-testSpec.js" + "windows/windows-chrome-testSpec.js", + "windows/windows-olb-testSpec.js" ]; \ No newline at end of file diff --git a/tests/platform/linux/configs/linux-chromesst-config.json b/tests/platform/linux/configs/linux-chromesst-config.json new file mode 100644 index 000000000..efe06cb58 --- /dev/null +++ b/tests/platform/linux/configs/linux-chromesst-config.json @@ -0,0 +1,21 @@ +{ + "typeName": "acceptanceTests.linux.chrome", + "options": { + "components": { + "server": { + "options": { + "components": { + "deviceReporter": { + "options": { + "installedSolutionsUrl": "file://%root/../../../testData/deviceReporter/acceptanceTests/chrome_sst.json" + } + } + } + } + } + } + }, + "includes": [ + "${universal}/tests/configs/localInstall.json" + ] +} diff --git a/tests/platform/linux/configs/linux-chromesst-config.txt b/tests/platform/linux/configs/linux-chromesst-config.txt new file mode 100644 index 000000000..acb4dfb58 --- /dev/null +++ b/tests/platform/linux/configs/linux-chromesst-config.txt @@ -0,0 +1,8 @@ +This configuration file is used for testing the sst-chrome extension in linux + +It includes to the basic localInstall setup for acceptance tests (modifying the +preferences folder used), which in turn includes the standard development +config file (running GPII locally, using development setup). + +This config sets the device reporter file to be 'chrome_sst.json', which will report +the Cloud4all SST-Chrome extension for Google Chrome as being installed on the system. \ No newline at end of file diff --git a/tests/platform/linux/linux-chromeSST-testSpec.js b/tests/platform/linux/linux-chromeSST-testSpec.js new file mode 100644 index 000000000..00ba96486 --- /dev/null +++ b/tests/platform/linux/linux-chromeSST-testSpec.js @@ -0,0 +1,153 @@ +/* +GPII Integration and Acceptance Testing + +Copyright 2014 Emergya + +Licensed under the New BSD license. You may not use this file except in +compliance with this License. + +You may obtain a copy of the License at +https://github.com/gpii/universal/LICENSE.txt +*/ + +"use strict"; +var fluid = require("universal"), + gpii = fluid.registerNamespace("gpii"); + +gpii.loadTestingSupport(); + +fluid.registerNamespace("gpii.tests.linux.chromeSST"); + + + +gpii.tests.linux.chromeSST = [ + { + name: "Acceptance test for SST translate service in Chrome", + userToken: "chrome_sst_translate", + settingsHandlers: { + "gpii.settingsHandlers.webSockets": { + "data": [ + { + "settings": { + "serviceName": "Translatewebpage", + "serviceInput": { + "targetLanguage": "fr" + } + }, + "options": { + "path": "com.certh.service-synthesis", + "SSTURL": "http://160.40.50.183:8080/CLOUD4All_SST_Restful_WS/SST/call_" + } + } + ] + } + }, + processes: [] + }, + { + name: "Acceptance test for SST font converter service in Chrome", + userToken: "chrome_sst_fontconverter", + settingsHandlers: { + "gpii.settingsHandlers.webSockets": { + "data": [ + { + "settings": { + "serviceName": "FontConverter", + "serviceInput": { + "targetFontSize": "16", + "inputUrl": "", + "targetFontFamily": "Arial", + "targetBackground": "yellow", + "targetColor": "red" + } + }, + "options": { + "path": "com.certh.service-synthesis", + "SSTURL": "http://160.40.50.183:8080/CLOUD4All_SST_Restful_WS/SST/call_" + } + } + ] + } + }, + processes: [] + }, + { + name: "Acceptance test for SST CallWebAnywhere service in Chrome", + userToken: "chrome_sst_callwebanywhere", + settingsHandlers: { + "gpii.settingsHandlers.webSockets": { + "data": [ + { + "settings": { + "serviceName": "CallWebAnywhere", + "serviceInput": { + "voiceLanguage": "fr", + "inputUrl": "" + } + }, + "options": { + "path": "com.certh.service-synthesis", + "SSTURL": "http://160.40.50.183:8080/CLOUD4All_SST_Restful_WS/SST/call_" + } + } + ] + } + }, + processes: [] + }, + { + name: "Acceptance test for combined service in Chrome", + userToken: "chrome_sst_combined", + settingsHandlers: { + "gpii.settingsHandlers.webSockets": { + "data": [ + { + "settings": { + "serviceName": "callCombinedServices", + "serviceInput": { + "input": [ + { + "serviceName": "Translatewebpage", + "serviceInput": { + "inputUrl": "", + "targetLanguage": "fr" + } + }, + { + "serviceName": "CallWebAnywhere" + } + ], + "mappedVariables": [ + { + "fromServiceName": "Translatewebpage", + "fromVariableName": "finalUrl", + "toServiceName": "CallWebAnywhere", + "toVariableName": "inputUrl" + }, + { + "fromServiceName": "Translatewebpage", + "fromVariableName": "targetLanguageCode", + "toServiceName": "CallWebAnywhere", + "toVariableName": "voiceLanguage" + } + ] + } + }, + "options": { + "path": "com.certh.service-synthesis", + "SSTURL": "http://160.40.50.183:8080/CLOUD4All_SST_Restful_WS/SST/call_" + } + } + ] + } + }, + processes: [] + } +]; + +module.exports = gpii.test.bootstrap({ + testDefs: "gpii.tests.linux.chromeSST", + configName: "linux-chromesst-config", + configPath: "configs" +}, ["gpii.test.integration.testCaseHolder.linux"], + module, require, __dirname); diff --git a/tests/platform/linux/linux-chromeSST-testSpec.txt b/tests/platform/linux/linux-chromeSST-testSpec.txt new file mode 100644 index 000000000..587acccab --- /dev/null +++ b/tests/platform/linux/linux-chromeSST-testSpec.txt @@ -0,0 +1,12 @@ +linux-chromeSST-testSpec.txt + +Descriptions: + +* Solution: Cloud4all's SST-Chrome extension for Google Chrome (SSTChrome4cloud) +* Configuration file: linux-chromesst-config.json +* Device reporter file: chrome_sst.json +* NP sets: + * chrome_sst_translate + * chrome_sst_fontconverter + * chrome_sst_callwebanywhere + * chrome_sst_combined \ No newline at end of file diff --git a/tests/platform/windows/AcceptanceTests_olb.js b/tests/platform/windows/AcceptanceTests_olb.js new file mode 100644 index 000000000..e908f2b9d --- /dev/null +++ b/tests/platform/windows/AcceptanceTests_olb.js @@ -0,0 +1,129 @@ +/* +GPII Integration and Acceptance Testing + +Copyright 2015 Hochschule der Medien (HdM) / Stuttgart Media University + +Licensed under the New BSD license. You may not use this file except in +compliance with this License. + +The research leading to these results has received funding from the European Union's +Seventh Framework Programme (FP7/2007-2013) under grant agreement no. 289016. + +You may obtain a copy of the License at +https://github.com/GPII/universal/blob/master/LICENSE.txt +*/ + +/*global require*/ + +"use strict"; +var fluid = require("universal"), + gpii = fluid.registerNamespace("gpii"); + +gpii.loadTestingSupport(); + +var testDefs = [ + { + name: "Acceptance test with empty preference set for OLB", + userToken: "olb_empty", + solutionId: "eu.gpii.olb", + expected: { + "eu.gpii.olb": { + } + } + }, + { + name: "Test for Online Banking demonstrator (OLB) with Online Flow Manager (German sign language).", + userToken: "olb_Lara", + solutionId: "eu.gpii.olb", + expected: { + "eu.gpii.olb": { + "language": "de-DE", + "signLanguageEnabled": true, + "signLanguage": "gsg", + "interpreterType": "human", + "interpreterName": "default" + } + } + }, + { + name: "Test for Online Banking demonstrator (OLB) with Online Flow Manager (US sign language).", + userToken: "olb_KimCallahan", + solutionId: "eu.gpii.olb", + expected: { + "eu.gpii.olb": { + "language": "en-US", + "signLanguageEnabled": true, + "signLanguage": "ase", + "interpreterType": "avatar", + "textStyle": "verdana" + } + } + }, + { + name: "Test for Online Banking demonstrator (OLB) with Online Flow Manager (contrast and large text).", + userToken: "olb_Carla", + solutionId: "eu.gpii.olb", + expected: { + "eu.gpii.olb": { + "language": "en-GB", + "textSize": 2, + "links": true, + "contrastTheme": "wb", + "signLanguageEnabled": false, + "signLanguage": "ils", + "lineSpacing": 2, + "inputsLarger": true + } + } + }, + { + name: "Test for Online Banking demonstrator (OLB) with only application-specific terms.", + userToken: "olb_applicationSpecific_01", + solutionId: "eu.gpii.olb", + expected: { + "eu.gpii.olb": { + "textSize": 1.1, + "lineSpacing": 2, + "textStyle": "comic", + "toc": true, + "links": true, + "inputsLarger": true, + "contrastTheme": "yb", + "signLanguageEnabled": true, + "signLanguage": "ils", + "interpreterType": "avatar", + "interpreterName": "Neytiri", + "pictogramsEnabled": false + } + } + }, + { + name: "Test for Online Banking demonstrator (OLB) with Online Flow Manager: unsupported sign language.", + userToken: "olb_QinKesheng", + solutionId: "eu.gpii.olb", + expected: { + "eu.gpii.olb": { + "language": "zho", + "signLanguageEnabled": true, + "signLanguage": "ils", + "interpreterType": "avatar" + } + } + }, + { + name: "Test for Online Banking demonstrator (OLB) with Online Flow Manager: simplified UI.", + userToken: "olb_Alicia_cmn", + solutionId: "eu.gpii.olb", + expected: { + "eu.gpii.olb": { + "language": "en-GB", + "contrastTheme": "wb", + "signLanguage": "ils", // see https://issues.gpii.net/browse/GPII-1125 + "simplifiedUiEnabled": true + } + } + } +]; + +module.exports = gpii.test.cloudBased.bootstrap(testDefs, __dirname); + diff --git a/tests/platform/windows/AcceptanceTests_olb.txt b/tests/platform/windows/AcceptanceTests_olb.txt new file mode 100644 index 000000000..9f718f8ab --- /dev/null +++ b/tests/platform/windows/AcceptanceTests_olb.txt @@ -0,0 +1,19 @@ +AcceptanceTests_olb.js + +Description: +This is a set of acceptance tests for the Online Banking demonstrator (OLB) using the Online Flow Manager. +It relies on the following preference sets in ..\..\testData\preferences\acceptanceTests: +* olb_empty.json +* olb_Carla.json +* olb_KimCallahan.json +* olb_Lara.json +* olb_QinKesheng.json +* olb_applicationSpecific_01.json +* olb_Alicia_cmn.json + + +Requirements: +Since the Online Banking demonstrator uses the Online Flow Manager (or "Cloud-based Flow Manager"), there are no requirements other than a local instance of the GPII running with NODE_ENV set to "cloudBased.development.all.local" and starting the server from the "universal" folder by typing "node node_modules/kettle/lib/init.js gpii/configs/". +Note: +Using the Online Flow Manager is a temporary workaround until there is infrastructure that allows web applications to request settings through the local Flow Manager. + diff --git a/tests/platform/windows/configs/windows-chromesst-config.json b/tests/platform/windows/configs/windows-chromesst-config.json new file mode 100644 index 000000000..d2baad8d6 --- /dev/null +++ b/tests/platform/windows/configs/windows-chromesst-config.json @@ -0,0 +1,21 @@ +{ + "typeName": "acceptanceTests.windows.chrome", + "options": { + "components": { + "server": { + "options": { + "components": { + "deviceReporter": { + "options": { + "installedSolutionsUrl": "file://%root/../../../testData/deviceReporter/acceptanceTests/chrome_sst.json" + } + } + } + } + } + } + }, + "includes": [ + "${universal}/tests/configs/localInstall.json" + ] +} diff --git a/tests/platform/windows/configs/windows-chromesst-config.txt b/tests/platform/windows/configs/windows-chromesst-config.txt new file mode 100644 index 000000000..899bd6387 --- /dev/null +++ b/tests/platform/windows/configs/windows-chromesst-config.txt @@ -0,0 +1,8 @@ +This configuration file is used for testing the sst-chrome extension in Windows + +It includes to the basic localInstall setup for acceptance tests (modifying the +preferences folder used), which in turn includes the standard development +config file (running GPII locally, using development setup). + +This config sets the device reporter file to be 'chrome_sst.json', which will report +the Cloud4all SST-Chrome extension for Google Chrome as being installed on the system. \ No newline at end of file diff --git a/tests/platform/windows/windows-chromeSST-testSpec.js b/tests/platform/windows/windows-chromeSST-testSpec.js new file mode 100644 index 000000000..76d1cbede --- /dev/null +++ b/tests/platform/windows/windows-chromeSST-testSpec.js @@ -0,0 +1,153 @@ +/* +GPII Integration and Acceptance Testing + +Copyright 2014 Emergya + +Licensed under the New BSD license. You may not use this file except in +compliance with this License. + +You may obtain a copy of the License at +https://github.com/gpii/universal/LICENSE.txt +*/ + +"use strict"; +var fluid = require("universal"), + gpii = fluid.registerNamespace("gpii"); + +gpii.loadTestingSupport(); + +fluid.registerNamespace("gpii.tests.windows.chromeSST"); + + + +gpii.tests.windows.chromeSST = [ + { + name: "Acceptance test for SST translate service in Chrome", + userToken: "chrome_sst_translate", + settingsHandlers: { + "gpii.settingsHandlers.webSockets": { + "data": [ + { + "settings": { + "serviceName": "Translatewebpage", + "serviceInput": { + "targetLanguage": "fr" + } + }, + "options": { + "path": "com.certh.service-synthesis", + "SSTURL": "http://160.40.50.183:8080/CLOUD4All_SST_Restful_WS/SST/call_" + } + } + ] + } + }, + processes: [] + }, + { + name: "Acceptance test for SST font converter service in Chrome", + userToken: "chrome_sst_fontconverter", + settingsHandlers: { + "gpii.settingsHandlers.webSockets": { + "data": [ + { + "settings": { + "serviceName": "FontConverter", + "serviceInput": { + "targetFontSize": "16", + "inputUrl": "", + "targetFontFamily": "Arial", + "targetBackground": "yellow", + "targetColor": "red" + } + }, + "options": { + "path": "com.certh.service-synthesis", + "SSTURL": "http://160.40.50.183:8080/CLOUD4All_SST_Restful_WS/SST/call_" + } + } + ] + } + }, + processes: [] + }, + { + name: "Acceptance test for SST CallWebAnywhere service in Chrome", + userToken: "chrome_sst_callwebanywhere", + settingsHandlers: { + "gpii.settingsHandlers.webSockets": { + "data": [ + { + "settings": { + "serviceName": "CallWebAnywhere", + "serviceInput": { + "voiceLanguage": "fr", + "inputUrl": "" + } + }, + "options": { + "path": "com.certh.service-synthesis", + "SSTURL": "http://160.40.50.183:8080/CLOUD4All_SST_Restful_WS/SST/call_" + } + } + ] + } + }, + processes: [] + }, + { + name: "Acceptance test for combined service in Chrome", + userToken: "chrome_sst_combined", + settingsHandlers: { + "gpii.settingsHandlers.webSockets": { + "data": [ + { + "settings": { + "serviceName": "callCombinedServices", + "serviceInput": { + "input": [ + { + "serviceName": "Translatewebpage", + "serviceInput": { + "inputUrl": "", + "targetLanguage": "fr" + } + }, + { + "serviceName": "CallWebAnywhere" + } + ], + "mappedVariables": [ + { + "fromServiceName": "Translatewebpage", + "fromVariableName": "finalUrl", + "toServiceName": "CallWebAnywhere", + "toVariableName": "inputUrl" + }, + { + "fromServiceName": "Translatewebpage", + "fromVariableName": "targetLanguageCode", + "toServiceName": "CallWebAnywhere", + "toVariableName": "voiceLanguage" + } + ] + } + }, + "options": { + "path": "com.certh.service-synthesis", + "SSTURL": "http://160.40.50.183:8080/CLOUD4All_SST_Restful_WS/SST/call_" + } + } + ] + } + }, + processes: [] + } +]; + +module.exports = gpii.test.bootstrap({ + testDefs: "gpii.tests.windows.chromeSST", + configName: "windows-chromesst-config", + configPath: "configs" +}, ["gpii.test.integration.testCaseHolder.windows"], + module, require, __dirname); diff --git a/tests/platform/windows/windows-chromeSST-testSpec.txt b/tests/platform/windows/windows-chromeSST-testSpec.txt new file mode 100644 index 000000000..dad7fdf95 --- /dev/null +++ b/tests/platform/windows/windows-chromeSST-testSpec.txt @@ -0,0 +1,12 @@ +windows-chromeSST-testSpec.txt + +Descriptions: + +* Solution: Cloud4all's SST-Chrome extension for Google Chrome (SSTChrome4cloud) +* Configuration file: windows-chromesst-config.json +* Device reporter file: chrome_sst.json +* NP sets: + * chrome_sst_translate + * chrome_sst_fontconverter + * chrome_sst_callwebanywhere + * chrome_sst_combined \ No newline at end of file