Repository: asyncapi/generator
Pull request #1467: chore: add acceptance testing with microcks mocks
Author: login: derberg
Labels: name: ready-to-merge
name: bounty
description: AsyncAPI Bounty program related label
Created: 2025-04-02T17:18:54Z | Merged: 2025-04-14T13:31:19Z

fixes: https://github.com/asyncapi/generator/issues/1417

we use microcks and podman for efficient testing that can even run on local

we test send and receive messages - both python and javascript

it is not automated and optimized - as it was not the goal of that task - the goal was to find the best solution and this is done and works. Rest marked with `TODO` in code

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
	- Enhanced WebSocket messaging with improved asynchronous operations for reliable echo and timestamp interactions.
	- Introduced real-time examples that illustrate expected message formats.
	- Added a new shell script for verifying the health status of Microcks containers.
	- Introduced new configuration files for asynchronous API features and Podman setup.

- **Documentation**
	- Added comprehensive setup and testing guides with clear instructions for environment configuration and debugging.
	- Created a README file detailing testing procedures for WebSocket clients.

- **Tests**
	- Expanded automated tests to validate robust WebSocket communication and service readiness.
	- Introduced new acceptance tests for the HoppscotchEchoWebSocketClient.

- **Chore**
	- Updated source control settings for streamlined project management.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/.gitignore b/.gitignore
index ba58fd4ff9..7d3e23014a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,4 +16,6 @@ coverage
 
 /.idea
 temp
-__pycache__
\ No newline at end of file
+__pycache__
+
+microcks-data
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index bb105cbbff..f6927edb8f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10313,6 +10313,10 @@
         "@pkgjs/parseargs": "^0.11.0"
       }
     },
+    "node_modules/javascript": {
+      "resolved": "packages/templates/clients/websocket/test/javascript",
+      "link": true
+    },
     "node_modules/jest": {
       "version": "27.5.1",
       "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz",
@@ -18159,6 +18163,19 @@
         "jest-esm-transformer": "^1.0.0",
         "rimraf": "^3.0.2"
       }
+    },
+    "packages/templates/clients/websocket/test/javascript": {
+      "devDependencies": {
+        "@babel/cli": "^7.25.9",
+        "@babel/core": "^7.26.0",
+        "@babel/preset-env": "^7.26.0",
+        "@babel/preset-react": "^7.25.9",
+        "eslint": "^6.8.0",
+        "eslint-plugin-jest": "^23.8.2",
+        "eslint-plugin-react": "^7.34.1",
+        "eslint-plugin-sonarjs": "^0.5.0",
+        "jest-esm-transformer": "^1.0.0"
+      }
     }
   }
 }
