eslint-plugin-cypress 4.2.0 → 4.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/circle.yml +82 -9
- package/eslint.config.mjs +1 -0
- package/package.json +6 -6
- package/test-project/README.md +48 -0
- package/test-project/cypress/e2e/1-getting-started/todo.cy.js +143 -0
- package/test-project/cypress/e2e/2-advanced-examples/actions.cy.js +321 -0
- package/test-project/cypress/e2e/2-advanced-examples/aliasing.cy.js +39 -0
- package/test-project/cypress/e2e/2-advanced-examples/assertions.cy.js +176 -0
- package/test-project/cypress/e2e/2-advanced-examples/connectors.cy.js +98 -0
- package/test-project/cypress/e2e/2-advanced-examples/cookies.cy.js +118 -0
- package/test-project/cypress/e2e/2-advanced-examples/cypress_api.cy.js +185 -0
- package/test-project/cypress/e2e/2-advanced-examples/files.cy.js +85 -0
- package/test-project/cypress/e2e/2-advanced-examples/location.cy.js +32 -0
- package/test-project/cypress/e2e/2-advanced-examples/misc.cy.js +90 -0
- package/test-project/cypress/e2e/2-advanced-examples/navigation.cy.js +55 -0
- package/test-project/cypress/e2e/2-advanced-examples/network_requests.cy.js +163 -0
- package/test-project/cypress/e2e/2-advanced-examples/querying.cy.js +114 -0
- package/test-project/cypress/e2e/2-advanced-examples/spies_stubs_clocks.cy.js +204 -0
- package/test-project/cypress/e2e/2-advanced-examples/storage.cy.js +117 -0
- package/test-project/cypress/e2e/2-advanced-examples/traversal.cy.js +121 -0
- package/test-project/cypress/e2e/2-advanced-examples/utilities.cy.js +107 -0
- package/test-project/cypress/e2e/2-advanced-examples/viewport.cy.js +58 -0
- package/test-project/cypress/e2e/2-advanced-examples/waiting.cy.js +30 -0
- package/test-project/cypress/e2e/2-advanced-examples/window.cy.js +22 -0
- package/test-project/cypress/fixtures/example.json +5 -0
- package/test-project/cypress/support/commands.js +25 -0
- package/test-project/cypress/support/e2e.js +17 -0
- package/test-project/cypress.config.js +9 -0
- package/test-project/eslint-configs/eslint.default.mjs +9 -0
- package/test-project/eslint-configs/eslint.globals.mjs +4 -0
- package/test-project/eslint-configs/eslint.recommended.mjs +9 -0
- package/test-project/eslint.config.mjs +9 -0
- package/test-project/package.json +9 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/// <reference types="cypress" />
|
|
2
|
+
|
|
3
|
+
/// JSON fixture file can be loaded directly using
|
|
4
|
+
// the built-in JavaScript bundler
|
|
5
|
+
const requiredExample = require('../../fixtures/example')
|
|
6
|
+
|
|
7
|
+
context('Files', () => {
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
cy.visit('https://example.cypress.io/commands/files')
|
|
10
|
+
|
|
11
|
+
// load example.json fixture file and store
|
|
12
|
+
// in the test context object
|
|
13
|
+
cy.fixture('example.json').as('example')
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('cy.fixture() - load a fixture', () => {
|
|
17
|
+
// https://on.cypress.io/fixture
|
|
18
|
+
|
|
19
|
+
// Instead of writing a response inline you can
|
|
20
|
+
// use a fixture file's content.
|
|
21
|
+
|
|
22
|
+
// when application makes an Ajax request matching "GET **/comments/*"
|
|
23
|
+
// Cypress will intercept it and reply with the object in `example.json` fixture
|
|
24
|
+
cy.intercept('GET', '**/comments/*', { fixture: 'example.json' }).as('getComment')
|
|
25
|
+
|
|
26
|
+
// we have code that gets a comment when
|
|
27
|
+
// the button is clicked in scripts.js
|
|
28
|
+
cy.get('.fixture-btn').click()
|
|
29
|
+
|
|
30
|
+
cy.wait('@getComment').its('response.body')
|
|
31
|
+
.should('have.property', 'name')
|
|
32
|
+
.and('include', 'Using fixtures to represent data')
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('cy.fixture() or require - load a fixture', function () {
|
|
36
|
+
// we are inside the "function () { ... }"
|
|
37
|
+
// callback and can use test context object "this"
|
|
38
|
+
// "this.example" was loaded in "beforeEach" function callback
|
|
39
|
+
expect(this.example, 'fixture in the test context')
|
|
40
|
+
.to.deep.equal(requiredExample)
|
|
41
|
+
|
|
42
|
+
// or use "cy.wrap" and "should('deep.equal', ...)" assertion
|
|
43
|
+
cy.wrap(this.example)
|
|
44
|
+
.should('deep.equal', requiredExample)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('cy.readFile() - read file contents', () => {
|
|
48
|
+
// https://on.cypress.io/readfile
|
|
49
|
+
|
|
50
|
+
// You can read a file and yield its contents
|
|
51
|
+
// The filePath is relative to your project's root.
|
|
52
|
+
cy.readFile(Cypress.config('configFile')).then((config) => {
|
|
53
|
+
expect(config).to.be.an('string')
|
|
54
|
+
})
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('cy.writeFile() - write to a file', () => {
|
|
58
|
+
// https://on.cypress.io/writefile
|
|
59
|
+
|
|
60
|
+
// You can write to a file
|
|
61
|
+
|
|
62
|
+
// Use a response from a request to automatically
|
|
63
|
+
// generate a fixture file for use later
|
|
64
|
+
cy.request('https://jsonplaceholder.cypress.io/users')
|
|
65
|
+
.then((response) => {
|
|
66
|
+
cy.writeFile('cypress/fixtures/users.json', response.body)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
cy.fixture('users').should((users) => {
|
|
70
|
+
expect(users[0].name).to.exist
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
// JavaScript arrays and objects are stringified
|
|
74
|
+
// and formatted into text.
|
|
75
|
+
cy.writeFile('cypress/fixtures/profile.json', {
|
|
76
|
+
id: 8739,
|
|
77
|
+
name: 'Jane',
|
|
78
|
+
email: 'jane@example.com',
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
cy.fixture('profile').should((profile) => {
|
|
82
|
+
expect(profile.name).to.eq('Jane')
|
|
83
|
+
})
|
|
84
|
+
})
|
|
85
|
+
})
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/// <reference types="cypress" />
|
|
2
|
+
|
|
3
|
+
context('Location', () => {
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
cy.visit('https://example.cypress.io/commands/location')
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
it('cy.hash() - get the current URL hash', () => {
|
|
9
|
+
// https://on.cypress.io/hash
|
|
10
|
+
cy.hash().should('be.empty')
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it('cy.location() - get window.location', () => {
|
|
14
|
+
// https://on.cypress.io/location
|
|
15
|
+
cy.location().should((location) => {
|
|
16
|
+
expect(location.hash).to.be.empty
|
|
17
|
+
expect(location.href).to.eq('https://example.cypress.io/commands/location')
|
|
18
|
+
expect(location.host).to.eq('example.cypress.io')
|
|
19
|
+
expect(location.hostname).to.eq('example.cypress.io')
|
|
20
|
+
expect(location.origin).to.eq('https://example.cypress.io')
|
|
21
|
+
expect(location.pathname).to.eq('/commands/location')
|
|
22
|
+
expect(location.port).to.eq('')
|
|
23
|
+
expect(location.protocol).to.eq('https:')
|
|
24
|
+
expect(location.search).to.be.empty
|
|
25
|
+
})
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('cy.url() - get the current URL', () => {
|
|
29
|
+
// https://on.cypress.io/url
|
|
30
|
+
cy.url().should('eq', 'https://example.cypress.io/commands/location')
|
|
31
|
+
})
|
|
32
|
+
})
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/// <reference types="cypress" />
|
|
2
|
+
|
|
3
|
+
context('Misc', () => {
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
cy.visit('https://example.cypress.io/commands/misc')
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
it('cy.exec() - execute a system command', () => {
|
|
9
|
+
// execute a system command.
|
|
10
|
+
// so you can take actions necessary for
|
|
11
|
+
// your test outside the scope of Cypress.
|
|
12
|
+
// https://on.cypress.io/exec
|
|
13
|
+
|
|
14
|
+
// we can use Cypress.platform string to
|
|
15
|
+
// select appropriate command
|
|
16
|
+
// https://on.cypress/io/platform
|
|
17
|
+
cy.log(`Platform ${Cypress.platform} architecture ${Cypress.arch}`)
|
|
18
|
+
|
|
19
|
+
// on CircleCI Windows build machines we have a failure to run bash shell
|
|
20
|
+
// https://github.com/cypress-io/cypress/issues/5169
|
|
21
|
+
// so skip some of the tests by passing flag "--env circle=true"
|
|
22
|
+
const isCircleOnWindows = Cypress.platform === 'win32' && Cypress.env('circle')
|
|
23
|
+
|
|
24
|
+
if (isCircleOnWindows) {
|
|
25
|
+
cy.log('Skipping test on CircleCI')
|
|
26
|
+
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// cy.exec problem on Shippable CI
|
|
31
|
+
// https://github.com/cypress-io/cypress/issues/6718
|
|
32
|
+
const isShippable = Cypress.platform === 'linux' && Cypress.env('shippable')
|
|
33
|
+
|
|
34
|
+
if (isShippable) {
|
|
35
|
+
cy.log('Skipping test on ShippableCI')
|
|
36
|
+
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
cy.exec('echo Jane Lane')
|
|
41
|
+
.its('stdout').should('contain', 'Jane Lane')
|
|
42
|
+
|
|
43
|
+
if (Cypress.platform === 'win32') {
|
|
44
|
+
cy.exec(`print ${Cypress.config('configFile')}`)
|
|
45
|
+
.its('stderr').should('be.empty')
|
|
46
|
+
} else {
|
|
47
|
+
cy.exec(`cat ${Cypress.config('configFile')}`)
|
|
48
|
+
.its('stderr').should('be.empty')
|
|
49
|
+
|
|
50
|
+
cy.exec('pwd')
|
|
51
|
+
.its('code').should('eq', 0)
|
|
52
|
+
}
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it('cy.focused() - get the DOM element that has focus', () => {
|
|
56
|
+
// https://on.cypress.io/focused
|
|
57
|
+
cy.get('.misc-form').find('#name').click()
|
|
58
|
+
cy.focused().should('have.id', 'name')
|
|
59
|
+
|
|
60
|
+
cy.get('.misc-form').find('#description').click()
|
|
61
|
+
cy.focused().should('have.id', 'description')
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
context('Cypress.Screenshot', function () {
|
|
65
|
+
it('cy.screenshot() - take a screenshot', () => {
|
|
66
|
+
// https://on.cypress.io/screenshot
|
|
67
|
+
cy.screenshot('my-image')
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
it('Cypress.Screenshot.defaults() - change default config of screenshots', function () {
|
|
71
|
+
Cypress.Screenshot.defaults({
|
|
72
|
+
blackout: ['.foo'],
|
|
73
|
+
capture: 'viewport',
|
|
74
|
+
clip: { x: 0, y: 0, width: 200, height: 200 },
|
|
75
|
+
scale: false,
|
|
76
|
+
disableTimersAndAnimations: true,
|
|
77
|
+
screenshotOnRunFailure: true,
|
|
78
|
+
onBeforeScreenshot () { },
|
|
79
|
+
onAfterScreenshot () { },
|
|
80
|
+
})
|
|
81
|
+
})
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
it('cy.wrap() - wrap an object', () => {
|
|
85
|
+
// https://on.cypress.io/wrap
|
|
86
|
+
cy.wrap({ foo: 'bar' })
|
|
87
|
+
.should('have.property', 'foo')
|
|
88
|
+
.and('include', 'bar')
|
|
89
|
+
})
|
|
90
|
+
})
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/// <reference types="cypress" />
|
|
2
|
+
|
|
3
|
+
context('Navigation', () => {
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
cy.visit('https://example.cypress.io')
|
|
6
|
+
cy.get('.navbar-nav').contains('Commands').click()
|
|
7
|
+
cy.get('.dropdown-menu').contains('Navigation').click()
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
it('cy.go() - go back or forward in the browser\'s history', () => {
|
|
11
|
+
// https://on.cypress.io/go
|
|
12
|
+
|
|
13
|
+
cy.location('pathname').should('include', 'navigation')
|
|
14
|
+
|
|
15
|
+
cy.go('back')
|
|
16
|
+
cy.location('pathname').should('not.include', 'navigation')
|
|
17
|
+
|
|
18
|
+
cy.go('forward')
|
|
19
|
+
cy.location('pathname').should('include', 'navigation')
|
|
20
|
+
|
|
21
|
+
// clicking back
|
|
22
|
+
cy.go(-1)
|
|
23
|
+
cy.location('pathname').should('not.include', 'navigation')
|
|
24
|
+
|
|
25
|
+
// clicking forward
|
|
26
|
+
cy.go(1)
|
|
27
|
+
cy.location('pathname').should('include', 'navigation')
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('cy.reload() - reload the page', () => {
|
|
31
|
+
// https://on.cypress.io/reload
|
|
32
|
+
cy.reload()
|
|
33
|
+
|
|
34
|
+
// reload the page without using the cache
|
|
35
|
+
cy.reload(true)
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('cy.visit() - visit a remote url', () => {
|
|
39
|
+
// https://on.cypress.io/visit
|
|
40
|
+
|
|
41
|
+
// Visit any sub-domain of your current domain
|
|
42
|
+
// Pass options to the visit
|
|
43
|
+
cy.visit('https://example.cypress.io/commands/navigation', {
|
|
44
|
+
timeout: 50000, // increase total time for the visit to resolve
|
|
45
|
+
onBeforeLoad (contentWindow) {
|
|
46
|
+
// contentWindow is the remote page's window object
|
|
47
|
+
expect(typeof contentWindow === 'object').to.be.true
|
|
48
|
+
},
|
|
49
|
+
onLoad (contentWindow) {
|
|
50
|
+
// contentWindow is the remote page's window object
|
|
51
|
+
expect(typeof contentWindow === 'object').to.be.true
|
|
52
|
+
},
|
|
53
|
+
})
|
|
54
|
+
})
|
|
55
|
+
})
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/// <reference types="cypress" />
|
|
2
|
+
|
|
3
|
+
context('Network Requests', () => {
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
cy.visit('https://example.cypress.io/commands/network-requests')
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
// Manage HTTP requests in your app
|
|
9
|
+
|
|
10
|
+
it('cy.request() - make an XHR request', () => {
|
|
11
|
+
// https://on.cypress.io/request
|
|
12
|
+
cy.request('https://jsonplaceholder.cypress.io/comments')
|
|
13
|
+
.should((response) => {
|
|
14
|
+
expect(response.status).to.eq(200)
|
|
15
|
+
// the server sometimes gets an extra comment posted from another machine
|
|
16
|
+
// which gets returned as 1 extra object
|
|
17
|
+
expect(response.body).to.have.property('length').and.be.oneOf([500, 501])
|
|
18
|
+
expect(response).to.have.property('headers')
|
|
19
|
+
expect(response).to.have.property('duration')
|
|
20
|
+
})
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('cy.request() - verify response using BDD syntax', () => {
|
|
24
|
+
cy.request('https://jsonplaceholder.cypress.io/comments')
|
|
25
|
+
.then((response) => {
|
|
26
|
+
// https://on.cypress.io/assertions
|
|
27
|
+
expect(response).property('status').to.equal(200)
|
|
28
|
+
expect(response).property('body').to.have.property('length').and.be.oneOf([500, 501])
|
|
29
|
+
expect(response).to.include.keys('headers', 'duration')
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('cy.request() with query parameters', () => {
|
|
34
|
+
// will execute request
|
|
35
|
+
// https://jsonplaceholder.cypress.io/comments?postId=1&id=3
|
|
36
|
+
cy.request({
|
|
37
|
+
url: 'https://jsonplaceholder.cypress.io/comments',
|
|
38
|
+
qs: {
|
|
39
|
+
postId: 1,
|
|
40
|
+
id: 3,
|
|
41
|
+
},
|
|
42
|
+
})
|
|
43
|
+
.its('body')
|
|
44
|
+
.should('be.an', 'array')
|
|
45
|
+
.and('have.length', 1)
|
|
46
|
+
.its('0') // yields first element of the array
|
|
47
|
+
.should('contain', {
|
|
48
|
+
postId: 1,
|
|
49
|
+
id: 3,
|
|
50
|
+
})
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('cy.request() - pass result to the second request', () => {
|
|
54
|
+
// first, let's find out the userId of the first user we have
|
|
55
|
+
cy.request('https://jsonplaceholder.cypress.io/users?_limit=1')
|
|
56
|
+
.its('body') // yields the response object
|
|
57
|
+
.its('0') // yields the first element of the returned list
|
|
58
|
+
// the above two commands its('body').its('0')
|
|
59
|
+
// can be written as its('body.0')
|
|
60
|
+
// if you do not care about TypeScript checks
|
|
61
|
+
.then((user) => {
|
|
62
|
+
expect(user).property('id').to.be.a('number')
|
|
63
|
+
// make a new post on behalf of the user
|
|
64
|
+
cy.request('POST', 'https://jsonplaceholder.cypress.io/posts', {
|
|
65
|
+
userId: user.id,
|
|
66
|
+
title: 'Cypress Test Runner',
|
|
67
|
+
body: 'Fast, easy and reliable testing for anything that runs in a browser.',
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
// note that the value here is the returned value of the 2nd request
|
|
71
|
+
// which is the new post object
|
|
72
|
+
.then((response) => {
|
|
73
|
+
expect(response).property('status').to.equal(201) // new entity created
|
|
74
|
+
expect(response).property('body').to.contain({
|
|
75
|
+
title: 'Cypress Test Runner',
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
// we don't know the exact post id - only that it will be > 100
|
|
79
|
+
// since JSONPlaceholder has built-in 100 posts
|
|
80
|
+
expect(response.body).property('id').to.be.a('number')
|
|
81
|
+
.and.to.be.gt(100)
|
|
82
|
+
|
|
83
|
+
// we don't know the user id here - since it was in above closure
|
|
84
|
+
// so in this test just confirm that the property is there
|
|
85
|
+
expect(response.body).property('userId').to.be.a('number')
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
it('cy.request() - save response in the shared test context', () => {
|
|
90
|
+
// https://on.cypress.io/variables-and-aliases
|
|
91
|
+
cy.request('https://jsonplaceholder.cypress.io/users?_limit=1')
|
|
92
|
+
.its('body').its('0') // yields the first element of the returned list
|
|
93
|
+
.as('user') // saves the object in the test context
|
|
94
|
+
.then(function () {
|
|
95
|
+
// NOTE 👀
|
|
96
|
+
// By the time this callback runs the "as('user')" command
|
|
97
|
+
// has saved the user object in the test context.
|
|
98
|
+
// To access the test context we need to use
|
|
99
|
+
// the "function () { ... }" callback form,
|
|
100
|
+
// otherwise "this" points at a wrong or undefined object!
|
|
101
|
+
cy.request('POST', 'https://jsonplaceholder.cypress.io/posts', {
|
|
102
|
+
userId: this.user.id,
|
|
103
|
+
title: 'Cypress Test Runner',
|
|
104
|
+
body: 'Fast, easy and reliable testing for anything that runs in a browser.',
|
|
105
|
+
})
|
|
106
|
+
.its('body').as('post') // save the new post from the response
|
|
107
|
+
})
|
|
108
|
+
.then(function () {
|
|
109
|
+
// When this callback runs, both "cy.request" API commands have finished
|
|
110
|
+
// and the test context has "user" and "post" objects set.
|
|
111
|
+
// Let's verify them.
|
|
112
|
+
expect(this.post, 'post has the right user id').property('userId').to.equal(this.user.id)
|
|
113
|
+
})
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
it('cy.intercept() - route responses to matching requests', () => {
|
|
117
|
+
// https://on.cypress.io/intercept
|
|
118
|
+
|
|
119
|
+
let message = 'whoa, this comment does not exist'
|
|
120
|
+
|
|
121
|
+
// Listen to GET to comments/1
|
|
122
|
+
cy.intercept('GET', '**/comments/*').as('getComment')
|
|
123
|
+
|
|
124
|
+
// we have code that gets a comment when
|
|
125
|
+
// the button is clicked in scripts.js
|
|
126
|
+
cy.get('.network-btn').click()
|
|
127
|
+
|
|
128
|
+
// https://on.cypress.io/wait
|
|
129
|
+
cy.wait('@getComment').its('response.statusCode').should('be.oneOf', [200, 304])
|
|
130
|
+
|
|
131
|
+
// Listen to POST to comments
|
|
132
|
+
cy.intercept('POST', '**/comments').as('postComment')
|
|
133
|
+
|
|
134
|
+
// we have code that posts a comment when
|
|
135
|
+
// the button is clicked in scripts.js
|
|
136
|
+
cy.get('.network-post').click()
|
|
137
|
+
cy.wait('@postComment').should(({ request, response }) => {
|
|
138
|
+
expect(request.body).to.include('email')
|
|
139
|
+
expect(request.headers).to.have.property('content-type')
|
|
140
|
+
expect(response && response.body).to.have.property('name', 'Using POST in cy.intercept()')
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
// Stub a response to PUT comments/ ****
|
|
144
|
+
cy.intercept({
|
|
145
|
+
method: 'PUT',
|
|
146
|
+
url: '**/comments/*',
|
|
147
|
+
}, {
|
|
148
|
+
statusCode: 404,
|
|
149
|
+
body: { error: message },
|
|
150
|
+
headers: { 'access-control-allow-origin': '*' },
|
|
151
|
+
delayMs: 500,
|
|
152
|
+
}).as('putComment')
|
|
153
|
+
|
|
154
|
+
// we have code that puts a comment when
|
|
155
|
+
// the button is clicked in scripts.js
|
|
156
|
+
cy.get('.network-put').click()
|
|
157
|
+
|
|
158
|
+
cy.wait('@putComment')
|
|
159
|
+
|
|
160
|
+
// our 404 statusCode logic in scripts.js executed
|
|
161
|
+
cy.get('.network-put-comment').should('contain', message)
|
|
162
|
+
})
|
|
163
|
+
})
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/// <reference types="cypress" />
|
|
2
|
+
|
|
3
|
+
context('Querying', () => {
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
cy.visit('https://example.cypress.io/commands/querying')
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
// The most commonly used query is 'cy.get()', you can
|
|
9
|
+
// think of this like the '$' in jQuery
|
|
10
|
+
|
|
11
|
+
it('cy.get() - query DOM elements', () => {
|
|
12
|
+
// https://on.cypress.io/get
|
|
13
|
+
|
|
14
|
+
cy.get('#query-btn').should('contain', 'Button')
|
|
15
|
+
|
|
16
|
+
cy.get('.query-btn').should('contain', 'Button')
|
|
17
|
+
|
|
18
|
+
cy.get('#querying .well>button:first').should('contain', 'Button')
|
|
19
|
+
// ↲
|
|
20
|
+
// Use CSS selectors just like jQuery
|
|
21
|
+
|
|
22
|
+
cy.get('[data-test-id="test-example"]').should('have.class', 'example')
|
|
23
|
+
|
|
24
|
+
// 'cy.get()' yields jQuery object, you can get its attribute
|
|
25
|
+
// by invoking `.attr()` method
|
|
26
|
+
cy.get('[data-test-id="test-example"]')
|
|
27
|
+
.invoke('attr', 'data-test-id')
|
|
28
|
+
.should('equal', 'test-example')
|
|
29
|
+
|
|
30
|
+
// or you can get element's CSS property
|
|
31
|
+
cy.get('[data-test-id="test-example"]')
|
|
32
|
+
.invoke('css', 'position')
|
|
33
|
+
.should('equal', 'static')
|
|
34
|
+
|
|
35
|
+
// or use assertions directly during 'cy.get()'
|
|
36
|
+
// https://on.cypress.io/assertions
|
|
37
|
+
cy.get('[data-test-id="test-example"]')
|
|
38
|
+
.should('have.attr', 'data-test-id', 'test-example')
|
|
39
|
+
.and('have.css', 'position', 'static')
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
it('cy.contains() - query DOM elements with matching content', () => {
|
|
43
|
+
// https://on.cypress.io/contains
|
|
44
|
+
cy.get('.query-list')
|
|
45
|
+
.contains('bananas')
|
|
46
|
+
.should('have.class', 'third')
|
|
47
|
+
|
|
48
|
+
// we can pass a regexp to `.contains()`
|
|
49
|
+
cy.get('.query-list')
|
|
50
|
+
.contains(/^b\w+/)
|
|
51
|
+
.should('have.class', 'third')
|
|
52
|
+
|
|
53
|
+
cy.get('.query-list')
|
|
54
|
+
.contains('apples')
|
|
55
|
+
.should('have.class', 'first')
|
|
56
|
+
|
|
57
|
+
// passing a selector to contains will
|
|
58
|
+
// yield the selector containing the text
|
|
59
|
+
cy.get('#querying')
|
|
60
|
+
.contains('ul', 'oranges')
|
|
61
|
+
.should('have.class', 'query-list')
|
|
62
|
+
|
|
63
|
+
cy.get('.query-button')
|
|
64
|
+
.contains('Save Form')
|
|
65
|
+
.should('have.class', 'btn')
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('.within() - query DOM elements within a specific element', () => {
|
|
69
|
+
// https://on.cypress.io/within
|
|
70
|
+
cy.get('.query-form').within(() => {
|
|
71
|
+
cy.get('input:first').should('have.attr', 'placeholder', 'Email')
|
|
72
|
+
cy.get('input:last').should('have.attr', 'placeholder', 'Password')
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
it('cy.root() - query the root DOM element', () => {
|
|
77
|
+
// https://on.cypress.io/root
|
|
78
|
+
|
|
79
|
+
// By default, root is the document
|
|
80
|
+
cy.root().should('match', 'html')
|
|
81
|
+
|
|
82
|
+
cy.get('.query-ul').within(() => {
|
|
83
|
+
// In this within, the root is now the ul DOM element
|
|
84
|
+
cy.root().should('have.class', 'query-ul')
|
|
85
|
+
})
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
it('best practices - selecting elements', () => {
|
|
89
|
+
// https://on.cypress.io/best-practices#Selecting-Elements
|
|
90
|
+
cy.get('[data-cy=best-practices-selecting-elements]').within(() => {
|
|
91
|
+
// Worst - too generic, no context
|
|
92
|
+
cy.get('button').click()
|
|
93
|
+
|
|
94
|
+
// Bad. Coupled to styling. Highly subject to change.
|
|
95
|
+
cy.get('.btn.btn-large').click()
|
|
96
|
+
|
|
97
|
+
// Average. Coupled to the `name` attribute which has HTML semantics.
|
|
98
|
+
cy.get('[name=submission]').click()
|
|
99
|
+
|
|
100
|
+
// Better. But still coupled to styling or JS event listeners.
|
|
101
|
+
cy.get('#main').click()
|
|
102
|
+
|
|
103
|
+
// Slightly better. Uses an ID but also ensures the element
|
|
104
|
+
// has an ARIA role attribute
|
|
105
|
+
cy.get('#main[role=button]').click()
|
|
106
|
+
|
|
107
|
+
// Much better. But still coupled to text content that may change.
|
|
108
|
+
cy.contains('Submit').click()
|
|
109
|
+
|
|
110
|
+
// Best. Insulated from all changes.
|
|
111
|
+
cy.get('[data-cy=submit]').click()
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
})
|