Service d'Interception
wdio-intercept-service est un package tiers, pour plus d'informations, veuillez consulter GitHub | npm
đž Capturez et vĂ©rifiez les appels HTTP ajax dans webdriver.io
Ceci est un plugin pour webdriver.io. Si vous ne le connaissez pas encore, jetez-y un Ćil, c'est plutĂŽt cool.
Bien que selenium et webdriver soient utilisĂ©s pour les tests e2e et particuliĂšrement les tests UI, vous pourriez vouloir Ă©valuer les requĂȘtes HTTP effectuĂ©es par votre code client (par exemple, lorsque vous n'avez pas de retour UI immĂ©diat, comme dans les mĂ©triques ou les appels de suivi). Avec wdio-intercept-service, vous pouvez intercepter les appels HTTP ajax initiĂ©s par une action utilisateur (par exemple, un appui sur un bouton, etc.) et faire des assertions sur la requĂȘte et les rĂ©ponses correspondantes plus tard.
Il y a cependant une contrainte : vous ne pouvez pas intercepter les appels HTTP qui sont initiĂ©s au chargement de la page (comme dans la plupart des SPA), car cela nĂ©cessite un travail de configuration qui ne peut ĂȘtre effectuĂ© qu'aprĂšs le chargement de la page (en raison des limitations de selenium). Cela signifie que vous pouvez seulement capturer les requĂȘtes qui ont Ă©tĂ© initiĂ©es Ă l'intĂ©rieur d'un test. Si cela vous convient, ce plugin pourrait ĂȘtre pour vous, alors continuez la lecture.
PrĂ©requisâ
- webdriver.io v5.x ou plus récent.
Attention ! Si vous utilisez encore webdriver.io v4, veuillez utiliser la branche v2.x de ce plugin !
Installationâ
npm install wdio-intercept-service -D
Utilisationâ
Utilisation avec WebDriver CLIâ
Il devrait ĂȘtre aussi simple que d'ajouter wdio-intercept-service Ă votre wdio.conf.js
:
exports.config = {
// ...
services: ['intercept']
// ...
};
et tout est prĂȘt.
Utilisation avec WebDriver Standaloneâ
Lorsque vous utilisez WebdriverIO Standalone, les fonctions before
et beforeTest
/ beforeScenario
doivent ĂȘtre appelĂ©es manuellement.
import { remote } from 'webdriverio';
import WebdriverAjax from 'wdio-intercept-service'
const WDIO_OPTIONS = {
port: 9515,
path: '/',
capabilities: {
browserName: 'chrome'
},
}
let browser;
const interceptServiceLauncher = WebdriverAjax();
beforeAll(async () => {
browser = await remote(WDIO_OPTIONS)
interceptServiceLauncher.before(null, null, browser)
})
beforeEach(async () => {
interceptServiceLauncher.beforeTest()
})
afterAll(async () => {
await client.deleteSession()
});
describe('', async () => {
... // See example usage
});
Une fois initialisées, certaines fonctions connexes sont ajoutées à votre chaßne de commandes de navigateur (voir API).
DĂ©marrage rapideâ
Exemple d'utilisation :
browser.url('http://foo.bar');
browser.setupInterceptor(); // capture ajax calls
browser.expectRequest('GET', '/api/foo', 200); // expect GET request to /api/foo with 200 statusCode
browser.expectRequest('POST', '/api/foo', 400); // expect POST request to /api/foo with 400 statusCode
browser.expectRequest('GET', /\/api\/foo/, 200); // can validate a URL with regex, too
browser.click('#button'); // button that initiates ajax request
browser.pause(1000); // maybe wait a bit until request is finished
browser.assertRequests(); // validate the requests
Obtenir des dĂ©tails sur les requĂȘtes :
browser.url('http://foo.bar')
browser.setupInterceptor();
browser.click('#button')
browser.pause(1000);
var request = browser.getRequest(0);
assert.equal(request.method, 'GET');
assert.equal(request.response.headers['content-length'], '42');
Navigateurs pris en chargeâ
Il devrait fonctionner avec les versions relativement récentes de tous les navigateurs. Veuillez signaler un problÚme s'il ne semble pas fonctionner avec le vÎtre.
APIâ
Consultez le fichier de dĂ©claration TypeScript pour connaĂźtre la syntaxe complĂšte des commandes personnalisĂ©es ajoutĂ©es Ă l'objet navigateur WebdriverIO. En gĂ©nĂ©ral, toute mĂ©thode qui prend un objet "options" comme paramĂštre peut ĂȘtre appelĂ©e sans ce paramĂštre pour obtenir le comportement par dĂ©faut. Ces objets "options" optionnels sont suivis par ?: = {}
et les valeurs par défaut déduites sont décrites pour chaque méthode.
Descriptions des optionsâ
Cette bibliothÚque offre une petite quantité de configuration lors de l'émission de commandes. Les options de configuration utilisées par plusieurs méthodes sont décrites ici (voir la définition de chaque méthode pour déterminer le support spécifique).
orderBy
('START' | 'END'
) : Cette option contrĂŽle l'ordre des requĂȘtes capturĂ©es par l'intercepteur, lorsqu'elles sont renvoyĂ©es Ă votre test. Pour la compatibilitĂ© avec les versions existantes de cette bibliothĂšque, l'ordre par dĂ©faut est'END'
, qui correspond au moment oĂč la requĂȘte a Ă©tĂ© complĂ©tĂ©e. Si vous dĂ©finissez l'optionorderBy
sur'START'
, alors les requĂȘtes seront ordonnĂ©es selon le moment oĂč elles ont Ă©tĂ© dĂ©marrĂ©es.includePending
(boolean
) : Cette option contrĂŽle si les requĂȘtes non encore terminĂ©es seront renvoyĂ©es. Pour la compatibilitĂ© avec les versions existantes de cette bibliothĂšque, la valeur par dĂ©faut estfalse
, et seules les requĂȘtes terminĂ©es seront renvoyĂ©es.
browser.setupInterceptor()â
Capture les appels ajax dans le navigateur. Vous devez toujours appeler la fonction de configuration afin d'Ă©valuer les requĂȘtes ultĂ©rieurement.
browser.disableInterceptor()â
EmpĂȘche la capture supplĂ©mentaire d'appels ajax dans le navigateur. Toutes les informations de requĂȘte capturĂ©es sont supprimĂ©es. La plupart des utilisateurs n'auront pas besoin de dĂ©sactiver l'intercepteur, mais si un test est particuliĂšrement long ou dĂ©passe la capacitĂ© de stockage de session, la dĂ©sactivation de l'intercepteur peut ĂȘtre utile.
browser.excludeUrls(urlRegexes: (string | RegExp)[])
â
Exclut les requĂȘtes provenant de certaines URLs d'ĂȘtre enregistrĂ©es. Elle prend un tableau de chaĂźnes ou d'expressions rĂ©guliĂšres. Avant d'Ă©crire dans le stockage, teste l'url de la requĂȘte par rapport Ă chaque chaĂźne ou regex. Si c'est le cas, la requĂȘte n'est pas Ă©crite dans le stockage. Comme disableInterceptor, cela peut ĂȘtre utile si vous rencontrez des problĂšmes de dĂ©passement de capacitĂ© du stockage de session.
browser.expectRequest(method: string, url: string, statusCode: number)â
DĂ©finir des attentes concernant les requĂȘtes ajax qui vont ĂȘtre initiĂ©es pendant le test. Peut (et devrait) ĂȘtre chaĂźnĂ©. L'ordre des attentes devrait correspondre Ă l'ordre des requĂȘtes effectuĂ©es.
method
(String
) : mĂ©thode http attendue. Peut ĂȘtre n'importe quoi quexhr.open()
accepte comme premier argument.url
(String
|RegExp
) : URL exacte qui est appelĂ©e dans la requĂȘte sous forme de chaĂźne ou RegExp Ă faire correspondrestatusCode
(Number
) : code de statut attendu de la réponse
browser.getExpectations()â
Méthode auxiliaire. Renvoie toutes les attentes que vous avez définies jusqu'à ce point
browser.resetExpectations()â
Méthode auxiliaire. Réinitialise toutes les attentes que vous avez définies jusqu'à ce point
browser.assertRequests({ orderBy?: 'START' | 'END' }?: = {})
â
Appelez cette mĂ©thode lorsque toutes les requĂȘtes ajax attendues sont terminĂ©es. Elle compare les attentes aux requĂȘtes rĂ©elles effectuĂ©es et affirme ce qui suit :
- Nombre de requĂȘtes qui ont Ă©tĂ© effectuĂ©es
- L'ordre des requĂȘtes
- La mĂ©thode, l'URL et le statusCode doivent correspondre pour chaque requĂȘte effectuĂ©e
- L'objet options a par défaut
{ orderBy: 'END' }
, c'est-Ă -dire quand les requĂȘtes ont Ă©tĂ© complĂ©tĂ©es, pour ĂȘtre cohĂ©rent avec le comportement de la v4.1.10 et antĂ©rieures. Lorsque l'optionorderBy
est définie sur'START'
, les requĂȘtes seront ordonnĂ©es selon le moment oĂč elles ont Ă©tĂ© initiĂ©es par la page.
browser.assertExpectedRequestsOnly({ inOrder?: boolean, orderBy?: 'START' | 'END' }?: = {})
â
Similaire Ă browser.assertRequests
, mais valide uniquement les requĂȘtes que vous spĂ©cifiez dans vos directives expectRequest
, sans avoir Ă cartographier toutes les requĂȘtes rĂ©seau qui pourraient se produire autour de cela. Si l'option inOrder
est true
(par dĂ©faut), les requĂȘtes sont censĂ©es ĂȘtre trouvĂ©es dans le mĂȘme ordre qu'elles ont Ă©tĂ© configurĂ©es avec expectRequest
.
browser.getRequest(index: number, { includePending?: boolean, orderBy?: 'START' | 'END' }?: = {})
â
Pour faire des assertions plus sophistiquĂ©es sur une requĂȘte spĂ©cifique, vous pouvez obtenir des dĂ©tails pour une requĂȘte spĂ©cifique. Vous devez fournir l'index basĂ© sur 0 de la requĂȘte Ă laquelle vous souhaitez accĂ©der, dans l'ordre oĂč les requĂȘtes ont Ă©tĂ© complĂ©tĂ©es (par dĂ©faut), ou initiĂ©es (en passant l'option orderBy: 'START'
).
index
(number
) : numĂ©ro de la requĂȘte Ă laquelle vous souhaitez accĂ©deroptions
(object
) : Options de configurationoptions.includePending
(boolean
) : Si les requĂȘtes non encore terminĂ©es doivent ĂȘtre renvoyĂ©es. Par dĂ©faut, c'est false, pour correspondre au comportement de la bibliothĂšque en v4.1.10 et antĂ©rieures.options.orderBy
('START' | 'END'
) : Comment les requĂȘtes doivent ĂȘtre ordonnĂ©es. Par dĂ©faut, c'est'END'
, pour correspondre au comportement de la bibliothÚque en v4.1.10 et antérieures. Si'START'
, les requĂȘtes seront ordonnĂ©es par le moment de l'initiation, plutĂŽt que par le moment de la fin de la requĂȘte. (Comme une requĂȘte en attente n'est pas encore terminĂ©e, lors de l'ordre par'END'
toutes les requĂȘtes en attente viendront aprĂšs toutes les requĂȘtes terminĂ©es.)
Retourne l'objet request
:
request.url
: URL demandéerequest.method
: méthode HTTP utiliséerequest.body
: donnĂ©es de charge utile/corps utilisĂ©es dans la requĂȘterequest.headers
: en-tĂȘtes http de la requĂȘte sous forme d'objet JSrequest.pending
: indicateur boolĂ©en indiquant si cette requĂȘte est terminĂ©e (c'est-Ă -dire a une propriĂ©tĂ©response
), ou en cours.request.response
: un objet JS qui n'est prĂ©sent que si la requĂȘte est terminĂ©e (c'est-Ă -direrequest.pending === false
), contenant des données sur la réponse.request.response?.headers
: en-tĂȘtes http de rĂ©ponse sous forme d'objet JSrequest.response?.body
: corps de la réponse (sera analysé comme JSON si possible)request.response?.statusCode
: code d'état de la réponse
Une note sur request.body
: wdio-intercept-service essaiera d'analyser le corps de la requĂȘte comme suit :
- chaĂźne : Renvoie simplement la chaĂźne (
'value'
) - JSON : Analyse l'objet JSON en utilisant
JSON.parse()
(({ key: value })
) - FormData : Affichera les FormData au format
{ key: [value1, value2, ...] }
- ArrayBuffer : Essaiera de convertir le tampon en chaßne (expérimental)
- Tout autre chose : Utilisera un brutal
JSON.stringify()
sur vos données. Bonne chance !
Pour l'API fetch
, nous ne prenons en charge que les données de type chaßne et JSON !
browser.getRequests({ includePending?: boolean, orderBy?: 'START' | 'END' }?: = {})
â
Obtenez toutes les requĂȘtes capturĂ©es sous forme de tableau, en prenant en charge les mĂȘmes options optionnelles que getRequest
.
Retourne un tableau d'objets request
.
browser.hasPendingRequests()â
Une mĂ©thode utilitaire qui vĂ©rifie si des requĂȘtes HTTP sont encore en attente. Peut ĂȘtre utilisĂ©e par les tests pour s'assurer que toutes les requĂȘtes sont terminĂ©es dans un dĂ©lai raisonnable, ou pour vĂ©rifier qu'un appel Ă getRequests()
ou assertRequests()
inclura toutes les requĂȘtes HTTP souhaitĂ©es.
Retourne booléen
Support TypeScriptâ
Ce plugin fournit ses propres types TS. Pointez simplement votre tsconfig vers les extensions de type comme mentionné ici :
"compilerOptions": {
// ..
"types": ["node", "webdriverio", "wdio-intercept-service"]
},
ExĂ©cution des testsâ
Des versions rĂ©centes de Chrome et Firefox sont nĂ©cessaires pour exĂ©cuter les tests localement. Vous devrez peut-ĂȘtre mettre Ă jour les dĂ©pendances chromedriver
et geckodriver
pour correspondre à la version installée sur votre systÚme.
npm test
Contributionâ
Je suis heureux pour chaque contribution. Ouvrez simplement un problĂšme ou directement un PR.
Veuillez noter que cette bibliothÚque d'intercepteur est écrite pour fonctionner avec des navigateurs hérités tels qu'Internet Explorer. En tant que tel, tout code utilisé dans lib/interceptor.js
doit au moins ĂȘtre analysable par le runtime JavaScript d'Internet Explorer.
Licenceâ
MIT