Aller au contenu principal

Mocks et espions de requĂȘtes

WebdriverIO est livrĂ© avec une prise en charge intĂ©grĂ©e pour modifier les rĂ©ponses rĂ©seau, ce qui vous permet de vous concentrer sur les tests de votre application frontend sans avoir Ă  configurer votre backend ou un serveur de simulation. Vous pouvez dĂ©finir des rĂ©ponses personnalisĂ©es pour les ressources web comme les requĂȘtes d'API REST dans votre test et les modifier dynamiquement.

info

Notez que l'utilisation de la commande mock nécessite la prise en charge du protocole Chrome DevTools. Cette prise en charge est assurée si vous exécutez des tests localement dans un navigateur basé sur Chromium, via Selenium Grid v4 ou supérieur, ou via un fournisseur cloud prenant en charge le protocole Chrome DevTools (par exemple SauceLabs, BrowserStack, LambdaTest). La prise en charge complÚte multi-navigateurs sera disponible une fois que les primitives requises seront intégrées dans Webdriver Bidi et implémentées dans les navigateurs respectifs.

CrĂ©ation d'un mock​

Avant de pouvoir modifier des rĂ©ponses, vous devez d'abord dĂ©finir un mock. Ce mock est dĂ©crit par l'URL de la ressource et peut ĂȘtre filtrĂ© par la mĂ©thode de requĂȘte ou les en-tĂȘtes. La ressource prend en charge les expressions glob via minimatch :

// simuler toutes les ressources se terminant par "/users/list"
const userListMock = await browser.mock('**/users/list')

// ou vous pouvez spĂ©cifier le mock en filtrant les ressources par en-tĂȘtes ou
// code d'Ă©tat, ne simuler que les requĂȘtes rĂ©ussies vers les ressources json
const strictMock = await browser.mock('**', {
// simuler toutes les réponses json
requestHeaders: { 'Content-Type': 'application/json' },
// qui ont réussi
statusCode: 200
})

SpĂ©cification de rĂ©ponses personnalisĂ©es​

Une fois que vous avez dĂ©fini un mock, vous pouvez dĂ©finir des rĂ©ponses personnalisĂ©es pour celui-ci. Ces rĂ©ponses personnalisĂ©es peuvent ĂȘtre soit un objet pour rĂ©pondre en JSON, un fichier local pour rĂ©pondre avec un fixture personnalisĂ© ou une ressource web pour remplacer la rĂ©ponse par une ressource provenant d'Internet.

Simulation des requĂȘtes API​

Pour simuler des requĂȘtes API oĂč vous attendez une rĂ©ponse JSON, il vous suffit d'appeler respond sur l'objet mock avec un objet arbitraire que vous souhaitez renvoyer, par exemple :

const mock = await browser.mock('https://todo-backend-express-knex.herokuapp.com/')

mock.respond([{
title: 'Injected (non) completed Todo',
order: null,
completed: false
}, {
title: 'Injected completed Todo',
order: null,
completed: true
}], {
headers: {
'Access-Control-Allow-Origin': '*'
},
fetchResponse: false
})

await browser.url('https://todobackend.com/client/index.html?https://todo-backend-express-knex.herokuapp.com/')

await $('#todo-list li').waitForExist()
console.log(await $$('#todo-list li').map(el => el.getText()))
// affiche: "[ 'Injected (non) completed Todo', 'Injected completed Todo' ]"

Vous pouvez Ă©galement modifier les en-tĂȘtes de rĂ©ponse ainsi que le code d'Ă©tat en passant des paramĂštres de rĂ©ponse mock comme suit :

mock.respond({ ... }, {
// répondre avec le code d'état 404
statusCode: 404,
// fusionner les en-tĂȘtes de rĂ©ponse avec les en-tĂȘtes suivants
headers: { 'x-custom-header': 'foobar' }
})

Si vous ne voulez pas que le mock appelle le backend du tout, vous pouvez passer false pour le drapeau fetchResponse.

mock.respond({ ... }, {
// ne pas appeler le backend réel
fetchResponse: false
})

Il est recommandé de stocker les réponses personnalisées dans des fichiers de fixture afin de pouvoir simplement les importer dans votre test comme suit :

