Skip to content

Commit f224e94

Browse files
committed
refactor: use axios library instead of Fetch API to make series sales import tests pass under htmlunit.
Workaround for HtmlUnit/htmlunit#78 Part of #1072
1 parent 2a86686 commit f224e94

File tree

5 files changed

+103
-82
lines changed

5 files changed

+103
-82
lines changed

Diff for: pom.xml

+16
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,19 @@
303303
<scope>runtime</scope>
304304
</dependency>
305305

306+
<dependency>
307+
<groupId>org.webjars.npm</groupId>
308+
<artifactId>axios</artifactId>
309+
<version>${axios.version}</version>
310+
<scope>runtime</scope>
311+
<exclusions>
312+
<exclusion>
313+
<groupId>org.webjars.npm</groupId>
314+
<artifactId>follow-redirects</artifactId>
315+
</exclusion>
316+
</exclusions>
317+
</dependency>
318+
306319
<dependency>
307320
<groupId>org.webjars.npm</groupId>
308321
<artifactId>react</artifactId>
@@ -506,6 +519,9 @@
506519
<!-- Redefine default value from spring-boot-dependencies -->
507520
<assertj.version>3.14.0</assertj.version>
508521

522+
<!-- Don't forget to update version in the ResourceUrl class and in the src/main/webapp/WEB-INF/views/series/add.html -->
523+
<axios.version>0.19.2</axios.version>
524+
509525
<!-- Don't forget to update version in the ResourceUrl class -->
510526
<bootstrap.version>3.4.1</bootstrap.version>
511527

Diff for: src/main/frontend/src/components/SeriesSaleImportForm.js

+39-51
Original file line numberDiff line numberDiff line change
@@ -40,61 +40,49 @@ class SeriesSaleImportForm extends React.Component {
4040
validationErrors: []
4141
});
4242

43-
const headers = new Headers();
44-
headers.set('Content-Type', 'application/json; charset=UTF-8');
45-
headers.set(this.props.csrfHeaderName, this.props.csrfTokenValue);
46-
47-
const request = new Request(
43+
axios.post(
4844
this.props.url,
4945
{
50-
method: 'POST',
51-
headers,
52-
body: JSON.stringify({ 'url': this.state.url }),
53-
cache: 'no-store'
46+
'url': this.state.url
47+
},
48+
{
49+
headers: {
50+
[this.props.csrfHeaderName]: this.props.csrfTokenValue,
51+
'Cache-Control': 'no-store'
52+
},
53+
validateStatus: (status) => {
54+
return status == 200 || status == 400;
55+
}
56+
}
57+
).then(response => {
58+
const data = response.data;
59+
if (data.hasOwnProperty('fieldErrors')) {
60+
this.setState({ isDisabled: false, validationErrors: data.fieldErrors.url });
61+
return;
62+
}
63+
64+
const today = DateUtils.formatDateToDdMmYyyy(new Date());
65+
document.getElementById('date').value = today;
66+
document.getElementById('url').value = this.state.url;
67+
68+
if (data.price) {
69+
document.getElementById('price').value = data.price;
70+
}
71+
72+
if (data.currency) {
73+
document.getElementById('currency').value = data.currency;
74+
}
75+
76+
if (data.sellerId) {
77+
document.getElementById('seller').value = data.sellerId;
5478
}
55-
);
79+
80+
this.setState({ isDisabled: false, url: '' });
5681

57-
fetch(request)
58-
.then(response => {
59-
if (response.ok || response.status == 400) {
60-
return response.json();
61-
}
62-
throw new Error(response.statusText);
63-
})
64-
.then(data => {
65-
if (data.hasOwnProperty('fieldErrors')) {
66-
this.setState({
67-
isDisabled: false,
68-
validationErrors: data.fieldErrors.url
69-
});
70-
return;
71-
}
72-
73-
const today = DateUtils.formatDateToDdMmYyyy(new Date());
74-
document.getElementById('date').value = today;
75-
76-
document.getElementById('url').value = this.state.url;
77-
78-
if (data.price) {
79-
document.getElementById('price').value = data.price;
80-
}
81-
82-
if (data.currency) {
83-
document.getElementById('currency').value = data.currency;
84-
}
85-
86-
if (data.sellerId) {
87-
document.getElementById('seller').value = data.sellerId;
88-
}
89-
this.setState({ isDisabled: false, url: '' });
90-
})
91-
.catch(error => {
92-
console.error(error);
93-
this.setState({
94-
isDisabled: false,
95-
hasServerError: true
96-
});
97-
});
82+
}).catch(error => {
83+
console.error(error);
84+
this.setState({ isDisabled: false, hasServerError: true });
85+
});
9886
}
9987

