Update JavaScript tests

This commit is contained in:
gplane 2017-11-29 13:52:32 +08:00
parent 4ebd54707e
commit b834264c3e
6 changed files with 235 additions and 97 deletions

View File

@ -548,16 +548,30 @@ describe('tests for "update" module', () => {
file_size: 5000 file_size: 5000
}); });
}) })
.mockImplementationOnce(() => Promise.resolve()); .mockImplementationOnce(() => Promise.resolve())
.mockImplementationOnce(() => Promise.resolve({ msg: 'ok' }))
.mockImplementationOnce(() => Promise.reject())
.mockImplementationOnce(({ beforeSend }) => {
beforeSend && beforeSend();
return Promise.resolve({
file_size: 5000
});
})
.mockImplementationOnce(() => Promise.resolve())
.mockImplementationOnce(() => Promise.resolve({ msg: 'ok' }));
const url = jest.fn(path => path); const url = jest.fn(path => path);
const toastr = { const toastr = {
success: jest.fn(), success: jest.fn(),
warning: jest.fn() warning: jest.fn()
}; };
const modal = jest.fn(); const modal = jest.fn();
const swal = jest.fn()
.mockReturnValueOnce(Promise.resolve())
.mockReturnValueOnce(Promise.reject());
window.fetch = fetch; window.fetch = fetch;
window.url = url; window.url = url;
window.toastr = toastr; window.toastr = toastr;
window.swal = swal;
window.showAjaxError = jest.fn(); window.showAjaxError = jest.fn();
$.fn.modal = modal; $.fn.modal = modal;
@ -565,6 +579,8 @@ describe('tests for "update" module', () => {
<div id="file-size"></div> <div id="file-size"></div>
<div id="modal-start-download"></div> <div id="modal-start-download"></div>
<button id="update-button"></button> <button id="update-button"></button>
<div class="modal-title"></div>
<div class="modal-body"></div>
`; `;
const downloadUpdates = require(modulePath).downloadUpdates; const downloadUpdates = require(modulePath).downloadUpdates;
@ -586,6 +602,38 @@ describe('tests for "update" module', () => {
type: 'POST', type: 'POST',
dataType: 'json' dataType: 'json'
}); });
expect($('.modal-title').html().includes('admin.extracting')).toBe(true);
expect($('.modal-body').html().includes('admin.downloadCompleted')).toBe(true);
expect(swal).toBeCalledWith({ type: 'success', html: 'ok' });
expect(url).toBeCalledWith('/');
await downloadUpdates();
expect(window.showAjaxError).toBeCalled();
await downloadUpdates();
expect(url).toBeCalledWith('/');
});
it('download progress polling', async () => {
const fetch = jest.fn().mockReturnValueOnce(Promise.resolve({ size: 50 }));
const url = jest.fn(path => path);
window.fetch = fetch;
window.url = url;
document.body.innerHTML = `
<div id="imported-progress"></div>
<div class="progress-bar"></div>
`;
const { progressPolling } = require(modulePath);
await progressPolling(100)();
expect(fetch).toBeCalledWith({
url: 'admin/update/download?action=get-file-size',
type: 'GET'
});
expect($('#imported-progress').html()).toBe('50.00');
expect($('.progress-bar').css('width')).toBe('50%');
expect($('.progress-bar').attr('aria-valuenow')).toBe('50.00');
}); });
it('check for updates', async () => { it('check for updates', async () => {

View File

@ -1,6 +1,5 @@
/* eslint no-unused-vars: "off" */ /* eslint no-unused-vars: "off" */
jest.dontMock('jquery');
const $ = require('jquery'); const $ = require('jquery');
window.$ = window.jQuery = $; window.$ = window.jQuery = $;
@ -9,6 +8,30 @@ window.getQueryString = jest.fn((key, defaultValue) => defaultValue);
describe('tests for "index" module', () => { describe('tests for "index" module', () => {
const modulePath = '../skinlib/index'; const modulePath = '../skinlib/index';
it('initialize skin library', () => {
const fetch = jest.fn().mockReturnValue(Promise.resolve({ items: [] }));
const url = jest.fn(path => path);
const trans = jest.fn(key => key);
const showAjaxError = jest.fn();
window.fetch = fetch;
window.url = url;
window.trans = trans;
window.showAjaxError = showAjaxError;
$.fn.jqPaginator = jest.fn();
const { initSkinlib } = require(modulePath);
initSkinlib();
expect(fetch).not.toBeCalled();
document.body.innerHTML = `
<div id="skinlib-container"></div>
<div id="skinlib-paginator"></div>
<div class="sort"></div>
`;
initSkinlib();
expect(fetch).toBeCalled();
});
it('render skin library', () => { it('render skin library', () => {
const trans = jest.fn(key => key); const trans = jest.fn(key => key);
const url = jest.fn(path => path); const url = jest.fn(path => path);
@ -216,12 +239,16 @@ describe('tests for "index" module', () => {
it('change page', () => { it('change page', () => {
document.body.innerHTML = ` document.body.innerHTML = `
<div class="overlay" style="display: none"></div> <div class="overlay" style="display: none"></div>
<select class="pagination">
<option value="2"></option>
</select>
`; `;
const { onPageChange } = require(modulePath); const { onPageChange } = require(modulePath);
onPageChange(1, 'init'); onPageChange(1, 'init');
expect($.skinlib.page).toBe(1); expect($.skinlib.page).toBe(1);
onPageChange(2); //onPageChange(2);
$('select').trigger('change');
expect($('div').css('display')).not.toBe('none'); expect($('div').css('display')).not.toBe('none');
expect($.skinlib.page).toBe(2); expect($.skinlib.page).toBe(2);
}); });
@ -238,11 +265,65 @@ describe('tests for "index" module', () => {
updateFilter.call($('div'), new Event('click')); updateFilter.call($('div'), new Event('click'));
expect($.skinlib.uploader).toBe(4); expect($.skinlib.uploader).toBe(4);
}); });
it('change sort type', () => {
const fetch = jest.fn().mockReturnValue(Promise.resolve());
window.fetch = fetch;
document.body.innerHTML = `
<a class="sort" data-sort="likes"></a>
`;
require(modulePath);
$('a').click();
expect(fetch).toBeCalled();
expect($.skinlib.sort).toBe('likes');
});
it('search texture', async () => {
const fetch = jest.fn().mockReturnValue(Promise.resolve());
window.fetch = fetch;
document.body.innerHTML = `
<form id="search-form">
<input id="navbar-search-input" name="q" value="keyword">
</form>
`;
$('#search-form').trigger('submit');
expect(fetch).toBeCalled();
expect($.skinlib.keyword).toBe('keyword');
});
}); });
describe('tests for "operations" module', () => { describe('tests for "operations" module', () => {
const modulePath = '../skinlib/operations'; const modulePath = '../skinlib/operations';
it('toggle liked', async () => {
const fetch = jest.fn().mockReturnValue(Promise.resolve());
const swal = jest.fn().mockReturnValue(Promise.resolve());
const url = jest.fn(path => path);
window.fetch = fetch;
window.swal = swal;
window.url = url;
document.body.innerHTML = `
<a tid="5" class="anonymous"></a>
`;
const { toggleLiked } = require(modulePath);
await toggleLiked.call($('a'));
expect(fetch).not.toBeCalled();
$('a').removeClass('anonymous');
const originGetJson = $.getJSON;
$.getJSON = jest.fn();
await toggleLiked.call($('a'));
expect($.getJSON).toBeCalled();
$.getJSON = originGetJson;
$('a').addClass('liked');
await toggleLiked.call($('a'));
expect(fetch).toBeCalled();
});
it('add to closet', async () => { it('add to closet', async () => {
const url = jest.fn(path => path); const url = jest.fn(path => path);
window.url = url; window.url = url;

View File

@ -1,12 +1,10 @@
'use strict'; 'use strict';
function downloadUpdates() { async function downloadUpdates() {
var fileSize = 0; console.log('Prepare trno download');
var progress = 0;
console.log('Prepare to download'); try {
const preparation = await fetch({
fetch({
url: url('admin/update/download?action=prepare-download'), url: url('admin/update/download?action=prepare-download'),
type: 'GET', type: 'GET',
dataType: 'json', dataType: 'json',
@ -15,10 +13,10 @@ function downloadUpdates() {
'<i class="fa fa-spinner fa-spin"></i> ' + trans('admin.preparing') '<i class="fa fa-spinner fa-spin"></i> ' + trans('admin.preparing')
).prop('disabled', 'disabled'); ).prop('disabled', 'disabled');
} }
}).then(json => { });
console.log(json); console.log(preparation);
fileSize = json.file_size; const { file_size: fileSize } = preparation;
$('#file-size').html(fileSize); $('#file-size').html(fileSize);
@ -29,63 +27,65 @@ function downloadUpdates() {
console.log('Start downloading'); console.log('Start downloading');
fetch({ // Downloading progress polling
const interval_id = setInterval(progressPolling(fileSize), 300);
const download = await fetch({
url: url('admin/update/download?action=start-download'), url: url('admin/update/download?action=start-download'),
type: 'POST', type: 'POST',
dataType: 'json' dataType: 'json'
}).then(json => { });
// Set progress to 100 when got the response
progress = 100; clearInterval(interval_id);
console.log('Downloading finished'); console.log('Downloading finished');
console.log(json); console.log(download);
}).catch(showAjaxError);
// Downloading progress polling
let interval_id = setInterval(() => {
$('#imported-progress').html(progress);
$('.progress-bar').css('width', progress+'%').attr('aria-valuenow', progress);
if (progress == 100) {
clearInterval(interval_id);
$('.modal-title').html('<i class="fa fa-spinner fa-spin"></i> ' + trans('admin.extracting')); $('.modal-title').html('<i class="fa fa-spinner fa-spin"></i> ' + trans('admin.extracting'));
$('.modal-body').append(`<p>${trans('admin.downloadCompleted')}</p>`); $('.modal-body').append(`<p>${trans('admin.downloadCompleted')}</p>`);
console.log('Start extracting'); console.log('Start extracting');
fetch({ const extract = await fetch({
url: url('admin/update/download?action=extract'), url: url('admin/update/download?action=extract'),
type: 'POST', type: 'POST',
dataType: 'json' dataType: 'json'
}).then(json => { });
console.log('Package extracted and files are covered'); console.log('Package extracted and files are covered');
$('#modal-start-download').modal('toggle'); $('#modal-start-download').modal('toggle');
swal({ swal({
type: 'success', type: 'success',
html: json.msg html: extract.msg
}).then(function () { }).then(function () {
window.location = url('/'); window.location = url('/');
}, function () { }, function () {
window.location = url('/'); window.location = url('/');
}); });
}).catch(showAjaxError); } catch (error) {
showAjaxError(error);
} else { }
fetch({
url: url('admin/update/download?action=get-file-size'),
type: 'GET'
}).then(json => {
progress = (json.size / fileSize * 100).toFixed(2);
console.log('Progress: ' + progress);
}).catch(showAjaxError);
} }
}, 300); function progressPolling(fileSize) {
}).catch(showAjaxError); return async () => {
try {
const { size } = await fetch({
url: url('admin/update/download?action=get-file-size'),
type: 'GET'
});
const progress = (size / fileSize * 100).toFixed(2);
$('#imported-progress').html(progress);
$('.progress-bar')
.css('width', progress + '%')
.attr('aria-valuenow', progress);
} catch (error) {
// No need to show error if failed to get size
}
};
} }
async function checkForUpdates() { async function checkForUpdates() {
@ -104,6 +104,7 @@ async function checkForUpdates() {
if (typeof require !== 'undefined' && typeof module !== 'undefined') { if (typeof require !== 'undefined' && typeof module !== 'undefined') {
module.exports = { module.exports = {
checkForUpdates, checkForUpdates,
progressPolling,
downloadUpdates, downloadUpdates,
}; };
} }

View File

@ -8,7 +8,31 @@ $.skinlib = {
keyword: decodeURI(getQueryString('keyword', '')) keyword: decodeURI(getQueryString('keyword', ''))
}; };
$(document).ready(() => { $(document).ready(initSkinlib);
$('body').on('change', 'select.pagination', function () {
onPageChange(parseInt($(this).val()));
});
$('.filter').click(updateFilter);
$('body').on('click', '.sort', function (e) {
e.preventDefault();
$.skinlib.sort = $(this).data('sort');
console.log('Sort by ' + $.skinlib.sort);
reloadSkinlib();
});
$('body').on('submit', '#search-form', function (e) {
e.preventDefault();
$.skinlib.keyword = $('#navbar-search-input').val();
console.log('Search keyword: ' + $.skinlib.keyword);
reloadSkinlib();
});
function initSkinlib() {
if ($('#skinlib-container').length != 0) { if ($('#skinlib-container').length != 0) {
// Initially render skinlib // Initially render skinlib
requestSkinlibData().then(result => { requestSkinlibData().then(result => {
@ -20,29 +44,7 @@ $(document).ready(() => {
); );
}); });
} }
}); }
$('select.pagination').on('change', function () {
onPageChange(parseInt($(this).val()));
});
$('.filter').click(updateFilter);
$('.sort').click(function (e) {
e.preventDefault();
$.skinlib.sort = $(this).data('sort');
console.log('Sort by ' + $.skinlib.sort);
reloadSkinlib();
});
$('#search-form').submit(function (e) {
e.preventDefault();
$.skinlib.keyword = $('#navbar-search-input').val();
console.log('Search keyword: ' + $.skinlib.keyword);
reloadSkinlib();
});
function renderSkinlib(items) { function renderSkinlib(items) {
let container = $('#skinlib-container').html(''); let container = $('#skinlib-container').html('');
@ -228,6 +230,7 @@ function updateBreadCrumb() {
if (typeof require !== 'undefined' && typeof module !== 'undefined') { if (typeof require !== 'undefined' && typeof module !== 'undefined') {
module.exports = { module.exports = {
initSkinlib,
renderSkinlib, renderSkinlib,
reloadSkinlib, reloadSkinlib,
updatePaginator, updatePaginator,

View File

@ -1,6 +1,8 @@
'use strict'; 'use strict';
$(document).on('click', '.more.like', function () { $(document).on('click', '.more.like', toggleLiked);
function toggleLiked() {
let tid = $(this).attr('tid'); let tid = $(this).attr('tid');
if ($(this).hasClass('anonymous')) if ($(this).hasClass('anonymous'))
@ -11,7 +13,7 @@ $(document).on('click', '.more.like', function () {
} else { } else {
addToCloset(tid); addToCloset(tid);
} }
}); }
function addToCloset(tid) { function addToCloset(tid) {
$.getJSON(url(`skinlib/info/${tid}`), async ({ name }) => { $.getJSON(url(`skinlib/info/${tid}`), async ({ name }) => {
@ -222,6 +224,7 @@ async function deleteTexture(tid) {
if (typeof require !== 'undefined' && typeof module !== 'undefined') { if (typeof require !== 'undefined' && typeof module !== 'undefined') {
module.exports = { module.exports = {
toggleLiked,
addToCloset, addToCloset,
changePrivacy, changePrivacy,
deleteTexture, deleteTexture,

View File

@ -1,5 +1,7 @@
/* global MSP */ /* global MSP */
// TODO: Help wanted. This file needs to be tested.
'use strict'; 'use strict';
$('body') $('body')