Coder Social home page Coder Social logo

Comments (15)

jeanabraham avatar jeanabraham commented on June 18, 2024 1

Thanks, @NeoPhi! Using the implementation directly, we are running into another issue:

  Unable to find native implementation, or alternative implementation for WebSocket!
     
     at new SubscriptionClient (node_modules/subscriptions-transport-ws/dist/client.js:20:19)
     at Object.done (src/__tests__/socket-test.js:46:5)
     at process._tickCallback (internal/process/next_tick.js:103:7)

from subscriptions-transport-ws.

jeanabraham avatar jeanabraham commented on June 18, 2024 1

@NeoPhi, thanks! The new error after passing in the WebSocket explicitly:


    TypeError: this.wsImpl is not a constructor
      
      at SubscriptionClient.Object.<anonymous>.SubscriptionClient.connect (node_modules/subscriptions-transport-ws/dist/client.js:155:23)
      at new SubscriptionClient (node_modules/subscriptions-transport-ws/dist/client.js:36:14)
      at Object.done (src/__tests__/socket-test.js:46:5)

from subscriptions-transport-ws.

jeanabraham avatar jeanabraham commented on June 18, 2024

Just to add to @jayhuang75 comments, we are using Jest for our unit testing. We tried creating a simple test based on the unittest code that comes with the package within our test suite:


import * as WebSocket from 'ws';
import { SubscriptionServer, SubscriptionClient, addGraphQLSubscriptions } from 'subscriptions-transport-ws';
import {createServer, IncomingMessage, ServerResponse} from 'http';

const RAW_TEST_PORT = 8091;

const httpServerRaw = createServer(notFoundRequestListener);
httpServerRaw.listen(RAW_TEST_PORT);

Object.assign(global, {
  WebSocket: WebSocket,
});

function notFoundRequestListener(request: IncomingMessage, response: ServerResponse) {
  response.writeHead(404);
  response.end();
}

describe('Client', function () {

    let wsServer: WebSocket.Server;

    beforeEach(() => {
      wsServer = new WebSocket.Server({
        server: httpServerRaw,
      });
    });

    afterEach(() => {
      if (wsServer) {
        wsServer.close();
      }
    });

    it('should send INIT message when creating the connection', (done) => {
      wsServer.on('connection', (connection: any) => {
        connection.on('message', (message: any) => {
          const parsedMessage = JSON.parse(message);
          expect(parsedMessage.type).to.equals('init');
          done();
        });
      });

      new SubscriptionClient(`ws://localhost:${RAW_TEST_PORT}/`);
    });
  });

Fails with:

 FAIL  src/__tests__/socketTest.js
  ● Client › should send INIT message when creating the connection

    TypeError: _subscriptionsTransportWs.SubscriptionClient is not a constructor
      
      at Object.done ( src/__tests__/socketTest.js:44:5)
      at process._tickCallback (internal/process/next_tick.js:103:7)

from subscriptions-transport-ws.

NeoPhi avatar NeoPhi commented on June 18, 2024

The workaround for the time being is to use:
import {SubscriptionClient, addGraphQLSubscriptions} from 'subscriptions-transport-ws/dist/client';

from subscriptions-transport-ws.

NeoPhi avatar NeoPhi commented on June 18, 2024

You'll need to use the optional 3rd argument to the SubscriptionClient to specify the WebSocket implementation it should use. Something like this (untested) should work:

import WebSocket from 'ws';
import {SubscriptionClient, addGraphQLSubscriptions} from 'subscriptions-transport-ws/dist/client';
new SubscriptionClient('url', {}, WebSocket);

from subscriptions-transport-ws.

jeanabraham avatar jeanabraham commented on June 18, 2024

@NeoPhi, yep, had already tried that without luck:

 new SubscriptionClient(`ws://localhost:${RAW_TEST_PORT}/`, {
        reconnect: true,
        connectionParams: {
        }, WebSocket
      });

None of the unit tests for the library seem to require these optional parameters though.

I would think the below statement in the unit test should ensure that SubscriptionClient#Line6 get a WebSocket definition when it is looking for one.

Object.assign(global, {
  WebSocket: WebSocket,
});

from subscriptions-transport-ws.

NeoPhi avatar NeoPhi commented on June 18, 2024

In your code sample you have the WebSocket within the options argument, it is a separate 3rd argument being passed to the SubscriptionClient.

