Skip to content
This repository was archived by the owner on Oct 13, 2022. It is now read-only.

Commit 61127f4

Browse files
authored
Merge pull request #175 from cypress-io/10.0.0
2 parents 6b11d23 + 929b57e commit 61127f4

File tree

10 files changed

+8380
-393
lines changed

10 files changed

+8380
-393
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
version: 2.1
22
orbs:
3-
cypress: cypress-io/cypress@1.29.0
3+
cypress: cypress-io/cypress@2
44
jobs:
55
release:
66
executor: cypress/browsers-chrome78-ff70

README.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# cypress-xpath
22

3-
[![CircleCI](https://circleci.com/gh/cypress-io/cypress-xpath.svg?style=svg&circle-token=c1c1eb7da56fcc8a49b96e7155161728987f9878)](https://circleci.com/gh/cypress-io/cypress-xpath) [![renovate-app badge][renovate-badge]][renovate-app] ![cypress version](https://img.shields.io/badge/cypress-6.8.0-brightgreen)
3+
[![CircleCI](https://circleci.com/gh/cypress-io/cypress-xpath.svg?style=svg&circle-token=c1c1eb7da56fcc8a49b96e7155161728987f9878)](https://circleci.com/gh/cypress-io/cypress-xpath) [![renovate-app badge][renovate-badge]][renovate-app] ![cypress version](https://img.shields.io/badge/cypress-10.2.0-brightgreen)
44

55
> Adds XPath command to [Cypress.io](https://www.cypress.io) test runner
66
@@ -19,60 +19,60 @@ yarn add cypress-xpath --dev
1919
Then include in your project's [support file](https://on.cypress.io/support-file)
2020

2121
```js
22-
require("cypress-xpath");
22+
require('cypress-xpath');
2323
```
2424

2525
## Use
2626

2727
After installation your `cy` object will have `xpath` command.
2828

2929
```js
30-
it("finds list items", () => {
31-
cy.xpath('//ul[@class="todo-list"]//li').should("have.length", 3);
30+
it('finds list items', () => {
31+
cy.xpath('//ul[@class="todo-list"]//li').should('have.length', 3);
3232
});
3333
```
3434

3535
You can also chain `xpath` off of another command.
3636

3737
```js
38-
it("finds list items", () => {
39-
cy.xpath('//ul[@class="todo-list"]').xpath("./li").should("have.length", 3);
38+
it('finds list items', () => {
39+
cy.xpath('//ul[@class="todo-list"]').xpath('./li').should('have.length', 3);
4040
});
4141
```
4242

4343
As with other cy commands, it is scoped by `cy.within()`.
4444

4545
```js
46-
it("finds list items", () => {
46+
it('finds list items', () => {
4747
cy.xpath('//ul[@class="todo-list"]').within(() => {
48-
cy.xpath("./li").should("have.length", 3);
48+
cy.xpath('./li').should('have.length', 3);
4949
});
5050
});
5151
```
5252

5353
**note:** you can test XPath expressions from DevTools console using `$x(...)` function, for example `$x('//div')` to find all divs.
5454

55-
See [cypress/integration/spec.js](cypress/integration/spec.js)
55+
See [cypress/e2e/spec.cy.js](cypress/e2e/spec.cy.js)
5656

5757
## Beware the XPath // trap
5858

5959
In XPath the expression // means something very specific, and it might not be what you think. Contrary to common belief, // means "anywhere in the document" not "anywhere in the current context". As an example:
6060

6161
```js
62-
cy.xpath("//body").xpath("//script");
62+
cy.xpath('//body').xpath('//script');
6363
```
6464

6565
You might expect this to find all script tags in the body, but actually, it finds all script tags in the entire document, not only those in the body! What you're looking for is the .// expression which means "any descendant of the current node":
6666

6767
```js
68-
cy.xpath("//body").xpath(".//script");
68+
cy.xpath('//body').xpath('.//script');
6969
```
7070

7171
The same thing goes for within:
7272

7373
```js
74-
cy.xpath("//body").within(() => {
75-
cy.xpath(".//script");
74+
cy.xpath('//body').within(() => {
75+
cy.xpath('.//script');
7676
});
7777
```
7878

cypress.config.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const { defineConfig } = require('cypress');
2+
3+
module.exports = defineConfig({
4+
e2e: {
5+
excludeSpecPattern: '*.html',
6+
supportFile: 'cypress/support/index.js',
7+
},
8+
component: {
9+
excludeSpecPattern: '*.html',
10+
supportFile: 'cypress/support/index.js',
11+
},
12+
});

cypress.json

Lines changed: 0 additions & 3 deletions
This file was deleted.
File renamed without changes.

cypress/integration/spec.js renamed to cypress/e2e/spec.cy.js

Lines changed: 88 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -3,173 +3,175 @@
33

44
describe('cypress-xpath', () => {
55
it('adds xpath command', () => {
6-
expect(cy)
7-
.property('xpath')
8-
.to.be.a('function')
9-
})
6+
expect(cy).property('xpath').to.be.a('function');
7+
});
108

119
context('elements', () => {
1210
beforeEach(() => {
13-
cy.visit('cypress/integration/index.html')
14-
})
11+
cy.visit('cypress/e2e/index.html');
12+
});
1513

1614
it('finds h1', () => {
17-
cy.xpath('//h1').should('have.length', 1)
18-
})
15+
cy.xpath('//h1').should('have.length', 1);
16+
});
1917

2018
it('returns jQuery wrapped elements', () => {
21-
cy.xpath('//h1').then(el$ => {
22-
expect(el$).to.have.property('jquery')
23-
})
24-
})
19+
cy.xpath('//h1').then((el$) => {
20+
expect(el$).to.have.property('jquery');
21+
});
22+
});
2523

2624
it('returns primitives as is', () => {
27-
cy.xpath('string(//h1)').then(el$ => {
28-
expect(el$).to.not.have.property('jquery')
29-
})
30-
})
25+
cy.xpath('string(//h1)').then((el$) => {
26+
expect(el$).to.not.have.property('jquery');
27+
});
28+
});
3129

