Coder Social home page Coder Social logo

fakexmlhttprequest's Introduction

FakeXMLHttpRequest Build Status npm version

This library provide a fake XMLHttpRequest object for testing browser-based libraries. It is partially extracted (and in many places simplified) from Sinon.JS and attempts to match the behavior of XMLHttpRequest specification.

Why not just use Sinon.JS?

Sinon includes much more than just a fake XHR object which is useful in situations where you may not need mocks, spies, stubs, or fake servers.

How to use it

In addition to matching the native XMLHttpRequest's API, FakeXMLHttpRequest adds a respond function that takes three arguments: a HTTP response status number, a headers object, and a text response body:

// simulate successful response
import FakeXMLHttpRequest from 'fake-xml-http-request';

let xhr = new FakeXMLHttpRequest();
xhr.respond(200, { 'Content-Type': 'application/json' }, '{"key":"value"}');
xhr.status; // 200
xhr.statusText; // "OK"
xhr.responseText; // '{"key":"value"}'

// simulate failed response
xhr = new FakeXMLHttpRequest();
xhr.abort();

There is no mechanism for swapping the native XMLHttpRequest or for recording, finding, or playing back requests. Libraries using FakeXMLHttpRequest should provide this behavior.

Testing

Tests are written in QUnit and run through the Karma test runner.

Run with:

karma start

Code of Conduct

In order to have a more open and welcoming community this project adheres to a code of conduct adapted from the contributor covenant.

Please adhere to this code of conduct in any interactions you have with this project's community. If you encounter someone violating these terms, please let a maintainer (@trek) know and we will address it as soon as possible.

fakexmlhttprequest's People

Contributors

alexclarkofficial avatar bantic avatar cibernox avatar cowboyd avatar dependabot[bot] avatar eventualbuddha avatar givanse avatar kturney avatar maxmurdoch avatar mike-north avatar ohcibi avatar raido avatar rwjblue avatar sandersky avatar simonihmig avatar stefanpenner avatar thejchap avatar trek avatar xg-wang avatar yamadapc avatar zeppelin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

fakexmlhttprequest's Issues

Set-Cookie Header Ignored

Is there any reason why the Set-Cookie header is being explicitly ignored here and here? I'd love to simulate a login flow with using pretender to save a faux auth cookie.

Content-Type header has ";charset=utf-8" appended to it

In the send method for non-GET and non-HEAD requests, there is some code that either sets content-type to "text/plain;charset=utf-8" (when no explicit content-type header was set) or "<existing content-type header>;charset=utf-8" (when a content-type header was explicitly set):

        if (this.requestHeaders["Content-Type"]) {
          var value = this.requestHeaders["Content-Type"].split(";");
          this.requestHeaders["Content-Type"] = value[0] + ";charset=utf-8";
        } else {
          this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
        }

The specs for xhr.send() are (imo) somewhat hard to understand, but after reading it closely it appears that the content-type header should only have a ";charset=UTF-8" string appended to it when the content-type header was not explicitly set or when it was set but with an invalid ";charset=X" value.

This xhr send test page demonstrates some of the cases (also demonstrates lots of failing tests in various browsers). The important tests there are the ones that specify "If no charset= param is given, implementation should not add one".

It seems overkill to attempt to implement the entirety of the spec for setting/changing the "Content-Type" header, but it looks like it may be more correct to change this code to:

  • Only set the content-type (with the ";charset=UTF-8" param appended) when the content-type was not explicitly specified (and only for non-GET non-HEAD requests)
  • Change "utf-8" to "UTF-8" (uppercase)

For context, this issue came up when attempting to pass through PUT requests to S3 presigned urls for uploading files directly from the browser to S3. The presigned url's signature is calculated using the file's type ("image/png", "image/jpeg", etc), and when FakeXMLHttpRequest changes the passed-through xhr's content-type header to "image/png;charset=utf-8" S3 rejects the upload because the signature no longer matches.

If this does not seem like too minor of an issue I'd be happy to make a PR with this change.

fetch + pretender.js + AbortController - does not reject fetch() with AbortError

load event fires before abort thus making impossible to use with fetch + pretender.js + AbortController to signal fetch abort().

https://github.com/pretenderjs/FakeXMLHttpRequest/blob/master/src/fake-xml-http-request.js#L305 <-- this trigger ready state change update