The unit tests work since they explicitly import the client after ensuring that the global WebSocket reference is installed. I find that approach fragile as it is non-obvious and depending on the transpiler you are using may get reordered so prefer to pass in the implementation explicitly.

from subscriptions-transport-ws.

NeoPhi avatar NeoPhi commented on June 18, 2024

The import should be import WebSocket from 'ws'; instead of import * as WebSocket from 'ws';

from subscriptions-transport-ws.

jeanabraham avatar jeanabraham commented on June 18, 2024

Thanks for your help, @NeoPhi! It works now.

For reference, these were the required changes to get things working:

  1. Use SubscriptionClient implementation directly instead of interface.
    import {SubscriptionClient, addGraphQLSubscriptions} from 'subscriptions-transport-ws/dist/client';

  2. Pass in WebSocket object when invoking SubscriptionClient constructor.

 new SubscriptionClient(`ws://localhost:${RAW_TEST_PORT}/`, {
        reconnect: true,
        connectionParams: {
        }
      }, WebSocket);
  1. Use import WebSocket from 'ws'; instead of import * as WebSocket from 'ws';

from subscriptions-transport-ws.

jayhuang75 avatar jayhuang75 commented on June 18, 2024

Thanks for the help @jeanabraham @NeoPhi I follow the steps and yes the unit testing is pass. But once Im on the step 2, pass in WebSocket object
new SubscriptionClient(ws://localhost:${RAW_TEST_PORT}/, { reconnect: true, connectionParams: { } }, WebSocket);
the application is break with one warning. (can not receiving any websocket data no more)
./~/bindings/bindings.js Critical dependencies: 76:22-40 the request of a dependency is an expression 76:43-53 the request of a dependency is an expression @ ./~/bindings/bindings.js 76:22-40 76:43-53

And just for your information the GraphQL websocket server is running and once I remove the WebSocket object from the SubscriptionClient constructor, everything is back to normal, but the unit testing fail because of this reason
`
Unable to find native implementation, or alternative implementation for WebSocket!

 at new SubscriptionClient (node_modules/subscriptions-transport-ws/dist/client.js:20:19)
 at Object.done (src/__tests__/socket-test.js:46:5)
 at process._tickCallback (internal/process/next_tick.js:103:7)`

from subscriptions-transport-ws.

Urigo avatar Urigo commented on June 18, 2024

@jayhuang75 , looks like there were few issues here.

  1. that fact that you couldn't import subscriptionClient for test on Node.
    This was fixed in the latest release (0.5.4).
    Now you can just do import {SubscriptionClient, addGraphQLSubscriptions} from 'subscriptions-transport-ws'.

  2. In Node environment (where the tests run), you don't have native WebSockets implementation, so you have to use an alternative in the following format: import * as WebSocket from 'ws';
    You can either assign it to the global like @jeanabraham pointed out:

Object.assign(global, {
  WebSocket: WebSocket,
});

or you can pass the external websocket to subscriptionClient constructor as a third param like @NeoPhi has pointed out:
new SubscriptionClient('url', {}, WebSocket);

But as for your last comment, remember to close the websocket connection after each test. that might be related to your last problem.

To check out how we close that you can look at our tests file here: https://github.com/apollographql/subscriptions-transport-ws/blob/master/src/test/tests.ts#L213-L217

Please let me know it that solved your problems and we can close that issue

from subscriptions-transport-ws.

jayhuang75 avatar jayhuang75 commented on June 18, 2024

from subscriptions-transport-ws.

jayhuang75 avatar jayhuang75 commented on June 18, 2024

@Urigo I follow your recommendation. The only weird issues is once I add the WebSocket to my subscriptionClient constructor
const wsClient = new SubscriptionClient("ws://my-webscoket-url", { reconnect: true, reconnectionAttempts: 1, connectionParams: { // Pass any arguments you want for initialization }, }, WebSocket);
and the Request URL will replace my url
ws://my-webscoket-url by the
ws://localhost:3000/sockjs-node/393/vdcpziqp/websocket
and my WebSocket implementation break.

Any idea?

from subscriptions-transport-ws.

Urigo avatar Urigo commented on June 18, 2024

@jayhuang75 , when exactly do you notice that the URL changes? after the socket initialized?
Also, do you use ws package as client, right?

from subscriptions-transport-ws.

dotansimha avatar dotansimha commented on June 18, 2024

Closing for now. A lot has changed since this issue was opened.
@jayhuang75 if this issue is still relevant, please re-open or create a new issue.

from subscriptions-transport-ws.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.