-
Notifications
You must be signed in to change notification settings - Fork 4k
/
__experimental-fetch-url-data.js
147 lines (122 loc) · 3.9 KB
/
__experimental-fetch-url-data.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
141
142
143
144
145
146
147
/**
* Internal dependencies
*/
import fetchUrlData from '../__experimental-fetch-url-data';
/**
* WordPress dependencies
*/
import apiFetch from '@wordpress/api-fetch';
jest.mock( '@wordpress/api-fetch' );
describe( 'fetchUrlData', () => {
afterEach( () => {
apiFetch.mockReset();
} );
describe( 'return value settles as expected', () => {
it( 'resolves with response data upon fetch success', async () => {
const data = {
title: 'Lorem ipsum dolor',
icon: '',
image: '',
description:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
};
apiFetch.mockReturnValueOnce( Promise.resolve( data ) );
await expect(
fetchUrlData( 'https://www.wordpress.org' )
).resolves.toEqual( data );
expect( apiFetch ).toHaveBeenCalledTimes( 1 );
} );
it( 'rejects with error upon fetch failure', async () => {
apiFetch.mockReturnValueOnce( Promise.reject( 'fetch failed' ) );
await expect(
fetchUrlData( 'https://www.wordpress.org/1' )
).rejects.toEqual( 'fetch failed' );
} );
} );
describe( 'interaction with underlying fetch API', () => {
it( 'passes options argument through to fetch API', async () => {
apiFetch.mockReturnValueOnce( Promise.resolve() );
await fetchUrlData( 'https://www.wordpress.org/2', {
method: 'POST',
} );
expect( apiFetch ).toHaveBeenCalledTimes( 1 );
const argsPassedToFetchApi = apiFetch.mock.calls[ 0 ][ 0 ];
expect( argsPassedToFetchApi ).toEqual(
expect.objectContaining( {
method: 'POST',
} )
);
} );
} );
describe( 'client side caching', () => {
it( 'caches repeat requests to same url', async () => {
const targetUrl = 'https://www.wordpress.org/3';
const data = {
title: 'Lorem ipsum dolor',
icon: '',
image: '',
description:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
};
apiFetch.mockReturnValueOnce( Promise.resolve( data ) );
await expect( fetchUrlData( targetUrl ) ).resolves.toEqual( data );
expect( apiFetch ).toHaveBeenCalledTimes( 1 );
// Allow us to reassert on calls without it being polluted by first fetch
// but retains the mock implementation from earlier.
apiFetch.mockClear();
// Fetch the same URL again...should be cached.
await expect( fetchUrlData( targetUrl ) ).resolves.toEqual( data );
// Should now be in cache so no need to refetch from API.
expect( apiFetch ).toHaveBeenCalledTimes( 0 );
} );
it( 'does not cache failed requests', async () => {
const targetUrl = 'https://www.wordpress.org/4';
const data = {
title: 'Lorem ipsum dolor',
icon: '',
image: '',
description:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
};
apiFetch
.mockReturnValueOnce( Promise.reject( 'fetch failed' ) )
.mockReturnValueOnce( Promise.resolve( data ) );
await expect( fetchUrlData( targetUrl ) ).rejects.toEqual(
'fetch failed'
);
// Cache should not store the previous failed fetch and should retry
// with a new fetch.
await expect( fetchUrlData( targetUrl ) ).resolves.toEqual( data );
expect( apiFetch ).toHaveBeenCalledTimes( 2 );
} );
} );
describe( 'URL validation', () => {
it.each( [ '#internal-link' ] )(
'errors when an invalid URL is passed',
async ( targetUrl ) => {
expect( apiFetch ).toHaveBeenCalledTimes( 0 );
await expect( fetchUrlData( targetUrl ) ).rejects.toEqual(
expect.stringContaining(
`${ targetUrl } is not a valid URL.`
)
);
}
);
it.each( [
'tel:123456',
'ftp://something',
'mailto:example@wordpress.org',
'file:somefilehere',
] )(
'errors when a non-http protocol (%s) is passed as part of URL',
async ( targetUrl ) => {
expect( apiFetch ).toHaveBeenCalledTimes( 0 );
await expect( fetchUrlData( targetUrl ) ).rejects.toEqual(
expect.stringContaining(
`${ targetUrl } does not have a valid protocol.`
)
);
}
);
} );
} );