// nécessite Node.js v16.14.0 ou supérieur pour prendre en charge les assertions d'importation JSON
import responseFixture from './__fixtures__/apiResponse.json' assert { type: 'json' }
mock.respond(responseFixture)

Simulation des ressources textuelles​

Si vous souhaitez modifier des ressources textuelles comme des fichiers JavaScript, CSS ou d'autres ressources basées sur du texte, vous pouvez simplement passer un chemin de fichier et WebdriverIO remplacera la ressource originale par celui-ci, par exemple :

const scriptMock = await browser.mock('**/script.min.js')
scriptMock.respond('./tests/fixtures/script.js')

// ou répondre avec votre JS personnalisé
scriptMock.respond('alert("I am a mocked resource")')

Redirection des ressources web​

Vous pouvez Ă©galement remplacer une ressource web par une autre ressource web si votre rĂ©ponse souhaitĂ©e est dĂ©jĂ  hĂ©bergĂ©e sur le web. Cela fonctionne avec des ressources de page individuelles ainsi qu'avec une page web elle-mĂȘme, par exemple :

const pageMock = await browser.mock('https://google.com/')
await pageMock.respond('https://webdriver.io')
await browser.url('https://google.com')
console.log(await browser.getTitle()) // renvoie "WebdriverIO · Next-gen browser and mobile automation test framework for Node.js"

RĂ©ponses dynamiques​

Si votre réponse mock dépend de la réponse de la ressource originale, vous pouvez également modifier dynamiquement la ressource en passant une fonction qui reçoit la réponse originale en paramÚtre et définit le mock en fonction de la valeur de retour, par exemple :

const mock = await browser.mock('https://todo-backend-express-knex.herokuapp.com/', {
method: 'get'
})

mock.respond((req) => {
// remplacer le contenu de la tùche par leur numéro de liste
return req.body.map((item, i) => ({ ...item, title: i }))
})

await browser.url('https://todobackend.com/client/index.html?https://todo-backend-express-knex.herokuapp.com/')

await $('#todo-list li').waitForExist()
console.log(await $$('#todo-list li label').map((el) => el.getText()))
// renvoie
// [
// '0', '1', '2', '19', '20',
// '21', '3', '4', '5', '6',
// '7', '8', '9', '10', '11',
// '12', '13', '14', '15', '16',
// '17', '18', '22'
// ]

Annulation des mocks​

Au lieu de renvoyer une rĂ©ponse personnalisĂ©e, vous pouvez Ă©galement simplement annuler la requĂȘte avec l'une des erreurs HTTP suivantes :

  • Failed
  • Aborted
  • TimedOut
  • AccessDenied
  • ConnectionClosed
  • ConnectionReset
  • ConnectionRefused
  • ConnectionAborted
  • ConnectionFailed
  • NameNotResolved
  • InternetDisconnected
  • AddressUnreachable
  • BlockedByClient
  • BlockedByResponse

Ceci est trÚs utile si vous souhaitez bloquer des scripts tiers de votre page qui ont une influence négative sur votre test fonctionnel. Vous pouvez annuler un mock en appelant simplement abort ou abortOnce, par exemple :

const mock = await browser.mock('https://www.google-analytics.com/**')
mock.abort('Failed')

Espions​

Chaque mock est automatiquement un espion qui compte le nombre de requĂȘtes que le navigateur a effectuĂ©es vers cette ressource. Si vous n'appliquez pas de rĂ©ponse personnalisĂ©e ou de motif d'annulation au mock, il continue avec la rĂ©ponse par dĂ©faut que vous recevriez normalement. Cela vous permet de vĂ©rifier combien de fois le navigateur a effectuĂ© la requĂȘte, par exemple vers un certain point de terminaison API.

const mock = await browser.mock('**/user', { method: 'post' })
console.log(mock.calls.length) // renvoie 0

// enregistrer l'utilisateur
await $('#username').setValue('randomUser')
await $('password').setValue('password123')
await $('password_repeat').setValue('password123')
await $('button[type="submit"]').click()

// vĂ©rifier si la requĂȘte API a Ă©tĂ© effectuĂ©e
expect(mock.calls.length).toBe(1)

// vérifier la réponse
expect(mock.calls[0].body).toEqual({ success: true })

Welcome! How can I help?

WebdriverIO AI Copilot