Which ends up here: https://github.com/pretenderjs/FakeXMLHttpRequest/blob/master/src/fake-xml-http-request.js#L382

But this it is missing "this.aborted" check and blindly dispatches "load" event.

According to spec: https://xhr.spec.whatwg.org/#event-xhr-load <-- load should be edmitted only on success.

Solution 1
So for testing purposes I wrapped "load" event dispatch into "if (!this.aborted)" and I get proper AbortedError from "fetch" and everything.

Solution 2

Move https://github.com/pretenderjs/FakeXMLHttpRequest/blob/master/fake_xml_http_request.js#L317 - before https://github.com/pretenderjs/FakeXMLHttpRequest/blob/master/fake_xml_http_request.js#L310

But this probably breaks other behaviour, ie checking readyState in your abort event callback.

XMLHttpRequest readyState not available as a static property

After window.XMLHttpRequest is replaced by the FakeXMLHttpRequest, accessing the readyState constants returns undefined (e.g. XMLHttpRequest.DONE => undefined).

It is available on the instances of XMLHttpRequest, or on FakeXMLHttpRequest, but any code that relies on XMLHttpRequest.DONE will be broken.

dataless DELETE should be allowed an empty Content-Type

Hello there,

This code is setting up a Content-Type for DELETE requests without data.

The rfc states:

A payload within a DELETE request message has no defined semantics; sending a payload body on a DELETE request might cause some existing implementations to reject the request.

From this I get that a request without a payload shouldn't have a mandatory content type.

The solution seems pretty simple, just add a delete to the regex that checks the verb used. If you agree with what I stated I can open a PR for this.

onSend not documented

I want responses to be dependent on the request, so I was looking for a way to be called when a request was made, so that I could examine the request and make the appropriate response, like any normal server-side would.

I found onSend, on this line here: https://github.com/pretenderjs/FakeXMLHttpRequest/blob/master/src/fake-xml-http-request.js#L281

Which serves the purpose quite well, however I'm forced to use it like this:

var fakeXhr = require('fake-xml-http-request');

fakeXhr.prototype.onSend = function (xhr) {
  xhr.respond(200, {'Content-Type': 'text/plain'}, 'you requested ' + xhr.method + ' ' + xhr.url);
};

The bit I'm not sure about is, simply from an API point of view, that we should be overriding a method on the prototype. Shouldn't there be a more formal (and documented) API for responding to requests like this?

I'm thinking something like, perhaps: fakeXhr.on('request', function (xhr) { ... }), and fakeXhr.off('request', ...). Or fakeXhr.onrequest = function (xhr) { ... }.

Happy to make a PR if you have a preference.

By the way, I'm planning to use this in mock-xhr-router.

`abort()` should not fire `error` event

I just noticed that in one of my tests, calling xhr.abort() fires the error event, but this does not happen in Chrome or in Safari (only fires the abort event).

Looking at the tests, it's clear that this is the intended behavior.

The way I'm interpreting the spec, it doesn't appear that abort() should fire the onerror event, but there is definitely some ambiguity I can't quite work though.

https://www.w3.org/TR/XMLHttpRequest/#the-abort()-method

Finally I noticed that this bug appears to have been fixed in sinon's FakeXMLHttpRequest implementation here: sinonjs/sinon#861.

If you agree that this behavior should be changed, let me know and I can create a PR.

Not able to karma start or run test

I am trying to do below steps and not able to start, below has the steps

  1. git clone https://github.com/pretenderjs/FakeXMLHttpRequest.git
  2. npm install
  3. karma start

Error:

08 03 2021 12:17:36.694:ERROR [karma-server]: Server start failed on port 9876: Error: No provider for "framework:qunit"! (Resolving: framework:qunit)

or

npm test

FakeXMLHttpRequest git:(master) ✗ npm test

> [email protected] test
> esperanto -i src/fake-xml-http-request.js -t umd -b -n FakeXMLHttpRequest -o fake_xml_http_request.js && ./node_modules/karma/bin/karma start --single-run --browsers PhantomJS

fs.js:52
} = primordials;
    ^

