Tag Archives: Javascript

A simple chat application with javascript and ActiveMQ using STOMP messaging

Here is a small chat program that can be used for building a rich chat application, or if you just want a very simple chat program for your friends. It contains sending and receiving STOMP messages from an Apache ActiveMQ topic.

Prerequisites:
* Apace ActiveMQ server which can be found here: https://activemq.apache.org/components/classic/download/ Usually no configuration needed. Just start the server (./activemq start) and everything should work ok
* Stomp.js. A helper script for handling the WebSocket communication between ActiveMQ and your javascript application. This script can be found here, courtesy of Jeff Mesnil and Mark Broadbent: https://github.com/jmesnil/stomp-websocket/tree/master/lib

HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>A simple ActiveMQ chat application</title>
    
    <script src="stomp.js"></script>
    <script src="index.js"></script>
</head>
<body>
    <textarea id="chat" rows="10" cols="35"></textarea>
    <br />
    <input id="message" size="40" type="text">
    <br />
    <button id="send" type="button" onclick="send()">Send</button>
</body>
</html>

Javascript:

// Setup websocket connection
const client = Stomp.client("ws://localhost:61614/stomp", "v11.stomp");
// Setup header options
const headers = {id: 'JUST.FCX', ack: 'client'};

// Connect to ActiveMQ (via websocket)
client.connect("admin", "admin", function () {
    // Setup subscription of topic (/topic/chat)
    client.subscribe("/topic/chat",
        function (message) {
            const msg = message.body;
            // Add message to textarea
            document.getElementById("chat").value += msg + "\n";
            // Acknowledge the message
            message.ack();
        }, headers);
});

function send() {
    const message = document.getElementById("message");
    // Send message to topic (/topic/chat)
    client.send("/topic/chat", {}, message.value);
    // Reset input field
    message.value = "";
}

Tested on OSX 10.15.7 and Apache ActiveMQ v5.16.3

Vue testing with Jest: Mock window.location

The bottom line is that you can not mock window.location, BUT you can delete it and create your own to use in test. I will here show one example of how this can be achived:

describe('methodUnderTest', () => {
  // Save current windows.location
  const oldWindowLocation = window.location;
  // Some mocked value
  const mockedUrl = 'https://blog.niklasottosson.com';

  beforeEach(() => {
    // Remove windows.location so that we can create a new
    delete window.location;

    // Create a new mutable window.location
    window.location = Object.defineProperties(
      {},
       {   // copy all properties from the old window.location
        ...Object.getOwnPropertyDescriptors(oldWindowLocation),
        // Start mocking...
        assign: {
           configurable: true,
           value: jest.fn()
        },
        href: {
            configurable: true,
            value: mockedUrl
        }
     );
  });

  afterEach(() => {
    // Restore window.location
    window.location = oldWindowLocation;
  });

  // Start creating your tests...
  it('should...', () => {
    ...
  } 

Tested on OSX 10.15.7, Vue v2.6.12 and Jest v26.0.14

My time number format knockout binding

I made this binding so that I could correct the time number format written by a user (hh:mm). A way to make inputing time values easier. The binding will create time strings from one, two, three and four values. It vill also correct any mistyped characters in between hour and minutes

ko.bindingHandlers.timebox = {
  init: function(element, valueAccessor) {
    var allNumbers = /^\d{4}$/;
    var oneNumber = /^\d$/;
    var twoNumbers = /^\d{2}$/;
    var threeNumbers = /^\d{3}$/;
    var correct = /^\d{2}.\d{2}$/;
    var observable = valueAccessor();
    var formatted = ko.computed({
      read: function (key) {
        return observable();
      },
      write: function (value) {
        if(correct.test(value)){
          value = value.substring(0,2) + ':' + value.substring(3);
        }
        else if(allNumbers.test(value)) {
          value = value.substring(0,2) + ':' + value.substring(2);
        }
        else if(threeNumbers.test(value)) {
          value = '0' + value.substring(0,1) + ':' + value.substring(1);
        }
        else if(oneNumber.test(value)) {
          value = '0' + value + ':00';
        }
        else if(twoNumbers.test(value)) {
          value = value + ':00';
        }
        else {
          alert("Wrong time format specified (hh:mm)");
          value = '';
        }
        observable(value); // Write to underlying storage 
      },
      disposeWhenNodeIsRemoved: element                
    });
 
    //apply the actual value binding with our new computed
    ko.applyBindingsToNode(element, { value: formatted });
  }        
};

Using it is really easy. Just replace ‘value’ with ‘timebox’ like this:

<input id="my_id" type="text" data-bind="timebox:my_observable"/>

Tested on OSX 10.7.5, Chrome 37.0.2062.94, KnockoutJS 3.1.0