Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(api) allow overriding what kind of request is constructed #134

Closed
wants to merge 1 commit into from
Closed

Conversation

mbark
Copy link

@mbark mbark commented Dec 8, 2017

First of all I just wanted to say that when going through the code it is very legible and well-written!

Background

We use jest to test our angular application and want to introduce pact-testing for the frontend-backend-communication. However, we run into the following problem:

  • In order to run angular we need to have our environment set to jsdom due to zone.js patching XMLHttpRequest etc;
  • In order to run pact we need to have our environment set to node (see mockServer does not start() #10 for further discussion and background).

I modified the code so that we always used node-style requests (ignoring environment checks) which got it working for us. With that in mind I thought it might be possible to add an ability to override the default behaviour, allowing us in scenarios such as these to run in the jsdom environment but tell pact to use node-style requests.

System solution

This feature introduces an optional map of values to give when setting up the pact server. For now these options only contain one possible key: environment. The environment option can be used to force pact to use either a node-style request or a web-style request.

As part of this I also added xhr-mock and the ability to mock the window, which allowed running the test for Request preferring the XMLHttpRequest object.

If you think this is a good solution to go ahead with I can improve the tests a bit and document this new functionality in the readme.

@coveralls
Copy link

Coverage Status

Coverage increased (+1.1%) to 92.808% when pulling 3b05da0 on mbark:master into 9ca25de on pact-foundation:master.

1 similar comment
@coveralls
Copy link

coveralls commented Dec 8, 2017

Coverage Status

Coverage increased (+1.1%) to 92.808% when pulling 3b05da0 on mbark:master into 9ca25de on pact-foundation:master.

@mefellows
Copy link
Member

Hi @mbark, i'm so sorry for the delay in responding to this. Not sure how it didn't get on my radar (perhaps when I was on parental leave I saw it but didn't respond - crazy time), but in any case let's get into it and thanks for the kind words!

OK so if I understand correctly, the root cause of your problem is this line: if (typeof XMLHttpRequest === "function" || typeof window !== "undefined") {.

Because you are patching with libraries, this statement will never reflect the "true" environment and the pact library may not behave as expected, so we want to maintain complete control if possible, or default to the current behaviour if the user doesn't specify a preference?

In theory, I support this change.

In terms of implementation, here are my additional thoughts:

  • The assumption is that this functionality is not covered by either the pact (designed for node environments) orpact-web module (designed for non-node/browser environments)
  • Where possible, maintain backwards compatibility in types - I'd prefer not to bump a major version for this feature, so any new parameters must be optional in any public signatures/constructors, or optional in existing types (e.g. PactOptions)
  • Rather than have a separate parameter to the Pact constructor, add environment as an optional property in the PactOptionstype (instead of AdditionalOptions).
  • The use of xhr-mock is 👍

@mbark
Copy link
Author

mbark commented Jan 8, 2018

I rebased it against master and will go through your comments later today (or at the very latest this week).

@coveralls
Copy link

coveralls commented Jan 9, 2018

Coverage Status

Coverage increased (+1.5%) to 93.08% when pulling 1dbcff0 on mbark:master into 0ad8f57 on pact-foundation:master.

@mbark
Copy link
Author

mbark commented Jan 9, 2018

I added environment to PactOptions and made it optional. I also added it to the table describing the PactOptions parameters. Not entirely sure about the phrasing there to make it most clear how it works though.

Maybe you could take a look and see what you think?

It also seems like travis broke when installing node 8, which is not really related to what I have done at all. The other node versions work and so does 8, that was the version I tested against locally. (I'll try re-triggering the build to hopefully resolve it)

@coveralls
Copy link

coveralls commented Jan 9, 2018

Coverage Status

Coverage increased (+1.5%) to 93.08% when pulling 16eeb75 on mbark:master into 0ad8f57 on pact-foundation:master.

This feature introduces an optional map of values to give when setting up the
pact server. For now these options only contain one possible key, which is
'environment'.

The environment option can be used to force pact to use either a node-style
request or a web-style request.
@coveralls
Copy link

coveralls commented Jan 10, 2018

Coverage Status

Coverage increased (+1.5%) to 93.08% when pulling 1778a80 on mbark:master into 0ad8f57 on pact-foundation:master.

@mefellows
Copy link
Member

Thanks @mbark, I'll look into this over the weekend but on first glance it looks promising!

@mefellows
Copy link
Member

Added @mboudreau for his thoughts on this change also.

@mbark
Copy link
Author

mbark commented Jan 26, 2018

@mefellows is there any progress on getting this merged? Or anything more I can do to help getting it merged? :)

@mboudreau
Copy link
Contributor

mboudreau commented Jan 28, 2018 via email

@mboudreau
Copy link
Contributor

@mbark Thanks for your PR. I had a bit of a look and it looks mostly good except for a few opinionated things that I have, but before I want to get into that, I'm trying to understand your scenario better so that we can make the best call possible for the library and our users.

From what I understand (correct me where I'm wrong), but you want to run pact with your jest tests, but because of your environment setup, Request is confusing which actual environment it's in (web vs node) and causing some issues when the requests are actually built. You've found a workaround for now, but it isn't elegant.

I don't know jest that well, so I'm guessing it's a node based testing solution for React, but you want it to run for angular, hence the need to "fake" the environment with jsdom, causing the issue in the first place.

I want to try out a few solutions to see what works best in development. Do you have a very small sample project you can setup using your same scenario, that way I can test out to make sure it works for everyone.

Thanks. I promise that we'll find something that works for everyone :)

@mbark
Copy link
Author

mbark commented Jan 29, 2018

@mboudreau Regarding opinions about the code structure/names etc I'm all for you just making the changes you want to -- I'm interested in getting the feature merged, not the exact implementation of it. We can take that later though!

When it comes to your understanding of the problem I'd say that it is correct and I'll try to take some time later today to re-create our problem.

@mbark
Copy link
Author

mbark commented Jan 29, 2018

@mboudreau I have reproduction at: https://github.com/mbark/pact-jest

Run yarn jest --projects jest/test.config.js to run the tests (both pact and the dummy app.spec one). This should give you the error:


    console.error node_modules/jsdom/lib/jsdom/virtual-console.js:29
      Error: Error: connect ECONNREFUSED 127.0.0.1:1234
          at Object.dispatchError (/Users/martin.barksten/repos/pact-jest/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:65:19)
          at EventEmitter.client.on.err (/Users/martin.barksten/repos/pact-jest/node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:664:20)
          at EventEmitter.emit (events.js:164:20)
          at Request.preflightClient.on.err (/Users/martin.barksten/repos/pact-jest/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:409:47)
          at Request.emit (events.js:159:13)
          at Request.onRequestError (/Users/martin.barksten/repos/pact-jest/node_modules/request/request.js:878:8)
          at ClientRequest.emit (events.js:159:13)
          at Socket.socketErrorListener (_http_client.js:389:9)
          at Socket.emit (events.js:159:13)
          at emitErrorNT (internal/streams/destroy.js:64:8) undefined

If you then edit node_modules/@pact-foundation/pact/common/request.js and change:

  • typeof XMLHttpRequest === 'function' || typeof window !== 'undefined' to false;
  • typeof window === 'undefined' to true (both in the constructor and the send method).

Both tests should pass. You can also try setting @jest-environment node in the pact.spec.ts file to see the error when running in node rather than jsdom mode.

Hopefully that works as a simple reproduction of the problem :)

@mboudreau
Copy link
Contributor

mboudreau commented Jan 29, 2018 via email

@mboudreau
Copy link
Contributor

@mbark Hey man, I'm looking into using an external library that would handle both node/browser requests called Popsicle. I just tested it using your example project (gj on that btw) which seems to fix the issue. I'm going to add it to the codebase and create a new PR for it and close this one once it's gone through. Cheers and thanks for the help :)

@mboudreau
Copy link
Contributor

@mbark I've create a new PR with my proposed changes, let me know what you think #147

@mefellows
Copy link
Member

mefellows commented Feb 20, 2018

Thanks for this @mbark, really appreciate you taking the time with this PR. Will be closing this in favour of #147, however.

@mefellows mefellows closed this Feb 20, 2018
mefellows pushed a commit that referenced this pull request Feb 25, 2018
chore(request): make Request class work across both Node and Browser using Popsicle

Includes a number of changes and tidying ups:

* Add 'exit' flag to mocha to exit properly after tests are done
* Update superagent dependency
* Update dependencies for karma-pact to fix issue with peer dependencies
* Update standard version, make sure the ignore glob is correct
* Fix Mocha registering ts-node twice
* Update nock to 9.1.x and fix tests
* Update lock file for e2e tests
* Adding union type for http methods to gradually change to the enum

See #134 and #10 for background.
mefellows pushed a commit that referenced this pull request Feb 25, 2018
…using Popsicle

Includes a number of changes and tidying ups:

* Add 'exit' flag to mocha to exit properly after tests are done
* Update superagent dependency
* Update dependencies for karma-pact to fix issue with peer dependencies
* Update standard version, make sure the ignore glob is correct
* Fix Mocha registering ts-node twice
* Update nock to 9.1.x and fix tests
* Update lock file for e2e tests
* Adding union type for http methods to gradually change to the enum

See #134 and #10 for background.
blackbaud-joshlandi pushed a commit to blackbaud-joshlandi/pact-js that referenced this pull request Mar 2, 2018
…using Popsicle

Includes a number of changes and tidying ups:

* Add 'exit' flag to mocha to exit properly after tests are done
* Update superagent dependency
* Update dependencies for karma-pact to fix issue with peer dependencies
* Update standard version, make sure the ignore glob is correct
* Fix Mocha registering ts-node twice
* Update nock to 9.1.x and fix tests
* Update lock file for e2e tests
* Adding union type for http methods to gradually change to the enum

See pact-foundation#134 and pact-foundation#10 for background.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants