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
});
})
.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 toastr = {
success: jest.fn(),
warning: jest.fn()
};
const modal = jest.fn();
const swal = jest.fn()
.mockReturnValueOnce(Promise.resolve())
.mockReturnValueOnce(Promise.reject());
window.fetch = fetch;
window.url = url;
window.toastr = toastr;
window.swal = swal;
window.showAjaxError = jest.fn();
$.fn.modal = modal;
@ -565,6 +579,8 @@ describe('tests for "update" module', () => {
<div id="file-size"></div>
<div id="modal-start-download"></div>
<button id="update-button"></button>
<div class="modal-title"></div>
<div class="modal-body"></div>
`;
const downloadUpdates = require(modulePath).downloadUpdates;
@ -586,6 +602,38 @@ describe('tests for "update" module', () => {
type: 'POST',
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 () => {

View File

@ -1,6 +1,5 @@
/* eslint no-unused-vars: "off" */
jest.dontMock('jquery');
const $ = require('jquery');
window.$ = window.jQuery = $;
@ -9,6 +8,30 @@ window.getQueryString = jest.fn((key, defaultValue) => defaultValue);
describe('tests for "index" module', () => {
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', () => {
const trans = jest.fn(key => key);
const url = jest.fn(path => path);
@ -216,12 +239,16 @@ describe('tests for "index" module', () => {
it('change page', () => {
document.body.innerHTML = `
<div class="overlay" style="display: none"></div>
<select class="pagination">
<option value="2"></option>
</select>
`;
const { onPageChange } = require(modulePath);
onPageChange(1, 'init');
expect($.skinlib.page).toBe(1);
onPageChange(2);
//onPageChange(2);
$('select').trigger('change');
expect($('div').css('display')).not.toBe('none');
expect($.skinlib.page).toBe(2);
});
@ -238,11 +265,65 @@ describe('tests for "index" module', () => {
updateFilter.call($('div'), new Event('click'));
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', () => {
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 () => {
const url = jest.fn(path => path);
window.url = url;

View File

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

View File

@ -8,7 +8,31 @@ $.skinlib = {
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) {
// Initially render skinlib
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) {
let container = $('#skinlib-container').html('');
@ -228,6 +230,7 @@ function updateBreadCrumb() {
if (typeof require !== 'undefined' && typeof module !== 'undefined') {
module.exports = {
initSkinlib,
renderSkinlib,
reloadSkinlib,
updatePaginator,

View File

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

View File

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