Simplify fetch calls on high level

This commit is contained in:
Pig Fang 2018-09-11 18:53:18 +08:00
parent ab34d7aa4f
commit 205a8f54f0
4 changed files with 55 additions and 42 deletions

View File

@ -112,7 +112,6 @@
<script>
import FileUpload from 'vue-upload-component';
import toastr from 'toastr';
import { walkFetch } from '../../js/net';
import { swal } from '../../js/notify';
export default {
@ -168,16 +167,7 @@ export default {
data.append('public', !this.isPrivate);
this.uploading = true;
const request = new Request(`${blessing.base_url}/skinlib/upload`, {
body: data,
credentials: 'same-origin',
headers: {
Accept: 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
},
method: 'POST'
});
const { errno, msg, tid } = await walkFetch(request);
const { errno, msg, tid } = await this.$http.post('/skinlib/upload', data);
if (errno === 0) {
await swal({ type: 'success', text: msg });
toastr.info(this.$t('skinlib.redirecting'));

View File

@ -9,7 +9,6 @@ export const init = {
credentials: 'same-origin',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
};
@ -27,11 +26,16 @@ export async function walkFetch(request) {
try {
const response = await fetch(request);
if (response.ok) {
return response.json();
return response.headers.get('Content-Type') === 'application/json'
? response.json()
: response.text();
} else {
showAjaxError(await response.text());
const text = await response.text();
emit('fetchError', text);
showAjaxError(text);
}
} catch (error) {
emit('fetchError', error);
showAjaxError(error);
}
}
@ -55,11 +59,16 @@ export async function post(url, data = empty) {
data
});
return walkFetch(new Request(`${blessing.base_url}${url}`, {
body: JSON.stringify(data),
const isFormData = data instanceof FormData;
const request = new Request(`${blessing.base_url}${url}`, {
body: isFormData ? data : JSON.stringify(data),
method: 'POST',
...init
}));
});
!isFormData && request.headers.set('Content-Type', 'application/json');
return walkFetch(request);
}
Vue.use(_Vue => {
@ -69,4 +78,4 @@ Vue.use(_Vue => {
};
});
blessing.fetch = { get, post, walkFetch };
blessing.fetch = { get, post };

View File

@ -4,11 +4,9 @@ import Upload from '@/components/skinlib/Upload';
import { flushPromises } from '../../utils';
import toastr from 'toastr';
import { swal } from '@/js/notify';
import { walkFetch } from '@/js/net';
jest.mock('toastr');
jest.mock('@/js/notify');
jest.mock('@/js/net');
window.blessing.extra = {
textureNameRule: 'rule',
@ -96,7 +94,7 @@ test('process input file', () => {
test('upload file', async () => {
window.Request = jest.fn();
walkFetch
Vue.prototype.$http.post
.mockResolvedValueOnce({ errno: 1, msg: '1' })
.mockResolvedValueOnce({ errno: 0, msg: '0', tid: 1 });
jest.spyOn(toastr, 'info');
@ -108,32 +106,23 @@ test('upload file', async () => {
const button = wrapper.find('.box-footer > button');
button.trigger('click');
expect(walkFetch).not.toBeCalled();
expect(Vue.prototype.$http.post).not.toBeCalled();
expect(toastr.info).toBeCalledWith('skinlib.emptyUploadFile');
wrapper.setData({ files: [{ file: {}, name: 't', type: 'image/jpeg' }] });
button.trigger('click');
expect(walkFetch).not.toBeCalled();
expect(Vue.prototype.$http.post).not.toBeCalled();
expect(toastr.info).toBeCalledWith('skinlib.emptyTextureName');
wrapper.find('[type=text]').setValue('t');
button.trigger('click');
expect(walkFetch).not.toBeCalled();
expect(Vue.prototype.$http.post).not.toBeCalled();
expect(toastr.info).toBeCalledWith('skinlib.fileExtError');
wrapper.setData({ files: [{ file: new Blob, name: 't.png', type: 'image/png' }] });
button.trigger('click');
await flushPromises();
expect(window.Request).toBeCalledWith('/skinlib/upload', {
body: expect.any(FormData),
credentials: 'same-origin',
headers: {
Accept: 'application/json',
'X-CSRF-TOKEN': 'token'
},
method: 'POST'
});
expect(walkFetch).toBeCalledWith(expect.any(window.Request));
expect(Vue.prototype.$http.post).toBeCalledWith('/skinlib/upload', expect.any(FormData));
expect(swal).toBeCalledWith({ type: 'warning', text: '1' });
button.trigger('click');

View File

@ -14,7 +14,8 @@ test('the GET method', async () => {
const json = jest.fn().mockResolvedValue({});
window.fetch = jest.fn().mockResolvedValue({
ok: true,
json
json,
headers: new Map([['Content-Type', 'application/json']])
});
const stub = jest.fn();
@ -34,10 +35,12 @@ test('the GET method', async () => {
});
test('the POST method', async () => {
window.fetch = jest.fn().mockResolvedValue({
ok: true,
json: () => Promise.resolve({})
});
window.fetch = jest.fn()
.mockResolvedValue({
ok: true,
json: () => Promise.resolve({}),
headers: new Map([['Content-Type', 'application/json']])
});
const meta = document.createElement('meta');
meta.name = 'csrf-token';
@ -47,20 +50,29 @@ test('the POST method', async () => {
const stub = jest.fn();
on('beforeFetch', stub);
const formData = new FormData();
await net.post('/abc', formData);
expect(stub).toBeCalledWith({
method: 'POST',
url: '/abc',
data: formData
});
await net.post('/abc', { a: 'b' });
expect(stub).toBeCalledWith({
method: 'POST',
url: '/abc',
data: { a: 'b' }
});
const request = window.fetch.mock.calls[0][0];
const request = window.fetch.mock.calls[1][0];
expect(request.url).toBe('/abc');
expect(request.method).toBe('POST');
expect(request.body).toBe(JSON.stringify({ a: 'b' }));
expect(request.headers.get('X-CSRF-TOKEN')).toBe('token');
expect(request.headers.get('Content-Type')).toBe('application/json');
await net.post('/abc');
expect(window.fetch.mock.calls[1][0].body).toBe('{}');
expect(window.fetch.mock.calls[2][0].body).toBe('{}');
});
test('low level fetch', async () => {
@ -73,17 +85,30 @@ test('low level fetch', async () => {
})
.mockResolvedValueOnce({
ok: true,
json
json,
headers: new Map([['Content-Type', 'application/json']])
})
.mockResolvedValueOnce({
ok: true,
headers: new Map(),
text: () => Promise.resolve('text')
});
const request = { headers: new Map() };
const stub = jest.fn();
on('fetchError', stub);
await net.walkFetch(request);
expect(showAjaxError.mock.calls[0][0]).toBeInstanceOf(Error);
expect(stub).toBeCalledWith(expect.any(Error));
await net.walkFetch(request);
expect(showAjaxError).toBeCalledWith('404');
expect(stub).toBeCalledWith('404');
await net.walkFetch(request);
expect(json).toBeCalled();
expect(await net.walkFetch(request)).toBe('text');
});