1

I'm testing a web chat application. Everytime the user I'm chatting with send a message, it is appended to a text area, like any chat solution. I'd like to detect when new messages arrive and get its content (text).

It would be something like intercepting the javascript onChange event for a given Element. Is it possible to do that using Selenium WebDriver?

I'm interested in testing that for any browser that supports this feature. I'm not interested in testing this behavior for all possible browsers.

The intention is to develop something like a chat bot that sends back a message everytime the other end sends a message. For instance:

Remote user sends: Hello!
Selenium detects that and sends back: Your last message was "Hello!".

I can't change the chat app code.

Is it possible to do it without pooling the text area? My intention would be to listen to events however I couldn't find anything like that and I've been told it is not supported by Selenium WebDriver.

Marcus
  • 1,675
  • 3
  • 18
  • 29

2 Answers2

1

Well, to answer your question - "Is it possible?" - Definitely Yes !! And how ? - Well, it really depends on the chat application and how automation friendly is its interface.

Take for example this simple chat application (its like a chat bot) - http://www.unionplatform.com/?page_id=2247 (I have used its direct URL in the sample code).

Check the code below, I am just checking the <span> tag for the updated value and looped it 5 times to read that the user has entered and reply back with the same message + the loop count (to distinguish the message).

You may follow a similar approach, however again as I mentioned it all depends on the chat app.

Heres the code:

public class WhiteBoard {

public WebDriver driver;
public String css_chat_text = "div#chatPane>span";
public String css_input_msg = "input#outgoing";
public String css_send_button = "input[value='Send']";
public String last_message = "";

public static void main(String[] args) throws Exception {

    WhiteBoard objTest = new WhiteBoard();
    objTest.chatBot();

}

public void chatBot() throws Exception{

    driver = new FirefoxDriver();
    driver.navigate().to("http://unionplatform.com/samples/orbitermicro/UnionChatPart1/chat.html");

    List<WebElement> objChats = driver.findElements(By.cssSelector(css_chat_text));
    if(objChats.size() > 0){
        System.out.println("Starting chattter...");
        String status;
        //loop until chat ready
        do{
            Thread.sleep(3000);
            objChats = driver.findElements(By.cssSelector(css_chat_text));

            status = objChats.get(objChats.size()-1).getText().toString();
            System.out.println(status);

        }while(!status.contains("Chat ready!"));

        Thread.sleep(3000);
        //start chatting...
        sendMessage("Hello...");

        for(int i=0; i<5; i++) {
            objChats = driver.findElements(By.cssSelector(css_chat_text));
            last_message = objChats.get(objChats.size()-1).getText().toString().trim();
            sendMessage("LastMsg:" + last_message + "#" +i);
            Thread.sleep(5000);
        }
    }
    else{
        System.out.println("Chat not found...");
    }
}


public void sendMessage(String message){

    //start chatting...
    List<WebElement> objInput = driver.findElements(By.cssSelector(css_input_msg));
    if(objInput.size() > 0){
        objInput.get(0).sendKeys(message);
        System.out.println("Sent message..." + message);
        List<WebElement> btnSend = driver.findElements(By.cssSelector(css_send_button));
        btnSend.get(0).click();
    }
}

}

The sleeps are just to crudely kept to wait until the chatbox gets updated, ideally I would keep checking the <span> count and proceed once incremented.

The console output of the above code would look like - https://gist.github.com/anonymous/f1eef7198648d95f1d01

Also here's another interesting question on SO that may be of help - How to test chat web app

Community
  • 1
  • 1
DRVaya
  • 443
  • 4
  • 13
  • Great example! It is really useful. From what I've understood you are pooling the css_chat_text element. That's what I was trying to avoid, however it seems to be impossible (according to dming's answer). Thanks very much. – Marcus Mar 21 '15 at 14:58
1

I think Selenium WebDriver doesn't have built in support for listening to events so the best option would probably to poll for change in the element you are looking for.

Something like:

private void pollForTextChange()
{
    WebElement textArea = this.driver.findElement(By.tagName("textarea"));

    int maxPollTime = 60;
    String lastText = textArea.getText();
    String currentText = textArea.getText();
    for (int i=0; i<maxPollTime; i++)
    {
        Thread.sleep(maxPollTime * 1000);
        currentText = textArea.getText();
        if (!currentText.equals(lastText))
        {
            // Change detected, perform desired actions here

            // Assuming it's a chat app and the new text should always contain existing text
            // and you want to get the new content sent
            String newContent = "";
            if (currentText.contains(lastText))
            {
                newContent = currentText.replace(lastText, "").trim();
                // Found new input, performed desired actions here
            }
        }

        lastText = currentText;
    }
}
d3ming
  • 8,496
  • 5
  • 31
  • 33
  • Sure it works. However this is exactly what I was trying to avoid. I'm going to try to find an alternative approach. If can't find any, that's the way to go. Thanks very much. – Marcus Mar 21 '15 at 14:50