3230
it('provides jQuery wrapped elements to assertions', () => {
33-
cy.xpath('//h1').should(el$ => {
34-
expect(el$).to.have.property('jquery')
35-
})
36-
})
31+
cy.xpath('//h1').should((el$) => {
32+
expect(el$).to.have.property('jquery');
33+
});
34+
});
3735

3836
it('gets h1 text', () => {
3937
cy.xpath('//h1/text()')
4038
.its('0.textContent')
41-
.should('equal', 'cypress-xpath')
42-
})
39+
.should('equal', 'cypress-xpath');
40+
});
4341

4442
it('retries until element is inserted', () => {
4543
// the element will be inserted after 1 second
46-
cy.xpath('string(//*[@id="inserted"])').should('equal', 'inserted text')
47-
})
44+
cy.xpath('string(//*[@id="inserted"])').should('equal', 'inserted text');
45+
});
4846

4947
describe('chaining', () => {
5048
it('finds h1 within main', () => {
5149
// first assert that h1 doesn't exist as a child of the implicit document subject
52-
cy.xpath('./h1').should('not.exist')
50+
cy.xpath('./h1').should('not.exist');
5351

54-
cy.xpath('//main').xpath('./h1').should('exist')
55-
})
52+
cy.xpath('//main').xpath('./h1').should('exist');
53+
});
5654

5755
it('finds body outside of main when succumbing to // trap', () => {
5856
// first assert that body doesn't actually exist within main
59-
cy.xpath('//main').xpath('.//body').should('not.exist')
57+
cy.xpath('//main').xpath('.//body').should('not.exist');
6058

61-
cy.xpath('//main').xpath('//body').should('exist')
62-
})
59+
cy.xpath('//main').xpath('//body').should('exist');
60+
});
6361

6462
it('finds h1 within document', () => {
65-
cy.document().xpath('//h1').should('exist')
66-
})
63+
cy.document().xpath('//h1').should('exist');
64+
});
6765

6866
it('throws when subject is more than a single element', (done) => {
6967
cy.on('fail', (err) => {
70-
expect(err.message).to.eq('xpath() can only be called on a single element. Your subject contained 2 elements.')
71-
done()
72-
})
68+
expect(err.message).to.eq(
69+
'xpath() can only be called on a single element. Your subject contained 2 elements.'
70+
);
71+
done();
72+
});
7373

74-
cy.get('main, div').xpath('foo')
75-
})
76-
})
74+
cy.get('main, div').xpath('foo');
75+
});
76+
});
7777

7878
describe('within()', () => {
7979
it('finds h1 within within-subject', () => {
8080
// first assert that h1 doesn't exist as a child of the implicit document subject
81-
cy.xpath('./h1').should('not.exist')
81+
cy.xpath('./h1').should('not.exist');
8282

8383
cy.xpath('//main').within(() => {
84-
cy.xpath('./h1').should('exist')
85-
})
86-
})
84+
cy.xpath('./h1').should('exist');
85+
});
86+
});
8787