diff --git a/packages/templates/clients/websocket/javascript/components/SendEchoMessage.js b/packages/templates/clients/websocket/javascript/components/SendEchoMessage.js
index 68aff90c9f..64cee369f9 100644
--- a/packages/templates/clients/websocket/javascript/components/SendEchoMessage.js
+++ b/packages/templates/clients/websocket/javascript/components/SendEchoMessage.js
@@ -4,10 +4,17 @@ export function SendEchoMessage() {
   return (
     <Text newLines={2} indent={2}>
       {
-        `// Method to send an echo message to the server
-sendEchoMessage(message) {
-  this.websocket.send(JSON.stringify(message));
-  console.log('Sent message to echo server:', message);
+        `/**
+   * By default sends a message over a provided WebSocket connection.
+   * Useful when you already have an established WebSocket connection
+   * and want to send a message without creating a class instance.
+   *
+   * @param {Object} message - The message to send. It will be stringified to JSON.
+   * @param {WebSocket} socket - An existing WebSocket connection to use for sending the message.
+*/
+static sendEchoMessage(message, socket) {
+  const websocket = socket || this.websocket;
+  websocket.send(JSON.stringify(message));
 }`
       }
     </Text>
diff --git a/packages/templates/clients/websocket/javascript/test/__fixtures__/asyncapi-hoppscotch-echo.yml b/packages/templates/clients/websocket/javascript/test/__fixtures__/asyncapi-hoppscotch-echo.yml
index 83cf222205..74a3a11de8 100644
--- a/packages/templates/clients/websocket/javascript/test/__fixtures__/asyncapi-hoppscotch-echo.yml
+++ b/packages/templates/clients/websocket/javascript/test/__fixtures__/asyncapi-hoppscotch-echo.yml
@@ -44,6 +44,9 @@ components:
       summary: A message sent from server with current timestamp.
       payload: 
         $ref: '#/components/schemas/currentTime'
+      examples:
+        - name: someRandomDate
+          payload: 11:13:24 GMT+0000 (Coordinated Universal Time)
     echo:
       summary: A message exchanged with the echo server.
       payload: {}
diff --git a/packages/templates/clients/websocket/javascript/test/__fixtures__/asyncapi-postman-echo.yml b/packages/templates/clients/websocket/javascript/test/__fixtures__/asyncapi-postman-echo.yml
index 2ff9b70207..a9b9d0bc7c 100644
--- a/packages/templates/clients/websocket/javascript/test/__fixtures__/asyncapi-postman-echo.yml
+++ b/packages/templates/clients/websocket/javascript/test/__fixtures__/asyncapi-postman-echo.yml
@@ -26,7 +26,8 @@ operations:
     action: send
     channel: 
       $ref: '#/channels/echo'
-
+    messages:
+      - $ref: '#/channels/echo/messages/echo'
     reply:
       channel: 
         $ref: '#/channels/echo'
diff --git a/packages/templates/clients/websocket/javascript/test/__snapshots__/integration.test.js.snap b/packages/templates/clients/websocket/javascript/test/__snapshots__/integration.test.js.snap
index 5da478e49f..70e3caa5bb 100644
--- a/packages/templates/clients/websocket/javascript/test/__snapshots__/integration.test.js.snap
+++ b/packages/templates/clients/websocket/javascript/test/__snapshots__/integration.test.js.snap
@@ -92,10 +92,17 @@ class HoppscotchEchoWebSocketClient {
     if (cb) cb(message);
   }
 
-  // Method to send an echo message to the server
-  sendEchoMessage(message) {
-    this.websocket.send(JSON.stringify(message));
-    console.log('Sent message to echo server:', message);
+  /**
+     * By default sends a message over a provided WebSocket connection.
+     * Useful when you already have an established WebSocket connection
+     * and want to send a message without creating a class instance.
+     *
+     * @param {Object} message - The message to send. It will be stringified to JSON.
+     * @param {WebSocket} socket - An existing WebSocket connection to use for sending the message.
+  */
+  static sendEchoMessage(message, socket) {
+    const websocket = socket || this.websocket;
+    websocket.send(JSON.stringify(message));
   }
 
   // Method to close the WebSocket connection
@@ -204,10 +211,17 @@ class PostmanEchoWebSocketClientClient {
     if (cb) cb(message);
   }
 
-  // Method to send an echo message to the server
-  sendEchoMessage(message) {
-    this.websocket.send(JSON.stringify(message));
-    console.log('Sent message to echo server:', message);
+  /**
+     * By default sends a message over a provided WebSocket connection.
+     * Useful when you already have an established WebSocket connection
+     * and want to send a message without creating a class instance.
+     *
+     * @param {Object} message - The message to send. It will be stringified to JSON.
+     * @param {WebSocket} socket - An existing WebSocket connection to use for sending the message.
+  */
+  static sendEchoMessage(message, socket) {
+    const websocket = socket || this.websocket;
+    websocket.send(JSON.stringify(message));
   }
 
   // Method to close the WebSocket connection
diff --git a/packages/templates/clients/websocket/python/components/SendEchoMessage.js b/packages/templates/clients/websocket/python/components/SendEchoMessage.js
index 13dee6c085..b6d639ea8f 100644
--- a/packages/templates/clients/websocket/python/components/SendEchoMessage.js
+++ b/packages/templates/clients/websocket/python/components/SendEchoMessage.js
@@ -4,23 +4,50 @@ export function SendEchoMessage() {
   return (
     <Text newLines={2} indent={2}>
       {
-        `def send_message(self, message):
+        `async def send_message(self, message):
     """
-    Automatically process the outgoing message with registered processors and send it
-    using the active WebSocket connection.
+    Send a message using the WebSocket connection attached to this instance.
+
+    Args:
+        message (dict or str): The message to send. Will be serialized to JSON if it's a dictionary.
+
+    Raises:
+        Exception: If sending fails or the socket is not connected.
+    """
+    await self._send(message, self.ws_app)
+
+@staticmethod
+async def send_message_static(message, socket):
+    """
+    Send a message using a provided WebSocket connection, without needing an instance.
+
+    Args:
+        message (dict or str): The message to send.
+        socket (websockets.WebSocketCommonProtocol): The WebSocket to send through.
+
+    Raises:
+        Exception: If sending fails or the socket is not connected.
+    """
+    await HoppscotchEchoWebSocketClient._send(message, socket)
+
+@staticmethod
+async def _send(message, socket):
+    """
+    Internal helper to handle the actual sending logic.
+
+    Args:
+        message (dict or str): The message to send.
+        socket (websockets.WebSocketCommonProtocol): The WebSocket to send through.
+
+    Notes:
+        If message is a dictionary, it will be automatically converted to JSON.
     """
-    # Apply outgoing processors sequentially.
-    for processor in self.outgoing_processors:
-        message = processor(message)
-
-    if self.ws_app and self.ws_app.sock and self.ws_app.sock.connected:
-        try:
-            self.ws_app.send(json.dumps(message))
-            print("\\033[92mSent:\\033[0m", message)
-        except Exception as error:
-            self.handle_error(error)
-    else:
-        print("Error: WebSocket is not connected.")`
+    try:
+        if isinstance(message, dict):
+            message = json.dumps(message)
+        await socket.send(message)
+    except Exception as e:
+        print("Error sending:", e)`
       }
     </Text>
   );
diff --git a/packages/templates/clients/websocket/python/test/__snapshots__/integration.test.js.snap b/packages/templates/clients/websocket/python/test/__snapshots__/integration.test.js.snap
index e4a27149b8..6340510b87 100644
--- a/packages/templates/clients/websocket/python/test/__snapshots__/integration.test.js.snap
+++ b/packages/templates/clients/websocket/python/test/__snapshots__/integration.test.js.snap
@@ -107,23 +107,50 @@ class HoppscotchEchoWebSocketClient:
         for handler in self.error_handlers:
           handler(error)
 
-  def send_message(self, message):
+  async def send_message(self, message):
       \\"\\"\\"
-      Automatically process the outgoing message with registered processors and send it
-      using the active WebSocket connection.
+      Send a message using the WebSocket connection attached to this instance.
+
+      Args:
+          message (dict or str): The message to send. Will be serialized to JSON if it's a dictionary.
+
+      Raises:
+          Exception: If sending fails or the socket is not connected.
       \\"\\"\\"
-      # Apply outgoing processors sequentially.
-      for processor in self.outgoing_processors:
-          message = processor(message)
-
-      if self.ws_app and self.ws_app.sock and self.ws_app.sock.connected:
-          try:
-              self.ws_app.send(json.dumps(message))
-              print(\\"\\\\033[92mSent:\\\\033[0m\\", message)
-          except Exception as error:
-              self.handle_error(error)
-      else:
-          print(\\"Error: WebSocket is not connected.\\")
+      await self._send(message, self.ws_app)
+
+  @staticmethod
+  async def send_message_static(message, socket):
+      \\"\\"\\"
+      Send a message using a provided WebSocket connection, without needing an instance.
+
+      Args:
+          message (dict or str): The message to send.
+          socket (websockets.WebSocketCommonProtocol): The WebSocket to send through.
+
+      Raises:
+          Exception: If sending fails or the socket is not connected.
+      \\"\\"\\"
+      await HoppscotchEchoWebSocketClient._send(message, socket)
+
+  @staticmethod
+  async def _send(message, socket):
+      \\"\\"\\"
+      Internal helper to handle the actual sending logic.
+
+      Args:
+          message (dict or str): The message to send.
+          socket (websockets.WebSocketCommonProtocol): The WebSocket to send through.
+
+      Notes:
+          If message is a dictionary, it will be automatically converted to JSON.
+      \\"\\"\\"
+      try:
+          if isinstance(message, dict):
+              message = json.dumps(message)
+          await socket.send(message)
+      except Exception as e:
+          print(\\"Error sending:\\", e)
 
   def close(self):
       \\"\\"\\"Cleanly close the WebSocket connection.\\"\\"\\"
@@ -250,23 +277,50 @@ class PostmanEchoWebSocketClientClient:
         for handler in self.error_handlers:
           handler(error)
 
-  def send_message(self, message):
+  async def send_message(self, message):
       \\"\\"\\"
-      Automatically process the outgoing message with registered processors and send it
-      using the active WebSocket connection.
+      Send a message using the WebSocket connection attached to this instance.
+
+      Args:
+          message (dict or str): The message to send. Will be serialized to JSON if it's a dictionary.
+
+      Raises:
+          Exception: If sending fails or the socket is not connected.
       \\"\\"\\"
-      # Apply outgoing processors sequentially.
-      for processor in self.outgoing_processors:
-          message = processor(message)
-
-      if self.ws_app and self.ws_app.sock and self.ws_app.sock.connected:
-          try:
-              self.ws_app.send(json.dumps(message))
-              print(\\"\\\\033[92mSent:\\\\033[0m\\", message)
-          except Exception as error:
-              self.handle_error(error)
-      else:
-          print(\\"Error: WebSocket is not connected.\\")
+      await self._send(message, self.ws_app)
+
+  @staticmethod
+  async def send_message_static(message, socket):
+      \\"\\"\\"
+      Send a message using a provided WebSocket connection, without needing an instance.
+
+      Args:
+          message (dict or str): The message to send.
+          socket (websockets.WebSocketCommonProtocol): The WebSocket to send through.
+
+      Raises:
+          Exception: If sending fails or the socket is not connected.
+      \\"\\"\\"
+      await HoppscotchEchoWebSocketClient._send(message, socket)
+
+  @staticmethod
+  async def _send(message, socket):
+      \\"\\"\\"
+      Internal helper to handle the actual sending logic.
+
+      Args:
+          message (dict or str): The message to send.
+          socket (websockets.WebSocketCommonProtocol): The WebSocket to send through.
+
+      Notes:
+          If message is a dictionary, it will be automatically converted to JSON.
+      \\"\\"\\"
+      try:
+          if isinstance(message, dict):
+              message = json.dumps(message)
+          await socket.send(message)
+      except Exception as e:
+          print(\\"Error sending:\\", e)
 
   def close(self):
       \\"\\"\\"Cleanly close the WebSocket connection.\\"\\"\\"
diff --git a/packages/templates/clients/websocket/test/README.md b/packages/templates/clients/websocket/test/README.md
new file mode 100644
index 0000000000..152d50170c
--- /dev/null
+++ b/packages/templates/clients/websocket/test/README.md
@@ -0,0 +1,91 @@
+## Prerequisites
+
+Install [Podman](https://podman.io/docs/installation). 
+
+> Microcks needs some services running to simulate the infrastructure and this requires multiple resources. Docker is not the best solution for this, thus it's better to use Podman that manages resources better.
+
+You can also install [docker-compose](https://docs.docker.com/compose/install/) that `podman compose` will later use.
+
+## Test Project
+
+This `test` directory contains acceptance tests that check different clients with tests written in their respective languages. So JavaScript client is tested with JavaScript test, and Python with Python tests, and so on.
+
+To run tests: `podman compose -f ./microcks-setup/microcks-podman.yml --profile tests up -d`
+
+> You need to remember about `--profile tests` to run whole setup with tests. This way you ensure that proper importer container imports `__fixtures__/asyncapi-hoppscotch-server.yml` into Microcks and tests run against it.
+
+## Testing Clients with Microcks
+
+This instruction is just a set of notes about how to play locally with Microcks that we already use for automated testing.
+
+Tests also run in containers, although with provided configuration you can start also testing environment without running tests, just to play with Microcks and understand more how it works.
+
+### Concept
+
+Microcks is a tool for mocking. To test our generated clients, we need to mock the server. In other words, if we want to check if the generated client for Postman works well, we need to mock the server that the client will communicate with during testing.
+
+### Using Microcks locally
+
+> This instruction assumes you are located in directory where `microcks-setup` directory is located
+
+#### Start Microcks
+
+1. Start Microcks infrastructure: `podman compose -f ./microcks-setup/microcks-podman.yml up -d`.
+
+1. Check with `podman ps` command if all services are running. It may take few minutes to start all containers. You can also run a special script that will confirm that services are ready: `bash ./microcks-setup/checkMicrocksReady.sh`.
+
+1. Access Microcks UI with `open http://localhost:8080`.
+
+#### Load AsyncAPI documents
+
+To test clients, we need to mock the server. Remember to load AsyncAPI documents that represent the server.
+
+1. Install [Microcks CLI](https://microcks.io/documentation/guides/automation/cli/)
+
+1. Import AsyncAPI document
+    ```bash
+    microcks-cli import __fixtures__/asyncapi-hoppscotch-server.yml \
+      --microcksURL=http://localhost:8080/api/ \
+      --keycloakClientId=microcks-serviceaccount \
+      --keycloakClientSecret="ab54d329-e435-41ae-a900-ec6b3fe15c54"
+    ```
+
+1. See the mock in the Microcks UI with `open http://localhost:8080/#/services`
+
+#### Invoke Mocks tests
+
+Start simple testing of the mock to see if it was created properly. Tests should turn green.
+
+You should run tests only on one operation at a time.
+
+```bash
+# the higher timeout the more test samples will run
+microcks-cli test 'Hoppscotch WebSocket Server:1.0.0' ws://localhost:8081/api/ws/Hoppscotch+WebSocket+Server/1.0.0/sendTimeStampMessage ASYNC_API_SCHEMA \
+    --microcksURL=http://localhost:8080/api/ \
+    --insecure \
+    --waitFor=15sec \
+    --keycloakClientId=microcks-serviceaccount \
+    --keycloakClientSecret="ab54d329-e435-41ae-a900-ec6b3fe15c54" \
+    --filteredOperations="[\"SEND sendTimeStampMessage\"]"
+```
+
+You can also check the status of tests in the Microcks UI.
+
+### Debugging 
+
+File `microcks-podman.yml` contains commented out configuration for debbuging container you can start with the entire testing environment.
+
+It's also useful to connect to Microcks containers and checkout logs: `podman logs -f  microcks-async-minion`. Minion is the service that handles API calls.
+
+### Cleanup
+
+Run `podman compose -f ./microcks-setup/microcks-podman.yml down --remove-orphans` to clean everything.
+
+## Playing with Microcks Mock Server
+
+You can also check the websocket endpoints generated by Microcks in the terminal using [websocat](https://github.com/vi/websocat).
+
+Do below to start receiving example messages in the terminal:
+```
+websocat ws://localhost:8081/api/ws/Hoppscotch+WebSocket+Server/1.0.0/sendTimeStampMessage
+```
\ No newline at end of file
diff --git a/packages/templates/clients/websocket/test/__fixtures__/asyncapi-hoppscotch-server.yml b/packages/templates/clients/websocket/test/__fixtures__/asyncapi-hoppscotch-server.yml
new file mode 100644
index 0000000000..068ab3453b
--- /dev/null
+++ b/packages/templates/clients/websocket/test/__fixtures__/asyncapi-hoppscotch-server.yml
@@ -0,0 +1,71 @@
+asyncapi: 3.0.0
+defaultContentType: text/plain
+info:
+  title: Hoppscotch WebSocket Server
+  version: 1.0.0
+  description: >
+    This document is purely for mocking the official Hoppscotch Websocket Echo server.
+
+servers:
+  echoServer:
+    host: echo-websocket.hoppscotch.io
+    protocol: wss
+
+channels:
+  echo:
+    description: >
+      The single channel where messages are sent to and echoed back. Echo server also regularly drops a timestampl to that channel.
+    address: /
+    messages:
+      echo:
+        $ref: '#/components/messages/echo'
+      timestamp:
+        $ref: '#/components/messages/timestamp'
+    bindings:
+      ws:
+        method: POST
+
+operations:
+  sendTimeStampMessage:
+    action: send
+    channel: 
+      $ref: '#/channels/echo'
+    summary: Receive the timestamp message sent from server every second.
+    messages:
+      - $ref: '#/channels/echo/messages/timestamp'
+  handleEchoMessage:
+    action: receive
+    channel: 
+      $ref: '#/channels/echo'
+    summary: Send a message to the echo server.
+    messages:
+      - $ref: '#/channels/echo/messages/echo'
+
+components:
+  messages:
+    timestamp:
+      summary: A message sent from server with current timestamp.
+      payload: 
+        $ref: '#/components/schemas/currentTime'
+      examples:
+        - name: someRandomDate
+          payload: 11:13:24 GMT+0000 (Coordinated Universal Time)
+    echo:
+      summary: A message exchanged with the echo server.
+      payload: {}
+      examples:
+        - name: string
+          payload: "test"
+        - name: boolean
+          payload: true
+        - name: number
+          payload: 123
+        - name: object
+          payload: 
+            test: test text
+  
+  schemas:
+    currentTime:
+      type: string
+      description: A timestamp with GMT timezone.
+      example: 11:13:24 GMT+0000 (Coordinated Universal Time)
\ No newline at end of file
diff --git a/packages/templates/clients/websocket/test/javascript/acceptance.test.js b/packages/templates/clients/websocket/test/javascript/acceptance.test.js
new file mode 100644
index 0000000000..1553431a3f
--- /dev/null
+++ b/packages/templates/clients/websocket/test/javascript/acceptance.test.js
@@ -0,0 +1,105 @@
+/**
+ * @jest-environment node
+ */
+
+const WSClient = require('../../javascript/test/temp/snapshotTestResult/client-hoppscotch');
+const { waitForMessage, delay, waitForTestSuccess } = require('./utils');
+const fetch = require('node-fetch');
+const WebSocket = require('ws');
+const microcksTestEndpoint = 'http://microcks:8080/api/tests';
+
+describe('client - receiver tests', () => {
+  jest.setTimeout(10000);
+  /*
+  * TEST: we test if the generated client can be instantiated with custom URL
+  */
+  const wsClient = new WSClient(
+    'ws://microcks-async-minion:8081/api/ws/Hoppscotch+WebSocket+Server/1.0.0/sendTimeStampMessage'
+  );
+
+  it('javascript client should receive a message', async () => {
+    const received_messages = [];
+    const expectedMessage = '11:13:24 GMT+0000 (Coordinated Universal Time)';
+
+    /*
+    * TEST: we test if generated message handler can be registered and later records messages
+    */
+    // registering message handler that adds incomming messages to an array
+    // later messages from array are evaluated to make sure the message sent from server is received by the client
+    wsClient.registerMessageHandler((message) => {
+      received_messages.push(message);
+    });
+
+    /*
+    * TEST: we test if we can connect to server using genrated client
+    */
+    await wsClient.connect();
+
+    // wait for the incomming message to be logged
+    await waitForMessage(received_messages, expectedMessage);
+
+    const isReceived = received_messages.some((message) =>
+      message.includes(expectedMessage)
+    );
+
+    // checking if microcks mock send proper message and they were recorded by registered handler for incomming messages
+    expect(isReceived).toEqual(true);
+  });
+
+  afterAll(async () => {
+    wsClient.close();
+
+    //jest doesn't like that on client closure some logs are printed
+    // so we need to wait second or 2 until all logs are printed
+    await delay();
+  });
+});
+
+describe('client - sender tests', () => {
+  jest.setTimeout(100000);
+  const port = 8082;
+  const payload = JSON.stringify({
+    serviceId: 'Hoppscotch WebSocket Server:1.0.0',
+    testEndpoint: 'ws://websocket-acceptance-tester-js:8082/ws',
+    runnerType: 'ASYNC_API_SCHEMA',
+    timeout: 30000,
+    filteredOperations: ['RECEIVE handleEchoMessage'],
+  });
+
+  //this is a custom server that needs to be used to expose endpoint to which microcks will connect and await for messages comming from generated function
+  const wsServer = new WebSocket.Server({ port, path: '/ws' }, () => {
+    console.log(`Test WS server running on port ${port}`);
+  });
+
+  it('javascript client should send a valid message', async () => {
+    //await delay(100000);
+    const expectedMessage = 'Sending acceptance test message';
+
+    wsServer.on('connection', (socket) => {
+      /*
+      * TEST: sending message with generated function to microcks test client that connected to our custom server
+      */
+      WSClient.sendEchoMessage(expectedMessage, socket);
+    });
+
+    // Start test in Microcks
+    const response = await fetch(microcksTestEndpoint, {
+      method: 'POST',
+      headers: { 'Content-Type': 'application/json' },
+      body: payload,
+    });
+
+    //checking test result
+    const responseBody = await response.json();
+    const status = await waitForTestSuccess(`${microcksTestEndpoint}/${responseBody.id}`);
+
+    expect(status).toEqual(true);
+  });
+
+  afterAll(async () => {
+    wsServer.close();
+    //jest doesn't like that on client closure some logs are printed
+    // so we need to wait second or 2 until all logs are printed
+    await delay();
+  });
+});
diff --git a/packages/templates/clients/websocket/test/javascript/package.json b/packages/templates/clients/websocket/test/javascript/package.json
new file mode 100644
index 0000000000..37e85303b7
--- /dev/null
+++ b/packages/templates/clients/websocket/test/javascript/package.json
@@ -0,0 +1,32 @@
+{
+    "scripts": {
+        "test": "jest --coverage",
+        "lint": "eslint --max-warnings 0 --config ../../../../../../.eslintrc --ignore-path ../../../../../../.eslintignore .",
+        "lint:fix": "eslint --fix --max-warnings 0 --config ../../../../../../.eslintrc --ignore-path ../../../../../../.eslintignore ."
+    },
+    "devDependencies": {
+        "@babel/cli": "^7.25.9",
+        "@babel/core": "^7.26.0",
+        "@babel/preset-env": "^7.26.0",
+        "@babel/preset-react": "^7.25.9",
+        "eslint": "^6.8.0",
+        "eslint-plugin-jest": "^23.8.2",
+        "eslint-plugin-react": "^7.34.1",
+        "eslint-plugin-sonarjs": "^0.5.0",
+        "jest-esm-transformer": "^1.0.0"
+    },
+    "jest": {
+        "moduleFileExtensions": [
+            "js",
+            "json",
+            "jsx"
+        ],
+        "transform": {
+            "^.+\\.jsx?$": "babel-jest"
+        },
+        "moduleNameMapper": {
+            "^nimma/legacy$": "<rootDir>/../../../../../node_modules/nimma/dist/legacy/cjs/index.js",
+            "^nimma/(.*)": "<rootDir>/../../../../../node_modules/nimma/dist/cjs/$1"
+        }
+    }
+}
diff --git a/packages/templates/clients/websocket/test/javascript/utils.js b/packages/templates/clients/websocket/test/javascript/utils.js
new file mode 100644
index 0000000000..636ebba932
--- /dev/null
+++ b/packages/templates/clients/websocket/test/javascript/utils.js
@@ -0,0 +1,70 @@
+/* istanbul ignore file */
+const fetch = require('node-fetch');
+
+/**
+ * Polls the Microcks API every 2 seconds until a test with the given ID reports success.
+ *
+ * @param {string} url - link to endpoint providing info on particular test
+ * @returns {Promise<boolean>} Resolves with `true` when the test is marked as successful.
+ */
+async function waitForTestSuccess(url) {
+  while (true) {
+    try {
+      const response = await fetch(url, {
+        method: 'GET',
+        headers: { 'Content-Type': 'application/json' }
+      });
+
+      if (!response.ok) {
+        console.error(`Request failed with status: ${response.status}`);
+        break;
+      }
+
+      const data = await response.json();
+
+      if (data.success) {
+        return true;
+      }
+    } catch (err) {
+      break;
+    }
+
+    await new Promise(resolve => setTimeout(resolve, 2000)); // Wait 2 seconds
+  }
+
+  return false;
+}
+
+/**
+ * Wait for a specific message to appear in the spy's log calls.
+ * @param {array} a - array with messages
+ * @param {string} expectedMessage - The message to look for in logs.
+ * @param {number} timeout - Maximum time (in ms) to wait. Default is 3000ms.
+ * @param {number} interval - How long to wait (in ms) until next check. Default is 10ms.
+ * @returns {Promise<void>} Resolves if the message is found, otherwise rejects.
+ */
+async function waitForMessage(a, expectedMessage, timeout = 3000, interval = 10) {
+  const start = Date.now();
+  while (Date.now() - start < timeout) {
+    if (a.some(message => message.includes(expectedMessage))) {
+      return;
+    }
+    await delay(interval);
+  }
+  throw new Error(`Expected message "${expectedMessage}" not found within timeout`);
+}
+  
+/**
+   * Delay execution by a specified time.
+   * @param {number} time - Delay duration in milliseconds. Default is 1000ms.
+   * @returns {Promise<void>} Resolves after the specified delay.
+   */
+async function delay(time = 1000) {
+  return new Promise(resolve => setTimeout(resolve, time));
+}
+  
+module.exports = {
+  waitForMessage,
+  delay,
+  waitForTestSuccess
+};
\ No newline at end of file
diff --git a/packages/templates/clients/websocket/test/microcks-setup/checkMicrocksReady.sh b/packages/templates/clients/websocket/test/microcks-setup/checkMicrocksReady.sh
new file mode 100644
index 0000000000..5228e30c3f
--- /dev/null
+++ b/packages/templates/clients/websocket/test/microcks-setup/checkMicrocksReady.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# List the container names as defined in your Compose file
+containers=("microcks-db" "microcks-kafka" "microcks" "microcks-async-minion")
+
+# Function to check if all containers are healthy
+all_healthy() {
+  for container in "${containers[@]}"; do
+    # Use podman inspect to retrieve the health status
+    status=$(podman inspect --format '{{.State.Health.Status}}' "$container" 2>/dev/null)
+    if [[ "$status" != "healthy" ]]; then
+      echo "Container $container is not healthy yet (current status: $status)"
+      return 1
+    fi
+  done
+  return 0
+}
+
+echo "Waiting for all services to become healthy..."
+# Loop until all containers report healthy
+until all_healthy; do
+  echo "One or more services are not healthy. Waiting 5 seconds before checking again..."
+  sleep 5
+done
+
+echo "All services are healthy. Proceeding with the next steps..."
diff --git a/packages/templates/clients/websocket/test/microcks-setup/config/application.properties b/packages/templates/clients/websocket/test/microcks-setup/config/application.properties
new file mode 100644
index 0000000000..dcf21313a9
--- /dev/null
+++ b/packages/templates/clients/websocket/test/microcks-setup/config/application.properties
@@ -0,0 +1,28 @@
+# Async mocking support.
+async-api.enabled=true
+
+# Access to Microcks API server.
+%docker-compose.io.github.microcks.minion.async.client.MicrocksAPIConnector/mp-rest/url=http://microcks:8080
+
+# Access to Keycloak through docker network
+%docker-compose.keycloak.auth.url=http://keycloak:8080
+
+# Access to Kafka broker.
+%docker-compose.kafka.bootstrap.servers=kafka:19092
+
+# Do not save any consumer-offset on the broker as there's a re-sync on each minion startup.
+%docker-compose.mp.messaging.incoming.microcks-services-updates.enable.auto.commit=false
+%docker-compose.mp.messaging.incoming.microcks-services-updates.bootstrap.servers=kafka:19092
+
+# Explicitly telling the minion the protocols we want to support
+%docker-compose.minion.supported-bindings=KAFKA,WS
+
+# %docker-compose.minion.supported-bindings=KAFKA,WS,MQTT,AMQP,NATS
+
+# %docker-compose.mqtt.server=localhost:1883
+# %docker-compose.mqtt.username=microcks
+# %docker-compose.mqtt.password=microcks
+
+# %docker-compose.amqp.server=localhost:5672
+# %docker-compose.amqp.username=microcks
+# %docker-compose.amqp.password=microcks
\ No newline at end of file
diff --git a/packages/templates/clients/websocket/test/microcks-setup/config/features.properties b/packages/templates/clients/websocket/test/microcks-setup/config/features.properties
new file mode 100644
index 0000000000..b088c9c8f7
--- /dev/null
+++ b/packages/templates/clients/websocket/test/microcks-setup/config/features.properties
@@ -0,0 +1,8 @@
+features.feature.async-api.enabled=true
+features.feature.async-api.frequencies=3,10,30
+features.feature.async-api.default-binding=KAFKA
+features.feature.async-api.endpoint-KAFKA=localhost:9092
+features.feature.async-api.endpoint-MQTT=my-mqtt-broker.apps.try.microcks.io:1883
+features.feature.async-api.endpoint-AMQP=my-amqp-broker.apps.try.microcks.io:5672
+features.feature.async-api.endpoint-WS=localhost:8081
+features.feature.async-api.endpoint-NATS=localhost:4222
\ No newline at end of file
diff --git a/packages/templates/clients/websocket/test/microcks-setup/microcks-podman.yml b/packages/templates/clients/websocket/test/microcks-setup/microcks-podman.yml
new file mode 100644
index 0000000000..e93a306a0f
--- /dev/null
+++ b/packages/templates/clients/websocket/test/microcks-setup/microcks-podman.yml
@@ -0,0 +1,151 @@
+volumes:
+  microcks-data:
+  
+services:
+  mongo:
+    image: docker.io/mongo:4.4.29
+    container_name: microcks-db
+    volumes:
+      - microcks-data:/data/db
+    healthcheck:
+      test: ["CMD", "mongo", "--eval", "db.adminCommand('ping')"]
+      interval: 30s
+      timeout: 1s
+      retries: 3
+
+  kafka:
+    image: docker.io/redpandadata/redpanda:v24.3.1
+    container_name: microcks-kafka
+    command:
+      - redpanda
+      - start
+      - --overprovisioned
+      - --smp
+      - "1"
+      - --memory
+      - 1G
+      - --reserve-memory
+      - 0M
+      - --node-id
+      - "0"
+      - --check=false
+      - --kafka-addr
+      - PLAINTEXT://0.0.0.0:19092,EXTERNAL://0.0.0.0:9092
+      - --advertise-kafka-addr
+      - PLAINTEXT://kafka:19092,EXTERNAL://localhost:9092
+    ports:
+      - 9092:9092
+      - 19092:19092
+    healthcheck:
+      test: ["CMD-SHELL", "timeout 5 bash -c 'echo > /dev/tcp/localhost/19092'"]
+      interval: 10s
+      timeout: 5s
+      retries: 3
+      start_period: 10s
+
+  app:
+    depends_on:
+      - mongo
+    image: quay.io/microcks/microcks:1.11.2
+    container_name: microcks
+    volumes:
+      - ./config:/deployments/config:Z
+    ports:
+      - 8080:8080
+      - 9090:9090
+    environment:
+      SPRING_PROFILES_ACTIVE: prod
+      SPRING_DATA_MONGODB_URI: mongodb://mongo:27017
+      SPRING_DATA_MONGODB_DATABASE: microcks
+      POSTMAN_RUNNER_URL: http://postman:3000
+      TEST_CALLBACK_URL: http://microcks:8080
+      SERVICES_UPDATE_INTERVAL: "0 0 0/2 * * *"
+      KEYCLOAK_ENABLED: "false"
+      #MAX_UPLOAD_FILE_SIZE: 3MB
+      ASYNC_MINION_URL: http://microcks-async-minion:8081
+      KAFKA_BOOTSTRAP_SERVER: kafka:19092
+    healthcheck:
+      test: ["CMD", "curl", "-f", "http://localhost:8080/api/health"]
+      start_period: 35s
+      interval: 10s
+      timeout: 3s
+      retries: 3
+
+  async-minion:
+    depends_on:
+      - app
+    image: quay.io/microcks/microcks-async-minion:1.11.2
+    container_name: microcks-async-minion
+    restart: on-failure
+    volumes:
+      - ./config:/deployments/config:Z
+    ports:
+      - 8081:8081
+    environment:
+      QUARKUS_PROFILE: docker-compose
+    healthcheck:
+      test: ["CMD", "curl", "-f", "http://localhost:8081/q/health/ready"]
+      start_period: 10s
+      interval: 10s
+      timeout: 2s
+      retries: 3
+  
+  importer:
+    profiles:
+      - tests
+    image: quay.io/microcks/microcks-cli:latest
+    container_name: microcks-cli-importer
+    working_dir: /usr/src/app
+    volumes:
+      - ../:/usr/src/app
+    depends_on:
+      app:
+        condition: service_healthy
+    command: >
+      sh -c "microcks-cli import __fixtures__/asyncapi-hoppscotch-server.yml
+      --microcksURL=http://microcks:8080/api/
+      --keycloakClientId=microcks-serviceaccount
+      --keycloakClientSecret=ab54d329-e435-41ae-a900-ec6b3fe15c54"
+
+  #TODO:1: make these tester containers work in way that if test fails, they fails as well. So also good to do starting of podman in a way that it is awaiting status
+  #TODO:2: add CI/CD pipeline for these tests
+  tester-js:
+    profiles:
+      - tests
+    image: node:18
+    container_name: websocket-acceptance-tester-js
+    ports:
+      - 8082:8082
+    working_dir: /usr/src/app
+    volumes:
+      - ../../../../../../:/usr/src/app
+    depends_on:
+      app:
+        condition: service_healthy
+    command: ["sh", "-c", "npm install && cd packages/templates/clients/websocket/test/javascript && npm test"]
+  
+  tester-py:
+    profiles:
+      - tests
+    image: python:3.11
+    container_name: websocket-acceptance-tester-py
+    ports:
+      - "8083:8083"
+    working_dir: /usr/src/app
+    volumes:
+      - ../../../../../../:/usr/src/app
+    depends_on:
+      app:
+        condition: service_healthy
+    command: ["sh", "-c", "cd packages/templates/clients/websocket/python/test/temp/snapshotTestResult && pip install -r requirements.txt && cd ../../../../test/python && pip install -r requirements.txt && pytest"]
+
+  # Below for debugging purposes. 
+  # Just uncomment below and after starting environment you can enter the constainer with "podman exec -it net-debug sh" and use websocat to test the websocket connection
+
+  # net-debug:
+  #   image: nicolaka/netshoot
+  #   container_name: net-debug
+  #   stdin_open: true
+  #   tty: true
+  #   command: >
+  #     sh -c "apk add --no-cache websocat && sh"
\ No newline at end of file
diff --git a/packages/templates/clients/websocket/test/python/requirements.txt b/packages/templates/clients/websocket/test/python/requirements.txt
new file mode 100644
index 0000000000..ca03253b5d
--- /dev/null
+++ b/packages/templates/clients/websocket/test/python/requirements.txt
@@ -0,0 +1,5 @@
+pytest==7.4.4
+pytest-asyncio==0.23.3
+websockets==12.0
+requests==2.31.0
+certifi==2023.11.17
\ No newline at end of file
diff --git a/packages/templates/clients/websocket/test/python/test_acceptance.py b/packages/templates/clients/websocket/test/python/test_acceptance.py
new file mode 100644
index 0000000000..580541bce8
--- /dev/null
+++ b/packages/templates/clients/websocket/test/python/test_acceptance.py
@@ -0,0 +1,90 @@
+import time
+import sys
+import os
+import pytest
+import asyncio
+import websockets
+import requests
+
+module_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../python/test/temp/snapshotTestResult'))
+
+microcks_test_endpoint = 'http://microcks:8080/api/tests'
+
+# Add this directory to sys.path if it isn’t already there.
+if module_path not in sys.path:
+    sys.path.insert(0, module_path)
+
+from client_hoppscotch import HoppscotchEchoWebSocketClient
+
+def test_hoppscotch_client_receives_message():
+    # Instantiate the client using the default URL.
+    client = HoppscotchEchoWebSocketClient('ws://microcks-async-minion:8081/api/ws/Hoppscotch+WebSocket+Server/1.0.0/sendTimeStampMessage')
+
+    received_messages = []
+    expected_message = "GMT+0000 (Coordinated Universal Time)"
+
+    def message_handler(message):
+        received_messages.append(message)
+
+    client.register_message_handler(message_handler)
+
+    client.connect()
+
+    # Wait up to 10 seconds for a message to be received.
+    timeout = 10  # seconds
+    start_time = time.time()
+    while not received_messages and (time.time() - start_time < timeout):
+        time.sleep(0.1)
+
+    # Close the connection.
+    client.close()
+
+    assert expected_message in received_messages[0], (
+        f"Expected message '{expected_message}' but got '{received_messages[0]}'"
+    )
+
+@pytest.mark.asyncio
+async def test_hoppscotch_client_sends_message():
+    port = 8083
+    expected_outgoing_message = "Sending acceptance test message to Microcks."
+
+    # payload for trigger Microcks test
+    payload = {
+        "serviceId": "Hoppscotch WebSocket Server:1.0.0",
+        "testEndpoint": "ws://websocket-acceptance-tester-py:8083/ws",
+        "runnerType": "ASYNC_API_SCHEMA",
+        "timeout": 30000,
+        "filteredOperations": ["RECEIVE handleEchoMessage"]
+    }
+    # Create WebSocket server handler
+    async def handler(websocket):
+        ###############
+        #
+        # Most improtant part of test where we test clients send message
+        #
+        ###############
+        await HoppscotchEchoWebSocketClient.send_message_static(expected_outgoing_message, websocket)
+
+    # Start the WebSocket server
+    server = await websockets.serve(handler, port=port)
+    await asyncio.sleep(1)  # Give server time to start
+
+    # Start test in Microcks
+    response = requests.post(microcks_test_endpoint, json=payload)
+    response.raise_for_status()
+    response_data = response.json()
+    test_id = response_data.get('id')
+
+    # Poll Microcks for result
+    success = False
+    for _ in range(30):
+        result = requests.get(f"{microcks_test_endpoint}/{test_id}").json()
+        print("Polling Microcks:", result)
+        if result.get("success") is True:
+            success = True
+            break
+        await asyncio.sleep(2)
+    #await asyncio.sleep(1000)
+    server.close()
+
+    assert success, f"Microcks test {test_id} did not succeed"
\ No newline at end of file


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 8**

<details>
<summary>🧹 Nitpick comments (23)</summary><blockquote>

<details>
<summary>packages/templates/clients/websocket/test/python/requirements.txt (1)</summary><blockquote>

`1-5`: **Consider updating certifi version based on previous standards.**

The dependencies for Python integration testing look good overall. However, based on previous conventions in the project, consider using a forward-looking version for certifi.



From project learnings, it appears that other Python WebSocket templates use certifi with forward-looking versions:

```diff
-certifi==2023.11.17
+certifi==2025.1.31
```

This approach ensures up-to-date certificates when deployed, as noted in previous project conventions.

</blockquote></details>
<details>
<summary>packages/templates/clients/websocket/test/javascript/package.json (1)</summary><blockquote>

`1-6`: **Well-structured package.json and clear script definitions.**  
The `scripts` section defines testing and linting commands clearly. The relative paths for ESLint configuration are deep; please confirm that these paths work as intended in all environments.

</blockquote></details>
<details>
<summary>packages/templates/clients/websocket/javascript/test/__fixtures__/asyncapi-hoppscotch-echo.yml (1)</summary><blockquote>

`16-17`: **Typographical remark on channel description.**  
There is a minor typo in the channel description ("timestampl" on line 17). Consider correcting it to "timestamp" for clarity.

</blockquote></details>
<details>
<summary>packages/templates/clients/websocket/test/__fixtures__/asyncapi-hoppscotch-server.yml (2)</summary><blockquote>

`14-24`: **Consistent channel and binding definitions.**  
Channels, messages, and the binding over WebSocket are well defined. However, note the same typo ("timestampl") in the echo channel description (line 17).

---

`44-71`: **Attention to component definitions and trailing whitespace.**  
The components section (messages and schemas) is detailed and specifies examples clearly. Please remove the trailing spaces as flagged by the static analysis (e.g., on lines 31, 38, 48, 64, 66) and ensure a newline at the end of file (line 71).

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 48-48: trailing spaces

(trailing-spaces)

---

[error] 64-64: trailing spaces

(trailing-spaces)

---

[error] 66-66: trailing spaces

(trailing-spaces)

---

[error] 71-71: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

</blockquote></details>
<details>
<summary>packages/templates/clients/websocket/test/microcks-setup/config/application.properties (1)</summary><blockquote>

`1-28`: **Well-organized configuration file for Microcks setup.**  
The file provides clear settings for asynchronous API mocking, Microcks API, Keycloak, and Kafka broker access. The commented-out sections serve as useful reference for future configurations.  
Consider removing or further documenting the commented out lines if they are no longer needed to keep the configuration clean.

</blockquote></details>
<details>
<summary>packages/templates/clients/websocket/test/microcks-setup/checkMicrocksReady.sh (1)</summary><blockquote>

`9-11`: **Enhance robustness of health status check.**  
Consider handling cases where `podman inspect` might return an empty result. For example, you could modify the condition as follows to also catch an empty status:  
```diff
-    if [[ "$status" != "healthy" ]]; then
+    if [[ -z "$status" || "$status" != "healthy" ]]; then
```  
This ensures that a failure in retrieving the status doesn’t inadvertently pass the health check.

</blockquote></details>
<details>
<summary>packages/templates/clients/websocket/test/microcks-setup/config/features.properties (1)</summary><blockquote>

`1-8`: **Configuration looks good but consider environment variable support.**

The Microcks configuration properly enables async API features and defines endpoints for various protocols. For improved flexibility in different environments, consider using environment variables for the endpoint URLs rather than hardcoded values.


```diff
features.feature.async-api.enabled=true
features.feature.async-api.frequencies=3,10,30
features.feature.async-api.default-binding=KAFKA
-features.feature.async-api.endpoint-KAFKA=localhost:9092
-features.feature.async-api.endpoint-MQTT=my-mqtt-broker.apps.try.microcks.io:1883
-features.feature.async-api.endpoint-AMQP=my-amqp-broker.apps.try.microcks.io:5672
-features.feature.async-api.endpoint-WS=localhost:8081
-features.feature.async-api.endpoint-NATS=localhost:4222
+features.feature.async-api.endpoint-KAFKA=${KAFKA_ENDPOINT:localhost:9092}
+features.feature.async-api.endpoint-MQTT=${MQTT_ENDPOINT:my-mqtt-broker.apps.try.microcks.io:1883}
+features.feature.async-api.endpoint-AMQP=${AMQP_ENDPOINT:my-amqp-broker.apps.try.microcks.io:5672}
+features.feature.async-api.endpoint-WS=${WS_ENDPOINT:localhost:8081}
+features.feature.async-api.endpoint-NATS=${NATS_ENDPOINT:localhost:4222}
```

</blockquote></details>
<details>
<summary>packages/templates/clients/websocket/test/README.md (5)</summary><blockquote>

`15-15`: **Fix grammar and improve clarity.**

There are a few grammatical issues in this sentence.


```diff
-You need to remember about `--profile test` to run whole setup with tests. This way you ensure that proper importer container imports `__fixtures__/asyncapi-hoppscotch-server.yml` into Microcks and tests run against it.
+You need to remember about `--profile tests` to run the whole setup with tests. This way, you ensure that the proper importer container imports `__fixtures__/asyncapi-hoppscotch-server.yml` into Microcks and tests run against it.
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 LanguageTool</summary>

[uncategorized] ~15-~15: You might be missing the article “the” here.
Context: ... remember about `--profile test` to run whole setup with tests. This way you ensure t...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

---

[uncategorized] ~15-~15: A comma might be missing here.
Context: ...st` to run whole setup with tests. This way you ensure that proper importer contain...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)

</details>

</details>

---

`21-21`: **Fix grammar and word order.**

The sentence has some grammatical issues that affect readability.


```diff
-Tests also run in containers, although with provided configuration you can start also testing environment without running tests, just to play with Microcks and understand more how it works.
+Tests also run in containers, although with the provided configuration, you can also start the testing environment without running tests, just to play with Microcks and understand more about how it works.
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 LanguageTool</summary>

[uncategorized] ~21-~21: You might be missing the article “the” here.
Context: ...s also run in containers, although with provided configuration you can start also testin...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

---

[formatting] ~21-~21: Consider inserting a comma here, unless the first half is essential to the meaning of the sentence.
Context: ...n in containers, although with provided configuration you can start also testing environment ...

(WITH_THAT_COMMA)

---

[style] ~21-~21: To make your writing flow more naturally, try moving ‘also’ before the verb.
Context: ...lthough with provided configuration you can start also testing environment without running tes...

(ALSO_PLACEMENT)

</details>

</details>

---

`29-29`: **Add missing article.**


```diff
-This instruction assumes you are located in directory where `microcks-setup` directory is located
+This instruction assumes you are located in the directory where `microcks-setup` directory is located
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 LanguageTool</summary>

[uncategorized] ~29-~29: You might be missing the article “the” here.
Context: ... instruction assumes you are located in directory where `microcks-setup` directory is loc...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

</details>

</details>

---

`35-35`: **Fix grammatical issues.**


```diff
-Check with `podman ps` command if all services are running. It may take few minutes to start all containers. You can also run special script that will confirm services are ready: `bash ./microcks-setup/checkMicrocksReady.sh`.
+Check with the `podman ps` command if all services are running. It may take a few minutes to start all containers. You can also run a special script that will confirm services are ready: `bash ./microcks-setup/checkMicrocksReady.sh`.
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 LanguageTool</summary>

[uncategorized] ~35-~35: You might be missing the article “a” here.
Context: ...f all services are running. It may take few minutes to start all containers. You ca...

(AI_EN_LECTOR_MISSING_DETERMINER_A)

---

[uncategorized] ~35-~35: You might be missing the article “the” here.
Context: ...g. It may take few minutes to start all containers. You can also run special script that w...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

---

[uncategorized] ~35-~35: You might be missing the article “a” here.
Context: ... start all containers. You can also run special script that will confirm services are r...

(AI_EN_LECTOR_MISSING_DETERMINER_A)

</details>

</details>

---

`89-90`: **Add language specifier to fenced code block.**

According to Markdown best practices, fenced code blocks should have a language specified.


```diff
-```
+```bash
websocat ws://localhost:8081/api/ws/Hoppscotch+WebSocket+Server/1.0.0/sendTimeStampMessage
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

89-89: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

</details>

</details>

</blockquote></details>
<details>
<summary>packages/templates/clients/websocket/test/javascript/acceptance.test.js (4)</summary><blockquote>

`22-22`: **Expected message pattern is fragile.**

The test expects a very specific timestamp format which could make the test brittle. Consider using a more flexible pattern matching approach.


```diff
-    const expectedMessage = '11:13:24 GMT+0000 (Coordinated Universal Time)';
+    // Use regex or partial matching instead of exact time
+    const expectedTimePattern = /\d{2}:\d{2}:\d{2} GMT/;
```

Then modify the check at line 41-43:

```diff
-    const isReceived = received_messages.some((message) =>
-      message.includes(expectedMessage)
-    );
+    const isReceived = received_messages.some((message) =>
+      expectedTimePattern.test(message)
+    );
```

---

`75-75`: **Remove commented debugging code.**

There's a commented line with a long delay that appears to be debugging code.


```diff
-    //await delay(100000);
```

---

`11-56`: **Client receiver test looks good, but consider improving error handling.**

The test flow is logically sound and well-structured. To make it more robust, consider adding error handling and timeout messages to provide better debugging information.



Add a try-catch block and better error output when expected messages aren't received:

```diff
  it('javascript client should receive a message', async () => {
    const received_messages = [];
    const expectedMessage = '11:13:24 GMT+0000 (Coordinated Universal Time)';

    /*
    * TEST: we test if generated message handler can be registered and later records messages
    */
    // registering message handler that adds incomming messages to an array
    // later messages from array are evaluated to make sure the message sent from server is received by the client
    wsClient.registerMessageHandler((message) => {
      received_messages.push(message);
    });

    /*
    * TEST: we test if we can connect to server using genrated client
    */
+   try {
      await wsClient.connect();

      // wait for the incomming message to be logged
      await waitForMessage(received_messages, expectedMessage);

      const isReceived = received_messages.some((message) =>
        message.includes(expectedMessage)
      );

      // checking if microcks mock send proper message and they were recorded by registered handler for incomming messages
      expect(isReceived).toEqual(true);
+   } catch (error) {
+     console.error('Test failed with error:', error);
+     console.log('Received messages:', received_messages);
+     throw error;
+   }
  });
```

---

`58-97`: **Sender test implementation is correct but contains hardcoded values.**

The sender test implementation is logically sound. However, several hardcoded values could be moved to constants at the top of the file to improve maintainability.



Consider extracting hardcoded values to constants at the top of the file:

```diff
const WSClient = require('../../javascript/test/temp/snapshotTestResult/client-hoppscotch');
const { waitForMessage, delay, waitForTestSuccess } = require('./utils');
const fetch = require('node-fetch');
const WebSocket = require('ws');
-const microcksTestEndpoint = 'http://microcks:8080/api/tests';
+// Configuration constants
+const MICROCKS_HOST = 'microcks';
+const MICROCKS_PORT = 8080;
+const MICROCKS_TEST_ENDPOINT = `http://${MICROCKS_HOST}:${MICROCKS_PORT}/api/tests`;
+const SENDER_TEST_PORT = 8082;
+const SENDER_TEST_PATH = '/ws';
+const SERVICE_ID = 'Hoppscotch WebSocket Server:1.0.0';
+const TEST_TIMEOUT = 30000;
```

Then use these constants throughout the test.

</blockquote></details>
<details>
<summary>packages/templates/clients/websocket/test/python/test_acceptance.py (1)</summary><blockquote>

`63-65`: **Fix typo in comment**

There's a typo in the comment: "improtant" should be "important".

```diff
-        # Most improtant part of test where we test clients send message
+        # Most important part of test where we test clients send message
```

</blockquote></details>
<details>
<summary>packages/templates/clients/websocket/test/microcks-setup/microcks-podman.yml (3)</summary><blockquote>

`3-3`: **Fix YAML formatting issues**

There are trailing spaces on multiple lines and the file is missing a newline at the end.

```diff
-volumes:
-  microcks-data:
-  
+volumes:
+  microcks-data:
+
...
-    retries: 3
-  
+    retries: 3
+
...
-    command: ["sh", "-c", "npm install && cd packages/templates/clients/websocket/test/javascript && npm test"]
-  
+    command: ["sh", "-c", "npm install && cd packages/templates/clients/websocket/test/javascript && npm test"]
+
...
-  # Below for debugging purposes. 
+  # Below for debugging purposes.
...
-  #     sh -c "apk add --no-cache websocat && sh"
+  #     sh -c "apk add --no-cache websocat && sh"
+
```


Also applies to: 92-92, 126-126, 142-142, 151-151

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 3-3: trailing spaces

(trailing-spaces)

</details>

</details>

---

`110-111`: **Convert TODOs to tracked issues**

The TODOs should be tracked in your issue management system rather than remaining as comments in the code.

```diff
-  #TODO:1: make these tester containers work in way that if test fails, they fails as well. So also good to do starting of podman in a way that it is awaiting status
-  #TODO:2: add CI/CD pipeline for these tests
+  # See issue #XXXX: make these tester containers work in way that if test fails, they fails as well
+  # See issue #YYYY: add CI/CD pipeline for these tests
```

Would you like me to help draft the issue descriptions for these TODOs?

---

`140-140`: **Simplify long command by using a startup script**

The command for the Python tester is quite long and hard to read. Consider moving it to a dedicated script file.

Create a `run_python_tests.sh` script in the test directory with the command content, and then reference it from the YAML file:

```diff
-    command: ["sh", "-c", "cd packages/templates/clients/websocket/python/test/temp/snapshotTestResult && pip install -r requirements.txt && cd ../../../../test/python && pip install -r requirements.txt && pytest"]
+    command: ["sh", "-c", "packages/templates/clients/websocket/test/run_python_tests.sh"]
```

</blockquote></details>
<details>
<summary>packages/templates/clients/websocket/test/javascript/utils.js (2)</summary><blockquote>

`56-56`: **Remove trailing whitespace**

There are trailing spaces on lines 56 and 65.

```diff
 }
-  
+
...
 }
-  
+
```


Also applies to: 65-65

---

`46-55`: **Add more descriptive error message for waitForMessage**

The error message when a message isn't found could be more informative by including the actual messages that were received.

```diff
async function waitForMessage(a, expectedMessage, timeout = 3000, interval = 10) {
  const start = Date.now();
  while (Date.now() - start < timeout) {
    if (a.some(message => message.includes(expectedMessage))) {
      return;
    }
    await delay(interval);
  }
-  throw new Error(`Expected message "${expectedMessage}" not found within timeout`);
+  throw new Error(`Expected message "${expectedMessage}" not found within timeout. Received messages: ${JSON.stringify(a)}`);
}
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between f02dc4d58ca9de79a38b5e823ac9b8f5b1c585cb and 9c82787d81819d71f298d54d17b99ba9eade2c2e.

</details>

<details>
<summary>⛔ Files ignored due to path filters (3)</summary>

* `package-lock.json` is excluded by `!**/package-lock.json`
* `packages/templates/clients/websocket/javascript/test/__snapshots__/integration.test.js.snap` is excluded by `!**/*.snap`
* `packages/templates/clients/websocket/python/test/__snapshots__/integration.test.js.snap` is excluded by `!**/*.snap`

</details>

<details>
<summary>📒 Files selected for processing (16)</summary>

* `.gitignore` (1 hunks)
* `packages/templates/clients/websocket/javascript/components/SendEchoMessage.js` (1 hunks)
* `packages/templates/clients/websocket/javascript/test/__fixtures__/asyncapi-hoppscotch-echo.yml` (1 hunks)
* `packages/templates/clients/websocket/javascript/test/__fixtures__/asyncapi-postman-echo.yml` (1 hunks)
* `packages/templates/clients/websocket/python/components/SendEchoMessage.js` (1 hunks)
* `packages/templates/clients/websocket/test/README.md` (1 hunks)
* `packages/templates/clients/websocket/test/__fixtures__/asyncapi-hoppscotch-server.yml` (1 hunks)
* `packages/templates/clients/websocket/test/javascript/acceptance.test.js` (1 hunks)
* `packages/templates/clients/websocket/test/javascript/package.json` (1 hunks)
* `packages/templates/clients/websocket/test/javascript/utils.js` (1 hunks)
* `packages/templates/clients/websocket/test/microcks-setup/checkMicrocksReady.sh` (1 hunks)
* `packages/templates/clients/websocket/test/microcks-setup/config/application.properties` (1 hunks)
* `packages/templates/clients/websocket/test/microcks-setup/config/features.properties` (1 hunks)
* `packages/templates/clients/websocket/test/microcks-setup/microcks-podman.yml` (1 hunks)
* `packages/templates/clients/websocket/test/python/requirements.txt` (1 hunks)
* `packages/templates/clients/websocket/test/python/test_acceptance.py` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧠 Learnings (1)</summary>

<details>
<summary>packages/templates/clients/websocket/test/python/requirements.txt (1)</summary>

```
Learnt from: derberg
PR: asyncapi/generator#1416
File: packages/templates/clients/python/websocket/template/requirements.txt.js:8-8
Timestamp: 2025-04-10T08:04:22.371Z
Learning: The certifi Python package uses date-based versioning (YYYY.MM.DD format). In the python websocket client template, a forward-looking version (2025.1.31) is intentionally used to ensure up-to-date certificates when deployed.
```

</details>

</details><details>
<summary>🧬 Code Graph Analysis (2)</summary>

<details>
<summary>packages/templates/clients/websocket/test/javascript/acceptance.test.js (2)</summary><blockquote>

<details>
<summary>packages/templates/clients/websocket/test/javascript/utils.js (2)</summary>

* `fetch` (2-2)
* `response` (13-16)

</details>
<details>
<summary>packages/templates/clients/websocket/javascript/example.js (1)</summary>

* `message` (26-26)

</details>

</blockquote></details>
<details>
<summary>packages/templates/clients/websocket/test/javascript/utils.js (2)</summary><blockquote>

<details>
<summary>packages/templates/clients/websocket/test/javascript/acceptance.test.js (2)</summary>

* `fetch` (7-7)
* `require` (6-6)

</details>
<details>
<summary>packages/templates/clients/websocket/javascript/example.js (2)</summary>

* `interval` (25-25)
* `message` (26-26)

</details>

</blockquote></details>

</details><details>
<summary>🪛 LanguageTool</summary>

<details>
<summary>packages/templates/clients/websocket/test/README.md</summary>

[uncategorized] ~15-~15: You might be missing the article “the” here.
Context: ... remember about `--profile test` to run whole setup with tests. This way you ensure t...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

---

[uncategorized] ~15-~15: A comma might be missing here.
Context: ...st` to run whole setup with tests. This way you ensure that proper importer contain...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)

---

[uncategorized] ~21-~21: You might be missing the article “the” here.
Context: ...s also run in containers, although with provided configuration you can start also testin...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

---

[formatting] ~21-~21: Consider inserting a comma here, unless the first half is essential to the meaning of the sentence.
Context: ...n in containers, although with provided configuration you can start also testing environment ...

(WITH_THAT_COMMA)

---

[style] ~21-~21: To make your writing flow more naturally, try moving ‘also’ before the verb.
Context: ...lthough with provided configuration you can start also testing environment without running tes...

(ALSO_PLACEMENT)

---

[uncategorized] ~29-~29: You might be missing the article “the” here.
Context: ... instruction assumes you are located in directory where `microcks-setup` directory is loc...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

---

[uncategorized] ~35-~35: You might be missing the article “a” here.
Context: ...f all services are running. It may take few minutes to start all containers. You ca...

(AI_EN_LECTOR_MISSING_DETERMINER_A)

---

[uncategorized] ~35-~35: You might be missing the article “the” here.
Context: ...g. It may take few minutes to start all containers. You can also run special script that w...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

---

[uncategorized] ~35-~35: You might be missing the article “a” here.
Context: ... start all containers. You can also run special script that will confirm services are r...

(AI_EN_LECTOR_MISSING_DETERMINER_A)

</details>

</details>
<details>
<summary>🪛 Gitleaks (8.21.2)</summary>

<details>
<summary>packages/templates/clients/websocket/test/README.md</summary>

50-50: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

---

68-68: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

</details>
<details>
<summary>packages/templates/clients/websocket/test/microcks-setup/microcks-podman.yml</summary>

108-108: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

</details>

</details>
<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

<details>
<summary>packages/templates/clients/websocket/test/README.md</summary>

89-89: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

</details>

</details>
<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

<details>
<summary>packages/templates/clients/websocket/test/__fixtures__/asyncapi-hoppscotch-server.yml</summary>

[error] 31-31: trailing spaces

(trailing-spaces)

---

[error] 38-38: trailing spaces

(trailing-spaces)

---

[error] 48-48: trailing spaces

(trailing-spaces)

---

[error] 64-64: trailing spaces

(trailing-spaces)

---

[error] 66-66: trailing spaces

(trailing-spaces)

---

[error] 71-71: no new line character at the end of file

(new-line-at-end-of-file)

</details>
<details>
<summary>packages/templates/clients/websocket/test/microcks-setup/microcks-podman.yml</summary>

[error] 3-3: trailing spaces

(trailing-spaces)

---

[error] 92-92: trailing spaces

(trailing-spaces)

---

[error] 126-126: trailing spaces

(trailing-spaces)

---

[error] 142-142: trailing spaces

(trailing-spaces)

---

[error] 151-151: no new line character at the end of file

(new-line-at-end-of-file)

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: Test generator as dependency with Node 18
* GitHub Check: Test generator as dependency with Node 20

</details>

<details>
<summary>🔇 Additional comments (10)</summary><blockquote>

<details>
<summary>.gitignore (1)</summary>

`21-21`: **LGTM! Properly ignoring Microcks data directory.**

Adding `microcks-data` to the gitignore file is appropriate as it prevents committing test data generated by Microcks during integration testing.

</details>
<details>
<summary>packages/templates/clients/websocket/javascript/test/__fixtures__/asyncapi-postman-echo.yml (1)</summary>

`29-30`: **Good improvement to the AsyncAPI specification.**

Adding the messages property to the sendEchoMessage operation explicitly defines which message type is being sent during this operation, improving the clarity of the API contract.

</details>
<details>
<summary>packages/templates/clients/websocket/javascript/components/SendEchoMessage.js (1)</summary>

`7-14`: **Well-documented method with clear JSDoc comments.**

The addition of comprehensive JSDoc comments explains the purpose and parameters of the method, which improves code maintainability.

</details>
<details>
<summary>packages/templates/clients/websocket/test/javascript/package.json (2)</summary>

`7-17`: **Good dependency management.**  
The `devDependencies` section lists all necessary tools (Babel, ESLint, Jest, etc.) with explicit versions. This is good for consistency in development environments.

---

`18-33`: **Comprehensive Jest configuration.**  
The Jest configuration (module file extensions, transform rule, and module name mappings) is well specified to support both ES modules and legacy modules.

</details>
<details>
<summary>packages/templates/clients/websocket/javascript/test/__fixtures__/asyncapi-hoppscotch-echo.yml (1)</summary>

`47-49`: **Clear addition of example for timestamp message.**  
The new `examples` section with the `someRandomDate` example provides a concrete example of the expected payload format. This will help users understand the message schema better.

</details>
<details>
<summary>packages/templates/clients/websocket/test/__fixtures__/asyncapi-hoppscotch-server.yml (2)</summary>

`1-13`: **Solid AsyncAPI specification layout for server mocks.**  
The general structure (asyncapi version, info, servers) is clear and provides all necessary information for the mock server.

---

`29-43`: **Operation definitions are clear and appropriately reference components.**  
The operations for sending timestamp messages and handling echo messages are correctly linked to the channels and components, providing a well-integrated specification.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 31-31: trailing spaces

(trailing-spaces)

---

[error] 38-38: trailing spaces

(trailing-spaces)

</details>

</details>

</details>
<details>
<summary>packages/templates/clients/websocket/test/microcks-setup/checkMicrocksReady.sh (2)</summary>

`1-16`: **Solid implementation of container health-check logic.**  
The use of `podman inspect` and the looping mechanism in the `all_healthy` function is clear and serves the intended purpose.

---

`18-26`: **Clear and user-friendly waiting loop.**  
The loop that waits for all containers to become healthy, with a 5-second delay, is straightforward and well commented.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-10T08:13:23Z
user: login: Florence-Njeri
body: Hey @derberg I added a few suggestions for cohesion
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-14T10:58:18Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>♻️ Duplicate comments (2)</summary><blockquote>

<details>
<summary>packages/templates/clients/websocket/test/README.md (2)</summary><blockquote>

`47-51`: _🛠️ Refactor suggestion_

**Replace hardcoded client secret with a placeholder.**

On line 50 a hardcoded client secret is used. To prevent exposing sensitive information, replace it with a placeholder (e.g.,  
`--keycloakClientSecret="<your-client-secret>"`).

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Gitleaks (8.21.2)</summary>

50-50: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

</details>

</details>

---

`61-70`: _🛠️ Refactor suggestion_

**Remove hardcoded client secret from test command.**

Within the test command snippet (line 68), the hardcoded client secret should be replaced with a placeholder (e.g.,  
`--keycloakClientSecret="<your-client-secret>"`) to avoid security risks.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Gitleaks (8.21.2)</summary>

68-68: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (7)</summary><blockquote>

<details>
<summary>packages/templates/clients/websocket/test/README.md (7)</summary><blockquote>

`5-5`: **Rephrase for clarity regarding Podman usage.**

The sentence “Docker is not the best solution for this, thus it's better to use Podman that manages resources better.” could be reworded for improved flow. For example:  
> “Docker is not ideal for this purpose; instead, Podman manages resources more efficiently.”

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 LanguageTool</summary>

[typographical] ~5-~5: The word “thus” is an adverb that can’t be used like a conjunction, and therefore needs to be separated from the sentence.
Context: ...es. Docker is not the best solution for this, thus it's better to use Podman that manages ...

(THUS_SENTENCE)

</details>

</details>

---

`21-21`: **Add missing article for better readability.**

Consider revising “Tests also run in containers, although with provided configuration you can start also testing environment without running tests, just to play with Microcks and understand more how it works.” to “Tests also run in containers, although with the provided configuration you can also start the testing environment without running tests, just to play with Microcks and understand more about how it works.”

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 LanguageTool</summary>

[uncategorized] ~21-~21: You might be missing the article “the” here.
Context: ...s also run in containers, although with provided configuration you can start also testin...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

---

[formatting] ~21-~21: Consider inserting a comma here, unless the first half is essential to the meaning of the sentence.
Context: ...n in containers, although with provided configuration you can start also testing environment ...

(WITH_THAT_COMMA)

---

[style] ~21-~21: To make your writing flow more naturally, try moving ‘also’ before the verb.
Context: ...lthough with provided configuration you can start also testing environment without running tes...

(ALSO_PLACEMENT)

</details>

</details>

---

`29-29`: **Fix grammatical error regarding directory location.**

The sentence “This instruction assumes you are located in directory where `microcks-setup` directory is located” can be improved. Consider revising it to “This instruction assumes you are located in the directory where the `microcks-setup` directory is located.”

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 LanguageTool</summary>

[uncategorized] ~29-~29: You might be missing the article “the” here.
Context: ... instruction assumes you are located in directory where `microcks-setup` directory is loc...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

</details>

</details>

---

`35-35`: **Clarify time duration with proper articles.**

In the sentence “It may take few minutes to start all containers.”, add an article to read “a few minutes” for clarity.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 LanguageTool</summary>

[uncategorized] ~35-~35: Possible missing article found.
Context: ...f all services are running. It may take few minutes to start all containers. You ca...

(AI_HYDRA_LEO_MISSING_A)

</details>

</details>

---

`62-62`: **Clarify timeout behavior in comment.**

Consider revising “# the higher timeout the more test samples will run” to “# The higher the timeout, the more test samples will run” for clearer communication.

---

`76-76`: **Correct spelling error.**

“debbuging” should be corrected to “debugging” in the sentence describing the container configuration.

---

`89-92`: **Specify language for fenced code block.**

For the fenced code block used to display the websocat command, add a language identifier (e.g., ```bash) after the opening backticks to enable proper syntax highlighting.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

89-89: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 9c82787d81819d71f298d54d17b99ba9eade2c2e and 79e3ad022b231ce2dada9a2a2d698cc867f6d2d5.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `packages/templates/clients/websocket/test/README.md` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 LanguageTool</summary>

<details>
<summary>packages/templates/clients/websocket/test/README.md</summary>

[typographical] ~5-~5: The word “thus” is an adverb that can’t be used like a conjunction, and therefore needs to be separated from the sentence.
Context: ...es. Docker is not the best solution for this, thus it's better to use Podman that manages ...

(THUS_SENTENCE)

---

[uncategorized] ~21-~21: You might be missing the article “the” here.
Context: ...s also run in containers, although with provided configuration you can start also testin...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

---

[formatting] ~21-~21: Consider inserting a comma here, unless the first half is essential to the meaning of the sentence.
Context: ...n in containers, although with provided configuration you can start also testing environment ...

(WITH_THAT_COMMA)

---

[style] ~21-~21: To make your writing flow more naturally, try moving ‘also’ before the verb.
Context: ...lthough with provided configuration you can start also testing environment without running tes...

(ALSO_PLACEMENT)

---

[uncategorized] ~29-~29: You might be missing the article “the” here.
Context: ... instruction assumes you are located in directory where `microcks-setup` directory is loc...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

---

[uncategorized] ~35-~35: Possible missing article found.
Context: ...f all services are running. It may take few minutes to start all containers. You ca...

(AI_HYDRA_LEO_MISSING_A)

</details>

</details>
<details>
<summary>🪛 Gitleaks (8.21.2)</summary>

<details>
<summary>packages/templates/clients/websocket/test/README.md</summary>

50-50: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

---

68-68: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

</details>

</details>
<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

<details>
<summary>packages/templates/clients/websocket/test/README.md</summary>

89-89: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: Test generator as dependency with Node 18
* GitHub Check: Test generator as dependency with Node 20

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-14T12:00:56Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>♻️ Duplicate comments (3)</summary><blockquote>

<details>
<summary>packages/templates/clients/websocket/javascript/components/SendEchoMessage.js (1)</summary><blockquote>

`15-17`: **Fix potential `this` context issue in static method and add error handling.**

The current implementation still has issues with the `this` context in a static method. While you've adopted the approach of using `socket || this.websocket`, there's no error handling if both are undefined, which could lead to runtime errors.


```diff
-  const websocket = socket || this.websocket;
-  websocket.send(JSON.stringify(message));
+  const websocket = socket || this.websocket;
+  if (!websocket) {
+    throw new Error('WebSocket connection is required');
+  }
+  websocket.send(JSON.stringify(message));
```

Or for a cleaner solution that avoids `this` context issues entirely:

```diff
-static sendEchoMessage(message, socket) {
-  const websocket = socket || this.websocket;
-  websocket.send(JSON.stringify(message));
+static sendEchoMessage(message, socket) {
+  if (!socket) {
+    throw new Error('WebSocket connection is required');
+  }
+  socket.send(JSON.stringify(message));
```

</blockquote></details>
<details>
<summary>packages/templates/clients/websocket/test/README.md (2)</summary><blockquote>

`50-50`: _⚠️ Potential issue_

**Security Concern: Hardcoded Client Secret**  
Hardcoded client secrets may expose sensitive information. Replace the secret with a placeholder. For example:  
```diff
-      --keycloakClientSecret="ab54d329-e435-41ae-a900-ec6b3fe15c54"
+      --keycloakClientSecret="<your-client-secret>"
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Gitleaks (8.21.2)</summary>

50-50: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

</details>

</details>

---

`68-68`: _⚠️ Potential issue_

**Security Concern: Exposed Client Secret in Test Command**  
Avoid hardcoding the client secret in the test command. Update it to use a placeholder as shown below:  
```diff
-    --keycloakClientSecret="ab54d329-e435-41ae-a900-ec6b3fe15c54" \
+    --keycloakClientSecret="<your-client-secret>" \
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Gitleaks (8.21.2)</summary>

68-68: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (7)</summary><blockquote>

<details>
<summary>packages/templates/clients/websocket/test/README.md (7)</summary><blockquote>

`5-5`: **Sentence Clarity and Style Improvement**  
The sentence  
> "Docker is not the best solution for this, thus it's better to use Podman that manages resources better."  
can be rephrased for clarity and grammatical correctness. For example, you could update it to:  
> "Docker is not the best solution for this; it is recommended to use Podman, which manages resources more efficiently."

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 LanguageTool</summary>

[typographical] ~5-~5: The word “thus” is an adverb that can’t be used like a conjunction, and therefore needs to be separated from the sentence.
Context: ...es. Docker is not the best solution for this, thus it's better to use Podman that manages ...

(THUS_SENTENCE)

</details>

</details>

---

`15-15`: **Improve Instruction Clarity**  
The instruction  
> "You need to remember about `--profile tests` to run whole setup with tests. This way you ensure that proper importer container imports `__fixtures__/asyncapi-hoppscotch-server.yml` into Microcks and tests run against it."  
could be reworded for better readability. For example:  
> "Remember to include `--profile tests` when running the setup. This ensures that the importer container correctly loads `__fixtures__/asyncapi-hoppscotch-server.yml` into Microcks so that the tests run as expected."

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 LanguageTool</summary>

[uncategorized] ~15-~15: You might be missing the article “the” here.
Context: ...remember about `--profile tests` to run whole setup with tests. This way you ensure t...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

</details>

</details>

---

`21-21`: **Enhance Readability of Instruction**  
The sentence  
> "Tests also run in containers, although with provided configuration you can start also testing environment without running tests, just to play with Microcks and understand more how it works."  
could be improved for clarity. Consider revising it to:  
> "Tests run in containers. With the provided configuration, you can also start the testing environment without executing the tests, allowing you to explore and understand how Microcks works."

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 LanguageTool</summary>

[uncategorized] ~21-~21: You might be missing the article “the” here.
Context: ...s also run in containers, although with provided configuration you can start also testin...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

---

[formatting] ~21-~21: Consider inserting a comma here, unless the first half is essential to the meaning of the sentence.
Context: ...n in containers, although with provided configuration you can start also testing environment ...

(WITH_THAT_COMMA)

---

[style] ~21-~21: To make your writing flow more naturally, try moving ‘also’ before the verb.
Context: ...lthough with provided configuration you can start also testing environment without running tes...

(ALSO_PLACEMENT)

</details>

</details>

---

`29-29`: **Minor Grammar Correction**  
In the instruction:  
> "This instruction assumes you are located in directory where `microcks-setup` directory is located"  
adding the article "the" would improve readability. For example:  
> "This instruction assumes you are located in the directory where the `microcks-setup` directory is located."

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 LanguageTool</summary>

[uncategorized] ~29-~29: You might be missing the article “the” here.
Context: ... instruction assumes you are located in directory where `microcks-setup` directory is loc...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

</details>

</details>

---

`76-76`: **Fix Typographical Error**  
There is a typo in the sentence:  
> "File `microcks-podman.yml` contains commented out configuration for debbuging container you can start with the entire testing environment."  
Replace "debbuging" with "debugging":  
```diff
- configuration for debbuging container
+ configuration for debugging container
```

---

`88-88`: **Refine Instruction Wording**  
The sentence  
> "Do below to start receiving example messages in the terminal:"  
could be rephrased for clarity. Consider changing it to:  
> "Run the following command to start receiving example messages in the terminal:"

---

`89-91`: **Specify Language for Fenced Code Block**  
The fenced code block for the `websocat` command does not specify a language, which can affect syntax highlighting. Adding a language (e.g., `bash`) is recommended. For example:  
```diff
-```
+```bash
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

89-89: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

</details>

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 79e3ad022b231ce2dada9a2a2d698cc867f6d2d5 and 198eb462233e5a8bfe700cea0632b48f7917765f.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `packages/templates/clients/websocket/javascript/components/SendEchoMessage.js` (1 hunks)
* `packages/templates/clients/websocket/test/README.md` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🪛 LanguageTool</summary>

<details>
<summary>packages/templates/clients/websocket/test/README.md</summary>

[typographical] ~5-~5: The word “thus” is an adverb that can’t be used like a conjunction, and therefore needs to be separated from the sentence.
Context: ...es. Docker is not the best solution for this, thus it's better to use Podman that manages ...

(THUS_SENTENCE)

---

[uncategorized] ~15-~15: You might be missing the article “the” here.
Context: ...remember about `--profile tests` to run whole setup with tests. This way you ensure t...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

---

[uncategorized] ~21-~21: You might be missing the article “the” here.
Context: ...s also run in containers, although with provided configuration you can start also testin...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

---

[formatting] ~21-~21: Consider inserting a comma here, unless the first half is essential to the meaning of the sentence.
Context: ...n in containers, although with provided configuration you can start also testing environment ...

(WITH_THAT_COMMA)

---

[style] ~21-~21: To make your writing flow more naturally, try moving ‘also’ before the verb.
Context: ...lthough with provided configuration you can start also testing environment without running tes...

(ALSO_PLACEMENT)

---

[uncategorized] ~29-~29: You might be missing the article “the” here.
Context: ... instruction assumes you are located in directory where `microcks-setup` directory is loc...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

</details>

</details>
<details>
<summary>🪛 Gitleaks (8.21.2)</summary>

<details>
<summary>packages/templates/clients/websocket/test/README.md</summary>

50-50: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

---

68-68: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

</details>

</details>
<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

<details>
<summary>packages/templates/clients/websocket/test/README.md</summary>

89-89: Fenced code blocks should have a language specified
null

(MD040, fenced-code-language)

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: Test generator as dependency with Node 18
* GitHub Check: Test generator as dependency with Node 20

</details>

<details>
<summary>🔇 Additional comments (1)</summary><blockquote>

<details>
<summary>packages/templates/clients/websocket/javascript/components/SendEchoMessage.js (1)</summary>

`7-14`: **Good job on adding comprehensive JSDoc documentation.**

The added documentation clearly explains the purpose of the method, its parameters, and usage context. This improves code readability and maintainability.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: NONE
submitted_at: 2025-04-14T12:07:00Z
user: login: Florence-Njeri
body: LGTM :)
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-14T13:07:24Z
user: login: magicmatatjahu
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-14T13:25:49Z

Review comments:
diff_hunk: @@ -4,10 +4,17 @@ export function SendEchoMessage() {
   return (
     <Text newLines={2} indent={2}>
       {
-        `// Method to send an echo message to the server
-sendEchoMessage(message) {
+        `/**
+   * By default sends a message over a provided WebSocket connection.
+   * Useful when you already have an established WebSocket connection
+   * and want to send a message without creating a class instance.
+   *
+   * @param {Object} message - The message to send. It will be stringified to JSON.
+   * @param {WebSocket} socket - An existing WebSocket connection to use for sending the message.
+*/
+static sendEchoMessage(message, socket) {
+  if (socket) this.websocket = socket;
   this.websocket.send(JSON.stringify(message));
path: packages/templates/clients/websocket/javascript/components/SendEchoMessage.js
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Fix potential `this` context issue in static method.**

There's an issue with using `this.websocket` within a static method. In JavaScript, `this` in a static method refers to the class itself, not an instance, which means `this.websocket` might be undefined.


Consider one of these approaches:

```diff
-static sendEchoMessage(message, socket) {
-  if (socket) this.websocket = socket;
-  this.websocket.send(JSON.stringify(message));
+static sendEchoMessage(message, socket) {
+  // Use the provided socket or throw an error if none is provided
+  if (!socket) {
+    throw new Error('WebSocket connection is required');
+  }
+  socket.send(JSON.stringify(message));
```

Or if maintaining backward compatibility with instance usage is needed:

```diff
-static sendEchoMessage(message, socket) {
-  if (socket) this.websocket = socket;
-  this.websocket.send(JSON.stringify(message));
+static sendEchoMessage(message, socket) {
+  const websocket = socket || this.websocket;
+  if (!websocket) {
+    throw new Error('WebSocket connection is required');
+  }
+  websocket.send(JSON.stringify(message));
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
static sendEchoMessage(message, socket) {
  // Use the provided socket or throw an error if none is provided
  if (!socket) {
    throw new Error('WebSocket connection is required');
  }
  socket.send(JSON.stringify(message));
}
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-10T08:13:21Z
author_association: NONE
diff_hunk: @@ -4,23 +4,50 @@ export function SendEchoMessage() {
   return (
     <Text newLines={2} indent={2}>
       {
-        `def send_message(self, message):
+        `async def send_message(self, message):
     """
-    Automatically process the outgoing message with registered processors and send it
-    using the active WebSocket connection.
+    Send a message using the WebSocket connection attached to this instance.
+
+    Args:
+        message (dict or str): The message to send. Will be serialized to JSON if it's a dictionary.
+
+    Raises:
+        Exception: If sending fails or the socket is not connected.
+    """
+    await self._send(message, self.ws_app)
+
+@staticmethod
+async def send_message_static(message, socket):
+    """
+    Send a message using a provided WebSocket connection, without needing an instance.
+
+    Args:
+        message (dict or str): The message to send.
+        socket (websockets.WebSocketCommonProtocol): The WebSocket to send through.
+
+    Raises:
+        Exception: If sending fails or the socket is not connected.
+    """
+    await HoppscotchEchoWebSocketClient._send(message, socket)
+
+@staticmethod
+async def _send(message, socket):
+    """
+    Internal helper to handle the actual sending logic.
+
+    Args:
+        message (dict or str): The message to send.
+        socket (websockets.WebSocketCommonProtocol): The WebSocket to send through.
+
+    Notes:
+        If message is a dictionary, it will be automatically converted to JSON.
     """
-    # Apply outgoing processors sequentially.
-    for processor in self.outgoing_processors:
-        message = processor(message)
-
-    if self.ws_app and self.ws_app.sock and self.ws_app.sock.connected:
-        try:
-            self.ws_app.send(json.dumps(message))
-            print("\\033[92mSent:\\033[0m", message)
-        except Exception as error:
-            self.handle_error(error)
-    else:
-        print("Error: WebSocket is not connected.")`
+    try:
+        if isinstance(message, dict):
+            message = json.dumps(message)
+        await socket.send(message)
+    except Exception as e:
+        print("Error sending:", e)`
path: packages/templates/clients/websocket/python/components/SendEchoMessage.js
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Fix missing `json` import and class name inconsistency.**

The updated code has two issues that need addressing:
1. Missing `json` import for `json.dumps()` operation in line 47
2. Reference to `HoppscotchEchoWebSocketClient` in line 31 which might be inconsistent with the actual class name


```diff
async def send_message(self, message):
    """
    Send a message using the WebSocket connection attached to this instance.

    Args:
        message (dict or str): The message to send. Will be serialized to JSON if it's a dictionary.

    Raises:
        Exception: If sending fails or the socket is not connected.
    """
    await self._send(message, self.ws_app)

@staticmethod
async def send_message_static(message, socket):
    """
    Send a message using a provided WebSocket connection, without needing an instance.

    Args:
        message (dict or str): The message to send.
        socket (websockets.WebSocketCommonProtocol): The WebSocket to send through.

    Raises:
        Exception: If sending fails or the socket is not connected.
    """
-    await HoppscotchEchoWebSocketClient._send(message, socket)
+    await SendEchoMessage._send(message, socket)

@staticmethod
async def _send(message, socket):
    """
    Internal helper to handle the actual sending logic.

    Args:
        message (dict or str): The message to send.
        socket (websockets.WebSocketCommonProtocol): The WebSocket to send through.

    Notes:
        If message is a dictionary, it will be automatically converted to JSON.
    """
+    import json
    try:
        if isinstance(message, dict):
            message = json.dumps(message)
        await socket.send(message)
    except Exception as e:
        print("Error sending:", e)
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
async def send_message(self, message):
    """
    Send a message using the WebSocket connection attached to this instance.

    Args:
        message (dict or str): The message to send. Will be serialized to JSON if it's a dictionary.

    Raises:
        Exception: If sending fails or the socket is not connected.
    """
    await self._send(message, self.ws_app)

@staticmethod
async def send_message_static(message, socket):
    """
    Send a message using a provided WebSocket connection, without needing an instance.

    Args:
        message (dict or str): The message to send.
        socket (websockets.WebSocketCommonProtocol): The WebSocket to send through.

    Raises:
        Exception: If sending fails or the socket is not connected.
    """
    await SendEchoMessage._send(message, socket)

@staticmethod
async def _send(message, socket):
    """
    Internal helper to handle the actual sending logic.

    Args:
        message (dict or str): The message to send.
        socket (websockets.WebSocketCommonProtocol): The WebSocket to send through.

    Notes:
        If message is a dictionary, it will be automatically converted to JSON.
    """
    import json
    try:
        if isinstance(message, dict):
            message = json.dumps(message)
        await socket.send(message)
    except Exception as e:
        print("Error sending:", e)
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-10T08:13:21Z
author_association: NONE
diff_hunk: @@ -0,0 +1,91 @@
+## Prerequisites
+
+Install [Podman](https://podman.io/docs/installation). 
+
+> Microcks needs some services running to simulate the infrastructure and this requires multiple resources. Docker is not the best solution for this, thus better use Podman that manages resources better.
+
+You can also install [docker-compose](https://docs.docker.com/compose/install/) that `podman compose` will later use.
+
+## Test Project
+
+This `test` directory contains acceptance tests that check different clients with tests written in their respective languages. So JavaScript client is tested with JavaScript test, and Python with Python tests, and so on.
+
+To run tests: `podman compose -f ./microcks-setup/microcks-podman.yml --profile tests up -d`
+
+> You need to remember about `--profile test` to run whole setup with tests. This way you ensure that proper importer container imports `__fixtures__/asyncapi-hoppscotch-server.yml` into Microcks and tests run against it.
+
+## Testing Clients with Microcks
+
+This instruction is just a set of notes about how to play locally with Microcks that we already use for automated testing.
+
+Tests also run in containers, although with provided configuration you can start also testing environment without running tests, just to play with Microcks and understand more how it works.
+
+### Concept
+
+Microcks is a tool for mocking. To test our generated clients, we need to mock the server. In other words, if we want to check if the generated client for Postman works well, we need to mock the server that the client will communicate with while testing.
+
+### Using Microcks locally
+
+> This instruction assumes you are located in directory where `microcks-setup` directory is located
+
+#### Start Microcks
+
+1. Start Microcks infrastructure: `podman compose -f ./microcks-setup/microcks-podman.yml up -d`.
+
+1. Check with `podman ps` command if all services are running. It may take few minutes to start all containers. You can also run special script that will confirm services are ready: `bash ./microcks-setup/checkMicrocksReady.sh`.
+
+1. Access Microcks UI with `open http://localhost:8080`.
+
+#### Load AsyncAPI documents
+
+To test clients, we need to mock the server. Remember to load AsyncAPI documents that represent the server.
+
+1. Install [Microcks CLI](https://microcks.io/documentation/guides/automation/cli/)
+
+1. Import AsyncAPI document
+    ```bash
+    microcks-cli import __fixtures__/asyncapi-hoppscotch-server.yml \
+      --microcksURL=http://localhost:8080/api/ \
+      --keycloakClientId=microcks-serviceaccount \
+      --keycloakClientSecret="ab54d329-e435-41ae-a900-ec6b3fe15c54"
path: packages/templates/clients/websocket/test/README.md
user: login: coderabbitai[bot]
body: _⚠️ Potential issue_

**Security concern: Hardcoded secrets in documentation.**

The README contains hardcoded API keys/secrets which should never be included in documentation or repositories.


Replace the hardcoded client secret with a placeholder instruction to get the actual secret from a secure source or environment variable:

```diff
-  --keycloakClientSecret="ab54d329-e435-41ae-a900-ec6b3fe15c54"
+  --keycloakClientSecret="<your-client-secret>"
```

And similarly for the second occurrence:

```diff
-  --keycloakClientSecret="ab54d329-e435-41ae-a900-ec6b3fe15c54" \
+  --keycloakClientSecret="<your-client-secret>" \
```

Consider adding a note about securely obtaining this secret.


Also applies to: 68-68

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Gitleaks (8.21.2)</summary>

50-50: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-10T08:13:21Z
author_association: NONE
diff_hunk: @@ -0,0 +1,90 @@
+import time
+import sys
+import os
+import pytest
+import asyncio
+import websockets
+import requests
+
+module_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../python/test/temp/snapshotTestResult'))
+
+microcks_test_endpoint = 'http://microcks:8080/api/tests'
+
+# Add this directory to sys.path if it isn’t already there.
+if module_path not in sys.path:
+    sys.path.insert(0, module_path)
+
+from client_hoppscotch import HoppscotchEchoWebSocketClient
+
+def test_hoppscotch_client_receives_message():
+    # Instantiate the client using the default URL.
+    client = HoppscotchEchoWebSocketClient('ws://microcks-async-minion:8081/api/ws/Hoppscotch+WebSocket+Server/1.0.0/sendTimeStampMessage')
+
+    received_messages = []
+    expected_message = "GMT+0000 (Coordinated Universal Time)"
+
+    def message_handler(message):
+        received_messages.append(message)
+
+    client.register_message_handler(message_handler)
+
+    client.connect()
+
+    # Wait up to 10 seconds for a message to be received.
+    timeout = 10  # seconds
+    start_time = time.time()
+    while not received_messages and (time.time() - start_time < timeout):
+        time.sleep(0.1)
+
+    # Close the connection.
+    client.close()
+
+    assert expected_message in received_messages[0], (
+        f"Expected message '{expected_message}' but got '{received_messages[0]}'"
+    )
+
+@pytest.mark.asyncio
+async def test_hoppscotch_client_sends_message():
+    port = 8083
+    expected_outgoing_message = "Sending acceptance test message to Microcks."
+
+    # payload for trigger Microcks test
+    payload = {
+        "serviceId": "Hoppscotch WebSocket Server:1.0.0",
+        "testEndpoint": "ws://websocket-acceptance-tester-py:8083/ws",
+        "runnerType": "ASYNC_API_SCHEMA",
+        "timeout": 30000,
+        "filteredOperations": ["RECEIVE handleEchoMessage"]
+    }
+    # Create WebSocket server handler
+    async def handler(websocket):
+        ###############
+        #
+        # Most improtant part of test where we test clients send message
+        #
+        ###############
+        await HoppscotchEchoWebSocketClient.send_message_static(expected_outgoing_message, websocket)
+
+    # Start the WebSocket server
+    server = await websockets.serve(handler, port=port)
+    await asyncio.sleep(1)  # Give server time to start
path: packages/templates/clients/websocket/test/python/test_acceptance.py
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Ensure server starts properly before proceeding**

You're waiting for the server to start, but not checking if it started successfully. Consider adding verification logic to ensure the server is ready before proceeding with the test.

```diff
 # Start the WebSocket server
 server = await websockets.serve(handler, port=port)
 await asyncio.sleep(1)  # Give server time to start
+# Verify server is running
+assert server.is_serving(), "WebSocket server failed to start"
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
    server = await websockets.serve(handler, port=port)
    await asyncio.sleep(1)  # Give server time to start
    assert server.is_serving(), "WebSocket server failed to start"
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-10T08:13:21Z
author_association: NONE
diff_hunk: @@ -0,0 +1,90 @@
+import time
+import sys
+import os
+import pytest
+import asyncio
+import websockets
+import requests
+
+module_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../python/test/temp/snapshotTestResult'))
+
+microcks_test_endpoint = 'http://microcks:8080/api/tests'
+
+# Add this directory to sys.path if it isn’t already there.
+if module_path not in sys.path:
+    sys.path.insert(0, module_path)
+
+from client_hoppscotch import HoppscotchEchoWebSocketClient
+
+def test_hoppscotch_client_receives_message():
+    # Instantiate the client using the default URL.
+    client = HoppscotchEchoWebSocketClient('ws://microcks-async-minion:8081/api/ws/Hoppscotch+WebSocket+Server/1.0.0/sendTimeStampMessage')
+
+    received_messages = []
+    expected_message = "GMT+0000 (Coordinated Universal Time)"
+
+    def message_handler(message):
+        received_messages.append(message)
+
+    client.register_message_handler(message_handler)
+
+    client.connect()
+
+    # Wait up to 10 seconds for a message to be received.
+    timeout = 10  # seconds
+    start_time = time.time()
+    while not received_messages and (time.time() - start_time < timeout):
+        time.sleep(0.1)
+
+    # Close the connection.
+    client.close()
+
+    assert expected_message in received_messages[0], (
+        f"Expected message '{expected_message}' but got '{received_messages[0]}'"
+    )
+
+@pytest.mark.asyncio
+async def test_hoppscotch_client_sends_message():
+    port = 8083
+    expected_outgoing_message = "Sending acceptance test message to Microcks."
+
+    # payload for trigger Microcks test
+    payload = {
+        "serviceId": "Hoppscotch WebSocket Server:1.0.0",
+        "testEndpoint": "ws://websocket-acceptance-tester-py:8083/ws",
+        "runnerType": "ASYNC_API_SCHEMA",
+        "timeout": 30000,
+        "filteredOperations": ["RECEIVE handleEchoMessage"]
+    }
+    # Create WebSocket server handler
+    async def handler(websocket):
+        ###############
+        #
+        # Most improtant part of test where we test clients send message
+        #
+        ###############
+        await HoppscotchEchoWebSocketClient.send_message_static(expected_outgoing_message, websocket)
+
+    # Start the WebSocket server
+    server = await websockets.serve(handler, port=port)
+    await asyncio.sleep(1)  # Give server time to start
+
+    # Start test in Microcks
+    response = requests.post(microcks_test_endpoint, json=payload)
+    response.raise_for_status()
+    response_data = response.json()
+    test_id = response_data.get('id')
+
+    # Poll Microcks for result
+    success = False
+    for _ in range(30):
+        result = requests.get(f"{microcks_test_endpoint}/{test_id}").json()
+        print("Polling Microcks:", result)
+        if result.get("success") is True:
+            success = True
+            break
+        await asyncio.sleep(2)
+    #await asyncio.sleep(1000)
path: packages/templates/clients/websocket/test/python/test_acceptance.py
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Improve polling mechanism with better error handling**

The polling loop lacks explanatory comments about the 30 iterations limit, and there's no error handling if the API response fails.

```diff
 # Poll Microcks for result
 success = False
+max_attempts = 30  # Set timeout: 30 attempts * 2 seconds = 60 seconds total
-for _ in range(30):
+for attempt in range(max_attempts):
+    try:
         result = requests.get(f"{microcks_test_endpoint}/{test_id}").json()
         print("Polling Microcks:", result)
         if result.get("success") is True:
             success = True
             break
+    except Exception as e:
+        print(f"Error polling Microcks (attempt {attempt+1}/{max_attempts}): {e}")
     await asyncio.sleep(2)
-#await asyncio.sleep(1000)
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
    # Poll Microcks for result
    success = False
    max_attempts = 30  # Set timeout: 30 attempts * 2 seconds = 60 seconds total
    for attempt in range(max_attempts):
        try:
            result = requests.get(f"{microcks_test_endpoint}/{test_id}").json()
            print("Polling Microcks:", result)
            if result.get("success") is True:
                success = True
                break
        except Exception as e:
            print(f"Error polling Microcks (attempt {attempt+1}/{max_attempts}): {e}")
        await asyncio.sleep(2)
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-10T08:13:21Z
author_association: NONE
diff_hunk: @@ -0,0 +1,90 @@
+import time
+import sys
+import os
+import pytest
+import asyncio
+import websockets
+import requests
+
+module_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../python/test/temp/snapshotTestResult'))
+
+microcks_test_endpoint = 'http://microcks:8080/api/tests'
+
+# Add this directory to sys.path if it isn’t already there.
+if module_path not in sys.path:
+    sys.path.insert(0, module_path)
+
+from client_hoppscotch import HoppscotchEchoWebSocketClient
+
+def test_hoppscotch_client_receives_message():
+    # Instantiate the client using the default URL.
+    client = HoppscotchEchoWebSocketClient('ws://microcks-async-minion:8081/api/ws/Hoppscotch+WebSocket+Server/1.0.0/sendTimeStampMessage')
+
+    received_messages = []
+    expected_message = "GMT+0000 (Coordinated Universal Time)"
+
+    def message_handler(message):
+        received_messages.append(message)
+
+    client.register_message_handler(message_handler)
+
+    client.connect()
+
+    # Wait up to 10 seconds for a message to be received.
+    timeout = 10  # seconds
+    start_time = time.time()
+    while not received_messages and (time.time() - start_time < timeout):
+        time.sleep(0.1)
+
+    # Close the connection.
+    client.close()
+
+    assert expected_message in received_messages[0], (
+        f"Expected message '{expected_message}' but got '{received_messages[0]}'"
+    )
+
+@pytest.mark.asyncio
+async def test_hoppscotch_client_sends_message():
+    port = 8083
+    expected_outgoing_message = "Sending acceptance test message to Microcks."
+
+    # payload for trigger Microcks test
+    payload = {
+        "serviceId": "Hoppscotch WebSocket Server:1.0.0",
+        "testEndpoint": "ws://websocket-acceptance-tester-py:8083/ws",
+        "runnerType": "ASYNC_API_SCHEMA",
+        "timeout": 30000,
+        "filteredOperations": ["RECEIVE handleEchoMessage"]
+    }
+    # Create WebSocket server handler
+    async def handler(websocket):
+        ###############
+        #
+        # Most improtant part of test where we test clients send message
+        #
+        ###############
+        await HoppscotchEchoWebSocketClient.send_message_static(expected_outgoing_message, websocket)
+
+    # Start the WebSocket server
+    server = await websockets.serve(handler, port=port)
+    await asyncio.sleep(1)  # Give server time to start
+
+    # Start test in Microcks
+    response = requests.post(microcks_test_endpoint, json=payload)
+    response.raise_for_status()
+    response_data = response.json()
+    test_id = response_data.get('id')
+
+    # Poll Microcks for result
+    success = False
+    for _ in range(30):
+        result = requests.get(f"{microcks_test_endpoint}/{test_id}").json()
+        print("Polling Microcks:", result)
+        if result.get("success") is True:
+            success = True
+            break
+        await asyncio.sleep(2)
+    #await asyncio.sleep(1000)
+    server.close()
+
path: packages/templates/clients/websocket/test/python/test_acceptance.py
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Use a finally block to ensure server cleanup**

The server should be closed even if assertions fail. Use a try/finally pattern to ensure proper cleanup.

```diff
-#await asyncio.sleep(1000)
-server.close()
+# Clean up server resources regardless of test outcome
+try:
+    assert success, f"Microcks test {test_id} did not succeed"
+finally:
+    server.close()
+    await server.wait_closed()  # Ensure proper shutdown
-assert success, f"Microcks test {test_id} did not succeed"
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
    # Clean up server resources regardless of test outcome
    try:
        assert success, f"Microcks test {test_id} did not succeed"
    finally:
        server.close()
        await server.wait_closed()  # Ensure proper shutdown
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-10T08:13:21Z
author_association: NONE
diff_hunk: @@ -0,0 +1,151 @@
+volumes:
+  microcks-data:
+  
+services:
+  mongo:
+    image: docker.io/mongo:4.4.29
+    container_name: microcks-db
+    volumes:
+      - microcks-data:/data/db
+    healthcheck:
+      test: ["CMD", "mongo", "--eval", "db.adminCommand('ping')"]
+      interval: 30s
+      timeout: 1s
+      retries: 3
+
+  kafka:
+    image: docker.io/redpandadata/redpanda:v24.3.1
+    container_name: microcks-kafka
+    command:
+      - redpanda
+      - start
+      - --overprovisioned
+      - --smp
+      - "1"
+      - --memory
+      - 1G
+      - --reserve-memory
+      - 0M
+      - --node-id
+      - "0"
+      - --check=false
+      - --kafka-addr
+      - PLAINTEXT://0.0.0.0:19092,EXTERNAL://0.0.0.0:9092
+      - --advertise-kafka-addr
+      - PLAINTEXT://kafka:19092,EXTERNAL://localhost:9092
+    ports:
+      - 9092:9092
+      - 19092:19092
+    healthcheck:
+      test: ["CMD-SHELL", "timeout 5 bash -c 'echo > /dev/tcp/localhost/19092'"]
+      interval: 10s
+      timeout: 5s
+      retries: 3
+      start_period: 10s
+
+  app:
+    depends_on:
+      - mongo
+    image: quay.io/microcks/microcks:1.11.2
+    container_name: microcks
+    volumes:
+      - ./config:/deployments/config:Z
+    ports:
+      - 8080:8080
+      - 9090:9090
+    environment:
+      SPRING_PROFILES_ACTIVE: prod
+      SPRING_DATA_MONGODB_URI: mongodb://mongo:27017
+      SPRING_DATA_MONGODB_DATABASE: microcks
+      POSTMAN_RUNNER_URL: http://postman:3000
+      TEST_CALLBACK_URL: http://microcks:8080
+      SERVICES_UPDATE_INTERVAL: "0 0 0/2 * * *"
+      KEYCLOAK_ENABLED: "false"
+      #MAX_UPLOAD_FILE_SIZE: 3MB
+      ASYNC_MINION_URL: http://microcks-async-minion:8081
+      KAFKA_BOOTSTRAP_SERVER: kafka:19092
+    healthcheck:
+      test: ["CMD", "curl", "-f", "http://localhost:8080/api/health"]
+      start_period: 35s
+      interval: 10s
+      timeout: 3s
+      retries: 3
+
+  async-minion:
+    depends_on:
+      - app
+    image: quay.io/microcks/microcks-async-minion:1.11.2
+    container_name: microcks-async-minion
+    restart: on-failure
+    volumes:
+      - ./config:/deployments/config:Z
+    ports:
+      - 8081:8081
+    environment:
+      QUARKUS_PROFILE: docker-compose
+    healthcheck:
+      test: ["CMD", "curl", "-f", "http://localhost:8081/q/health/ready"]
+      start_period: 10s
+      interval: 10s
+      timeout: 2s
+      retries: 3
+  
+  importer:
+    profiles:
+      - tests
+    image: quay.io/microcks/microcks-cli:latest
+    container_name: microcks-cli-importer
+    working_dir: /usr/src/app
+    volumes:
+      - ../:/usr/src/app
+    depends_on:
+      app:
+        condition: service_healthy
+    command: >
+      sh -c "microcks-cli import __fixtures__/asyncapi-hoppscotch-server.yml
+      --microcksURL=http://microcks:8080/api/
+      --keycloakClientId=microcks-serviceaccount
+      --keycloakClientSecret=ab54d329-e435-41ae-a900-ec6b3fe15c54"
path: packages/templates/clients/websocket/test/microcks-setup/microcks-podman.yml
user: login: coderabbitai[bot]
body: _💡 Verification agent_

<details>
<summary>🧩 Analysis chain</summary>

**Security concern: Hardcoded credentials**

The configuration contains a hardcoded client secret that appears to be a valid credential.


Consider using environment variables or a secrets management solution instead of hardcoding credentials in the configuration file:

```diff
-      --keycloakClientSecret=ab54d329-e435-41ae-a900-ec6b3fe15c54"
+      --keycloakClientSecret=${KEYCLOAK_CLIENT_SECRET:-dummy-secret}"
```

---

🏁 Script executed:

```shell
#!/bin/bash
# Check if this appears to be a real UUID
CLIENT_SECRET="ab54d329-e435-41ae-a900-ec6b3fe15c54"

# Validate if this is a UUID format (which suggests it might be a real credential)
if [[ $CLIENT_SECRET =~ ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$ ]]; then
  echo "WARNING: The string appears to be a valid UUID format, which suggests it could be a real credential"
  
  # Search for other instances of this secret in the codebase
  echo "Checking for other instances of this secret in the codebase:"
  rg -i "$CLIENT_SECRET" --type yaml --type js --type ts --type json --type py
else
  echo "The string doesn't match UUID format, might be a placeholder"
fi

# Check if it's mentioned in documentation or README files
echo "Checking if the token is documented:"
rg -i "ab54d329|keycloakClientSecret" --type md --type txt
```

Length of output: 1130

---



</details>

**Critical Security Vulnerability: Hardcoded Client Secret Detected**

The analysis confirms that the client secret in question is a valid UUID and is hardcoded in multiple locations, both in the Podman YAML configuration and the README documentation. Hardcoding such credentials risks exposing sensitive information.

**Affected files:**
- `packages/templates/clients/websocket/test/microcks-setup/microcks-podman.yml` (line 108)
- `packages/templates/clients/websocket/test/README.md`

**Recommendation:**
Replace the hardcoded secret with an environment variable or integrate a secrets management solution. For example:

```diff
-      --keycloakClientSecret=ab54d329-e435-41ae-a900-ec6b3fe15c54"
+      --keycloakClientSecret=${KEYCLOAK_CLIENT_SECRET:-dummy-secret}"
```

Please ensure that similar changes are applied to any other instances where this secret is used or documented.



<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
      --keycloakClientSecret=${KEYCLOAK_CLIENT_SECRET:-dummy-secret}"
`````

</details>

<!-- suggestion_end -->

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 Gitleaks (8.21.2)</summary>

108-108: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-10T08:13:22Z
author_association: NONE
diff_hunk: @@ -0,0 +1,70 @@
+/* istanbul ignore file */
+const fetch = require('node-fetch');
+
+/**
+ * Polls the Microcks API every 2 seconds until a test with the given ID reports success.
+ *
+ * @param {string} url - link to endpoint providing info on particular test
+ * @returns {Promise<boolean>} Resolves with `true` when the test is marked as successful.
+ */
+async function waitForTestSuccess(url) {
+  while (true) {
+    try {
+      const response = await fetch(url, {
+        method: 'GET',
+        headers: { 'Content-Type': 'application/json' }
+      });
+
+      if (!response.ok) {
+        console.error(`Request failed with status: ${response.status}`);
+        break;
+      }
+
+      const data = await response.json();
+
+      if (data.success) {
+        return true;
+      }
+    } catch (err) {
+      break;
+    }
+
+    await new Promise(resolve => setTimeout(resolve, 2000)); // Wait 2 seconds
+  }
+
+  return false;
+}
path: packages/templates/clients/websocket/test/javascript/utils.js
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Add timeout parameter to prevent infinite polling**

The `waitForTestSuccess` function lacks a timeout parameter, which could lead to an infinite loop if the server never responds with success.

```diff
/**
 * Polls the Microcks API every 2 seconds until a test with the given ID reports success.
 *
 * @param {string} url - link to endpoint providing info on particular test
+ * @param {number} timeout - Maximum time (in ms) to wait before giving up. Default is 60000ms (1 minute).
 * @returns {Promise<boolean>} Resolves with `true` when the test is marked as successful.
 */
-async function waitForTestSuccess(url) {
+async function waitForTestSuccess(url, timeout = 60000) {
+  const startTime = Date.now();
   while (true) {
+    // Check if we've exceeded the timeout
+    if (Date.now() - startTime > timeout) {
+      console.error(`Test polling timed out after ${timeout}ms`);
+      return false;
+    }
+
     try {
       const response = await fetch(url, {
         method: 'GET',
         headers: { 'Content-Type': 'application/json' }
       });

       if (!response.ok) {
         console.error(`Request failed with status: ${response.status}`);
-        break;
+        // Continue polling despite error
+        await new Promise(resolve => setTimeout(resolve, 2000));
+        continue;
       }

       const data = await response.json();

       if (data.success) {
         return true;
       }
     } catch (err) {
-      break;
+      console.error(`Error polling test status: ${err.message}`);
+      // Continue polling despite error
+      await new Promise(resolve => setTimeout(resolve, 2000));
+      continue;
     }

     await new Promise(resolve => setTimeout(resolve, 2000)); // Wait 2 seconds
   }
-
-  return false;
}
```


<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
/**
 * Polls the Microcks API every 2 seconds until a test with the given ID reports success.
 *
 * @param {string} url - link to endpoint providing info on particular test
 * @param {number} timeout - Maximum time (in ms) to wait before giving up. Default is 60000ms (1 minute).
 * @returns {Promise<boolean>} Resolves with `true` when the test is marked as successful.
 */
async function waitForTestSuccess(url, timeout = 60000) {
  const startTime = Date.now();
  while (true) {
    // Check if we've exceeded the timeout
    if (Date.now() - startTime > timeout) {
      console.error(`Test polling timed out after ${timeout}ms`);
      return false;
    }

    try {
      const response = await fetch(url, {
        method: 'GET',
        headers: { 'Content-Type': 'application/json' }
      });

      if (!response.ok) {
        console.error(`Request failed with status: ${response.status}`);
        // Continue polling despite error
        await new Promise(resolve => setTimeout(resolve, 2000));
        continue;
      }

      const data = await response.json();

      if (data.success) {
        return true;
      }
    } catch (err) {
      console.error(`Error polling test status: ${err.message}`);
      // Continue polling despite error
      await new Promise(resolve => setTimeout(resolve, 2000));
      continue;
    }

    await new Promise(resolve => setTimeout(resolve, 2000)); // Wait 2 seconds
  }
}
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-10T08:13:22Z
author_association: NONE
diff_hunk: @@ -0,0 +1,91 @@
+## Prerequisites
+
+Install [Podman](https://podman.io/docs/installation). 
+
+> Microcks needs some services running to simulate the infrastructure and this requires multiple resources. Docker is not the best solution for this, thus better use Podman that manages resources better.
path: packages/templates/clients/websocket/test/README.md
user: login: Florence-Njeri
body: ```suggestion
> Microcks needs some services running to simulate the infrastructure and this requires multiple resources. Docker is not the best solution for this, thus it's better to use Podman that manages resources better.
```
created_at: 2025-04-14T10:44:15Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,91 @@
+## Prerequisites
+
+Install [Podman](https://podman.io/docs/installation). 
+
+> Microcks needs some services running to simulate the infrastructure and this requires multiple resources. Docker is not the best solution for this, thus better use Podman that manages resources better.
+
+You can also install [docker-compose](https://docs.docker.com/compose/install/) that `podman compose` will later use.
+
+## Test Project
+
+This `test` directory contains acceptance tests that check different clients with tests written in their respective languages. So JavaScript client is tested with JavaScript test, and Python with Python tests, and so on.
+
+To run tests: `podman compose -f ./microcks-setup/microcks-podman.yml --profile tests up -d`
+
+> You need to remember about `--profile test` to run whole setup with tests. This way you ensure that proper importer container imports `__fixtures__/asyncapi-hoppscotch-server.yml` into Microcks and tests run against it.
+
+## Testing Clients with Microcks
+
+This instruction is just a set of notes about how to play locally with Microcks that we already use for automated testing.
+
+Tests also run in containers, although with provided configuration you can start also testing environment without running tests, just to play with Microcks and understand more how it works.
+
+### Concept
+
+Microcks is a tool for mocking. To test our generated clients, we need to mock the server. In other words, if we want to check if the generated client for Postman works well, we need to mock the server that the client will communicate with while testing.
path: packages/templates/clients/websocket/test/README.md
user: login: Florence-Njeri
body: ```suggestion
Microcks is a tool for mocking. To test our generated clients, we need to mock the server. In other words, if we want to check if the generated client for Postman works well, we need to mock the server that the client will communicate with during testing.
```
created_at: 2025-04-14T10:48:38Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,91 @@
+## Prerequisites
+
+Install [Podman](https://podman.io/docs/installation). 
+
+> Microcks needs some services running to simulate the infrastructure and this requires multiple resources. Docker is not the best solution for this, thus better use Podman that manages resources better.
+
+You can also install [docker-compose](https://docs.docker.com/compose/install/) that `podman compose` will later use.
+
+## Test Project
+
+This `test` directory contains acceptance tests that check different clients with tests written in their respective languages. So JavaScript client is tested with JavaScript test, and Python with Python tests, and so on.
+
+To run tests: `podman compose -f ./microcks-setup/microcks-podman.yml --profile tests up -d`
+
+> You need to remember about `--profile test` to run whole setup with tests. This way you ensure that proper importer container imports `__fixtures__/asyncapi-hoppscotch-server.yml` into Microcks and tests run against it.
+
+## Testing Clients with Microcks
+
+This instruction is just a set of notes about how to play locally with Microcks that we already use for automated testing.
+
+Tests also run in containers, although with provided configuration you can start also testing environment without running tests, just to play with Microcks and understand more how it works.
+
+### Concept
+
+Microcks is a tool for mocking. To test our generated clients, we need to mock the server. In other words, if we want to check if the generated client for Postman works well, we need to mock the server that the client will communicate with while testing.
+
+### Using Microcks locally
+
+> This instruction assumes you are located in directory where `microcks-setup` directory is located
+
+#### Start Microcks
+
+1. Start Microcks infrastructure: `podman compose -f ./microcks-setup/microcks-podman.yml up -d`.
+
+1. Check with `podman ps` command if all services are running. It may take few minutes to start all containers. You can also run special script that will confirm services are ready: `bash ./microcks-setup/checkMicrocksReady.sh`.
path: packages/templates/clients/websocket/test/README.md
user: login: Florence-Njeri
body: ```suggestion
1. Check with `podman ps` command if all services are running. It may take few minutes to start all containers. You can also run a special script that will confirm that services are ready: `bash ./microcks-setup/checkMicrocksReady.sh`.
```
created_at: 2025-04-14T10:50:33Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,91 @@
+## Prerequisites
+
+Install [Podman](https://podman.io/docs/installation). 
+
+> Microcks needs some services running to simulate the infrastructure and this requires multiple resources. Docker is not the best solution for this, thus better use Podman that manages resources better.
+
+You can also install [docker-compose](https://docs.docker.com/compose/install/) that `podman compose` will later use.
+
+## Test Project
+
+This `test` directory contains acceptance tests that check different clients with tests written in their respective languages. So JavaScript client is tested with JavaScript test, and Python with Python tests, and so on.
+
+To run tests: `podman compose -f ./microcks-setup/microcks-podman.yml --profile tests up -d`
+
+> You need to remember about `--profile test` to run whole setup with tests. This way you ensure that proper importer container imports `__fixtures__/asyncapi-hoppscotch-server.yml` into Microcks and tests run against it.
+
+## Testing Clients with Microcks
+
+This instruction is just a set of notes about how to play locally with Microcks that we already use for automated testing.
+
+Tests also run in containers, although with provided configuration you can start also testing environment without running tests, just to play with Microcks and understand more how it works.
+
+### Concept
+
+Microcks is a tool for mocking. To test our generated clients, we need to mock the server. In other words, if we want to check if the generated client for Postman works well, we need to mock the server that the client will communicate with while testing.
+
+### Using Microcks locally
+
+> This instruction assumes you are located in directory where `microcks-setup` directory is located
+
+#### Start Microcks
+
+1. Start Microcks infrastructure: `podman compose -f ./microcks-setup/microcks-podman.yml up -d`.
+
+1. Check with `podman ps` command if all services are running. It may take few minutes to start all containers. You can also run special script that will confirm services are ready: `bash ./microcks-setup/checkMicrocksReady.sh`.
+
+1. Access Microcks UI with `open http://localhost:8080`.
+
+#### Load AsyncAPI documents
+
+To test clients, we need to mock the server. Remember to load AsyncAPI documents that represent the server.
+
+1. Install [Microcks CLI](https://microcks.io/documentation/guides/automation/cli/)
+
+1. Import AsyncAPI document
+    ```bash
+    microcks-cli import __fixtures__/asyncapi-hoppscotch-server.yml \
+      --microcksURL=http://localhost:8080/api/ \
+      --keycloakClientId=microcks-serviceaccount \
+      --keycloakClientSecret="ab54d329-e435-41ae-a900-ec6b3fe15c54"
+    ```
+
+1. See the mock in the Microcks UI with `open http://localhost:8080/#/services`
+
+#### Invoke Mocks tests
+
+Start simple testing of the mock to see if it was created properly. Tests should turn green.
+
+You should run tests only on one operation at a time.
+
+```bash
+# the higher timeout the more test samples will run
+microcks-cli test 'Hoppscotch WebSocket Server:1.0.0' localhost:8081/api/ws/Hoppscotch+WebSocket+Server/1.0.0/sendTimeStampMessage ASYNC_API_SCHEMA \
+    --microcksURL=http://localhost:8080/api/ \
+    --insecure \
+    --waitFor=15sec \
+    --keycloakClientId=microcks-serviceaccount \
+    --keycloakClientSecret="ab54d329-e435-41ae-a900-ec6b3fe15c54" \
+    --filteredOperations="[\"SEND sendTimeStampMessage\"]"
+```
+
+You can also check the status of tests in the Microcks UI.
+
+### Debugging 
+
+File `microcks-podman.yml` contains commented out configuration for debbuging container you can start with the entire testing environment.
+
+Useful is also to connect to Microcks containers and checkout logs: `podman logs -f  microcks-async-minion`. Minion is the service that handles API calls.
path: packages/templates/clients/websocket/test/README.md
user: login: Florence-Njeri
body: ```suggestion
It's also useful to connect to Microcks containers and checkout logs: `podman logs -f  microcks-async-minion`. Minion is the service that handles API calls.
```
created_at: 2025-04-14T10:56:07Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,91 @@
+## Prerequisites
+
+Install [Podman](https://podman.io/docs/installation). 
+
+> Microcks needs some services running to simulate the infrastructure and this requires multiple resources. Docker is not the best solution for this, thus better use Podman that manages resources better.
+
+You can also install [docker-compose](https://docs.docker.com/compose/install/) that `podman compose` will later use.
+
+## Test Project
+
+This `test` directory contains acceptance tests that check different clients with tests written in their respective languages. So JavaScript client is tested with JavaScript test, and Python with Python tests, and so on.
+
+To run tests: `podman compose -f ./microcks-setup/microcks-podman.yml --profile tests up -d`
+
+> You need to remember about `--profile test` to run whole setup with tests. This way you ensure that proper importer container imports `__fixtures__/asyncapi-hoppscotch-server.yml` into Microcks and tests run against it.
+
+## Testing Clients with Microcks
+
+This instruction is just a set of notes about how to play locally with Microcks that we already use for automated testing.
+
+Tests also run in containers, although with provided configuration you can start also testing environment without running tests, just to play with Microcks and understand more how it works.
+
+### Concept
+
+Microcks is a tool for mocking. To test our generated clients, we need to mock the server. In other words, if we want to check if the generated client for Postman works well, we need to mock the server that the client will communicate with while testing.
+
+### Using Microcks locally
+
+> This instruction assumes you are located in directory where `microcks-setup` directory is located
+
+#### Start Microcks
+
+1. Start Microcks infrastructure: `podman compose -f ./microcks-setup/microcks-podman.yml up -d`.
+
+1. Check with `podman ps` command if all services are running. It may take few minutes to start all containers. You can also run special script that will confirm services are ready: `bash ./microcks-setup/checkMicrocksReady.sh`.
+
+1. Access Microcks UI with `open http://localhost:8080`.
+
+#### Load AsyncAPI documents
+
+To test clients, we need to mock the server. Remember to load AsyncAPI documents that represent the server.
+
+1. Install [Microcks CLI](https://microcks.io/documentation/guides/automation/cli/)
+
+1. Import AsyncAPI document
+    ```bash
+    microcks-cli import __fixtures__/asyncapi-hoppscotch-server.yml \
+      --microcksURL=http://localhost:8080/api/ \
+      --keycloakClientId=microcks-serviceaccount \
+      --keycloakClientSecret="ab54d329-e435-41ae-a900-ec6b3fe15c54"
+    ```
+
+1. See the mock in the Microcks UI with `open http://localhost:8080/#/services`
+
+#### Invoke Mocks tests
+
+Start simple testing of the mock to see if it was created properly. Tests should turn green.
+
+You should run tests only on one operation at a time.
+
+```bash
+# the higher timeout the more test samples will run
+microcks-cli test 'Hoppscotch WebSocket Server:1.0.0' localhost:8081/api/ws/Hoppscotch+WebSocket+Server/1.0.0/sendTimeStampMessage ASYNC_API_SCHEMA \
+    --microcksURL=http://localhost:8080/api/ \
+    --insecure \
+    --waitFor=15sec \
+    --keycloakClientId=microcks-serviceaccount \
+    --keycloakClientSecret="ab54d329-e435-41ae-a900-ec6b3fe15c54" \
+    --filteredOperations="[\"SEND sendTimeStampMessage\"]"
+```
+
+You can also check the status of tests in the Microcks UI.
+
+### Debugging 
+
+File `microcks-podman.yml` contains commented out configuration for debbuging container you can start with the entire testing environment.
+
+Useful is also to connect to Microcks containers and checkout logs: `podman logs -f  microcks-async-minion`. Minion is the service that handles API calls.
+
+### Cleanup
+
+Run `podman compose -f ./microcks-setup/microcks-podman.yml down --remove-orphans` to clean everything.
+
+## Playing with Microcks Mock Server
+
+You can also check websocket endpoints generated by Microcks in terminal using [websocat](https://github.com/vi/websocat).
path: packages/templates/clients/websocket/test/README.md
user: login: Florence-Njeri
body: ```suggestion
You can also check the websocket endpoints generated by Microcks in the terminal using [websocat](https://github.com/vi/websocat).
```
created_at: 2025-04-14T10:57:48Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,91 @@
+## Prerequisites
+
+Install [Podman](https://podman.io/docs/installation). 
+
+> Microcks needs some services running to simulate the infrastructure and this requires multiple resources. Docker is not the best solution for this, thus it's better to use Podman that manages resources better.
+
+You can also install [docker-compose](https://docs.docker.com/compose/install/) that `podman compose` will later use.
+
+## Test Project
+
+This `test` directory contains acceptance tests that check different clients with tests written in their respective languages. So JavaScript client is tested with JavaScript test, and Python with Python tests, and so on.
+
+To run tests: `podman compose -f ./microcks-setup/microcks-podman.yml --profile tests up -d`
+
+> You need to remember about `--profile test` to run whole setup with tests. This way you ensure that proper importer container imports `__fixtures__/asyncapi-hoppscotch-server.yml` into Microcks and tests run against it.
path: packages/templates/clients/websocket/test/README.md
user: login: coderabbitai[bot]
body: _🛠️ Refactor suggestion_

**Ensure consistency in profile naming.**

The command on line 13 uses `--profile tests` while the note on line 15 refers to `--profile test`. Please verify and standardize the profile name across the documentation to avoid confusion.

<!-- This is an auto-generated comment by CodeRabbit -->
created_at: 2025-04-14T12:00:56Z
author_association: NONE

PR comments:
user: login: changeset-bot[bot]
created_at: 2025-04-02T17:18:58Z
body: ###  ⚠️  No Changeset found

Latest commit: edcf88ed44902b999d06780223da21a713c44a9f

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. **If these changes should result in a version bump, you need to add a changeset.**

<details><summary>This PR includes no changesets</summary>

  When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

</details>

[Click here to learn what changesets are, and how to add one](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add a changeset to this PR](https://github.com/derberg/generator/new/microcks?filename=.changeset/twenty-readers-notice.md&value=---%0A%22%40asyncapi%2Ftemplate-js-websocket-client%22%3A%20patch%0A%22%40asyncapi%2Ftemplate-python-websocket-client%22%3A%20patch%0A%22undefined%22%3A%20patch%0A---%0A%0Achore%3A%20add%20acceptance%20testing%20with%20microcks%20mocks%0A)


author_association: NONE
user: login: coderabbitai[bot]
created_at: 2025-04-02T17:19:12Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- This is an auto-generated comment: skip review by coderabbit.ai -->

> [!IMPORTANT]
> ## Review skipped
> 
> Review was skipped due to path filters
> 
> <details>
> <summary>:no_entry: Files ignored due to path filters (1)</summary>
> 
> * `packages/templates/clients/websocket/javascript/test/__snapshots__/integration.test.js.snap` is excluded by `!**/*.snap`
> 
> </details>
> 
> CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including `**/dist/**` will override the default block on the `dist` directory, by removing the pattern from both the lists.
> 
> You can disable this status message by setting the `reviews.review_status` to `false` in the CodeRabbit configuration file.

<!-- end of auto-generated comment: skip review by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough
The pull request introduces multiple enhancements for WebSocket client testing and messaging. In both JavaScript and Python clients, message-sending methods are updated to support static and asynchronous operations. Several AsyncAPI documents now include additional examples and message definitions, while new acceptance tests, utility scripts, and configuration files have been added to facilitate contract testing with Microcks. The changes also include Podman configuration and a health-check script for the testing environment, along with an update to the `.gitignore` file to exclude the `microcks-data` directory.

## Changes

| Files | Change Summary |
| --- | --- |
| `.gitignore` | Added entry to ignore the `microcks-data` directory. |
| `packages/.../javascript/components/SendEchoMessage.js` | Converted `sendEchoMessage` to a static method with an added `socket` parameter and updated documentation. |
| `packages/.../python/components/SendEchoMessage.js` | Updated `send_message` to be asynchronous and added `send_message_static` and `_send` methods with updated docs. |
| `packages/.../javascript/test/__fixtures__/asyncapi-*.yml` | Added AsyncAPI example under the `timestamp` message, introduced a `messages` property in Postman echo spec, and created a new server spec for Hoppscotch. |
| `packages/.../test/(javascript|python)/**` | Added new acceptance tests, utility functions, `package.json`, and Python `requirements.txt` for WebSocket client testing. |
| `packages/.../test/microcks-setup/**` and `README.md` | Introduced Podman configuration files, a health-check script, and configuration for Microcks testing environment. |

## Sequence Diagram(s)
```mermaid
sequenceDiagram
    participant Tester as Acceptance Test
    participant Client as WSClient
    participant Server as WebSocket Server
    participant Microcks as Microcks API

    Tester->>Client: Initialize WebSocket connection
    Client->>Server: Send message via static/async method
    Server->>Client: Echo message back
    Client->>Tester: Deliver received message
    Tester->>Microcks: POST test request for contract validation
    Microcks-->>Tester: Return test success confirmation
```

## Assessment against linked issues

| Objective                                                                                                          | Addressed | Explanation |
|--------------------------------------------------------------------------------------------------------------------|-----------|-------------|
| MVP for better testing of the templates with contract testing using mocks (#1417)                                  | ✅        |             | 

## Suggested labels
`ready-to-merge`

## Suggested reviewers
- asyncapi-bot-eve
- magicmatatjahu
- jonaslagoni

## Poem
> I'm a little rabbit, hopping through the code,  
> With async tests and messages in cheerful mode.  
> New features bloom like carrots in a row,  
> Microcks and Podman set the workflow aglow.  
> I nibble on changes with a joyful heart so light—  
> Celebrate the merge, and code on through the night!  
> 🐰✨

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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= -->

<!-- internal state end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=asyncapi/generator&utm_content=1467):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: NONE
user: login: derberg
created_at: 2025-04-10T16:18:54Z
body: you Rabbit, are you sure you don't have anything more interesting to do, rather than commenting my PR 😄
author_association: MEMBER
user: login: Adi-204
created_at: 2025-04-11T18:00:14Z
body: @derberg I tried running setup locally. 
On below command run (given in README.md of tests) the tests fails because in testEndpoint `ws://` is missing in starting. 

```bash
# the higher timeout the more test samples will run
microcks-cli test 'Hoppscotch WebSocket Server:1.0.0' localhost:8081/api/ws/Hoppscotch+WebSocket+Server/1.0.0/sendTimeStampMessage ASYNC_API_SCHEMA \
    --microcksURL=http://localhost:8080/api/ \
    --insecure \
    --waitFor=15sec \
    --keycloakClientId=microcks-serviceaccount \
    --keycloakClientSecret="ab54d329-e435-41ae-a900-ec6b3fe15c54" \
    --filteredOperations="[\"SEND sendTimeStampMessage\"]"
```

When I added `ws://` ahead then it pass. You can check below screenshot only Endpoints are different - 

![image](https://github.com/user-attachments/assets/08bae643-7e8f-4ee2-b64d-813cc34dbc6a)

author_association: MEMBER
user: login: sonarqubecloud[bot]
created_at: 2025-04-14T12:06:55Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=asyncapi_generator&pullRequest=1467) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=1467&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=asyncapi_generator&pullRequest=1467&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=asyncapi_generator&pullRequest=1467&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=asyncapi_generator&pullRequest=1467&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=asyncapi_generator&pullRequest=1467&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=asyncapi_generator&pullRequest=1467)


author_association: NONE
user: login: derberg
created_at: 2025-04-14T12:07:29Z
body: @Florence-Njeri thanks, all suggestions applied

@Adi-204 thanks a lot for checking - fixed

btw, I also made some changes thanks to rabbit
author_association: MEMBER
user: login: derberg
created_at: 2025-04-14T13:31:01Z
body: /rtm
author_association: MEMBER
user: login: aeworxet
created_at: 2025-04-16T02:13:14Z
body: @asyncapi/bounty_team 
author_association: NONE