10088
render() {

Diff for: src/main/java/ru/mystamps/web/config/MvcConfig.java

+2
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ public void addResourceHandlers(ResourceHandlerRegistry registry) {
127127
.addResolver(resourceResolver);
128128

129129
// For WebJars. See also ResourceUrl class
130+
registry.addResourceHandler("/public/axios/**")
131+
.addResourceLocations("classpath:/META-INF/resources/webjars/axios/");
130132
registry.addResourceHandler("/public/bootstrap/**")
131133
.addResourceLocations("classpath:/META-INF/resources/webjars/bootstrap/");
132134
registry.addResourceHandler("/public/jquery/**")

Diff for: src/main/java/ru/mystamps/web/feature/site/ResourceUrl.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public final class ResourceUrl {
3232
public static final String STATIC_RESOURCES_URL = "https://stamps.filezz.ru";
3333

3434
// MUST be updated when any of our resources were modified
35-
public static final String RESOURCES_VERSION = "v0.4.2.2";
35+
public static final String RESOURCES_VERSION = "v0.4.2.3";
3636

3737
// CheckStyle: ignore LineLength for next 10 lines
3838
private static final String CATALOG_UTILS_JS = "/public/js/" + RESOURCES_VERSION + "/CatalogUtils.min.js";
@@ -48,6 +48,7 @@ public final class ResourceUrl {
4848
private static final String FAVICON_ICO = "/favicon.ico";
4949

5050
// see also pom.xml and MvcConfig.addResourceHandlers()
51+
private static final String AXIOS_JS = "0.19.2/dist/axios.min.js";
5152
private static final String BOOTSTRAP_CSS = "/bootstrap/3.4.1/css/bootstrap.min.css";
5253
private static final String BOOTSTRAP_JS = "/bootstrap/3.4.1/js/bootstrap.min.js";
5354
private static final String JQUERY_JS = "/jquery/1.9.1/jquery.min.js";
@@ -82,6 +83,7 @@ public static void exposeResourcesToView(Map<String, String> resources, String h
8283
// see also MvcConfig.addResourceHandlers()
8384
public static void exposeWebjarResourcesToView(Map<String, String> resources, boolean useCdn) {
8485
if (useCdn) {
86+
put(resources, "https://unpkg.com/axios@", "AXIOS_JS", AXIOS_JS);
8587
put(resources, "https://maxcdn.bootstrapcdn.com", "BOOTSTRAP_CSS", BOOTSTRAP_CSS);
8688
put(resources, "https://maxcdn.bootstrapcdn.com", "BOOTSTRAP_JS", BOOTSTRAP_JS);
8789
put(resources, "https://yandex.st", "JQUERY_JS", JQUERY_JS);
@@ -93,6 +95,7 @@ public static void exposeWebjarResourcesToView(Map<String, String> resources, bo
9395
return;
9496
}
9597

98+
put(resources, "/public/axios/", "AXIOS_JS", AXIOS_JS);
9699
put(resources, "/public", "BOOTSTRAP_CSS", BOOTSTRAP_CSS);
97100
put(resources, "/public", "BOOTSTRAP_JS", BOOTSTRAP_JS);
98101
put(resources, "/public", "JQUERY_JS", JQUERY_JS);

Diff for: src/main/webapp/WEB-INF/views/series/info.html

+42-30
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,7 @@ <h5 th:text="#{t_add_info_who_selling_series}">Add info about selling/buying thi
788788
/*/-->
789789
<script src="https://unpkg.com/[email protected]/umd/react.development.js" th:src="${REACT_JS}"></script>
790790
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js" th:src="${REACT_DOM_JS}"></script>
791+
<script src="https://unpkg.com/[email protected]/dist/axios.js" th:src="${AXIOS_JS}"></script>
791792
<script src="../../../../../../target/classes/js/components/SeriesSaleImportForm.js" th:src="${SALE_IMPORT_FORM_JS}"></script>
792793
<script th:inline="javascript">
793794
/*[+
@@ -807,37 +808,48 @@ <h5 th:text="#{t_add_info_who_selling_series}">Add info about selling/buying thi
807808
/*[- */
808809
var props = { 'l10n': {} };
809810
var responseCount = 0;
810-
window.fetch = function() {
811-
var possibleOutcomes = [ 'failOnForm', 'failOnField', 'success' ];
812-
var outcome = possibleOutcomes[responseCount % possibleOutcomes.length];
813-
var stubResponse;
814-
815-
if (outcome === 'failOnForm') {
816-
stubResponse = new Response(null, { status: 500, statusText: 'Fake Server Error' });
817-
818-
} else if (outcome === 'failOnField') {
819-
var body = new Blob(
820-
[ '{ "fieldErrors": { "url": [ "Invalid value" ] } }' ],
821-
{ type : 'application/json' }
822-
);
823-
stubResponse = new Response(body, { status: 400 });
824-
825-
} else if (outcome === 'success') {
826-
var body = new Blob(
827-
[ '{ "sellerId": 3, "price": 3.5, "currency" : "USD" }' ],
828-
{ type : 'application/json' }
829-
);
830-
stubResponse = new Response(body, { status: 200 });
811+
window.axios = {
812+
post: function() {
813+
var possibleOutcomes = [ 'failOnForm', 'failOnField', 'success' ];
814+
var outcome = possibleOutcomes[responseCount % possibleOutcomes.length];
815+
var stubResponse;
816+
817+
if (outcome === 'failOnForm') {
818+
stubResponse = {
819+
status: 500,
820+
statusText: 'Fake Server Error'
821+
};
822+
823+
} else if (outcome === 'failOnField') {
824+
stubResponse = {
825+
status: 400,
826+
data: {
827+
"fieldErrors": {
828+
"url": [ "Invalid value" ]
829+
}
830+
}
831+
};
832+
833+
} else if (outcome === 'success') {
834+
stubResponse = {
835+
status: 200,
836+
data: {
837+
"sellerId": 3,
838+
"price": 3.5,
839+
"currency" : "USD"
840+
}
841+
};
842+
}
843+
844+
responseCount++;
845+
846+
return new Promise(function delayExecution(resolve) {
847+
setTimeout(resolve, 500 /* 0.5 second */);
848+
849+
}).then(function returnResponse() {
850+
return stubResponse.status == 500 ? Promise.reject(stubResponse) : Promise.resolve(stubResponse);
851+
});
831852
}
832-
833-
responseCount++;
834-
835-
return new Promise(function delayExecution(resolve) {
836-
setTimeout(resolve, 500 /* 0.5 second */);
837-
838-
}).then(function returnResponse() {
839-
return Promise.resolve(stubResponse);
840-
});
841853
};
842854
/* -]*/
843855

0 commit comments

Comments
 (0)