silverbucket/teste

View on GitHub
lib/tools/WebSocketClient.js

Summary

Maintainability
C
1 day
Test Coverage
/**
 * Function: WebSocketClient
 *
 * The WebSocketClient object is used to create an object for simplifying
 * WebSocketClient requests.
 *
 *      env.WebSocketClient = new this.WebSocketClient();
 *      env.WebSocketClient.connect('ws://localhost:9992/',
 *                     'echo-protocol',
 *                      function(connection) {
 *           env.connection = connection;
 *           env.connection.send('command', _this);
 *      });
 *
 * Parameters:
 *
 *   baseUrl - the baseUrl of all your WebSocketClient calls
 *
 * Returns:
 *
 *   returns a WebSocketClient object a connect() function, sendAndVerify(),
 *   and sendWithCallback()
 */
if (typeof define !== 'function') {
  var define = require('amdefine')(module);
}

//FIXME is this a nice way to just ommit websocket support

if(typeof window === 'undefined') { // node
  define(['websocket', 'jaribu/tools/Write'], function (WebSocket, Write, undefined) {
    var writeObj = new Write();
    var write = writeObj.func;
    
    var WebSocketClient = function (cfg) {
      if (typeof cfg.url === 'string') {
        this.url = cfg.url;
      }
      if (typeof cfg.type === 'string') {
        this.type = cfg.type;
      }
    };

    WebSocketClient.prototype = {
      url: undefined,
      type: undefined
    };

    WebSocketClient.prototype.setTest = function (test) {
      this.test = test;
    };

    WebSocketClient.prototype.connect = function (onComplete) {
      var client = new WebSocket.client();
      var self = this;

      client.on('connectFailed', function (error) {
        write('[WebSocketClient]: Connect Error: ' + error.toString());
      });

      client.on('connect', function (connection) {
        write('[WebSocketClient]: connected');
        var cmd = {
          command: '',
          callbacks: {
            onMessage: undefined,
            onError: undefined,
            onComplete: undefined
          },
          autoVerify: false
        }; // ASYNC ?

        connection.on('error', function (error) {
          write("[WebSocketClient]: Connection Error: " + error.toString());
        });

        connection.on('close', function () {
          write('[WebSocketClient]: Connection Closed');
        });

        connection.on('message', function (message) {
          var key;
          if (cmd.autoVerify === true) {
            //console.log('self.test.result:'+self.test.result);

            self.test.assertFailAnd(cmd.expected, undefined, 'sendAndVerify result (second param) undefined');
            var msg = JSON.parse(message.utf8Data);
            //msg = msg.replace(/["]/g,'');

            if (message.type === 'utf8') {
              write("[WebSocketClient]: Received Response: " + message.utf8Data);

              if ((typeof cmd.confirmProps !== 'undefined') &&
                  (!cmd.receivedConfirm)) {
                // confirmation expected, and not received yet. check to see if this is it
                for (key in cmd.confirmProps) {
                  self.test.assertAnd(cmd.confirmProps[key], msg[key], 'checking for property: '+key);
                }
                //console.log('self.test.result(): '+self.test.result());
                if (self.test.result() !== false) {
                  console.log('RECEIVED CONFIRM');
                  cmd.receivedConfirm = true;
                }
                //self.test.result(true);
              } else if ((cmd.expected !== undefined) && ((cmd.receivedConfirm) || (typeof cmd.confirmProps === 'undefined'))) {
                // either confirmation received already, or not expected, continue with
                // check

                //console.log('actual response: ', message.utf8Data);
                var onComplete = false;
                if (cmd.callbacks.onComplete !== undefined) {
                  // if onComplete was called, we dont want this assert to finish
                  // the test if the match is successful, only if theres a failure.
                  // which is why we use assertAnd, instead of just assert.
                  onComplete = true;
                }

                if (typeof cmd.expected === 'string') {
                  // if the command is a string, it's probably json, lets compare it directly in that case
                  if (onComplete) {
                    self.test.assertAnd(cmd.expected, message.utf8Data, 'tried to compare json strings');
                  } else {
                    self.test.assert(cmd.expected, message.utf8Data, 'tried to compare json strings');
                  }
                } else {
                  //console.log('MSG: ', msg);
                  //console.log('RES: ', self.test.result);
                  if (onComplete) {
                    self.test.assertAnd(cmd.expected,
                                        msg, 'obj vs msg object');
                  } else {
                    for (key in cmd.expected) {
                      self.test.assertAnd(cmd.expected[key], msg[key], 'checking for property: '+key);
                    }
                    console.log('self.self.test.result(): ', self.test.assert.msg);
                    if (self.test.result() !== false) {
                      self.test.result(true);
                    } else {
                      self.test.result(false, self.test._message);
                    }
                    //console.log("HERE: ", self.test);
                    /*self.test.assert(self.test.result,
                      msg, 'obj vs msg object');*/
                  }
                }

                // control flow shouldn't get this far if the callback wasn't defined
                if (onComplete) {
                  cmd.callbacks.onComplete(msg);
                }
              } else {
                self.test.result(false, 'WebSocketClient: no result set to auto verify');
              }
            }
          } else if (typeof cmd.callbacks.onMessage === 'function') {
            cmd.callbacks.onMessage(message);
          }
        });

        // helper function for tests to verify the command and mark test
        // complete if the verification is successful against the test
        // data passed in during the instantiation in the controller.
        connection.sendAndVerify = function (command, expected, confirmProps, junk) {
          if (typeof junk === 'object') {
            // backward compatibility for when we used to have the test object
            // passed in, before confirmProps. (command, expected, test, confirmProps)
            cmd.confirmProps = junk;
          } else {
            if ((typeof confirmProps === 'object') &&
                (confirmProps.type !== 'Scaffolding')) {
              // not a test object, so we can use it
              cmd.confirmProps = confirmProps;
            }
          }
          cmd.receivedConfirm = false;
          cmd.command = command;
          cmd.expected = expected;
          cmd.autoVerify = true;
          connection.sendUTF(command);
        };
        // another helper function to assist with an async test that doesn't
        // want to use auto-verify. You can do your verification in the
        // callback methods you specify
        connection.sendWithCallback = function (command, onMessage, onError) {
          cmd.command = command;
          cmd.autoVerify = false;
          cmd.callbacks.onMessage= onMessage;
          cmd.callbacks.onError = onError;
          connection.sendUTF(command);
        };

        // meant to replace sendWithCallback and sendAndVerify, using a params object
        // to specify all the various details which configure the behavior of the
        // function.
        //
        // {
        //   send: JSON.stringify(data),
        //   expect: expected,
        //   confirmProps: confirmProps,
        //   autoVerify: true,
        //   onComplete: function() { }, // if callback function is called, verification is used with assertAnd, not assert
        //   onMessage: function() { },
        //   onError: function() { },
        // }
        connection.sendWith = function (params) {
          cmd.command = (params.send) ? params.send : undefined;
          cmd.confirmProps = (params.confirmProps) ? params.confirmProps : undefined;
          cmd.expected = (params.expect) ? params.expect : undefined;
          cmd.receivedConfirm = false;
          cmd.autoVerify = (params.autoVerify) ? true : false;
          cmd.callbacks.onComplete = (params.onComplete) ? params.onComplete : undefined;
          cmd.callbacks.onMessage= (params.onMessage) ? params.onMessage : undefined;
          cmd.callbacks.onError = (params.onError) ? params.onError : undefined;

          if ((cmd.callbacks.onMessage === undefined) && (cmd.autoVerify === false)) {
            write('[WebSocketClient]: neither autoVerify or onMessage were specified, no resolution can occur.');
          }
          connection.sendUTF(cmd.command);
        };

        onComplete(connection); // connection established, return
        // modified connection object to test suite.
      });

      client.connect(this.url, this.type);
    };

    return WebSocketClient;
  });
} else { //Browser
  define([], function() { return {}});
}