mirror of
https://github.com/kiwix/kiwix-js.git
synced 2025-08-03 11:16:38 -04:00
Converted Q Unit tests to Mocha Tests (#1301)
* Added Files * Fixed the init file Signed-off-by: THEBOSS0369 <anujkumsharma9876@gmail.com> * Trying again * Adding coverage folders in gitignore * Fixed fallback errors & some grammatical checks Signed-off-by: THEBOSS0369 <anujkumsharma9876@gmail.com> * Added unit test coverage Signed-off-by: THEBOSS0369 <anujkumsharma9876@gmail.com> * Revert "Added unit test coverage" This reverts commit 444e215d79665da1cb8631b9268bdea1f8e701d8. * Fixing merge conflicts Signed-off-by: THEBOSS0369 <anujkumsharma9876@gmail.com> * Integrate tests into workflows Signed-off-by: THEBOSS0369 <anujkumsharma9876@gmail.com> * removing unit-watch Signed-off-by: THEBOSS0369 <anujkumsharma9876@gmail.com> --------- Signed-off-by: THEBOSS0369 <anujkumsharma9876@gmail.com>
This commit is contained in:
parent
c628aa64b6
commit
b3c404451b
14
.github/workflows/CI.yml
vendored
14
.github/workflows/CI.yml
vendored
@ -52,7 +52,7 @@ jobs:
|
||||
run: npm ci
|
||||
|
||||
- name: Unit tests (Linux)
|
||||
run: npm run test-unit-browsers
|
||||
run: npm run test-unit
|
||||
|
||||
- name: Test a full build of the app
|
||||
run: npm run build
|
||||
@ -179,17 +179,7 @@ jobs:
|
||||
run: npm run build-min
|
||||
|
||||
- name: Unit tests (Windows)
|
||||
run: |
|
||||
$AggregateExitCode = 0
|
||||
npm run test-unit-edge
|
||||
$AggregateExitCode += $LastExitCode
|
||||
npm run test-unit-firefox
|
||||
$AggregateExitCode += $LastExitCode
|
||||
if ($AggregateExitCode -ne 0) {
|
||||
echo " "
|
||||
Write-Error "Number of failed tests: $AggregateExitCode"
|
||||
}
|
||||
exit $AggregateExitCode
|
||||
run: npm run test-unit
|
||||
|
||||
- name: End-to-end tests on Edge Chromium (Windows)
|
||||
env:
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -36,6 +36,8 @@ intermediate
|
||||
publish
|
||||
.idea
|
||||
nbproject/private
|
||||
.nyc_output
|
||||
coverage
|
||||
|
||||
# build script local files
|
||||
build/buildinfo.properties
|
||||
|
11
.mocharc.json
Normal file
11
.mocharc.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"extension": ["js"],
|
||||
"spec": "tests/unit/**/*.test.js",
|
||||
"timeout": 5000,
|
||||
"recursive": true,
|
||||
"exit": true,
|
||||
"require": [
|
||||
"@babel/register",
|
||||
"./tests/unit/setup.js"
|
||||
]
|
||||
}
|
20
.nycrc
Normal file
20
.nycrc
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"all": true,
|
||||
"include": [
|
||||
"src/**/*.js"
|
||||
],
|
||||
"exclude": [
|
||||
"**/*.test.js",
|
||||
"tests/**",
|
||||
"node_modules/**"
|
||||
],
|
||||
"reporter": [
|
||||
"text",
|
||||
"lcov"
|
||||
],
|
||||
"check-coverage": true,
|
||||
"branches": 70,
|
||||
"lines": 70,
|
||||
"functions": 70,
|
||||
"statements": 70
|
||||
}
|
7115
package-lock.json
generated
7115
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
24
package.json
24
package.json
@ -14,12 +14,9 @@
|
||||
"prebuild-src": "del-cli dist",
|
||||
"build-src": "rollup --config --file dist/www/js/bundle.js",
|
||||
"del-dist": "del-cli dist",
|
||||
"test": "testcafe all ./tests/unit/initTestCafe.js --app \"http-server --silent -p 8080 .\"",
|
||||
"test-unit-browsers": "testcafe firefox:headless,chrome:headless,edge:headless ./tests/unit/initTestCafe.js --app \"http-server --silent -p 8080 .\"",
|
||||
"test-unit-firefox": "testcafe firefox:headless ./tests/unit/initTestCafe.js --app \"http-server --silent -p 8080 .\"",
|
||||
"test-unit-chrome": "testcafe chrome:headless ./tests/unit/initTestCafe.js --app \"http-server --silent -p 8080 .\"",
|
||||
"test-unit-edge": "testcafe edge:headless ./tests/unit/initTestCafe.js --app \"http-server --silent -p 8080 .\"",
|
||||
"test-unit-mac": "testcafe safari ./tests/unit/initTestCafe.js --app \"http-server --silent -p 8080 .\"",
|
||||
"test": "mocha --experimental-modules --node-option experimental-specifier-resolution=node --require @babel/register --require tests/unit/setup.js 'tests/unit/spec/**/*.test.js'",
|
||||
"test-unit": "mocha --experimental-modules --node-option experimental-specifier-resolution=node --require @babel/register --require tests/unit/setup.js 'tests/unit/spec/**/*.test.js'",
|
||||
"test-unit-coverage": "nyc --experimental-modules --node-option experimental-specifier-resolution=node mocha --require @babel/register --require tests/unit/setup.js 'tests/unit/spec/**/*.test.js'",
|
||||
"web-server": "http-server -p 8080 .",
|
||||
"test-e2e": "npm run test-e2e-firefox && npm run test-e2e-chrome && npm run test-e2e-edge && npm run test-e2e-iemode",
|
||||
"test-e2e-firefox": "npx start-server-and-test 'http-server --silent' 8080 'npx mocha ./tests/e2e/runners/firefox/firefox.e2e.runner.js'",
|
||||
@ -35,12 +32,14 @@
|
||||
"@types/fs-extra": "^9.0.11",
|
||||
"bootstrap": "^4.6.2",
|
||||
"core-js": "3.30.2",
|
||||
"jquery": "^3.7.0"
|
||||
"jquery": "^3.7.0",
|
||||
"xhr2": "^0.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.21.5",
|
||||
"@babel/core": "^7.21.5",
|
||||
"@babel/preset-env": "^7.21.5",
|
||||
"@babel/core": "^7.26.0",
|
||||
"@babel/preset-env": "^7.26.0",
|
||||
"@babel/register": "^7.25.9",
|
||||
"@rollup/plugin-babel": "^6.0.4",
|
||||
"@rollup/plugin-commonjs": "^25.0.7",
|
||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||
@ -48,6 +47,7 @@
|
||||
"@rollup/plugin-terser": "^0.4.4",
|
||||
"@vitejs/plugin-legacy": "^6.0.2",
|
||||
"babel-plugin-polyfill-corejs3": "^0.7.1",
|
||||
"chai": "^5.1.2",
|
||||
"del-cli": "^5.0.0",
|
||||
"eslint": "^8.42.0",
|
||||
"eslint-config-standard": "^17.1.0",
|
||||
@ -55,13 +55,15 @@
|
||||
"eslint-plugin-n": "^16.0.0",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"http-server": "^14.1.1",
|
||||
"mocha": "^10.2.0",
|
||||
"jsdom": "^25.0.1",
|
||||
"mocha": "^10.8.2",
|
||||
"nyc": "^17.1.0",
|
||||
"qunit": "^2.19.4",
|
||||
"rollup": "^4.5.0",
|
||||
"rollup-plugin-copy": "^3.4.0",
|
||||
"selenium-webdriver": "^4.11.1",
|
||||
"sinon": "^19.0.2",
|
||||
"start-server-and-test": "^2.0.0",
|
||||
"testcafe": "^3.0.0",
|
||||
"vite": "^6.2.2"
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +0,0 @@
|
||||
/* global fixture, test */
|
||||
|
||||
import { Selector } from 'testcafe'; // first import testcafe selectors
|
||||
|
||||
fixture`Start QUnit tests`// declare the fixture
|
||||
.page`http://localhost:8080/tests/unit/`; // specify the start page
|
||||
|
||||
// then create a test and place your code within it
|
||||
test('Check for success', async t => {
|
||||
await t
|
||||
// Use the assertion to check if actual header text equals expected text
|
||||
.expect(Selector('#qunit-testresult-display').innerText, { timeout: 10000 }).match(/0\s+failed.+?0\s+skipped.+?0\s+todo/, { timeout: 7000 });
|
||||
});
|
@ -1,5 +1,6 @@
|
||||
/* eslint-disable no-useless-constructor */
|
||||
/**
|
||||
* init.js : Configuration for the library require.js
|
||||
* init.js : Global configuration of the app
|
||||
* This file handles the dependencies between javascript libraries, for the unit tests
|
||||
*
|
||||
* Copyright 2013-2014 Mossroy and contributors
|
||||
@ -34,6 +35,41 @@ params['sourceVerification'] = false;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
var webpMachine = false;
|
||||
|
||||
// Create a mock Image class for Node.js environment
|
||||
if (typeof window === 'undefined') {
|
||||
// We're in Node.js
|
||||
global.Image = class Image {
|
||||
constructor () {
|
||||
this.height = 0;
|
||||
setTimeout(() => {
|
||||
// Simulate successful WebP support
|
||||
this.height = 2;
|
||||
if (typeof this.onload === 'function') {
|
||||
this.onload();
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
};
|
||||
|
||||
global.document = {
|
||||
head: {
|
||||
appendChild: function () {} // Mock appendChild
|
||||
},
|
||||
createElement: function () {
|
||||
return {
|
||||
onload: null,
|
||||
src: ''
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
global.webpHero = {
|
||||
WebpMachine: class WebpMachine {
|
||||
constructor () {}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// We use a self-invoking function here to avoid defining unnecessary global functions and variables
|
||||
(function (callback) {
|
||||
// Tests for native WebP support
|
||||
|
227
tests/unit/setup.js
Normal file
227
tests/unit/setup.js
Normal file
@ -0,0 +1,227 @@
|
||||
/* eslint-disable no-prototype-builtins */
|
||||
/* eslint-disable import/no-named-default */
|
||||
/**
|
||||
* Mocha test environment setup
|
||||
*
|
||||
* This file configures the test environment for Mocha tests,
|
||||
* including any global setup, hooks or configuration needed
|
||||
* before running the tests.
|
||||
*/
|
||||
|
||||
import { JSDOM } from 'jsdom';
|
||||
import { expect, assert } from 'chai';
|
||||
import * as sinon from 'sinon';
|
||||
import { default as jQuery } from 'jquery';
|
||||
|
||||
// Initialize params before anything else
|
||||
globalThis.params = {
|
||||
sourceVerification: false
|
||||
};
|
||||
|
||||
// Create JSDOM instance
|
||||
const dom = new JSDOM('<!DOCTYPE html><html><body></body></html>', {
|
||||
url: 'http://localhost',
|
||||
referrer: 'http://localhost',
|
||||
contentType: 'text/html',
|
||||
includeNodeLocations: true,
|
||||
storageQuota: 10000000,
|
||||
pretendToBeVisual: true,
|
||||
resources: 'usable'
|
||||
});
|
||||
|
||||
// Set up the global environment properly
|
||||
const { window } = dom;
|
||||
const { document } = window;
|
||||
|
||||
// Define self
|
||||
globalThis.self = globalThis;
|
||||
window.self = window;
|
||||
|
||||
// Define Image class before setting up window
|
||||
class Image {
|
||||
constructor () {
|
||||
this.height = 0;
|
||||
this.onload = null;
|
||||
this.onerror = null;
|
||||
|
||||
setTimeout(() => {
|
||||
this.height = 2;
|
||||
if (typeof this.onload === 'function') {
|
||||
this.onload();
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
|
||||
set src (value) {
|
||||
this._src = value;
|
||||
if (this.onload) {
|
||||
setTimeout(this.onload, 0);
|
||||
}
|
||||
}
|
||||
|
||||
get src () {
|
||||
return this._src;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy window properties to global
|
||||
Object.defineProperty(globalThis, 'window', {
|
||||
value: window,
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Object.defineProperty(globalThis, 'document', {
|
||||
value: document,
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
// Make params available on window as well
|
||||
Object.defineProperty(window, 'params', {
|
||||
value: globalThis.params,
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
// Add Image to both global and window
|
||||
Object.defineProperty(globalThis, 'Image', {
|
||||
value: Image,
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
Object.defineProperty(window, 'Image', {
|
||||
value: Image,
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
// Mock Worker if needed for xzdec_wrapper.js
|
||||
class Worker {
|
||||
constructor (stringUrl) {
|
||||
this.url = stringUrl;
|
||||
this.onmessage = null;
|
||||
this.onerror = null;
|
||||
}
|
||||
|
||||
postMessage (msg) {
|
||||
// Implement any worker simulation logic here if needed
|
||||
if (this.onmessage) {
|
||||
setTimeout(() => {
|
||||
this.onmessage({ data: {} });
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
terminate () {
|
||||
// If needed then cleanup logic will be added
|
||||
}
|
||||
}
|
||||
|
||||
globalThis.Worker = Worker;
|
||||
window.Worker = Worker;
|
||||
|
||||
// Add other required globals
|
||||
globalThis.HTMLElement = window.HTMLElement;
|
||||
globalThis.CustomEvent = window.CustomEvent;
|
||||
globalThis.Event = window.Event;
|
||||
globalThis.Node = window.Node;
|
||||
globalThis.location = window.location;
|
||||
globalThis.history = window.history;
|
||||
globalThis.Element = window.Element;
|
||||
|
||||
// Mock webpHero
|
||||
globalThis.webpHero = {
|
||||
WebpMachine: class WebpMachine {
|
||||
constructor (options) {
|
||||
this.options = options;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Setup jQuery
|
||||
const $ = jQuery(window);
|
||||
Object.defineProperty(globalThis, '$', {
|
||||
value: $,
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(globalThis, 'jQuery', {
|
||||
value: $,
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
|
||||
// Setup test utilities
|
||||
globalThis.expect = expect;
|
||||
globalThis.assert = assert;
|
||||
globalThis.sinon = sinon;
|
||||
|
||||
// Add custom test helpers
|
||||
globalThis.createTestElement = (html) => {
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = html;
|
||||
return div.firstElementChild;
|
||||
};
|
||||
|
||||
// Clean up function for tests
|
||||
globalThis.cleanupDOM = () => {
|
||||
document.body.innerHTML = '';
|
||||
};
|
||||
|
||||
// Mock createElement for script tags
|
||||
const originalCreateElement = document.createElement.bind(document);
|
||||
document.createElement = (tagName) => {
|
||||
const element = originalCreateElement(tagName);
|
||||
if (tagName.toLowerCase() === 'script') {
|
||||
setTimeout(() => {
|
||||
if (element.onload) {
|
||||
element.onload();
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
return element;
|
||||
};
|
||||
|
||||
// Add necessary DOM APIs that might be missing
|
||||
if (!window.requestAnimationFrame) {
|
||||
window.requestAnimationFrame = function (callback) {
|
||||
return setTimeout(callback, 0);
|
||||
};
|
||||
}
|
||||
|
||||
if (!window.cancelAnimationFrame) {
|
||||
window.cancelAnimationFrame = function (id) {
|
||||
clearTimeout(id);
|
||||
};
|
||||
}
|
||||
|
||||
// Set up localStorage mock
|
||||
if (!window.localStorage) {
|
||||
window.localStorage = {
|
||||
getItem: function (key) {
|
||||
return this[key] || null;
|
||||
},
|
||||
setItem: function (key, value) {
|
||||
this[key] = value.toString();
|
||||
},
|
||||
removeItem: function (key) {
|
||||
delete this[key];
|
||||
},
|
||||
clear: function () {
|
||||
for (const key in this) {
|
||||
if (this.hasOwnProperty(key)) {
|
||||
delete this[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
319
tests/unit/spec/mocha.test.js
Normal file
319
tests/unit/spec/mocha.test.js
Normal file
@ -0,0 +1,319 @@
|
||||
/* eslint-disable no-unused-expressions */
|
||||
/* eslint-disable no-undef */
|
||||
// Converted Test from test.js file
|
||||
import { expect } from 'chai';
|
||||
import { promises as fs } from 'fs';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { dirname, join } from 'path';
|
||||
import '../js/init.js';
|
||||
import zimArchive from '../../../www/js/lib/zimArchive.js';
|
||||
import zimDirEntry from '../../../www/js/lib/zimDirEntry.js';
|
||||
import util from '../../../www/js/lib/util.js';
|
||||
import uiUtil from '../../../www/js/lib/uiUtil.js';
|
||||
import utf8 from '../../../www/js/lib/utf8.js';
|
||||
|
||||
let localZimArchive;
|
||||
|
||||
/**
|
||||
* Read a file and return it as a Blob
|
||||
*
|
||||
* @param {String} filePath Path to the file
|
||||
* @param {String} name Name to give to the Blob instance
|
||||
* @returns {Promise<Blob>} A Promise for the Blob
|
||||
*/
|
||||
async function readFileAsBlob (filePath, name) {
|
||||
try {
|
||||
const buffer = await fs.readFile(filePath);
|
||||
const blob = new Blob([buffer], { type: 'application/octet-stream' });
|
||||
blob.name = name;
|
||||
return blob;
|
||||
} catch (error) {
|
||||
console.error('Error reading file:', filePath, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the directory of the current module
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
// Load test files before running tests
|
||||
let zimArchiveFiles = [];
|
||||
before(async function () {
|
||||
const testFolder = join(__dirname, '../../../tests/zims/legacy-ray-charles');
|
||||
const splitBlobs = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'].map(function (c) {
|
||||
const filename = 'wikipedia_en_ray_charles_2015-06.zima' + c;
|
||||
return readFileAsBlob(join(testFolder, filename), filename);
|
||||
});
|
||||
|
||||
zimArchiveFiles = await Promise.all(splitBlobs);
|
||||
return new Promise((resolve) => {
|
||||
localZimArchive = new zimArchive.ZIMArchive(zimArchiveFiles, null, function () {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Environment', function () {
|
||||
it('Configure Mocha Test', function () {
|
||||
expect('test').to.equal('test');
|
||||
});
|
||||
|
||||
it('Load archive files', function () {
|
||||
expect(zimArchiveFiles && zimArchiveFiles[0] && zimArchiveFiles[0].size > 0).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
describe('Utils', function () {
|
||||
it('Correctly read an IEEE_754 float from 4 bytes', function () {
|
||||
const byteArray = new Uint8Array([194, 237, 64, 0]);
|
||||
const float = util.readFloatFrom4Bytes(byteArray, 0);
|
||||
expect(float).to.equal(-118.625);
|
||||
});
|
||||
|
||||
it('Handle upper/lower case variation', function () {
|
||||
const testCases = [
|
||||
{ input: 'téléphone', expected: 'Téléphone', description: 'The first letter should be uppercase' },
|
||||
{ input: 'Paris', expected: 'paris', description: 'The first letter should be lowercase' },
|
||||
{ input: 'le Couvre-chef Est sur le porte-manteaux', expected: 'Le Couvre-Chef Est Sur Le Porte-Manteaux', description: 'The first letter of every word should be uppercase' },
|
||||
{ input: 'épée', expected: 'Épée', description: 'The first letter should be uppercase (with accent)' },
|
||||
{ input: '$¥€"«xριστός» †¡Ἀνέστη!"', expected: '$¥€"«Xριστός» †¡ἀνέστη!"', description: 'First non-punctuation/non-currency Unicode letter should be uppercase, second (with breath mark) lowercase' },
|
||||
{ input: 'Καλά Νερά Μαγνησία žižek', expected: 'ΚΑΛΆ ΝΕΡΆ ΜΑΓΝΗΣΊΑ ŽIŽEK', options: 'full', description: 'All Unicode letters should be uppercase' }
|
||||
];
|
||||
|
||||
testCases.forEach(({ input, expected, options, description }) => {
|
||||
const results = options
|
||||
? util.allCaseFirstLetters(input, options)
|
||||
: util.allCaseFirstLetters(input);
|
||||
|
||||
expect(results, description).to.be.an('array');
|
||||
expect(results.some(result => result === expected), description).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
it('Remove parameters from URLs', function () {
|
||||
const baseUrl = "A/Che cosa e l'amore?.html";
|
||||
const testUrls = [
|
||||
"A/Che%20cosa%20e%20l'amore%3F.html?param1=toto¶m2=titi",
|
||||
"A/Che%20cosa%20e%20l'amore%3F.html?param1=toto¶m2=titi#anchor",
|
||||
"A/Che%20cosa%20e%20l'amore%3F.html#anchor"
|
||||
];
|
||||
|
||||
testUrls.forEach(testUrl => {
|
||||
const result = uiUtil.removeUrlParameters(testUrl);
|
||||
// Compare normalized strings (removing special characters)
|
||||
const normalizedResult = decodeURIComponent(result).normalize('NFD').replace(/[\u0300-\u036f]/g, '');
|
||||
const normalizedExpected = baseUrl.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
|
||||
expect(normalizedResult).to.equal(normalizedExpected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('ZIM initialization', function () {
|
||||
it('Set archive as ready', function () {
|
||||
expect(localZimArchive.isReady()).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
describe('ZIM metadata', function () {
|
||||
it('Read ZIM language', async function () {
|
||||
const language = await new Promise(resolve => {
|
||||
localZimArchive.getMetadata('Language', resolve);
|
||||
});
|
||||
expect(language).to.equal('eng');
|
||||
});
|
||||
|
||||
it('Handle missing metadata', async function () {
|
||||
const result = await new Promise(resolve => {
|
||||
localZimArchive.getMetadata('zzz', resolve);
|
||||
});
|
||||
expect(result).to.be.undefined;
|
||||
});
|
||||
});
|
||||
|
||||
describe('ZIM directory entry search and read', function () {
|
||||
it('DirEntry.fromStringId "A Fool for You"', async function () {
|
||||
const aFoolForYouDirEntry = zimDirEntry.DirEntry.fromStringId(
|
||||
localZimArchive.file,
|
||||
'5856|7|A|0|2|A_Fool_for_You.html|A Fool for You|false|undefined'
|
||||
);
|
||||
|
||||
const htmlArticle = await new Promise(resolve => {
|
||||
localZimArchive.readUtf8File(aFoolForYouDirEntry, (_, article) => resolve(article));
|
||||
});
|
||||
|
||||
expect(htmlArticle).to.have.length.above(0);
|
||||
const normalizedArticle = htmlArticle.replace(/[\r\n]/g, ' ');
|
||||
expect(normalizedArticle).to.match(/^.*<h1[^>]*>A Fool for You<\/h1>/);
|
||||
});
|
||||
|
||||
it('FindDirEntriesWithPrefix "A"', async function () {
|
||||
const dirEntryList = await new Promise(resolve => {
|
||||
localZimArchive.findDirEntriesWithPrefix({ prefix: 'A', size: 5 }, resolve, true);
|
||||
});
|
||||
|
||||
expect(dirEntryList).to.have.length(5);
|
||||
expect(dirEntryList[0].getTitleOrUrl()).to.equal('A Fool for You');
|
||||
});
|
||||
|
||||
it('FindDirEntriesWithPrefix "a"', async function () {
|
||||
const dirEntryList = await new Promise(resolve => {
|
||||
localZimArchive.findDirEntriesWithPrefix({ prefix: 'a', size: 5 }, resolve, true);
|
||||
});
|
||||
|
||||
expect(dirEntryList).to.have.length(5);
|
||||
expect(dirEntryList[0].getTitleOrUrl()).to.equal('A Fool for You');
|
||||
});
|
||||
|
||||
it('FindDirEntriesWithPrefix "blues brothers"', async function () {
|
||||
const dirEntryList = await new Promise(resolve => {
|
||||
localZimArchive.findDirEntriesWithPrefix({ prefix: 'blues brothers', size: 5 }, resolve, true);
|
||||
});
|
||||
|
||||
expect(dirEntryList).to.have.length(3);
|
||||
expect(dirEntryList[0].getTitleOrUrl()).to.equal('Blues Brothers (film)');
|
||||
});
|
||||
|
||||
it('Redirect article "(The Night Time Is) The Right Time" to "Night Time Is the Right Time"', async function () {
|
||||
const dirEntry = await localZimArchive.getDirEntryByPath('A/(The_Night_Time_Is)_The_Right_Time.html');
|
||||
expect(dirEntry).to.not.be.null;
|
||||
expect(dirEntry.isRedirect()).to.be.true;
|
||||
expect(dirEntry.getTitleOrUrl()).to.equal('(The Night Time Is) The Right Time');
|
||||
|
||||
const resolvedDirEntry = await new Promise(resolve => {
|
||||
localZimArchive.resolveRedirect(dirEntry, resolve);
|
||||
});
|
||||
|
||||
expect(resolvedDirEntry).to.not.be.null;
|
||||
expect(resolvedDirEntry.isRedirect()).to.be.false;
|
||||
expect(resolvedDirEntry.getTitleOrUrl()).to.equal('Night Time Is the Right Time');
|
||||
});
|
||||
|
||||
it('Redirect article "Raelettes" to "The Raelettes"', async function () {
|
||||
const dirEntry = await localZimArchive.getDirEntryByPath('A/Raelettes.html');
|
||||
expect(dirEntry).to.not.be.null;
|
||||
expect(dirEntry.isRedirect()).to.be.true;
|
||||
expect(dirEntry.getTitleOrUrl()).to.equal('Raelettes');
|
||||
|
||||
const resolvedDirEntry = await new Promise(resolve => {
|
||||
localZimArchive.resolveRedirect(dirEntry, resolve);
|
||||
});
|
||||
|
||||
expect(resolvedDirEntry).to.not.be.null;
|
||||
expect(resolvedDirEntry.isRedirect()).to.be.false;
|
||||
expect(resolvedDirEntry.getTitleOrUrl()).to.equal('The Raelettes');
|
||||
});
|
||||
|
||||
it('Redirect article "Bein Green" to "Bein\' Green"', async function () {
|
||||
const dirEntry = await localZimArchive.getDirEntryByPath('A/Bein_Green.html');
|
||||
expect(dirEntry).to.not.be.null;
|
||||
expect(dirEntry.isRedirect()).to.be.true;
|
||||
expect(dirEntry.getTitleOrUrl()).to.equal('Bein Green');
|
||||
|
||||
const resolvedDirEntry = await new Promise(resolve => {
|
||||
localZimArchive.resolveRedirect(dirEntry, resolve);
|
||||
});
|
||||
|
||||
expect(resolvedDirEntry).to.not.be.null;
|
||||
expect(resolvedDirEntry.isRedirect()).to.be.false;
|
||||
expect(resolvedDirEntry.getTitleOrUrl()).to.equal("Bein' Green");
|
||||
});
|
||||
|
||||
it('Redirect article "America, the Beautiful" to "America the Beautiful"', async function () {
|
||||
const dirEntry = await localZimArchive.getDirEntryByPath('A/America,_the_Beautiful.html');
|
||||
expect(dirEntry).to.not.be.null;
|
||||
expect(dirEntry.isRedirect()).to.be.true;
|
||||
expect(dirEntry.getTitleOrUrl()).to.equal('America, the Beautiful');
|
||||
|
||||
const resolvedDirEntry = await new Promise(resolve => {
|
||||
localZimArchive.resolveRedirect(dirEntry, resolve);
|
||||
});
|
||||
|
||||
expect(resolvedDirEntry).to.not.be.null;
|
||||
expect(resolvedDirEntry.isRedirect()).to.be.false;
|
||||
expect(resolvedDirEntry.getTitleOrUrl()).to.equal('America the Beautiful');
|
||||
});
|
||||
|
||||
it('Load image "m/RayCharles_AManAndHisSoul.jpg"', async function () {
|
||||
const dirEntry = await localZimArchive.getDirEntryByPath('I/m/RayCharles_AManAndHisSoul.jpg');
|
||||
expect(dirEntry).to.not.be.null;
|
||||
expect(dirEntry.namespace + '/' + dirEntry.url).to.equal('I/m/RayCharles_AManAndHisSoul.jpg');
|
||||
expect(dirEntry.getMimetype()).to.equal('image/jpeg');
|
||||
|
||||
const data = await new Promise(resolve => {
|
||||
localZimArchive.readBinaryFile(dirEntry, (_, data) => resolve(data));
|
||||
});
|
||||
|
||||
expect(data.length).to.equal(4951);
|
||||
const beginning = new Uint8Array([255, 216, 255, 224, 0, 16, 74, 70, 73, 70, 0, 1, 1, 0, 0, 1]);
|
||||
expect(data.slice(0, beginning.length).toString()).to.equal(beginning.toString());
|
||||
});
|
||||
|
||||
it('Load stylesheet "-/s/style.css"', async function () {
|
||||
const dirEntry = await localZimArchive.getDirEntryByPath('-/s/style.css');
|
||||
expect(dirEntry).to.not.be.null;
|
||||
expect(dirEntry.namespace + '/' + dirEntry.url).to.equal('-/s/style.css');
|
||||
expect(dirEntry.getMimetype()).to.equal('text/css');
|
||||
|
||||
const data = await new Promise(resolve => {
|
||||
localZimArchive.readBinaryFile(dirEntry, (_, data) => resolve(data));
|
||||
});
|
||||
|
||||
expect(data.length).to.equal(104495);
|
||||
const parsedData = utf8.parse(data);
|
||||
const beginning = '\n/* start http://en.wikipedia.org/w/load.php?debug=false&lang=en&modules=site&only=styles&skin=vector';
|
||||
expect(parsedData.slice(0, beginning.length)).to.equal(beginning);
|
||||
});
|
||||
|
||||
it('Load javascript "-/j/local.js"', async function () {
|
||||
const dirEntry = await localZimArchive.getDirEntryByPath('-/j/local.js');
|
||||
expect(dirEntry).to.not.be.null;
|
||||
expect(dirEntry.namespace + '/' + dirEntry.url).to.equal('-/j/local.js');
|
||||
expect(dirEntry.getMimetype()).to.equal('application/javascript');
|
||||
|
||||
const data = await new Promise(resolve => {
|
||||
localZimArchive.readBinaryFile(dirEntry, (_, data) => resolve(data));
|
||||
});
|
||||
|
||||
expect(data.length).to.equal(41);
|
||||
const parsedData = utf8.parse(data);
|
||||
const beginning = 'console.log( "mw.loader';
|
||||
expect(parsedData.slice(0, beginning.length)).to.equal(beginning);
|
||||
});
|
||||
|
||||
it('Load split article "A/Ray_Charles.html"', async function () {
|
||||
const dirEntry = await localZimArchive.getDirEntryByPath('A/Ray_Charles.html');
|
||||
expect(dirEntry).to.not.be.null;
|
||||
expect(dirEntry.namespace + '/' + dirEntry.url).to.equal('A/Ray_Charles.html');
|
||||
expect(dirEntry.getMimetype()).to.equal('text/html');
|
||||
|
||||
const article = await new Promise(resolve => {
|
||||
localZimArchive.readUtf8File(dirEntry, (_, article) => resolve(article));
|
||||
});
|
||||
|
||||
expect(dirEntry.getTitleOrUrl()).to.equal('Ray Charles');
|
||||
expect(article.length).to.equal(157186);
|
||||
expect(article.indexOf('the only true genius in show business')).to.equal(5535);
|
||||
expect(article.indexOf('Random Access Memories')).to.equal(154107);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Zim random and main articles', function () {
|
||||
it('Find a random article', async function () {
|
||||
const dirEntry = await new Promise(resolve => {
|
||||
localZimArchive.getRandomDirEntry(resolve);
|
||||
});
|
||||
|
||||
expect(dirEntry).to.not.be.null;
|
||||
expect(dirEntry.getTitleOrUrl()).to.not.be.null;
|
||||
});
|
||||
|
||||
it('Find the main article', async function () {
|
||||
const dirEntry = await new Promise(resolve => {
|
||||
localZimArchive.getMainPageDirEntry(resolve);
|
||||
});
|
||||
|
||||
expect(dirEntry).to.not.be.null;
|
||||
expect(dirEntry.getTitleOrUrl()).to.equal('Summary');
|
||||
});
|
||||
});
|
@ -1,398 +0,0 @@
|
||||
/**
|
||||
* tests.js : Unit tests implemented with qunit
|
||||
*
|
||||
* Copyright 2013-2014 Mossroy and contributors
|
||||
* License GPL v3:
|
||||
*
|
||||
* This file is part of Kiwix.
|
||||
*
|
||||
* Kiwix is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Kiwix is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Kiwix (file LICENSE-GPLv3.txt). If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/* global QUnit, Promise */
|
||||
|
||||
// import '../www/js/lib/promisePolyfill.js';
|
||||
// import '../www/js/lib/arrayFromPolyfill.js';
|
||||
import '../js/init.js';
|
||||
// import '../www/js/app.js';
|
||||
import zimArchive from '../../../www/js/lib/zimArchive.js';
|
||||
import zimDirEntry from '../../../www/js/lib/zimDirEntry.js';
|
||||
import util from '../../../www/js/lib/util.js';
|
||||
import uiUtil from '../../../www/js/lib/uiUtil.js';
|
||||
import utf8 from '../../../www/js/lib/utf8.js';
|
||||
|
||||
var localZimArchive;
|
||||
|
||||
/**
|
||||
* Make an HTTP request for a Blob and return a Promise
|
||||
*
|
||||
* @param {String} url URL to download from
|
||||
* @param {String} name Name to give to the Blob instance
|
||||
* @returns {Promise<Blob>} A Promise for the Blob
|
||||
*/
|
||||
function makeBlobRequest (url, name) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', url);
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.readyState === XMLHttpRequest.DONE) {
|
||||
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 0) {
|
||||
var blob = new Blob([xhr.response], { type: 'application/octet-stream' });
|
||||
blob.name = name;
|
||||
resolve(blob);
|
||||
} else {
|
||||
console.error('Error reading file ' + url + ' status:' + xhr.status + ', statusText:' + xhr.statusText);
|
||||
reject(new Error({
|
||||
status: xhr.status,
|
||||
statusText: xhr.statusText
|
||||
}));
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.onerror = function () {
|
||||
console.error('Error reading file ' + url + ' status:' + xhr.status + ', statusText:' + xhr.statusText);
|
||||
reject(new Error({
|
||||
status: xhr.status,
|
||||
statusText: xhr.statusText
|
||||
}));
|
||||
};
|
||||
xhr.responseType = 'blob';
|
||||
xhr.send();
|
||||
});
|
||||
}
|
||||
|
||||
// Let's try to download the ZIM files
|
||||
var zimArchiveFiles = [];
|
||||
|
||||
var splitBlobs = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o'].map(function (c) {
|
||||
var filename = 'wikipedia_en_ray_charles_2015-06.zima' + c;
|
||||
return makeBlobRequest('tests/zims/legacy-ray-charles/' + filename, filename);
|
||||
});
|
||||
Promise.all(splitBlobs)
|
||||
.then(function (values) {
|
||||
zimArchiveFiles = values;
|
||||
}).then(function () {
|
||||
// Create a localZimArchive from selected files, in order to run the following tests
|
||||
localZimArchive = new zimArchive.ZIMArchive(zimArchiveFiles, null, function (zimArchive) {
|
||||
runTests();
|
||||
});
|
||||
});
|
||||
|
||||
var runTests = function () {
|
||||
QUnit.module('environment');
|
||||
QUnit.test('qunit test', function (assert) {
|
||||
assert.equal('test', 'test', 'QUnit is properly configured');
|
||||
});
|
||||
|
||||
QUnit.test('check archive files are read', function (assert) {
|
||||
assert.ok(zimArchiveFiles && zimArchiveFiles[0] && zimArchiveFiles[0].size > 0, 'ZIM file read and not empty');
|
||||
});
|
||||
|
||||
QUnit.module('utils');
|
||||
QUnit.test('check reading an IEEE_754 float from 4 bytes', function (assert) {
|
||||
var byteArray = new Uint8Array(4);
|
||||
// This example is taken from https://fr.wikipedia.org/wiki/IEEE_754#Un_exemple_plus_complexe
|
||||
// 1100 0010 1110 1101 0100 0000 0000 0000
|
||||
byteArray[0] = 194;
|
||||
byteArray[1] = 237;
|
||||
byteArray[2] = 64;
|
||||
byteArray[3] = 0;
|
||||
var float = util.readFloatFrom4Bytes(byteArray, 0);
|
||||
assert.equal(float, -118.625, 'the IEEE_754 float should be converted as -118.625');
|
||||
});
|
||||
QUnit.test('check upper/lower case variations', function (assert) {
|
||||
var testString1 = 'téléphone';
|
||||
var testString2 = 'Paris';
|
||||
var testString3 = 'le Couvre-chef Est sur le porte-manteaux';
|
||||
var testString4 = 'épée';
|
||||
var testString5 = '$¥€“«xριστός» †¡Ἀνέστη!”';
|
||||
var testString6 = 'Καλά Νερά Μαγνησία žižek';
|
||||
assert.equal(util.allCaseFirstLetters(testString1).indexOf('Téléphone') >= 0, true, 'The first letter should be uppercase');
|
||||
assert.equal(util.allCaseFirstLetters(testString2).indexOf('paris') >= 0, true, 'The first letter should be lowercase');
|
||||
assert.equal(util.allCaseFirstLetters(testString3).indexOf('Le Couvre-Chef Est Sur Le Porte-Manteaux') >= 0, true, 'The first letter of every word should be uppercase');
|
||||
assert.equal(util.allCaseFirstLetters(testString4).indexOf('Épée') >= 0, true, 'The first letter should be uppercase (with accent)');
|
||||
assert.equal(util.allCaseFirstLetters(testString5).indexOf('$¥€“«Xριστός» †¡ἀνέστη!”') >= 0, true, 'First non-punctuation/non-currency Unicode letter should be uppercase, second (with breath mark) lowercase');
|
||||
assert.equal(util.allCaseFirstLetters(testString6, 'full').indexOf('ΚΑΛΆ ΝΕΡΆ ΜΑΓΝΗΣΊΑ ŽIŽEK') >= 0, true, 'All Unicode letters should be uppercase');
|
||||
});
|
||||
QUnit.test('check removal of parameters in URL', function (assert) {
|
||||
var baseUrl = "A/Che cosa è l'amore?.html";
|
||||
var testUrls = [
|
||||
"A/Che%20cosa%20%C3%A8%20l'amore%3F.html?param1=toto¶m2=titi",
|
||||
"A/Che%20cosa%20%C3%A8%20l'amore%3F.html?param1=toto¶m2=titi#anchor",
|
||||
"A/Che%20cosa%20%C3%A8%20l'amore%3F.html#anchor"
|
||||
];
|
||||
testUrls.forEach(function (testUrl) {
|
||||
assert.equal(decodeURIComponent(
|
||||
uiUtil.removeUrlParameters(testUrl)
|
||||
), baseUrl);
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.module('ZIM initialisation');
|
||||
QUnit.test('ZIM archive is ready', function (assert) {
|
||||
assert.ok(localZimArchive.isReady() === true, 'ZIM archive should be set as ready');
|
||||
});
|
||||
|
||||
QUnit.module('ZIM metadata');
|
||||
QUnit.test('read ZIM language', function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(1);
|
||||
var callbackFunction = function (language) {
|
||||
assert.equal(language, 'eng', 'The language read inside the Metadata should be "eng" for "English"');
|
||||
done();
|
||||
};
|
||||
localZimArchive.getMetadata('Language', callbackFunction);
|
||||
});
|
||||
QUnit.test('try to read a missing metadata', function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(1);
|
||||
var callbackFunction = function (string) {
|
||||
assert.equal(string, undefined, 'The metadata zzz should not be found inside the ZIM');
|
||||
done();
|
||||
};
|
||||
localZimArchive.getMetadata('zzz', callbackFunction);
|
||||
});
|
||||
|
||||
QUnit.module('zim_direntry_search_and_read');
|
||||
QUnit.test("check DirEntry.fromStringId 'A Fool for You'", function (assert) {
|
||||
var done = assert.async();
|
||||
var aFoolForYouDirEntry = zimDirEntry.DirEntry.fromStringId(localZimArchive.file, '5856|7|A|0|2|A_Fool_for_You.html|A Fool for You|false|undefined');
|
||||
|
||||
assert.expect(2);
|
||||
var callbackFunction = function (dirEntry, htmlArticle) {
|
||||
assert.ok(htmlArticle && htmlArticle.length > 0, 'Article not empty');
|
||||
// Remove new lines
|
||||
htmlArticle = htmlArticle.replace(/[\r\n]/g, ' ');
|
||||
assert.ok(htmlArticle.match('^.*<h1[^>]*>A Fool for You</h1>'), "'A Fool for You' title somewhere in the article");
|
||||
done();
|
||||
};
|
||||
localZimArchive.readUtf8File(aFoolForYouDirEntry, callbackFunction);
|
||||
});
|
||||
QUnit.test("check findDirEntriesWithPrefix 'A'", function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(2);
|
||||
var callbackFunction = function (dirEntryList) {
|
||||
assert.ok(dirEntryList && dirEntryList.length === 5, 'Article list with 5 results');
|
||||
var firstDirEntry = dirEntryList[0];
|
||||
assert.equal(firstDirEntry.getTitleOrUrl(), 'A Fool for You', 'First result should be "A Fool for You"');
|
||||
done();
|
||||
};
|
||||
localZimArchive.findDirEntriesWithPrefix({ prefix: 'A', size: 5 }, callbackFunction, true);
|
||||
});
|
||||
QUnit.test("check findDirEntriesWithPrefix 'a'", function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(2);
|
||||
var callbackFunction = function (dirEntryList) {
|
||||
assert.ok(dirEntryList && dirEntryList.length === 5, 'Article list with 5 results');
|
||||
var firstDirEntry = dirEntryList[0];
|
||||
assert.equal(firstDirEntry.getTitleOrUrl(), 'A Fool for You', 'First result should be "A Fool for You"');
|
||||
done();
|
||||
};
|
||||
localZimArchive.findDirEntriesWithPrefix({ prefix: 'a', size: 5 }, callbackFunction, true);
|
||||
});
|
||||
QUnit.test("check findDirEntriesWithPrefix 'blues brothers'", function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(2);
|
||||
var callbackFunction = function (dirEntryList) {
|
||||
assert.ok(dirEntryList && dirEntryList.length === 3, 'Article list with 3 result');
|
||||
var firstDirEntry = dirEntryList[0];
|
||||
assert.equal(firstDirEntry.getTitleOrUrl(), 'Blues Brothers (film)', 'First result should be "Blues Brothers (film)"');
|
||||
done();
|
||||
};
|
||||
localZimArchive.findDirEntriesWithPrefix({ prefix: 'blues brothers', size: 5 }, callbackFunction, true);
|
||||
});
|
||||
QUnit.test("article '(The Night Time Is) The Right Time' correctly redirects to 'Night Time Is the Right Time'", function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(6);
|
||||
localZimArchive.getDirEntryByPath('A/(The_Night_Time_Is)_The_Right_Time.html').then(function (dirEntry) {
|
||||
assert.ok(dirEntry !== null, 'DirEntry found');
|
||||
if (dirEntry !== null) {
|
||||
assert.ok(dirEntry.isRedirect(), 'DirEntry is a redirect.');
|
||||
assert.equal(dirEntry.getTitleOrUrl(), '(The Night Time Is) The Right Time', 'Correct redirect title name.');
|
||||
localZimArchive.resolveRedirect(dirEntry, function (dirEntry) {
|
||||
assert.ok(dirEntry !== null, 'DirEntry found');
|
||||
assert.ok(!dirEntry.isRedirect(), 'DirEntry is not a redirect.');
|
||||
assert.equal(dirEntry.getTitleOrUrl(), 'Night Time Is the Right Time', 'Correct redirected title name.');
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
QUnit.test("article 'Raelettes' correctly redirects to 'The Raelettes'", function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(6);
|
||||
localZimArchive.getDirEntryByPath('A/Raelettes.html').then(function (dirEntry) {
|
||||
assert.ok(dirEntry !== null, 'DirEntry found');
|
||||
if (dirEntry !== null) {
|
||||
assert.ok(dirEntry.isRedirect(), 'DirEntry is a redirect.');
|
||||
assert.equal(dirEntry.getTitleOrUrl(), 'Raelettes', 'Correct redirect title name.');
|
||||
localZimArchive.resolveRedirect(dirEntry, function (dirEntry) {
|
||||
assert.ok(dirEntry !== null, 'DirEntry found');
|
||||
assert.ok(!dirEntry.isRedirect(), 'DirEntry is not a redirect.');
|
||||
assert.equal(dirEntry.getTitleOrUrl(), 'The Raelettes', 'Correct redirected title name.');
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
QUnit.test("article 'Bein Green' correctly redirects to 'Bein' Green", function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(6);
|
||||
localZimArchive.getDirEntryByPath('A/Bein_Green.html').then(function (dirEntry) {
|
||||
assert.ok(dirEntry !== null, 'DirEntry found');
|
||||
if (dirEntry !== null) {
|
||||
assert.ok(dirEntry.isRedirect(), 'DirEntry is a redirect.');
|
||||
assert.equal(dirEntry.getTitleOrUrl(), 'Bein Green', 'Correct redirect title name.');
|
||||
localZimArchive.resolveRedirect(dirEntry, function (dirEntry) {
|
||||
assert.ok(dirEntry !== null, 'DirEntry found');
|
||||
assert.ok(!dirEntry.isRedirect(), 'DirEntry is not a redirect.');
|
||||
assert.equal(dirEntry.getTitleOrUrl(), "Bein' Green", 'Correct redirected title name.');
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
QUnit.test("article 'America, the Beautiful' correctly redirects to 'America the Beautiful'", function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(6);
|
||||
localZimArchive.getDirEntryByPath('A/America,_the_Beautiful.html').then(function (dirEntry) {
|
||||
assert.ok(dirEntry !== null, 'DirEntry found');
|
||||
if (dirEntry !== null) {
|
||||
assert.ok(dirEntry.isRedirect(), 'DirEntry is a redirect.');
|
||||
assert.equal(dirEntry.getTitleOrUrl(), 'America, the Beautiful', 'Correct redirect title name.');
|
||||
localZimArchive.resolveRedirect(dirEntry, function (dirEntry) {
|
||||
assert.ok(dirEntry !== null, 'DirEntry found');
|
||||
assert.ok(!dirEntry.isRedirect(), 'DirEntry is not a redirect.');
|
||||
assert.equal(dirEntry.getTitleOrUrl(), 'America the Beautiful', 'Correct redirected title name.');
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
QUnit.test("Image 'm/RayCharles_AManAndHisSoul.jpg' can be loaded", function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(5);
|
||||
localZimArchive.getDirEntryByPath('I/m/RayCharles_AManAndHisSoul.jpg').then(function (dirEntry) {
|
||||
assert.ok(dirEntry !== null, 'DirEntry found');
|
||||
if (dirEntry !== null) {
|
||||
assert.equal(dirEntry.namespace + '/' + dirEntry.url, 'I/m/RayCharles_AManAndHisSoul.jpg', 'URL is correct.');
|
||||
assert.equal(dirEntry.getMimetype(), 'image/jpeg', 'MIME type is correct.');
|
||||
localZimArchive.readBinaryFile(dirEntry, function (title, data) {
|
||||
assert.equal(data.length, 4951, 'Data length is correct.');
|
||||
var beginning = new Uint8Array([255, 216, 255, 224, 0, 16, 74, 70,
|
||||
73, 70, 0, 1, 1, 0, 0, 1]);
|
||||
assert.equal(data.slice(0, beginning.length).toString(), beginning.toString(), 'Data beginning is correct.');
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
QUnit.test("Stylesheet '-/s/style.css' can be loaded", function (assert) {
|
||||
var done = assert.async();
|
||||
|
||||
assert.expect(5);
|
||||
localZimArchive.getDirEntryByPath('-/s/style.css').then(function (dirEntry) {
|
||||
assert.ok(dirEntry !== null, 'DirEntry found');
|
||||
if (dirEntry !== null) {
|
||||
assert.equal(dirEntry.namespace + '/' + dirEntry.url, '-/s/style.css', 'URL is correct.');
|
||||
assert.equal(dirEntry.getMimetype(), 'text/css', 'MIME type is correct.');
|
||||
localZimArchive.readBinaryFile(dirEntry, function (dirEntry, data) {
|
||||
assert.equal(data.length, 104495, 'Data length is correct.');
|
||||
data = utf8.parse(data);
|
||||
var beginning = '\n/* start http://en.wikipedia.org/w/load.php?debug=false&lang=en&modules=site&only=styles&skin=vector';
|
||||
assert.equal(data.slice(0, beginning.length), beginning, 'Content starts correctly.');
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
QUnit.test("Javascript '-/j/local.js' can be loaded", function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(5);
|
||||
localZimArchive.getDirEntryByPath('-/j/local.js').then(function (dirEntry) {
|
||||
assert.ok(dirEntry !== null, 'DirEntry found');
|
||||
if (dirEntry !== null) {
|
||||
assert.equal(dirEntry.namespace + '/' + dirEntry.url, '-/j/local.js', 'URL is correct.');
|
||||
assert.equal(dirEntry.getMimetype(), 'application/javascript', 'MIME type is correct.');
|
||||
localZimArchive.readBinaryFile(dirEntry, function (dirEntry, data) {
|
||||
assert.equal(data.length, 41, 'Data length is correct.');
|
||||
data = utf8.parse(data);
|
||||
var beginning = 'console.log( "mw.loader';
|
||||
assert.equal(data.slice(0, beginning.length), beginning, 'Content starts correctly.');
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
QUnit.test("Split article 'A/Ray_Charles.html' can be loaded", function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(7);
|
||||
localZimArchive.getDirEntryByPath('A/Ray_Charles.html').then(function (dirEntry) {
|
||||
assert.ok(dirEntry !== null, 'Title found');
|
||||
if (dirEntry !== null) {
|
||||
assert.equal(dirEntry.namespace + '/' + dirEntry.url, 'A/Ray_Charles.html', 'URL is correct.');
|
||||
assert.equal(dirEntry.getMimetype(), 'text/html', 'MIME type is correct.');
|
||||
localZimArchive.readUtf8File(dirEntry, function (dirEntry2, data) {
|
||||
assert.equal(dirEntry2.getTitleOrUrl(), 'Ray Charles', 'Title is correct.');
|
||||
assert.equal(data.length, 157186, 'Data length is correct.');
|
||||
assert.equal(data.indexOf('the only true genius in show business'), 5535, 'Specific substring at beginning found.');
|
||||
assert.equal(data.indexOf('Random Access Memories'), 154107, 'Specific substring at end found.');
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.module('zim_random_and_main_article');
|
||||
QUnit.test('check that a random article is found', function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(2);
|
||||
var callbackRandomArticleFound = function (dirEntry) {
|
||||
assert.ok(dirEntry !== null, 'One DirEntry should be found');
|
||||
assert.ok(dirEntry.getTitleOrUrl() !== null, 'The random DirEntry should have a title');
|
||||
|
||||
done();
|
||||
};
|
||||
localZimArchive.getRandomDirEntry(callbackRandomArticleFound);
|
||||
});
|
||||
QUnit.test('check that the main article is found', function (assert) {
|
||||
var done = assert.async();
|
||||
assert.expect(2);
|
||||
var callbackMainPageArticleFound = function (dirEntry) {
|
||||
assert.ok(dirEntry !== null, 'Main DirEntry should be found');
|
||||
assert.equal(dirEntry.getTitleOrUrl(), 'Summary', 'The main DirEntry should be called Summary');
|
||||
|
||||
done();
|
||||
};
|
||||
localZimArchive.getMainPageDirEntry(callbackMainPageArticleFound);
|
||||
});
|
||||
|
||||
QUnit.start();
|
||||
};
|
@ -31,7 +31,7 @@ import XZWASM from './xzdec-wasm.js';
|
||||
var XZMachineType = null;
|
||||
|
||||
// Select asm or wasm conditionally
|
||||
if ('WebAssembly' in self) {
|
||||
if ('WebAssembly' in self && 'Fetch' in self) {
|
||||
console.debug('Instantiating WASM xz decoder');
|
||||
XZMachineType = 'WASM';
|
||||
} else {
|
||||
|
@ -95,7 +95,7 @@ var instantiateDecoder = function (instance) {
|
||||
};
|
||||
|
||||
// Select asm or wasm conditionally
|
||||
if ('WebAssembly' in self) {
|
||||
if ('WebAssembly' in self && 'Fetch' in self) {
|
||||
console.debug('Instantiating WASM zstandard decoder');
|
||||
ZSTDMachineType = 'WASM';
|
||||
} else {
|
||||
|
Loading…
x
Reference in New Issue
Block a user