-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
stub-fetch-spec.cy.js
140 lines (119 loc) · 3.98 KB
/
stub-fetch-spec.cy.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/// <reference types="Cypress" />
// @ts-check
describe('stubbing', function () {
it('shows no Response message', () => {
cy.visit('/', {
onBeforeLoad (win) {
cy.stub(win, 'fetch').withArgs('/favorite-fruits')
.resolves({
ok: true,
json: () => [],
})
},
})
cy.contains('No favorites').should('be.visible')
})
it('directly stubs window.fetch to test loading indicator', () => {
// stub the "fetch(/favorite-fruits)" call from the app
cy.visit('/', {
onBeforeLoad (win) {
cy.stub(win, 'fetch').withArgs('/favorite-fruits')
.resolves(
// use Bluebird promise bundled with Cypress
// to resolve after 2000ms
Cypress.Promise.resolve({
ok: true,
json: () => ['Pineapple 🍍'],
}).delay(2000)
)
},
})
// at first, the app is showing the loading indicator
cy.get('.loader').should('be.visible')
// once the promise is resolved, the loading indicator goes away
cy.get('.loader').should('not.exist')
cy.contains('li', 'Pineapple 🍍')
})
// A big advantage of controlling the response is we can test
// how our app handles a slow response, which normally might be
// difficult against a fast development server
it('shows loader while fetching fruits', function () {
// stub the XHR request from the app
cy.intercept(
'/favorite-fruits',
{
body: [],
delay: 1000,
}
)
cy.visit('/')
cy.get('.loader').should('be.visible')
// once the network call finishes, the loader goes away
cy.get('.loader').should('not.exist')
cy.contains('.favorite-fruits', 'No favorites')
})
it('can spy on network calls from the second page', () => {
cy.intercept('/favorite-fruits').as('favoriteFruits')
cy.visit('/')
cy.wait('@favoriteFruits')
cy.contains('a', 'Go to page 2').click()
cy.url().should('match', /\/page2\.html$/)
// the second page also requests the fruits
cy.wait('@favoriteFruits')
})
it('can stub network calls for each page', () => {
cy.intercept('/favorite-fruits', ['apples 🍎'])
cy.visit('/')
cy.contains('apples 🍎')
// change the response before going to the second page
cy.intercept('/favorite-fruits', ['grapes 🍇'])
cy.contains('a', 'Go to page 2').click()
cy.url().should('match', /\/page2\.html$/)
cy.contains('grapes 🍇')
// change the response before going back to the index page
cy.intercept('/favorite-fruits', ['kiwi 🥝'])
cy.contains('a', 'Go back').click()
cy.contains('kiwi 🥝')
})
describe('when favorite fruits are returned', function () {
it('displays the list of fruits', function () {
// aliasing allows us to easily get access to our stub
cy.intercept('/favorite-fruits', ['Apple', 'Banana', 'Cantaloupe']).as('fetchFavorites')
cy.visit('/')
cy.wait('@fetchFavorites')
cy.get('.favorite-fruits li').as('favoriteFruits')
.should('have.length', 3)
cy.get('@favoriteFruits').first()
.should('have.text', 'Apple')
cy.get('@favoriteFruits').eq(1)
.should('have.text', 'Banana')
cy.get('@favoriteFruits').eq(2)
.should('have.text', 'Cantaloupe')
})
})
describe('when no favorite fruits are returned', function () {
it('displays empty message', function () {
cy.intercept('/favorite-fruits', [])
cy.visit('/')
cy.get('.favorite-fruits').should('have.text', 'No favorites')
})
})
describe('when request fails', function () {
it('displays error', function () {
cy.intercept(
'/favorite-fruits',
{
statusCode: 500,
body: '',
delay: 2000,
headers: {
'status-text': 'Orchard under maintenance',
},
}
)
cy.visit('/')
cy.get('.favorite-fruits')
.should('have.text', 'Failed loading favorite fruits: Orchard under maintenance')
})
})
})