text: /*
   * (C) Copyright 2014 Kurento (http://kurento.org/)
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *   http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   *
   */
  
  
  var nodeunit = require('nodeunit');
  var EventTarget = require('eventtarget');
  
  var RpcBuilder = require("..");
  var JsonRpcClient = RpcBuilder.clients.JsonRpcClient;
  var packer = RpcBuilder.packers.JsonRPC;
  
  var ws_uri = "ws://localhost:8888/kurento";
  
  const METHOD = 'test';
  
  
  function noop(error, result){};
  
  function connectCallback(){
    connected = true;
  }
  
  function disconnectCallback(){
    connected = false;
  }
  
  exports['encode JsonRPC 2.0'] =
  {
    setUp: function(callback)
    {
      this.rpcBuilder = new RpcBuilder(packer);
  
      callback();
    },
  
    tearDown: function(callback)
    {
      this.rpcBuilder.close();
  
      callback();
    },
  
    'notification': function(test)
    {
      test.expect(5);
  
      var notification = this.rpcBuilder.encode(METHOD);
  
      test.deepEqual(JSON.parse(notification),
      {
        jsonrpc: '2.0',
        method: METHOD
      });
  
      // Test notification
      notification = this.rpcBuilder.decode(notification);
  
      test.ok(notification instanceof RpcBuilder.RpcNotification);
      test.equal(notification.duplicate, undefined);
  
      test.equal(notification.method, METHOD);
      test.deepEqual(notification.params, {});
  
      test.done();
    },
  
    'request': function(test)
    {
      test.expect(5);
  
      var request = this.rpcBuilder.encode(METHOD, noop);
  
      test.deepEqual(JSON.parse(request),
      {
        jsonrpc: '2.0',
        method: METHOD,
        id: 0
      });
  
      // Test request
      request = this.rpcBuilder.decode(request);
  
      test.ok(request instanceof RpcBuilder.RpcNotification);
      test.equal(request.duplicated, false);
  
      test.equal(request.method, METHOD);
      test.deepEqual(request.params, {});
  
      test.done();
    },
  
    'request timeout': function(test)
    {
      test.expect(2);
  
      var request = this.rpcBuilder.encode(METHOD, function(error, result)
      {
        test.notEqual(error, undefined);
        test.deepEqual(error.request, request);
  
        test.done();
      });
    },
  
    'request timeout and retry': function(test)
    {
      var self = this;
  
      test.expect(4);
  
      var gotError = false;
  
      var request = this.rpcBuilder.encode(METHOD, function(error, result)
      {
        if(!gotError)
        {
          gotError = true;
  
          test.notEqual(error, undefined);
          test.deepEqual(error.request, request);
  
          var request2 = error.retry();
  
          test.deepEqual(request2, request);
  
          // Process request on 'server'
          request2 = self.rpcBuilder.decode(request2);
          var response = request2.reply();
  
          // Process response by 'client'
          self.rpcBuilder.decode(response);
        }
  
        else
        {
          test.equal(error, undefined);
  
          test.done();
        }
      });
    },
  
    'cancel request': function(test)
    {
      test.expect(0);
  
      var request = this.rpcBuilder.encode(METHOD, function(error, result)
      {
        test.ifError(error);
      });
  
      this.rpcBuilder.cancel(request);
  
      setTimeout(function()
      {
        test.done();
      }, 6*1000)
    },
  
    'duplicated request': function(test)
    {
      test.expect(3);
  
      var request = this.rpcBuilder.encode(METHOD, noop);
  
      // Test request
      var request1 = this.rpcBuilder.decode(request);
      test.equal(request1.duplicated, false);
  
      var reply1 = request1.reply(null, null);
  
      var request2 = this.rpcBuilder.decode(request);
      test.equal(request2.duplicated, true);
  
      var reply2 = request2.reply();
  
      test.deepEqual(reply1, reply2);
  
      test.done();
    },
  
    'duplicated request with transport': function(test)
    {
      test.expect(2);
  
      var request = this.rpcBuilder.encode(METHOD, noop);
  
      // Test request
      var request1 = this.rpcBuilder.decode(request);
      test.equal(request1.duplicated, false);
  
      var reply1 = request1.reply(null, null);
  
      var request2 = this.rpcBuilder.decode(request, function(reply2)
      {
        test.deepEqual(reply1, reply2);
  
        test.done();
      });
      test.equal(request2, undefined);
    },
  
    'override duplicated request': function(test)
    {
      test.expect(4);
  
      var request = this.rpcBuilder.encode(METHOD, noop);
  
      // Test request
      var request1 = this.rpcBuilder.decode(request);
      test.equal(request1.duplicated, false);
  
      var reply1 = request1.reply(null, null);
  
      var request2 = this.rpcBuilder.decode(request);
      test.equal(request2.duplicated, true);
  
      var reply2 = request2.reply(null, 'ok');
  
      test.equal(JSON.parse(reply1).result, null);
      test.equal(JSON.parse(reply2).result, 'ok');
  
      test.done();
    },
  
    'response': function(test)
    {
      test.expect(2);
  
      var request = this.rpcBuilder.encode(METHOD, function(error, result)
      {
        test.equal(result, null);
      });
  
      // Compose response manually from the request
      var response = JSON.parse(request);
  
      delete response.method;
      response.result = null;
  
      response = JSON.stringify(response);
  
      // Test response
      response = this.rpcBuilder.decode(response);
  
      test.equal(response, undefined);
  
      test.done();
    },
  
    'duplicate response': function(test)
    {
      test.expect(3);
  
      var request = this.rpcBuilder.encode(METHOD, function(error, result)
      {
        test.equal(result, null);
      });
  
      // Compose response manually from the request
      var response = JSON.parse(request);
  
      delete response.method;
      response.result = null;
  
      response = JSON.stringify(response);
  
      // Test response
      var result = this.rpcBuilder.decode(response);
      test.equal(result, undefined);
  
      // Ignored response
      var result = this.rpcBuilder.decode(response);
      test.equal(result, undefined);
  
      test.done();
    },
  
    'request reply response': function(test)
    {
      test.expect(3);
  
      var value = {'asdf': 'qwert'};
  
      var request = this.rpcBuilder.encode(METHOD, function(error, result)
      {
        test.deepEqual(result, value);
      });
  
      // Response request
      request = this.rpcBuilder.decode(request);
  
      var response = request.reply(null, value);
  
      // Test response message
      test.deepEqual(JSON.parse(response),
      {
        jsonrpc: '2.0',
        result: value,
        id: 0
      });
  
      response = this.rpcBuilder.decode(response);
  
      // Test response as processed
      test.equal(response, undefined);
  
      test.done();
    },
  
    'reply with transport': function(test)
    {
      test.expect(4);
  
      var self = this;
  
      var value = {'asdf': 'qwert'};
  
      var request = this.rpcBuilder.encode(METHOD, function(error, result)
      {
        test.deepEqual(result, value);
      });
  
      // Response request
      request = this.rpcBuilder.decode(request);
  
      var response = request.reply(null, value, function(message)
      {
        // Test response message
        test.deepEqual(JSON.parse(message),
        {
          jsonrpc: '2.0',
          result: value,
          id: 0
        });
  
        message = self.rpcBuilder.decode(message);
  
        // Test response as processed
        test.equal(message, undefined);
      });
  
      // Test response as send by reply transport
      test.equal(response, undefined);
  
      test.done();
    },
  
    'decode with transport': function(test)
    {
      test.expect(4);
  
      var self = this;
  
      var value = {'asdf': 'qwert'};
  
      var request = this.rpcBuilder.encode(METHOD, function(error, result)
      {
        test.deepEqual(result, value);
      });
  
      // Response request
      request = this.rpcBuilder.decode(request, function(message)
      {
        // Test response message
        test.deepEqual(JSON.parse(message),
        {
          jsonrpc: '2.0',
          result: value,
          id: 0
        });
  
        message = self.rpcBuilder.decode(message);
  
        // Test response as processed
        test.equal(message, undefined);
      });
  
      var response = request.reply(null, value);
  
      // Test response as send by reply transport
      test.equal(response, undefined);
  
      test.done();
    },
  
    'transport with message event': function(test)
    {
      test.expect(2);
  
      var self = this;
  
      var value = {'asdf': 'qwert'};
  
      var transport = new EventTarget;
          transport.onmessage = null;
          transport.send = function(message)
          {
            message = JSON.parse(message);
  
            var event =
            {
              type: 'message',
              data: JSON.stringify(
              {
                jsonrpc: '2.0',
                result: message.params,
                id: 0
              })
            };
  
            this.dispatchEvent(event);
          };
  
      this.rpcBuilder.transport = transport;
  
      var request = this.rpcBuilder.encode(METHOD, value, function(error, result)
      {
        test.ifError(error);
  
        test.deepEqual(result, value);
  
        test.done();
      });
  
      // Test response as send by reply transport
      test.equal(request, undefined);
    },
  
    'request event': function(test)
    {
      test.expect(1);
  
      var transport = new EventTarget;
          transport.onmessage = null;
  
      this.rpcBuilder.transport = transport;
      this.rpcBuilder.on('request', function(request)
      {
        test.deepEqual(request.method, METHOD);
  
        test.done();
      });
  
      var event =
      {
        type: 'message',
        data: JSON.stringify(
        {
          jsonrpc: '2.0',
          method: METHOD
        })
      };
      transport.dispatchEvent(event);
    },
  
    'create JsonRpcClientWs with WS': function(test)
    {
      test.expect(1);
  
      var configuration = {
        sendCloseMessage : false,
        ws : {
          uri : ws_uri,
          useSockJS: false,
          onconnected : connectCallback,
          ondisconnect : disconnectCallback,
          onreconnecting : disconnectCallback,
          onreconnected : connectCallback
        },
        rpc : {
          requestTimeout : 15000
        }
      };
  
      var jsonRpcClientWs = new JsonRpcClient(configuration);
  
      test.ok(jsonRpcClientWs instanceof JsonRpcClient);
  
      setTimeout(function()
      {
        jsonRpcClientWs.close();
        test.done();
      }, 4*1000)
  
    }
  };
  