Esta biblioteca é uma simulação de XMLHttpRequest
que fornece uma interface simples para simular interações com XMLHttpRequest
. É um substituto imediato para XMLHttpRequest
para seus testes.
Esta biblioteca implementa a interface XMLHttpRequest
e trata solicitações e eventos conforme especificado na especificação XMLHTTPRequest sem usar solicitações de rede reais. Você pode responder às solicitações simuladas de três maneiras:
Você pode simular respostas, fazer upload de progresso, erros e outras interações com os métodos de resposta simulada. Eles lidam automaticamente com o processamento de nível inferior, como a emissão de eventos e a alteração da propriedade readystate
de XMLHttpRequest
.
MockXhr
programaticamentetimeout
e os tempos limite de solicitaçãoMockXhr
MockXhrServer
MockXhrServer
MockXhr
MockXhr
MockXhrRequest
newMockXhr()
newServer()
XMLHttpRequest
via npm (gerenciador de pacotes de nó)
$ npm install mock-xmlhttprequest
import { newServer } from 'mock-xmlhttprequest' ;
import { functionToTest } from '../src/SomethingToTest' ;
// Adapt based on your testing framework. This example uses Mocha and Chai's syntax.
it ( 'should produce a success response' , async ( ) => {
const server = newServer ( {
get : [ '/my/url' , {
// status: 200 is the default
headers : { 'Content-Type' : 'application/json' } ,
body : '{ "message": "Success!" }' ,
} ] ,
} ) ;
try {
// Installs the server's XMLHttpRequest mock in the "global" context.
// After this, "new XMLHttpRequest()" creates a mock request to which the server replies.
server . install ( /* optional context; defaults to globalThis */ ) ;
// Do something that send()s an XMLHttpRequest to '/my/url' and returns a Promise
// that resolves to the parsed JSON response
const result = await functionToTest ( ) ;
assert . equal ( result . message , 'Success!' ) ;
} finally {
// Restore the original XMLHttpRequest
server . remove ( ) ;
}
} ) ;
A classe simulada XMLHttpRequest
é MockXhr
. Ele expõe a mesma interface que XMLHttpRequest
e é um substituto imediato para testar o código que usa XMLHttpRequest
.
Existem duas opções para controlar o comportamento das instâncias MockXhr
:
XMLHttpRequest
. Use isto se precisar de mais controle sobre as solicitações sem os recursos fornecidos pelo servidor simulado. A classe MockXhrServer
implementa o servidor simulado. Você cria um MockXhrServer
com newServer
. O MockXhrServer
responde automaticamente às solicitações MockXhr
e facilita a escrita de testes.
A estrutura básica dos testes que utilizam MockXhrServer
é:
import { newServer } from 'mock-xmlhttprequest' ;
const server = newServer ( /* routes */ ) ;
try {
server . install ( /* optional context; defaults to globalThis */ ) ;
// Test your code that creates XMLHttpRequests
} finally {
// Reverts server.install() at the end of the test.
// Only do this after the test case has finished creating XMLHttpRequests.
server . remove ( ) ;
}
Existem duas abordagens para fazer seu código usar a classe MockXhr
como um substituto para XMLHttpRequest
. Isso permite que o MockXhrServer
responda às solicitações:
install()
para substituir globalmente a classe XMLHttpRequest
pela classe MockXhr
do servidor. No final do caso de teste, chame remove()
para restaurar o estado original.XMLHttpRequest
, use a classe MockXhr
diretamente com uma das seguintes propriedades MockXhrServer
:xhrFactory
é uma função que cria uma instância MockXhr
.MockXhr
é a classe das instâncias criadas por xhrFactory
. Este código demonstra o uso de xhrFactory
:
import { newServer } from 'mock-xmlhttprequest' ;
const server = newServer ( /* routes */ ) ;
const savedFactory = MyClass . xhrFactory ;
try {
MyClass . xhrFactory = server . xhrFactory ;
// Test code that creates XMLHttpRequests through MyClass.xhrFactory()
} finally {
// Only do this after the test case has finished creating XMLHttpRequests.
MyClass . xhrFactory = savedFactory ;
}
As rotas definem como o MockXhrServer
responde às solicitações MockXhr
. Estes têm três partes:
Quando você envia uma solicitação MockXhr
, o MockXhrServer
encontra a primeira rota que corresponde ao método e URL da solicitação. Em seguida, ele responde com o manipulador de solicitações da rota. Você também pode definir um manipulador de solicitação padrão. Os manipuladores de solicitações são definidos de forma declarativa ou programática.
Por padrão, se o atributo timeout
de uma solicitação for definido com um valor diferente de zero e MockXhrServer
não responder à solicitação, ele eventualmente expirará.
Existem duas maneiras de adicionar rotas ao MockXhrServer
:
routes
do newServer
.MockXhrServer
que adicionam rotas. O MockXhrServer
registra todas as solicitações MockXhr
que recebe em um log de solicitações. Use isto para validar as solicitações XMLHttpRequest
que seu código envia.
O MockXhrServer
pode gerar eventos de progresso de solicitação (upload) e resposta (download) automaticamente. Isso está desabilitado por padrão. Use o campo progressRate
para habilitar isso.
Você também pode gerar eventos de progresso se responder às solicitações MockXhr
programaticamente com um manipulador de solicitações do tipo Function
.
As respostas às solicitações MockXhr
são assíncronas. Isso reproduz como funciona uma solicitação XMLHttpRequest
real. Portanto, você provavelmente precisará usar o suporte de teste assíncrono da sua estrutura de teste. Por exemplo, a documentação relevante para a estrutura de teste Mocha está aqui.
O gancho do ciclo de vida onSend
é necessário para responder às solicitações MockXhr
. O servidor simulado lida com isso automaticamente. A outra opção é usar os ganchos do ciclo de vida MockXhr
diretamente. Em ambos os casos, o gancho do ciclo de vida onSend
é executado após o contexto de execução que chama XMLHttpRequest.send()
ser concluído ou limpo. Internamente, esta biblioteca usa uma Promise
resolvida imediatamente para obter uma pilha de chamadas vazia.
MockXhr
programaticamente Existem vários métodos e propriedades MockXhr
para responder às solicitações. Esses métodos permitem as seguintes interações:
Consulte a seção Métodos de resposta simulados para obter detalhes.
timeout
e os tempos limite de solicitação Por padrão, se você definir o atributo timeout
de XMLHttpRequest
em seu código, as solicitações MockXhr
expirarão automaticamente após o atraso especificado. Isso emite o evento timeout
e cancela a solicitação conforme descrito na especificação.
Depender da passagem do tempo para testar como seu código lida com os tempos limite geralmente torna os testes frágeis e difíceis de depurar. Em vez disso, você pode acionar tempos limite programaticamente com setRequestTimeout()
.
Desative os tempos limite de solicitação automática com uma destas opções:
disableTimeout()
em um MockXhrServer
. Isso afeta todas as instâncias MockXhr
que ele gerencia.MockXhr.timeoutEnabled = false
. Esta propriedade estática na classe MockXhr
afeta cada uma de suas instâncias.timeoutEnabled
como false
em uma instância MockXhr
. Isso afeta apenas essa instância.MockXhr
Este é um padrão de uso alternativo que não usa o MockXhrServer
. Em vez disso, você usa os ganchos do ciclo de vida MockXhr
diretamente. Isso requer mais código, mas você tem mais controle sobre as solicitações MockXhr
.
Observe que você também pode usar os ganchos do ciclo de vida MockXhr
junto com MockXhrServer
se precisar apenas estender o servidor simulado.
Exemplo:
import { newMockXhr } from 'mock-xmlhttprequest' ;
import { functionToTest } from '../src/SomethingToTest' ;
// Adapt based on your testing framework. This example uses Mocha and Chai's syntax.
it ( 'should produce a success response' , async ( ) => {
// Get a "local" MockXhr subclass
const MockXhr = newMockXhr ( ) ;
// Mock JSON response
MockXhr . onSend = ( request ) => {
const responseHeaders = { 'Content-Type' : 'application/json' } ;
const response = '{ "message": "Success!" }' ;
request . respond ( 200 , responseHeaders , response ) ;
} ;
try {
// Install in the global context so "new XMLHttpRequest()" creates MockXhr instances
global . XMLHttpRequest = MockXhr ;
// Do something that send()s an XMLHttpRequest to '/my/url' and returns a Promise
// that resolves to the parsed JSON response
const result = await functionToTest ( ) ;
assert . equal ( result . message , 'Success!' ) ;
} finally {
// Restore the original XMLHttpRequest
delete global . XMLHttpRequest ;
}
} ) ;
MockXhrServer
Esta classe é um servidor simulado que responde às solicitações MockXhr
com base em sua URL e método.
MockXhrServer
MockXhrServer(routes)
Argumentos:
routes
: Objeto com o conjunto inicial de rotas do servidor. (opcional) Na maioria dos casos você deve usar newServer
em vez deste construtor diretamente.
As chaves do objeto routes
são métodos HTTP. Os valores são arrays com dois elementos: [url_matcher, request_handler]
.
Consulte também Correspondente de URL de solicitação e Manipulador de solicitação.
Exemplo:
const handlerFn = ( request ) => { request . respond ( ) ; } ;
newServer ( {
get : [ '/get' , { status : 200 } ] ,
'my-method' : [ '/my-method' , { status : 201 } ] ,
post : [ '/post' , [ handlerFn , { status : 404 } ] ] ,
} ) ;
install(context = globalThis)
Argumentos:
context
: se você fornecer um valor, o método install
definirá a propriedade XMLHttpRequest
neste contexto em vez do contexto global. (opcional) Instala a simulação MockXhr
do servidor no contexto global para substituir a classe XMLHttpRequest
. Reverta com remove().
remove()
Reverte as alterações feitas por install(). Chame isso após seus testes.
progressRate
Se você definir progressRate
como um number
maior que 0, o servidor gerará automaticamente eventos de progresso de solicitação (upload) e resposta (download). Cada evento de progresso é incrementado em bytes progressRate
.
progressRate
se aplica apenas a manipuladores de solicitação do tipo object
.
disableTimeout()
e enableTimeout()
Esses métodos desabilitam ou habilitam os efeitos do atributo timeout
de MockXhr
. Consulte "O atributo timeout
e os tempos limite de solicitação".
As rotas configuram como o servidor responde às solicitações MockXhr
. Suas três partes são descritas abaixo.
O conceito de rota é vagamente baseado na estrutura Express.
Qualquer string
com um método de solicitação HTTP válido é permitida. Os métodos válidos incluem métodos padrão como GET
, POST
, PUT
e DELETE
, bem como outros nomes de métodos. Os nomes dos métodos padrão não diferenciam maiúsculas de minúsculas.
A correspondência de URL de solicitação pode ser de um destes tipos:
string
(por exemplo '/my-url'
) para corresponder exatamente ao URL da solicitação.RegExp
para corresponder ao URL da solicitação.Function
que retorna true
se o URL da solicitação corresponder. A função recebe a URL como argumento. O manipulador de solicitação pode ser um destes tipos:
Um object
com as propriedades de resposta. Os valores padrão são:
{ status: 200, headers: {}, body: null, statusText: 'OK' }
Uma Function
que chama diretamente os métodos de resposta simulada. A função recebe uma instância MockXhrRequest
como argumento.
Uma string
com o valor 'error'
ou 'timeout'
. Isso aciona um erro ou tempo limite, respectivamente.
Uma matriz dos outros tipos de manipuladores de solicitação acima. A primeira solicitação recebe o primeiro manipulador, a segunda recebe o segundo manipulador e assim por diante. O último manipulador é reutilizado quando não há mais manipuladores no array.
Para manipuladores de solicitação object
, o servidor adiciona automaticamente o cabeçalho de resposta Content-Length
ao comprimento do corpo da resposta.
Todos esses manipuladores são equivalentes:
const handlerObj = { } ;
const handlerFn = ( request ) => { request . respond ( 200 , { 'Content-Length' : '0' } ) ; } ;
const handlerArray = [ { } ] ;
get(urlMatcher, handler)
Argumentos:
urlMatcher
: Solicita correspondência de URL.handler
: manipulador de solicitação. Adiciona uma rota para o método GET
HTTP.
post(urlMatcher, handler)
Argumentos:
urlMatcher
: Solicita correspondência de URL.handler
: manipulador de solicitação. Adiciona uma rota para o método POST
HTTP.
put(urlMatcher, handler)
Argumentos:
urlMatcher
: Solicita correspondência de URL.handler
: manipulador de solicitação. Adiciona uma rota para o método PUT
HTTP.
delete(urlMatcher, handler)
Argumentos:
urlMatcher
: Solicita correspondência de URL.handler
: manipulador de solicitação. Adiciona uma rota para o método DELETE
HTTP.
addHandler(method, urlMatcher, handler)
Argumentos:
method
: método HTTP como uma string
.urlMatcher
: Solicita correspondência de URL.handler
: manipulador de solicitação. Adiciona uma rota para o method
HTTP.
setDefaultHandler(handler)
Argumentos:
handler
: manipulador de solicitação.Define um manipulador de solicitações padrão para solicitações que não correspondem a nenhuma rota.
setDefault404()
Define um manipulador de solicitação padrão que retorna respostas 404.
xhrFactory
Função que retorna uma nova instância MockXhr
.
MockXhr
A classe MockXhr
à qual o servidor se conecta. xhrFactory
cria instâncias desta classe.
getRequestLog()
Retorna uma matriz de todas as solicitações recebidas pelo servidor até o momento. Cada chamada retorna um novo array. Cada elemento da matriz é um objeto com estas propriedades:
method
: string
do método HTTP.url
: string
de URL.body
: corpo da solicitaçãoheaders
: solicita cabeçalhos como um objeto. Os nomes dos cabeçalhos estão em letras minúsculas.MockXhr
Esta classe é uma simulação de XMLHttpRequest
. Esta seção documenta seus métodos e propriedades que não estão na especificação.
MockXhr.timeoutEnabled
Esta propriedade boolean
estática controla o tempo limite automático de solicitações de todas as instâncias da classe.
timeoutEnabled
Esta propriedade boolean
controla o tempo limite automático desta instância MockXhr
.
getResponseHeadersHash()
Retorna todos os cabeçalhos de resposta como um objeto. Os nomes dos cabeçalhos estão em letras minúsculas.
MockXhr
Você pode definir métodos de retorno de chamada para os ganchos do ciclo de vida MockXhr
nestes locais:
MockXhr
. O gancho se aplica a todas as instâncias do MockXhr
e de suas subclasses.MockXhr
retornada por MockXhrServer.MockXhr
ou newMockXhr()
. O gancho se aplica a todas as instâncias dessa classe.MockXhr
. O gancho se aplica apenas a essa instância.Se você definir vários ganchos para um evento de ciclo de vida, eles serão chamados na ordem acima.
Geralmente, você deve preferir a terceira opção, que facilita o isolamento de seus casos de teste.
onCreate
Método de retorno de chamada que recebe estes argumentos:
xhr
: Nova instância MockXhr
. Use este gancho de ciclo de vida para interceptar instâncias do MockXhr
quando elas forem construídas.
Chamado quando uma instância do MockXhr
é criada, no final do seu construtor. Portanto, esse gancho de ciclo de vida está disponível apenas como uma propriedade estática.
import { MockXhr , newMockXhr } from 'mock-xmlhttprequest' ;
// Called for all instances of MockXhr and all its subclasses
MockXhr . onCreate = ( xhr ) => { /*...*/ } ;
// Called for all instances of this MockXhr subclass
const MockXhrSubclass = newMockXhr ( ) ;
MockXhrSubclass . onCreate = ( xhr ) => { /*...*/ } ;
onSend
Método de retorno de chamada que recebe estes argumentos:
request
: MockXhrRequest
para a solicitação.xhr
: a instância MockXhr
.Use este gancho de ciclo de vida para responder a uma solicitação com métodos de resposta simulados.
Chamado de forma assíncrona após cada chamada para send()
. Cada chamada para send()
gera uma chamada para onSend
com uma instância separada de MockXhrRequest
.
import { MockXhr , newMockXhr } from 'mock-xmlhttprequest' ;
// Called for all instances of MockXhr and all its subclasses
MockXhr . onSend = ( request ) => { /*...*/ } ;
// Called for all instances of this MockXhr subclass
const MockXhrSubclass = newMockXhr ( ) ;
MockXhrSubclass . onSend = ( request ) => { /*...*/ } ;
// Called for this instance only
const xhr = new MockXhrSubclass ( ) ;
xhr . onSend = ( request ) => { /*...*/ } ;
MockXhrRequest
Cada chamada para send()
cria um MockXhrRequest
que contém informações sobre o XMLHttpRequest
e fornece métodos para responder programaticamente.
requestHeaders
Um HeadersContainer
que contém uma cópia dos cabeçalhos da solicitação.
method
Uma string
com o método HTTP da solicitação.
url
Uma string
com o URL da solicitação.
body
O corpo da solicitação.
withCredentials
Um boolean
com o valor withCredentials
da solicitação.
getRequestBodySize()
number
de bytes no corpo da solicitação.
Nota: isso não é totalmente preciso quando o body
é um FormData
codificado multipart/form-data
. Cabeçalhos, codificação e outros fatores que contribuem para o tamanho real body
de um XMLHttpRequest
não simulado não são considerados. Você pode usar esse método para obter um valor mínimo para o tamanho real body
da solicitação. Isto é útil para simular eventos de progresso de upload.
Esses métodos fornecem uma interface programática para responder às solicitações MockXhr
.
Se uma chamada para um método de resposta for inválida, ela gerará um Error
com uma mensagem que contém "Mock usage error detected"
.
uploadProgress(transmitted)
Argumentos:
transmitted
: number
de bytes transmitidos.Dispara um progresso de upload de solicitação.
Você só pode chamar isso quando o body
da solicitação não for null
e o upload não estiver concluído.
Depois de chamar esse método, você poderá usar qualquer outro método de resposta simulada.
respond(status = 200, headers = {}, body = null, statusText = 'OK')
Argumentos:
status
: number
de status HTTP da resposta. (opcional)headers
: object
com os cabeçalhos de resposta. (opcional)body
: Corpo de resposta. (opcional)statusText
: texto de status HTTP de resposta string
. (opcional) Método de resposta completo que define os cabeçalhos e o corpo da resposta. Altera o readyState
da solicitação para DONE
.
Dispara os eventos apropriados, como readystatechange
, progress
e load
.
Este é um atalho para setResponseHeaders()
seguido por setResponseBody()
.
Depois de chamar esse método, você não poderá usar outros métodos de resposta simulados. Esta restrição será suspensa se você chamar open()
novamente.
setResponseHeaders(status = 200, headers = {}, statusText = 'OK')
Argumentos:
status
: number
de status HTTP da resposta. (opcional)headers
: object
com os cabeçalhos de resposta. (opcional)statusText
: texto de status HTTP de resposta string
. (opcional) Define os cabeçalhos de resposta. Altera o readyState
da solicitação para HEADERS_RECEIVED
.
Dispara os eventos apropriados, como readystatechange
, progress
e load
.
Depois de chamar esse método, você poderá usar os seguintes métodos de resposta simulada:
downloadProgress()
setResponseBody()
setNetworkError()
setRequestTimeout()
. downloadProgress(transmitted, length)
Argumentos:
transmitted
: number
de bytes transmitidos.length
: number
de bytes na resposta. Dispara um evento de progresso de resposta. Altera o readyState
da solicitação para LOADING
se for HEADERS_RECEIVED
.
Você deve chamar setResponseHeaders()
antes deste método.
setResponseBody(body = null)
Argumentos:
body
: Corpo de resposta. (opcional) Define o corpo da resposta. Altera o readyState
da solicitação para DONE
.
Dispara os eventos apropriados, como readystatechange
, progress
e load
.
Chama setResponseHeaders()
se ainda não foi chamado. Os cabeçalhos de resposta contêm apenas Content-Length
com um valor igual ao comprimento do corpo da resposta.
Depois de chamar esse método, você não poderá usar outros métodos de resposta simulados. Esta restrição será suspensa se você chamar open()
novamente.
setNetworkError()
Simula um erro de rede. Altera o readyState
da solicitação para DONE
.
Dispara os eventos apropriados, incluindo o evento error
.
Depois de chamar esse método, você não poderá usar outros métodos de resposta simulada. Esta restrição será suspensa se você chamar open()
novamente.
setRequestTimeout()
Simula um tempo limite de solicitação. Altera o readyState
da solicitação para DONE
.
Dispara os eventos apropriados, incluindo o evento timeout
.
Lança um erro se o atributo request
for igual a 0, pois os tempos limite não ocorrem nesse caso.
Depois de chamar esse método, você não poderá usar outros métodos de resposta simulados. Esta restrição será suspensa se você chamar open()
novamente.
newMockXhr()
Retorna uma nova subclasse MockXhr
.
Se você usar uma subclasse diferente de MockXhr
em cada caso de teste, será mais fácil garantir que eles sejam independentes. Por exemplo, se você definir a propriedade estática timeoutEnabled
em uma subclasse, ela afetará apenas essa subclasse e não as outras subclasses criadas em outros casos de teste. Como as subclasses não são reutilizadas, não é necessário um código de limpeza que reverta as alterações feitas em uma subclasse.
newServer(routes)
Argumentos:
routes
: Objeto com o conjunto inicial de rotas do servidor. (opcional) Retorna um novo MockXhrServer
com sua própria subclasse MockXhr
exclusiva. Veja newMockXhr()
.
Adicione rotas ao MockXhrServer
com o argumento opcional routes
. Consulte o construtor para obter detalhes.
XMLHttpRequest
Baseado na especificação XMLHTTPRequest versão '15 de agosto de 2022'.
open()
, setRequestHeader()
, send()
e abort()
.statusText
, cabeçalhos e corpo.timeout
(pode ser desabilitado).MockXhr.setNetworkError()
).MockXhr.setRequestTimeout()
).overrideMimeType()
é lançado quando necessário, mas não tem outro efeito.responseType
: ''
, 'text'
e 'json'
são totalmente suportados. Os valores responseType
não têm efeito no corpo da resposta passado para setResponseBody()
.responseXml
: o corpo da resposta não é convertido em uma resposta de documento. Para obter uma resposta de documento, passe-a diretamente como o corpo da resposta em setResponseBody()
.responseUrl
: o URL da solicitação final após os redirecionamentos não é definido automaticamente. Isso pode ser emulado em um manipulador de solicitações.async
definido como false
em open()
).open()
e lançando SyntaxError
em caso de falha. Contribuintes são bem-vindos! Consulte este guia para obter mais informações.
MIT