ReferenceError: primordials is not defined
    at fs.js:52:5
    at req_ (/Users/abadri/workspace/FakeXMLHttpRequest/node_modules/natives/index.js:143:24)
    at Object.req [as require] (/Users/abadri/workspace/FakeXMLHttpRequest/node_modules/natives/index.js:55:10)
    at Object.<anonymous> (/Users/abadri/workspace/FakeXMLHttpRequest/node_modules/sander/node_modules/graceful-fs/fs.js:1:37)
    at Module._compile (node:internal/modules/cjs/loader:1108:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1137:10)
    at Module.load (node:internal/modules/cjs/loader:973:32)
    at Function.Module._load (node:internal/modules/cjs/loader:813:14)
    at Module.require (node:internal/modules/cjs/loader:997:19)
    at require (node:internal/modules/cjs/helpers:92:18)
npm ERR! code 1
npm ERR! path /Users/abadri/workspace/FakeXMLHttpRequest
npm ERR! command failed
npm ERR! command sh -c esperanto -i src/fake-xml-http-request.js -t umd -b -n FakeXMLHttpRequest -o fake_xml_http_request.js && ./node_modules/karma/bin/karma start --single-run --browsers PhantomJS

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/abadri/.npm/_logs/2021-03-08T20_22_11_921Z-debug.log
➜  workspace git clone https://github.com/pretenderjs/FakeXMLHttpRequest.git
Cloning into 'FakeXMLHttpRequest'...
remote: Enumerating objects: 6, done.
remote: Counting objects: 100% (6/6), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 406 (delta 2), reused 0 (delta 0), pack-reused 400
Receiving objects: 100% (406/406), 249.39 KiB | 1.35 MiB/s, done.
Resolving deltas: 100% (212/212), done.
➜  workspace cd FakeXMLHttpRequest
➜  FakeXMLHttpRequest git:(master) npm install

added 282 packages, and audited 283 packages in 5s

40 vulnerabilities (17 low, 5 moderate, 18 high)

To address issues that do not require attention, run:
  npm audit fix

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.
➜  FakeXMLHttpRequest git:(master) ✗ karma start
zsh: command not found: karma
➜  FakeXMLHttpRequest git:(master) ✗ npm install -g karma

added 130 packages, and audited 131 packages in 3s

7 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
➜  FakeXMLHttpRequest git:(master) ✗ karma start
08 03 2021 12:17:36.694:ERROR [karma-server]: Server start failed on port 9876: Error: No provider for "framework:qunit"! (Resolving: framework:qunit)
➜  FakeXMLHttpRequest git:(master) ✗

`onloadend` event not fired

Hi @trek et al, thanks a lot for your work on this.

We recently started using pretender as part of ember-cli-mirage in our Ember app and noticed that our HLS videos are not playing correctly anymore in development.

We have a passthrough rule in our mirage config for the domain where we load our HLS manifest files from and you can see them correctly being loaded in the network pane of the Chrome devtools, but HLS.js (the library we use) is still throwing a manifestLoadTimeOut error.

Investigation indicates that HLS.js is simply not clearing its internal timeout because the onloadend event is never called for the request.

It only happens in our development environment and HLS.js just seems to have moved to using onreadystatechange (dailymotion/hls.js@55cabcf), so it is not criticial, but I wanted to report the issue anyway.

We are using mirage 0.2.1, pretender 1.1.0, and FakeXMLHttpRequest 1.4.0

Let me know if there are additional information that would be helpful for you.

withCredentials property missing

I'm using ember-cli-mirage and trying to use mapbox.js inside the project. Mapbox is doing a check for the withCredentials property for IE support:

var x = new window.XMLHttpRequest();

if (cors && !('withCredentials' in x)) {
  x = new window.XDomainRequest();
  ...
}

Because withCredentials is missing from the FakeXMLHttpRequest this fails outright. I understand Pretender.js added CORS support so would this fall inline with that?

The `response` attribute is not set when response type is `json`

When making my actual API requests to my backend server (Rails), the xhr has the response key, which is the parsed data. However the FakeXMLHttpRequest (I'm using pretender) does not have it. I originally was using the responseText property and parsing it myself, but the responses from my server don't have it.

My guess is this might also have something to do with my client xhr library (I'm using rxjs5).

But I think it makes sense to have the parsed response attribute (especially since I need it ;) ).

Hoping you'll accept a PR, gonna try and get it out tonight

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.