Zusätzliche Zypressen -Abfragenbefehle für v12+
Fügen Sie dieses Paket als Entwicklerabhängigkeit hinzu:
$ npm i -D cypress-map
# or using Yarn
$ yarn add -D cypress-map
Fügen Sie dieses Paket in Ihre Spezifikation oder Support -Datei ein, um alle benutzerdefinierten Abfragenbefehle zu verwenden
import 'cypress-map'
Alternative: Importieren Sie nur die von Ihnen benötigten Abfragebefehle:
import 'cypress-map/commands/map'
import 'cypress-map/commands/tap'
// and so on, see the /commands folder
const double = ( n ) => n * 2
cy . wrap ( 100 ) . apply ( double ) . should ( 'equal' , 200 )
Es funktioniert wie cy.then
aber cy.apply(fn)
ist ein Abfragebefehl. Funktion fn
fn
synchron sein, reine Funktion, die nur das Subjektargument verwendet und einen neuen Wert zurückgibt cy
Sie können zusätzliche linke Argumente an die Rückruffunktion weitergeben. Dann wird das Thema als das letzte Argument vorgenommen, bevor er die Funktion aufruft:
cy . wrap ( 8 ) . apply ( Cypress . _ . subtract , 4 ) . should ( 'equal' , - 4 )
Ohne Argumente funktioniert cy.applyRight
genauso wie cy.apply
. Wenn Sie Argumente verabschieden, werden das Thema plus die Argumente zu den Argumenten zum Rückruf. Das Subjekt befindet sich links (erster) Position
cy . wrap ( 8 ) . applyRight ( Cypress . _ . subtract , 4 ) . should ( 'equal' , 4 )
// same as
cy . wrap ( 8 )
. apply ( ( subject ) => Cypress . _ . subtract ( subject , 4 ) )
. should ( 'equal' , 4 )
Manchmal haben Sie den Rückruf zu bewerben und kennen die ersten Argumente (n) und müssen das Thema nur an die letzte Position bringen. Hier können Sie die bekannten Argumente teilweise auf den angegebenen Rückruf anwenden.
// the Cypress._.add takes to arguments (a, b)
// we know the first argument a = 5
// so we partially apply it and wait for the subject = b argument
cy . wrap ( 100 ) . partial ( Cypress . _ . add , 5 ) . should ( 'equal' , 105 )
// same as
cy . wrap ( 100 )
. apply ( ( subject ) => Cypress . _ . add ( 5 , subject ) )
. should ( 'equal' , 105 )
Wenn es sich bei dem aktuellen Thema um ein Array oder ein JQuery -Objekt handelt, können Sie den angegebenen Rückruf mit Argumenten auf das erste Element oder Element anwenden. Das aktuelle Thema wird das letzte Argument sein.
// cy.applyToFirst(callback, ...args)
cy . wrap ( Cypress . $ ( '<div>100</div><div>200</div>' ) )
. applyToFirst ( ( base , el ) => parseInt ( el . innerText , base ) , 10 )
. should ( 'equal' , 100 )
Wenn es sich bei dem aktuellen Thema um ein Array oder ein JQuery -Objekt handelt, können Sie den angegebenen Rückruf mit Argumenten auf das erste Element oder Element anwenden. Das aktuelle Thema wird das erste Argument sein.
// cy.applyToFirstRight(callback, ...args)
cy . wrap ( Cypress . $ ( '<div>100</div><div>200</div>' ) )
. applyToFirstRight ( ( el , base ) => parseInt ( el . innerText , base ) , 10 )
. should ( 'equal' , 100 )
Wir müssen oft nur eine Methode für das erste Element / Element im aktuellen Thema aufrufen
cy . get ( selector ) . invokeFirst ( 'getBoundingClientRect' )
// compute the vertical center for example
Verwandelt jedes Objekt in der angegebenen Sammlung, indem Sie es durch die angegebene Rückruffunktion ausführen. Kann auch jedes Objekt seiner Eigenschaft zuordnen. Ein Objekt kann ein Array oder ein JQuery -Objekt sein.
// map elements by invoking a function
cy . wrap ( [ '10' , '20' , '30' ] ) . map ( Number ) // [10, 20, 30]
// map elements by a property
cy . get ( '.matching' )
. map ( 'innerText' )
. should ( 'deep.equal' , [ 'first' , 'third' , 'fourth' ] )
Sie können sogar Eigenschaften eines Objekts durch Auflisten von Rückrufen abbilden. Lassen Sie uns beispielsweise die age
von einer Zeichenfolge in eine Zahl konvertieren
cy . wrap ( {
age : '42' ,
lucky : true ,
} )
. map ( {
age : Number ,
} )
. should ( 'deep.equal' , {
age : 42 ,
lucky : true ,
} )
Sie können jede Konvertierung vermeiden, um einfach die Liste der Eigenschaften aus einem Objekt auszuwählen
const person = {
name : 'Joe' ,
age : 21 ,
occupation : 'student' ,
}
cy . wrap ( person ) . map ( [ 'name' , 'age' ] ) . should ( 'deep.equal' , {
name : 'Joe' ,
age : 21 ,
} )
Sie können verschachtelte Pfade mit "" -"extrahieren." in Ihrem Eigenschaftspfad
cy . wrap ( people )
. map ( 'name.first' )
. should ( 'deep.equal' , [ 'Joe' , 'Anna' ] )
// equivalent to
cy . wrap ( people )
. map ( 'name' )
. map ( 'first' )
. should ( 'deep.equal' , [ 'Joe' , 'Anna' ] )
cy . get ( '#items li' )
. find ( '.price' )
. map ( 'innerText' )
. mapInvoke ( 'replace' , '$' , '' )
. mapInvoke ( 'trim' )
cy . get ( '#items li' )
. find ( '.price' )
. map ( 'innerText' )
. mapInvoke ( 'replace' , '$' , '' )
. map ( parseFloat )
. reduce ( ( max , n ) => ( n > max ? n : max ) )
// yields the highest price
Sie können den anfänglichen Akkumulatorwert angeben
cy . wrap ( [ 1 , 2 , 3 ] )
. reduce ( ( sum , n ) => sum + n , 10 )
. should ( 'equal' , 16 )
Siehe record.cy.js
cy . get ( '#items li' )
. find ( '.price' )
. map ( 'innerText' )
. tap ( ) // console.log by default
. mapInvoke ( 'replace' , '$' , '' )
. mapInvoke ( 'trim' )
// console.info with extra label
. tap ( console . info , 'trimmed strings' )
Hinweis: Wenn das Etikett bereitgestellt wird, wird die Rückruffunktion mit Etikett und dem Thema aufgerufen.
Eine Wiederholungsabfrage, die die angegebene Konstruktorfunktion mit dem new
Schlüsselwort und dem aktuellen Thema als Argument aufruft.
cy . wrap ( 'Jan 1, 2019' )
// same as "new Date('Jan 1, 2019')"
. make ( Date )
. invoke ( 'getFullYear' )
. should ( 'equal' , 2019 )
Ein besseres cy.log
: Ergibt den Wert, intelligent Stringwerte mit %
und String-Format-Notation.
cy . wrap ( 42 )
. print ( ) // "42"
// and yields the value
. should ( 'equal' , 42 )
// pass formatting string
cy . wrap ( 42 ) . print ( 'the answer is %d' ) // "the answer is 42"
cy . wrap ( { name : 'Joe' } ) . print ( 'person %o' ) // 'person {"name":"Joe"}'
// use {0} with dot notation, supported deep properties
// https://github.com/davidchambers/string-format
cy . wrap ( { name : 'Joe' } ) . print ( 'person name {0.name}' ) // "person name Joe"
// print the length of an array
cy . wrap ( arr ) . print ( 'array length {0.length}' ) // "array length ..."
// pass your own function to return formatted string
cy . wrap ( arr ) . print ( ( a ) => `array with ${ a . length } items` )
// if you return a non-string, it will attempt to JSON.stringify it
cy . wrap ( arr ) . print ( ( list ) => list [ 2 ] ) // JSON.stringify(arr[2])
Weitere Beispiele finden Sie unter print.cy.js
Findet im Thema einen einzelnen Element. Angenommen, das Thema ist ein Array oder ein JQuery -Objekt. Verwendet die Lodash _.find
-Methode.
// using predicate function
const isThree = n => n === 3
cy . wrap ( [ ... ] ) . findOne ( isThree ) . should ( 'equal' , 3 )
// using partial known properties of an object
cy . wrap ( [ ... ] ) . findOne ( { name : 'Anna' } ) . should ( 'have.property' , 'name' , 'Anna' )
Siehe Find-One.cy.js
cy . get ( '.matching' )
. map ( 'innerText' )
. primo ( )
. invoke ( 'toUpperCase' )
. should ( 'equal' , 'FIRST' )
Siehe primo.cy.js
Funktioniert wie cy.its
für Objekte, erhält die Eigenschaft für JQuery -Objekte, die cy.its
nicht tut
cy . get ( '#items li.matching' )
. last ( )
. prop ( 'ariaLabel' )
. should ( 'equal' , 'four' )
Siehe prop.cy.js
Ändert eine einzelne Eigenschaft innerhalb des Subjekts, indem Sie sie durch die angegebene Rückruffunktion ausführen. Nützlich, um Conversions zu typern, wandeln wir beispielsweise die Eigenschaft "Alter" in eine Zahl um
cy . wrap ( { age : '20' } )
. update ( 'age' , Number )
. should ( 'deep.equal' , { age : 20 } )
Gibt ein DOM -Element von JQuery -Objekt an Position k
zurück. Gibt einen Artikel von Array an Position k
zurück. Für den negativen Index zählt die Elemente vom Ende.
cy . get ( '#items li' ) . at ( - 1 ) . its ( 'innerText' ) . should ( 'equal' , 'fifth' )
Siehe at.cy.js
Gibt ein zufällig ausgewähltes Element oder Element aus dem aktuellen Thema zurück
cy . get ( '#items li' ) . sample ( ) . should ( 'have.text' , 'four' )
Wenn Sie eine positive Zahl übergeben, wählt es mehrere Elemente oder Elemente aus
// yields jQuery object with 3 random items
cy . get ( '#items li' ) . sample ( 3 ) . should ( 'have.length' , 3 )
Siehe Sample.cy.js
Ergibt das zweite Element aus dem aktuellen Thema. Könnte ein Element oder ein Array -Element sein.
cy . get ( '#items li' ) . second ( ) . should ( 'have.text' , 'second' )
Siehe Second.cy.js
Ergibt das dritte Element aus dem aktuellen Thema. Könnte ein Element oder ein Array -Element sein.
cy . get ( '#items li' ) . third ( ) . should ( 'have.text' , 'third' )
Siehe dritte.cy.js
Speichert das aktuelle Thema im Cypress.env
-Objekt. HINWEIS: Cypress.Env -Objekt wird vor dem Spezifikationslauf zurückgesetzt, die geänderten Werte werden jedoch von der Test zu Test übergeben. So können Sie leicht einen Wert vom ersten Test zum zweiten übergeben.
it ( 'saves value in this test' , ( ) => {
cy . wrap ( 'hello, world' ) . asEnv ( 'greeting' )
} )
it ( 'saved value is available in this test' , ( ) => {
expect ( Cypress . env ( 'greeting' ) , 'greeting' ) . to . equal ( 'hello, world' )
} )
Möchten Sie die Tests wirklich voneinander abhängen?
Fragen Sie die Seite mit mehreren Selektoren ab und geben die gefundenen Elemente in der angegebenen Reihenfolge zurück, unabhängig davon, wie sie im Dokument bestellt werden. Wiederholungen, wenn einer der Selektoren nicht gefunden wird.
cy . getInOrder ( 'selector1' , 'selector2' , 'selector3' , ... )
// yields a single jQuery subject with
// elements for selector1
// and selector2,
// and selector3, etc
Sie können auch ein einzelnes Array von Selektor -Zeichenfolgen verwenden
cy . getInOrder ( [ 'h1' , 'h2' , 'h3' ] )
Manchmal möchten Sie nur warten, bis das Element stabil ist. Wenn sich der Textinhalt des Elements beispielsweise für N -Millisekunden nicht ändert, können wir das Element als text
betrachten.
cy . get ( '#message' ) . stable ( 'text' )
// yields the element
Unterstützte Typen: text
, value
(für Eingabeelemente), css
und element
(vergleicht die Elementreferenz)
Sie können die Ruhezeit (Millisekunden) steuern und das log
und die timeout
übergeben
// stable for 500ms
// without logging
// with maximum retries duration of 6 seconds
cy . get ( '#message' ) . stable ( 'text' , 500 , { log : false , timeout : 6_000 } )
Geben Sie beim stabilen Überprüfen der CSS -Eigenschaft den Namen der Eigenschaft an:
// retries until the CSS animation finishes
// and the background color is red
cy . get ( '#message' )
. stable ( 'css' , 'background-color' , 100 )
// yields the element
. should ( 'have.css' , 'background-color' , 'rgb(255, 0, 0)' )
Siehe Stable.cy.js und Stable-css.cy.js
Experimental-
Wiederholt das Element mit dem angegebenen Selektor von DOM.
cy . contains ( 'Click to re-render' ) . click ( )
cy . detaches ( '#list' )
Manchmal kann die Ablösung mit der Aktion richtig erfolgen und die cy.detaches(selector)
zu spät sind. Wenn Sie wissen, dass die Abteilung möglicherweise bereits passiert ist, müssen Sie sich darauf vorbereiten, indem Sie einen Alias verwenden, der im Cypress.env
-Objekt gespeichert ist:
cy . get ( '#name2' ) . asEnv ( 'name' )
cy . contains ( 'Click to remove Joe' ) . click ( )
cy . detaches ( '@name' )
Das JQuery -Objekt wird in der Cypress.env
unter der name
-Eigenschaft gespeichert.
Siehe detach.cy.js
Berechnet ein Objekt/Arrays der Differenz mit dem aktuellen Subjektobjekt/-array.
cy . wrap ( { name : 'Joe' , age : 20 } )
. difference ( { name : 'Joe' , age : 30 } )
. should ( 'deep.equal' , { age : { actual : 20 , expected : 30 } } )
Sie können synchrone Prädikatfunktionen verwenden, um Eigenschaften zu validieren
// confirm the value of the "age" property
// is larger than 15
. difference ( { name : 'Joe' , age : ( n ) => n > 15 } )
Berichte fehlende und zusätzliche Eigenschaften. Siehe differenz.cy.js
HINWEIS: Verwenden Sie have.length
um die Anzahl der Elemente in einem Array zu validieren:
// let's check if there are 3 objects in the array
// INSTEAD OF THIS
. difference ( [ Cypress . _ . object , Cypress . _ . object , Cypress . _ . object ] )
// USE AN ASSERTION
. should ( 'have.length' , 3 )
Sie können jedes Element im Array -Subjekt unter Verwendung von Werten / Prädikaten aus dem erwarteten Objekt überprüfen.
// list of people objects
cy . wrap ( people )
. difference ( {
name : Cypress . _ . isString ,
age : ( age ) => age > 1 && age < 100 ,
} )
. should ( 'be.empty' )
Um mehr über den Befehl cy.table
zu erfahren, lesen Sie die HTML -Tabellen des Blog -Beitrags mit Cy.Table Query -Befehl.
Extrahiert alle Zellen aus der aktuellen Subjekttabelle. Ergibt eine 2D -Reihe von Saiten.
cy . get ( 'table' ) . table ( )
Sie können die Tabelle in Scheiben schneiden, um nur einen Region zu ergeben .table(x, y, w, h)
Zum Beispiel können Sie 2 mal 2 Subregion erhalten
cy . get ( 'table' )
. table ( 0 , 2 , 2 , 2 )
. should ( 'deep.equal' , [
[ 'Cary' , '30' ] ,
[ 'Joe' , '28' ] ,
] )
Weitere Beispiele finden Sie in der technischen Tabelle.cy.js.
Tipp: Sie können cy.table
mit cy.map
, cy.mapInvoke
kombinieren, um die Teile der Tabelle zu erhalten. Zum Beispiel könnte der gleiche 2x2 -Teil der Tabelle mit:
cy . get ( 'table' )
. table ( )
. invoke ( 'slice' , 2 , 4 )
. mapInvoke ( 'slice' , 0 , 2 )
. should ( 'deep.equal' , [
[ 'Cary' , '30' ] ,
[ 'Joe' , '28' ] ,
] )
Tipp 2: .its
die Überschriftenreihe .table
erhalten
cy . get ( 'table' )
. table ( 0 , 0 , 3 , 1 )
. its ( 0 )
. should ( 'deep.equal' , [ 'Name' , 'Age' , 'Date (YYYY-MM-DD)' ] )
Um die letzte Reihe zu bekommen, könnten Sie:
cy . get ( 'table' ) . table ( ) . invoke ( 'slice' , - 1 ) . its ( 0 )
Um die erste Spalte in ein einzelnes Array zu bringen (anstelle von Array von 1x1 -Arrays)
cy . get ( 'table' )
. table ( 0 , 1 , 1 ) // skip the heading "Name" cell
// combine 1x1 arrays into one array
. invoke ( 'flatMap' , Cypress . _ . identity )
. should ( 'deep.equal' , [ 'Dave' , 'Cary' , 'Joe' , 'Anna' ] )
Eine Abfrage zum Umwandeln spezieller DOM -Objekte in einfache Objekte. Zum Beispiel um deep.equal
DOMStringMap
cy . get ( 'article' )
. should ( 'have.prop' , 'dataset' )
. toPlainObject ( )
. should ( 'deep.equal' , {
columns : '3' ,
indexNumber : '12314' ,
parent : 'cars' ,
} )
Verwendet standardmäßig JSON Stringify und Parse zurück. Wenn Sie mithilfe von entries
und fromEntries
konvertieren möchten, fügen Sie ein Argument hinzu:
cy . wrap ( new URLSearchParams ( searchParams ) ) . toPlainObject ( 'entries' )
In Cypress V12 cy.invoke
wurde eine Frage, die die Arbeit mit asynchronen Methoden wirklich unhandlich machte. Die cy.invokeOnce
ist eine Rückgabe der alten Art, die Methode aufzurufen und den gelösten Wert zu ergeben.
cy . wrap ( app )
// app.fetchName is an asynchronous method
// that returns a Promise
. invokeOnce ( 'fetchName' )
. should ( 'equal' , 'My App' )
Weitere Beispiele finden Sie in der Spec Incoke-once.cy.js.
Hier sind einige Beispiele, um die Unterschiede zwischen cy.invoke
, cy.map
und cy.mapInvoke
-Query -Befehlen zu klären, siehe diff.cy.js
const list = [ 'apples' , 'plums' , 'bananas' ]
// cy.invoke
cy . wrap ( list )
// calls ".sort()" on the list
. invoke ( 'sort' )
. should ( 'deep.equal' , [ 'apples' , 'bananas' , 'plums' ] )
// cy.mapInvoke
cy . wrap ( list )
// calls ".toUpperCase()" on every string in the list
. mapInvoke ( 'toUpperCase' )
. should ( 'deep.equal' , [ 'APPLES' , 'PLUMS' , 'BANANAS' ] )
// cy.map
const reverse = ( s ) => s . split ( '' ) . reverse ( ) . join ( '' )
cy . wrap ( list )
// reverses each string in the list
. map ( reverse )
. should ( 'deep.equal' , [ 'selppa' , 'smulp' , 'sananab' ] )
// grabs the "length" property from each string
. map ( 'length' )
. should ( 'deep.equal' , [ 6 , 5 , 7 ] )
Ich habe diesem Paket einen weiteren nützlichen Befehl (keine Abfrage!) Hinzugefügt. Sie können Elemente im Array -Subjekt nacheinander über synchrone, asynchrone oder cy
-Befehlsfunktionen verarbeiten. Dies liegt daran, dass die gemeinsame Lösung für das Abrufen von Elementen mit cy.each
beispielsweise nicht funktioniert:
// fetch the users from a list of ids
// DOES NOT WORK
cy . get ( ids ) . each ( id => cy . request ( '/users/' + id ) ) . then ( users => ... )
// Nope, the yielded "users" result is ... still the "ids" subject
// ✅ CORRECT SOLUTION
cy . get ( ids ) . mapChain ( id => cy . request ( '/users/' + id ) ) . then ( users => ... )
Dieses Paket enthält die Befehlsdefinitionen von TypeScript für seine benutzerdefinierten Befehle in den Dateibefehlen/index.d.ts. Um es aus Ihren JavaScript -Spezifikationen zu verwenden:
/// <reference types="cypress-map" />
Wenn Sie TypeScript verwenden, geben Sie dieses Modul in Ihre Typ -Liste ein
{
"compilerOptions" : {
"types" : [ " cypress " , " cypress-map " ]
}
}
Der Quellcode befindet sich im Ordner SRC/Befehl. Der Befehl Build erstellt ES5 -Code, der in den commands
eingeht (sollte nicht in die Quellcode -Steuerung untersucht werden). Das package.json
in seiner NPM -Verteilung enthält commands
plus die Typen aus src/commands/index.d.ts
Datei.
should(callback)
im laufenden Fliegen haben. HINWEIS: Dieses Modul hat keine filter
, da Cypress -API Abfragebefehle Cy.Filter und Cy.invoke enthält, mit denen Sie Elemente in einem JQuery -Objekt oder Elementen in einem Array filtern können. Siehe die Beispiele in filter.cy.js spec. Siehe Videofilterelemente und Elemente mit Wiederholungen.
Autor: Gleb Bahmutov <[email protected]> © 2022
Lizenz: MIT - Mach etwas mit dem Code, aber beschuldige mich nicht, wenn es nicht funktioniert.
Support: Wenn Sie Probleme mit diesem Modul finden, E -Mail / Tweet / Öffnen Sie das Problem auf GitHub