Wednesday, July 15, 2026 2:05:00 AM
> websocket_spec.rb
# frozen_string_literal: true

describe ESM::Websocket do
  # This test requires esm_community/esm_server
  let!(:esm_community) { create(:esm_community) }
  let!(:esm_malden) { create(:esm_malden, community_id: esm_community.id) }
  let!(:esm_malden_wsc) { WebsocketClient.new(esm_malden) }

  before do
    wait_for { esm_malden_wsc.connected? }.to be(true)
  end

  after do
    esm_malden_wsc.disconnect!
  end

  it "raises invalid key" do
    bad_ws = WebsocketClient.new(OpenStruct.new(server_key: "Nope!", server_id: "Nope!"))
    expect(bad_ws).not_to be_nil
    wait_for { bad_ws.connected? }.to be(false)
  end

  describe "Connections" do
    let!(:second_community) { create(:community) }
    let!(:second_server) { create(:server, community_id: second_community.id) }
    let!(:second_connection) { WebsocketClient.new(second_server) }

    before do
      wait_for { second_connection.connected? }.to be(true)
    end

    after do
      second_connection.disconnect!
    end

    it "adds" do
      expect(ESM::Websocket.connections[second_server.server_id]).not_to be_nil
    end

    it "removes" do
      other_connection = ESM::Websocket.connections[second_server.server_id]

      expect(other_connection).not_to be_nil
      expect { ESM::Websocket.remove_connection(other_connection) }.not_to raise_error
      expect(ESM::Websocket.connections[second_server.server_id]).to be_nil
    end
  end

  describe "#deliver!" do
    it "delivers" do
      connection = ESM::Websocket.connections[esm_malden.server_id]

      user = create(:user).discord_user
      command = ESM::Command::Test::BaseV1.new

      request = ESM::Websocket::Request.new(
        command: command,
        user: user,
        channel: nil,
        parameters: [],
        timeout: 15
      )

      ESM::Websocket.deliver!(esm_malden.server_id, request)

      # The synchronous fake processes the response immediately and clears the
      # queue, so we verify via the most-recent-request handle instead.
      expect(connection.last_request).to eq(request)
    end
  end

  describe "#on_message" do
    include_context "command" do
      let!(:command_class) { ESM::Command::Test::BaseV1 }
      let!(:community) {}
    end

    let!(:ws_connection) { ESM::Websocket.connections[esm_malden.server_id] }
    let!(:channel) { esm_community.discord_server.channels.first }

    let(:request) do
      request = ESM::Websocket::Request.new(
        command: previous_command,
        user: user,
        channel: channel,
        parameters: [],
        timeout: 15
      )

      ws_connection.requests << request
      request
    end

    before do
      execute!(
        channel: channel,
        arguments: {
          community_id: esm_community.community_id,
          server_id: esm_malden.server_id,
          target: user.discord_id,
          _integer: "1",
          _preserve: "PRESERVE",
          _display_as: "display_name",
          _default: "default"
        }
      )
    end

    # Ignored commands do not remove the request.
    it "handles ignored requests" do
      message = {
        commandID: request.id,
        ignore: true
      }.to_json

      expect(ws_connection.requests.size).to eq(1)
      ws_connection.send(:on_message, OpenStruct.new(data: message))
      expect(ws_connection.requests.size).to eq(1)
    end

    it "sends an error message (error)" do
      message = {
        commandID: request.id,
        error: Faker::Lorem.sentence
      }.to_json

      ws_connection.send(:on_message, OpenStruct.new(data: message))

      message = message.to_ostruct
      ESM.discord_bot.test_outbox.await_size(1)
      error_message = ESM.discord_bot.test_outbox.first.content

      expect(error_message).not_to be_nil
      expect(error_message.description).to eq("#{user.discord_user.mention}, #{message.error}")
      expect(error_message.color).to eq("#c62551")
    end

    it "sends an error message (parameters)" do
      message = {
        commandID: request.id,
        parameters: [{
          error: Faker::Lorem.sentence
        }]
      }.to_json

      ws_connection.send(:on_message, OpenStruct.new(data: message))

      message = message.to_ostruct
      ESM.discord_bot.test_outbox.await_size(1)
      error_message = ESM.discord_bot.test_outbox.first.content

      expect(error_message).not_to be_nil
      expect(error_message.description).to eq("#{user.discord_user.mention}, #{message.parameters.first.error}")
      expect(error_message.color).to eq("#c62551")
    end
  end
end
All opinions represented herein are my own
- © 2024 - 2026 itsthedevman
- build 43aa0d7