@@ -18,7 +18,7 @@ import sinon from 'sinon';
18
18
import * as Ajax from './Ajax' ;
19
19
import { getFilenameFromContentDisposition } from './Ajax' ;
20
20
21
- function mockXHR ( ) {
21
+ function mockXHR ( ) : void {
22
22
let xhr : sinon . SinonFakeXMLHttpRequestStatic ;
23
23
24
24
afterEach ( ( ) => {
@@ -41,109 +41,129 @@ function request(options: Ajax.RequestOptions): FakeXMLHttpRequest {
41
41
return Ajax . request ( options ) as FakeXMLHttpRequest ;
42
42
}
43
43
44
- describe ( 'request' , ( ) => {
45
- mockXHR ( ) ;
46
-
47
- it ( 'should require configuration' , ( ) => {
48
- expect ( ( ) => {
49
- ( Ajax . request as any ) ( ) ;
50
- } ) . toThrow ( 'a URL is required to make a request' ) ;
51
- expect ( ( ) => {
52
- ( Ajax . request as any ) ( { } ) ;
53
- } ) . toThrow ( 'a URL is required to make a request' ) ;
54
- } ) ;
55
- it ( 'should make request with only url' , ( ) => {
56
- expect ( request ( { url : '/users' } ) . url ) . toEqual ( '/users' ) ;
44
+ describe ( 'Ajax' , ( ) => {
45
+ describe ( 'request' , ( ) => {
46
+ mockXHR ( ) ;
47
+
48
+ it ( 'should require configuration' , ( ) => {
49
+ expect ( ( ) => {
50
+ ( Ajax . request as any ) ( ) ;
51
+ } ) . toThrow ( 'a URL is required to make a request' ) ;
52
+ expect ( ( ) => {
53
+ ( Ajax . request as any ) ( { } ) ;
54
+ } ) . toThrow ( 'a URL is required to make a request' ) ;
55
+ } ) ;
56
+ it ( 'should make request with only url' , ( ) => {
57
+ expect ( request ( { url : '/users' } ) . url ) . toEqual ( '/users' ) ;
58
+ } ) ;
57
59
} ) ;
58
- } ) ;
59
-
60
- describe ( 'request headers' , ( ) => {
61
- mockXHR ( ) ;
62
60
63
- const testCSRF = 'TEST_CSRF_TOKEN' ;
64
- const contentTypeForm = 'application/x-www-form-urlencoded;charset=utf-8' ;
61
+ describe ( 'request headers' , ( ) => {
62
+ mockXHR ( ) ;
65
63
66
- it ( 'should apply DEFAULT_HEADERS' , ( ) => {
67
- const requestHeaders = request ( { url : '/projects' } ) . requestHeaders ;
68
-
69
- expect ( requestHeaders [ 'Content-Type' ] ) . toEqual ( contentTypeForm ) ;
70
- expect ( requestHeaders [ 'X-Requested-With' ] ) . toEqual ( 'XMLHttpRequest' ) ;
71
- expect ( requestHeaders [ 'X-LABKEY-CSRF' ] ) . toEqual ( testCSRF ) ;
72
- } ) ;
73
- it ( 'should apply custom headers' , ( ) => {
74
- const requestHeaders = request ( {
75
- url : '/projects' ,
76
- headers : {
77
- foo : 'bar' ,
78
- } ,
79
- } ) . requestHeaders ;
80
-
81
- expect ( requestHeaders [ 'foo' ] ) . toEqual ( 'bar' ) ;
82
- expect ( requestHeaders [ 'X-LABKEY-CSRF' ] ) . toEqual ( testCSRF ) ; // it shouldn't lose other headers
83
- } ) ;
84
- } ) ;
64
+ const testCSRF = 'TEST_CSRF_TOKEN' ;
65
+ const contentTypeForm = 'application/x-www-form-urlencoded;charset=utf-8' ;
85
66
86
- describe ( 'request method ', ( ) => {
87
- mockXHR ( ) ;
67
+ it ( 'should apply DEFAULT_HEADERS ', ( ) => {
68
+ const requestHeaders = request ( { url : '/projects' } ) . requestHeaders ;
88
69
89
- it ( 'should default to GET' , ( ) => {
90
- expect ( request ( { url : '/users' } ) . method ) . toEqual ( 'GET' ) ;
91
- } ) ;
92
- it ( 'should default to POST with data' , ( ) => {
93
- expect (
94
- request ( {
95
- url : '/users' ,
96
- jsonData : {
97
- userId : 123 ,
98
- } ,
99
- } ) . method
100
- ) . toEqual ( 'POST' ) ;
101
- } ) ;
102
- it ( 'should accept GET with data' , ( ) => {
103
- expect (
104
- request ( {
105
- url : '/users' ,
106
- method : 'GET' ,
107
- jsonData : {
108
- userId : 123 ,
70
+ expect ( requestHeaders [ 'Content-Type' ] ) . toEqual ( contentTypeForm ) ;
71
+ expect ( requestHeaders [ 'X-Requested-With' ] ) . toEqual ( 'XMLHttpRequest' ) ;
72
+ expect ( requestHeaders [ 'X-LABKEY-CSRF' ] ) . toEqual ( testCSRF ) ;
73
+ } ) ;
74
+ it ( 'should apply custom headers' , ( ) => {
75
+ const requestHeaders = request ( {
76
+ url : '/projects' ,
77
+ headers : {
78
+ foo : 'bar' ,
109
79
} ,
110
- } ) . method
111
- ) . toEqual ( 'GET' ) ;
112
- } ) ;
113
- it ( 'should accept any method' , ( ) => {
114
- expect ( request ( { url : '/users' , method : 'DELETE' } ) . method ) . toEqual ( 'DELETE' ) ;
115
- expect ( request ( { url : '/users' , method : 'PUT' } ) . method ) . toEqual ( 'PUT' ) ;
116
- expect ( request ( { url : '/users' , method : 'BEEP' } ) . method ) . toEqual ( 'BEEP' ) ;
117
- } ) ;
118
- } ) ;
119
-
120
- describe ( 'getFilenameFromContentDisposition' , ( ) => {
121
- it ( 'should not find a file if there is no attachment prefix' , ( ) => {
122
- expect ( getFilenameFromContentDisposition ( 'other: filename=data.tsv' ) ) . toBeUndefined ( ) ;
123
- expect ( getFilenameFromContentDisposition ( 'other: filename=attachment.tsv' ) ) . toBeUndefined ( ) ;
124
- } ) ;
80
+ } ) . requestHeaders ;
125
81
126
- it ( 'should find a file with the filename= prefix' , ( ) => {
127
- expect ( getFilenameFromContentDisposition ( 'attachment; filename=data.xlsx' ) ) . toBe ( 'data.xlsx' ) ;
128
- expect ( getFilenameFromContentDisposition ( 'attachment; filename=d%20ata.xlsx' ) ) . toBe ( 'd ata.xlsx' ) ;
82
+ expect ( requestHeaders [ 'foo' ] ) . toEqual ( 'bar' ) ;
83
+ expect ( requestHeaders [ 'X-LABKEY-CSRF' ] ) . toEqual ( testCSRF ) ; // it shouldn't lose other headers
84
+ } ) ;
129
85
} ) ;
130
86
131
- it ( 'should find a file with the filename*= prefix' , ( ) => {
132
- expect ( getFilenameFromContentDisposition ( 'attachment; filename*=data.xlsx' ) ) . toBe ( 'data.xlsx' ) ;
133
- expect ( getFilenameFromContentDisposition ( 'attachment; filename*=d%20ata.xlsx' ) ) . toBe ( 'd ata.xlsx' ) ;
134
- expect ( getFilenameFromContentDisposition ( "attachment; filename*=UTF-8''data.xlsx" ) ) . toBe ( 'data.xlsx' ) ;
135
- expect ( getFilenameFromContentDisposition ( "attachment; filename*=UTF-8''d%20ata.xlsx" ) ) . toBe ( 'd ata.xlsx' ) ;
87
+ describe ( 'request method' , ( ) => {
88
+ mockXHR ( ) ;
89
+
90
+ it ( 'should default to GET' , ( ) => {
91
+ expect ( request ( { url : '/users' } ) . method ) . toEqual ( 'GET' ) ;
92
+ } ) ;
93
+ it ( 'should default to POST with data' , ( ) => {
94
+ expect (
95
+ request ( {
96
+ url : '/users' ,
97
+ jsonData : {
98
+ userId : 123 ,
99
+ } ,
100
+ } ) . method
101
+ ) . toEqual ( 'POST' ) ;
102
+ } ) ;
103
+ it ( 'should accept GET with data' , ( ) => {
104
+ expect (
105
+ request ( {
106
+ url : '/users' ,
107
+ method : 'GET' ,
108
+ jsonData : {
109
+ userId : 123 ,
110
+ } ,
111
+ } ) . method
112
+ ) . toEqual ( 'GET' ) ;
113
+ } ) ;
114
+ it ( 'should accept any method' , ( ) => {
115
+ expect ( request ( { url : '/users' , method : 'DELETE' } ) . method ) . toEqual ( 'DELETE' ) ;
116
+ expect ( request ( { url : '/users' , method : 'PUT' } ) . method ) . toEqual ( 'PUT' ) ;
117
+ expect ( request ( { url : '/users' , method : 'BEEP' } ) . method ) . toEqual ( 'BEEP' ) ;
118
+ } ) ;
136
119
} ) ;
137
120
138
- it ( 'should use the first filename specified' , ( ) => {
139
- expect ( getFilenameFromContentDisposition ( 'attachment; filename*=data.xlsx; filename=other.csv' ) ) . toBe (
140
- 'data.xlsx'
141
- ) ;
142
- expect ( getFilenameFromContentDisposition ( 'attachment; filename=data.xlsx; filename*=other.csv' ) ) . toBe (
143
- 'data.xlsx'
144
- ) ;
145
- expect ( getFilenameFromContentDisposition ( "attachment; filename*=UTF-8''d%20ata.xlsx; filename=other.csv" ) ) . toBe (
146
- 'd ata.xlsx'
147
- ) ;
121
+ describe ( 'getFilenameFromContentDisposition' , ( ) => {
122
+ it ( 'should not find a file if there is no attachment prefix' , ( ) => {
123
+ expect ( getFilenameFromContentDisposition ( 'other; filename=data.tsv' ) ) . toBeUndefined ( ) ;
124
+ expect ( getFilenameFromContentDisposition ( 'other; filename=attachment.tsv' ) ) . toBeUndefined ( ) ;
125
+ } ) ;
126
+
127
+ it ( 'should not find a file if there is not a valid filename prefix' , ( ) => {
128
+ expect ( getFilenameFromContentDisposition ( 'attachment; filename=d ata.xl sx' ) ) . toBeUndefined ( ) ;
129
+ expect ( getFilenameFromContentDisposition ( 'attachment; filename*=data.tsv' ) ) . toBeUndefined ( ) ;
130
+ expect ( getFilenameFromContentDisposition ( 'attachment; filename*=attachment.tsv' ) ) . toBeUndefined ( ) ;
131
+ } ) ;
132
+
133
+ it ( 'should find a file with the filename= prefix' , ( ) => {
134
+ expect ( getFilenameFromContentDisposition ( 'attachment; filename=data.xlsx' ) ) . toBe ( 'data.xlsx' ) ;
135
+ expect ( getFilenameFromContentDisposition ( 'attachment; filename="d ata.xl sx"' ) ) . toBe ( 'd ata.xl sx' ) ;
136
+ expect ( getFilenameFromContentDisposition ( 'attachment;filename="plans.pdf" \t; \t\t foo=bar' ) ) . toBe (
137
+ 'plans.pdf'
138
+ ) ;
139
+ expect ( getFilenameFromContentDisposition ( 'attachment; filename="£ rates.pdf"' ) ) . toBe ( '£ rates.pdf' ) ;
140
+ } ) ;
141
+
142
+ it ( 'should find a file with the filename*= prefix' , ( ) => {
143
+ expect (
144
+ getFilenameFromContentDisposition ( "attachment; filename=data.xlsx; filename*=UTF-8''datastar.xlsx" )
145
+ ) . toBe ( 'datastar.xlsx' ) ;
146
+ expect (
147
+ getFilenameFromContentDisposition ( 'attachment; filename="d ata.xl sx"; filename*=utf-8\'\'d%20ata.xlsx' )
148
+ ) . toBe ( 'd ata.xlsx' ) ;
149
+ expect ( getFilenameFromContentDisposition ( "attachment; filename*=UTF-8''%E2%82%AC%20rates.pdf" ) ) . toBe (
150
+ '€ rates.pdf'
151
+ ) ;
152
+ expect (
153
+ getFilenameFromContentDisposition ( "attachment; filename*=utf-8''data.xlsx; filename=other.csv" )
154
+ ) . toBe ( 'data.xlsx' ) ;
155
+ expect (
156
+ getFilenameFromContentDisposition ( "attachment; filename=data.xlsx; filename*=utf-8''other.csv" )
157
+ ) . toBe ( 'other.csv' ) ;
158
+ expect (
159
+ getFilenameFromContentDisposition ( "attachment; filename*=UTF-8''d%20ata.xlsx; filename=other.csv" )
160
+ ) . toBe ( 'd ata.xlsx' ) ;
161
+ // Issue 50628: verify content-disposition parsing of filenames that include encoded characters
162
+ expect (
163
+ getFilenameFromContentDisposition (
164
+ 'attachment; filename="=?UTF-8?Q?ELN-1005-20240903-5523_London,_England.pdf?="; filename*=UTF-8\'\'ELN-1005-20240903-5523%20London%2C%20England.pdf'
165
+ )
166
+ ) . toBe ( 'ELN-1005-20240903-5523 London, England.pdf' ) ;
167
+ } ) ;
148
168
} ) ;
149
169
} ) ;
0 commit comments