8888
it('finds body outside of within-subject when succumbing to // trap', () => {
8989
// first assert that body doesn't actually exist within main
9090
cy.xpath('//main').within(() => {
91-
cy.xpath('.//body').should('not.exist')
91+
cy.xpath('.//body').should('not.exist');
9292
});
9393

9494
cy.xpath('//main').within(() => {
95-
cy.xpath('//body').should('exist')
95+
cy.xpath('//body').should('exist');
9696
});
97-
})
98-
})
97+
});
98+
});
9999

100100
describe('primitives', () => {
101101
it('counts h1 elements', () => {
102-
cy.xpath('count(//h1)').should('equal', 1)
103-
})
102+
cy.xpath('count(//h1)').should('equal', 1);
103+
});
104104

105105
it('returns h1 text content', () => {
106-
cy.xpath('string(//h1)').should('equal', 'cypress-xpath')
107-
})
106+
cy.xpath('string(//h1)').should('equal', 'cypress-xpath');
107+
});
108108

109109
it('returns boolean', () => {
110-
cy.xpath('boolean(//h1)').should('be.true')
111-
cy.xpath('boolean(//h2)').should('be.false')
112-
})
113-
})
110+
cy.xpath('boolean(//h1)').should('be.true');
111+
cy.xpath('boolean(//h2)').should('be.false');
112+
});
113+
});
114114

115115
describe('typing', () => {
116116
it('works on text input', () => {
117-
cy.xpath('//*[@id="name"]').type('World')
118-
cy.contains('span#greeting', 'Hello, World')
119-
})
120-
})
117+
cy.xpath('//*[@id="name"]').type('World');
118+
cy.contains('span#greeting', 'Hello, World');
119+
});
120+
});
121121

122122
describe('clicking', () => {
123123
it('on button', () => {
124124
// this button invokes window.alert when clicked
125-
const alert = cy.stub()
126-
cy.on('window:alert', alert)
125+
const alert = cy.stub();
126+
cy.on('window:alert', alert);
127127
cy.xpath('//*[@id="first-button"]')
128128
.click()
129129
.then(() => {
130-
expect(alert).to.have.been.calledOnce
131-
})
132-
})
133-
})
134-
})
130+
expect(alert).to.have.been.calledOnce;
131+
});
132+
});
133+
});
134+
});
135135

136136
context('logging', () => {
137137
beforeEach(() => {
138-
cy.visit('cypress/integration/index.html')
139-
})
138+
cy.visit('cypress/e2e/index.html');
139+
});
140140

141141
it('should log by default', () => {
142-
cy.spy(Cypress, 'log').log(false)
142+
cy.spy(Cypress, 'log').log(false);
143143

144144
cy.xpath('//h1').then(() => {
145-
expect(Cypress.log).to.be.calledWithMatch({ name: 'xpath' })
146-
})
147-
})
145+
expect(Cypress.log).to.be.calledWithMatch({ name: 'xpath' });
146+
});
147+
});
148148

149149
it('logs the selector when not found', (done) => {
150-
cy.xpath('//h1') // does exist
150+
cy.xpath('//h1'); // does exist
151151
cy.on('fail', (e) => {
152152
const isExpectedErrorMessage = (message) =>
153153
message.includes('Timed out retrying') &&
154-
message.includes('Expected to find element: `//h2`, but never found it.')
154+
message.includes(
155+
'Expected to find element: `//h2`, but never found it.'
156+
);
155157

156158
if (!isExpectedErrorMessage(e.message)) {
157-
console.error('Cypress test failed with an unexpected error message')
158-
console.error(e)
159-
return done(e)
159+
console.error('Cypress test failed with an unexpected error message');
160+
console.error(e);
161+
return done(e);
160162
}
161163
// no errors, the error message for not found selector is correct
162-
done()
163-
})
164-
cy.xpath('//h2', { timeout: 100 }) // does not exist
165-
})
164+
done();
165+
});
166+
cy.xpath('//h2', { timeout: 100 }); // does not exist
167+
});
166168

167169
it('should not log when provided log: false', () => {
168-
cy.spy(Cypress, 'log').log(false)
170+
cy.spy(Cypress, 'log').log(false);
169171

170172
cy.xpath('//h1', { log: false }).then(() => {
171-
expect(Cypress.log).to.not.be.calledWithMatch({ name: 'xpath' })
172-
})
173-
})
174-
})
175-
})
173+
expect(Cypress.log).to.not.be.calledWithMatch({ name: 'xpath' });
174+
});
175+
});
176+
});
177+
});

cypress/plugins/index.js

Lines changed: 0 additions & 17 deletions
This file was deleted.

0 commit comments

Comments
 (0)