WebSocket Help

Hi,

I need to test our application for WebSocket. The real behaviour of our application is WebSocket connection is automatically created for the user when the user logs in the application. At this point 100 users log in before doing another action. Then at one point let’s say at 2:00 o’clock all users hit one button at the same time which sends all 100 WebSocket requests at the same time and users get the response back.

To mimic the real scenario I put the Login and WebSocket Connection request in One scenario and Subsequent actions in a different scenario. So that all users are logged in and make WebSocket connections before doing the subsequent actions concurrently. The issue is Login and WebSocket connections are Successful but for subsequent actions the error is coming that “No open WebSocket connection is fetched”

If I put the WebSocket connection and subsequent actions in a single scenario then all is going fine. What is wrong I am doing. Below is my code snippet

`
val httpProtocol = http
.baseUrl(“https://qa-oh-etime-api.celayix.com”)
.inferHtmlResources(BlackList("""..js""", “”"..css""", “”"..gif""", “”"..jpeg""", “”"..jpg""", “”"..ico""", “”"..woff""", “”"..(t|o)tf""", “”".*.png"""), WhiteList())
.doNotTrackHeader(“1”)
.userAgentHeader(“Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36”)
.wsBaseUrl(“wss://qa-oh-socket-api.celayix.com”)

val headers_10 = Map(
“Accept” → “application/json, text/javascript, /; q=0.01”,
“Content-Type” → “application/json; charset=UTF-8”,
“Origin” → “https://team-xpress.celayix.com”)

val uri1 = “https://dev-or-etime-api.celayix.com/CheckLogin
val uri5 = “https://celadev.celayix.com:8453
val ClientID = “qaevent03”

// Method CheckLogin

def checkLogin() = {

exec(http(“CHECK_LOGIN”)
.post(“https://qa-oh-etime-api.celayix.com/CheckLogin”)
.headers(headers_10)
.body(ElFileBody(“bodies/Check_Login.txt”)).asJson
.check( jsonPath( “$” ).saveAs( “RESPONSE_DATA” ) )
.check(bodyString.saveAs(“Response_Body”))
.check(substring(“Successful Login”).exists)
.check(jsonPath("$.pcResult").is(“OK”))
.check(regex(“pcwxSessionID”,“contextValue”:"(.+?)"").saveAs(“Session_ID”))
.check(regex(“pcBranchID”,“contextValue”:"(.+?)"").saveAs(“Branch_ID”))
.check(regex(“pcCompanyID”,“contextValue”:"(.+?)"").saveAs(“Company_ID”))
.check(regex(“pcEmployeeID”,“contextValue”:"(.+?)"").saveAs(“Employee_ID”)))

.exec( session => {
println( “TeamXP Login Response Body:” )
//println( session( “RESPONSE_DATA” ).as[String] )
println(session (“Response_Body”).as[String])
println( “TeamXP SESSION_ID:” )
//Session_ID = session(“Session_ID”).as[String]
println(session (“Session_ID”).as[String])
Session_ID_Queue.offer(session(“Session_ID”).as[String]) // Keep session ID’s in queue
//println(Session_ID_Queue)
Employee_ID_Queue.offer(session(“Employee_ID”).as[String]) // Keep employee ID’s in a queue
//println(Employee_ID_Queue)
Company_ID = session(“Company_ID”).as[String]
Branch_ID = session(“Branch_ID”).as[String]

//println(session (“ID”).as[String])
session
})
}

//Method getSelfSchedule

def getSelfSchedule() = {

exec(ws(“Get_Self_Schedule”)

.sendText(
“”"{“GetSelfSchedules payload”}""")

.await(100 )
(ws.checkTextMessage(“Get_Self_Schedule_Check”)
.check( jsonPath( “$” ).saveAs( “GET SELF SCHEDULES” ) )
.check(jsonPath("$.payload.pcResult").is(“OK”))
.check(regex(“pcTimeStamp”,“contextValue”:"(.+?)"").saveAs(“TimeStamp”))))

.exec( session => {
//println(“GET SELF SCHEDULES:”)
println(session(“GET SELF SCHEDULES”).as[String])
println(“GET SELF SCHEDULES TIME STAMP:”)
Time_Stamp_Queue.offer(session(“TimeStamp”).as[String])
TimeStamp = session(“TimeStamp”).as[String]
println(session(“TimeStamp”).as[String])
//(session(“TimeStamp1”).as[String])
println(session(“Session_ID”).as[String])
session
})
}

// Method updateSelfSchedule

def updateSelfSchedule() = {
exec(ws(“Upadte Self Schedule”)
.sendText("""{“UpdateSelfSchedules payload”}""")

.await(100 )

(ws.checkTextMessage(“Update_Self_Schedule_Check”)
.check( jsonPath( “$” ).saveAs( “UPDATE SELF SCHEDULES” ) )
.check(jsonPath("$.payload.pcResult").is(“OK”))
.check(substring(“The following shift has been assigned:”))))

.exec( session => {
println(“UPDATE SELF SCHEDULES:”)
println(session(“UPDATE SELF SCHEDULES”).as[String])
session
})
}

val Session_ID_Queue = new ConcurrentLinkedQueueString
val Employee_ID_Queue = new ConcurrentLinkedQueueString
val Time_Stamp_Queue = new ConcurrentLinkedQueueString
@volatile var TimeStamp = “”
var Company_ID = “”
var Branch_ID = “”
val usersCount = 10
//@volatile var Session_ID = “”

//Get today date
var date = new Date()
val sdf = new SimpleDateFormat(“yyyy-MM-dd”)
var startDate = sdf.format(date)
println("Start date is: "+startDate)

// Get Future date (today+6)
val calendar: Calendar = Calendar.getInstance
calendar.add(Calendar.DAY_OF_YEAR, 5)
var endDate = sdf.format(calendar.getTime())
println("End date is: "+endDate)

// Scenario Check Login (Actual Script Starts here)

val EmployeeCredentialsFeeder = csv(“data/Test Employees.csv”).batch(30) // Employees Credential feeder(csv)

val TeamXP_Login = scenario(“TXP_Login”)

.feed(EmployeeCredentialsFeeder) // feed clientID, username and password for Login from csv file
.exec(checkLogin()) //Execute checkLogin method
.pause(1)

// Make Websocket Connection
.exec(ws(“ConnectSocket”)
.connect(“wss://qa-oh-socket-api.celayix.com/?clientId=${ClientID}&cid=${Company_ID}&bid=${Branch_ID}&sessionId=${Session_ID}&eid=${Employee_ID}”))
.exec(ws(“Connection Check”)
.sendText(“Ping”)
.await(30)
(ws.checkTextMessage(“response Check”)

.check(jsonPath("$").saveAs(“Body”)))
)
.exec( session => {
println(“Initial Body:”)
println(session(“Body”).as[String])
session
})

//create feeder for SessionID and Employee ID. poll() method will retrieve the head item from the queue and delete it
// Here Session ID’s and Employee ID’s are polled from queue and map to Session_ID and Employee_ID variable

val SessionIDFeeder = Iterator.continually(Map(“Session_ID” → Session_ID_Queue.poll()))
val EmployeeIDFeeder = Iterator.continually(Map(“Employee_ID” → Employee_ID_Queue.poll()))
val TimeStampFeeder = Iterator.continually(Map(“TimeStamp” → Time_Stamp_Queue.poll()))

// Get and Update self Scehdule

val WS_Connections = scenario(“Get_Assign_SelfSCH_Websocket”)

//Make the variables as session variables to have them avaiable in next scenario
.exec(.set(“startDate”,startDate))
.exec(
.set(“endDate”, endDate))
.exec(.set(“Company_ID”, Company_ID))
.exec(
.set(“Branch_ID”, Branch_ID))

//Feed the SessionID, EmployeeID, and clientID through the feeder

.feed(SessionIDFeeder)
.feed(EmployeeIDFeeder)
.feed(EmployeeCredentialsFeeder)

.exec(getSelfSchedule()) // run getSelfSchedule method

.pause(3)

.exec(updateSelfSchedule()) // run getSelfSchedule method
exec(ws(“Close WebSocket”).close)

setUp(TeamXP_Login.inject(rampUsers(usersCount) during(10)), WS_Connections.inject(nothingFor(15 seconds), rampUsers(usersCount) during(4)).protocols(httpProtocol))

}
`

Below is the response I am getting

`

If you want to share data across steps you need to make them a part of the same scenario. The users executing one scenario are not the same as those executing any others - they don’t share a session context.

Any reason why you just can’t put everything in one scenario?

Thanks James for the reply. I can put everything in one scenario. But to mimic the behaviour of real users I wanted to put them in separate scenario because real users start to login some time ahead and waiting to hit get self schedule shifts button. Then all real users are hitting the button at same time and within a minute all 1000 shifts are gone. real users are automatically connected to webSocket at the time of login.

Have a look at using ‘rendezVous’ to achieve this

Thank you so much James. This is exactly what I was looking for. You made my day.

Appreciate you so much.