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çãoMockXhrMockXhrServerMockXhrServerMockXhrMockXhrMockXhrRequestnewMockXhr()newServer()XMLHttpRequestvia 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.
onCreateMé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 ) => { /*...*/ } ; onSendMé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.
bodyO 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.
XMLHttpRequestBaseado 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