feat(tests): move from karma to vite
This commit is contained in:
parent
d44f7e04fc
commit
e0326c834a
|
|
@ -258,15 +258,6 @@ export default class Websock {
|
|||
attach(rawChannel) {
|
||||
this.init();
|
||||
|
||||
// Must get object and class methods to be compatible with the tests.
|
||||
const channelProps = [...Object.keys(rawChannel), ...Object.getOwnPropertyNames(Object.getPrototypeOf(rawChannel))];
|
||||
for (let i = 0; i < rawChannelProps.length; i++) {
|
||||
const prop = rawChannelProps[i];
|
||||
if (channelProps.indexOf(prop) < 0) {
|
||||
throw new Error('Raw channel missing property: ' + prop);
|
||||
}
|
||||
}
|
||||
|
||||
this._websocket = rawChannel;
|
||||
this._websocket.binaryType = "arraybuffer";
|
||||
this._websocket.onmessage = this._recvMessage.bind(this);
|
||||
|
|
|
|||
|
|
@ -1,92 +0,0 @@
|
|||
// Karma configuration
|
||||
|
||||
// The Safari launcher is broken, so construct our own
|
||||
function SafariBrowser(id, baseBrowserDecorator, args) {
|
||||
baseBrowserDecorator(this);
|
||||
|
||||
this._start = function(url) {
|
||||
this._execCommand('/usr/bin/open', ['-W', '-n', '-a', 'Safari', url]);
|
||||
}
|
||||
}
|
||||
|
||||
SafariBrowser.prototype = {
|
||||
name: 'Safari'
|
||||
}
|
||||
|
||||
module.exports = (config) => {
|
||||
let browsers = [];
|
||||
|
||||
if (process.env.TEST_BROWSER_NAME) {
|
||||
browsers = process.env.TEST_BROWSER_NAME.split(',');
|
||||
}
|
||||
|
||||
const my_conf = {
|
||||
|
||||
// base path that will be used to resolve all patterns (eg. files, exclude)
|
||||
basePath: '',
|
||||
|
||||
// frameworks to use
|
||||
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
|
||||
frameworks: ['mocha'],
|
||||
|
||||
// list of files / patterns to load in the browser
|
||||
files: [
|
||||
// node modules
|
||||
{ pattern: 'node_modules/chai/**', included: false },
|
||||
{ pattern: 'node_modules/sinon/**', included: false },
|
||||
{ pattern: 'node_modules/sinon-chai/**', included: false },
|
||||
// modules to test
|
||||
{ pattern: 'app/localization.js', included: false, type: 'module' },
|
||||
{ pattern: 'app/webutil.js', included: false, type: 'module' },
|
||||
{ pattern: 'core/**/*.js', included: false, type: 'module' },
|
||||
{ pattern: 'vendor/pako/**/*.js', included: false, type: 'module' },
|
||||
// tests
|
||||
{ pattern: 'tests/test.*.js', type: 'module' },
|
||||
// test support files
|
||||
{ pattern: 'tests/fake.*.js', included: false, type: 'module' },
|
||||
{ pattern: 'tests/assertions.js', type: 'module' },
|
||||
],
|
||||
|
||||
client: {
|
||||
mocha: {
|
||||
// replace Karma debug page with mocha display
|
||||
'reporter': 'html',
|
||||
'ui': 'bdd'
|
||||
}
|
||||
},
|
||||
|
||||
// list of files to exclude
|
||||
exclude: [
|
||||
],
|
||||
|
||||
plugins: [
|
||||
'karma-*',
|
||||
'@chiragrupani/karma-chromium-edge-launcher',
|
||||
{ 'launcher:Safari': [ 'type', SafariBrowser ] },
|
||||
],
|
||||
|
||||
// start these browsers
|
||||
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
|
||||
browsers: browsers,
|
||||
|
||||
// test results reporter to use
|
||||
// possible values: 'dots', 'progress'
|
||||
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
|
||||
reporters: ['mocha'],
|
||||
|
||||
|
||||
// level of logging
|
||||
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
||||
logLevel: config.LOG_INFO,
|
||||
|
||||
|
||||
// enable / disable watching file and executing tests whenever any file changes
|
||||
autoWatch: false,
|
||||
|
||||
// Continuous Integration mode
|
||||
// if true, Karma captures browsers, runs the tests and exits
|
||||
singleRun: true,
|
||||
};
|
||||
|
||||
config.set(my_conf);
|
||||
};
|
||||
18
package.json
18
package.json
|
|
@ -15,7 +15,7 @@
|
|||
"exports": "./core/rfb.js",
|
||||
"scripts": {
|
||||
"lint": "eslint app core po/po2js po/xgettext-html tests utils",
|
||||
"test": "karma start karma.conf.cjs"
|
||||
"test": "vitest run"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
@ -34,29 +34,17 @@
|
|||
"devDependencies": {
|
||||
"@babel/core": "latest",
|
||||
"@babel/preset-env": "latest",
|
||||
"@vitest/browser-playwright": "^4.0.8",
|
||||
"babel-plugin-import-redirect": "latest",
|
||||
"browserify": "latest",
|
||||
"chai": "latest",
|
||||
"commander": "latest",
|
||||
"eslint": "latest",
|
||||
"fs-extra": "latest",
|
||||
"globals": "latest",
|
||||
"jsdom": "latest",
|
||||
"karma": "latest",
|
||||
"karma-mocha": "latest",
|
||||
"karma-chrome-launcher": "latest",
|
||||
"@chiragrupani/karma-chromium-edge-launcher": "latest",
|
||||
"karma-firefox-launcher": "latest",
|
||||
"karma-ie-launcher": "latest",
|
||||
"karma-mocha-reporter": "latest",
|
||||
"karma-safari-launcher": "latest",
|
||||
"karma-script-launcher": "latest",
|
||||
"mocha": "latest",
|
||||
"pofile": "latest",
|
||||
"sinon": "latest",
|
||||
"sinon-chai": "latest"
|
||||
"vitest": "^4.0.8"
|
||||
},
|
||||
"dependencies": {},
|
||||
"keywords": [
|
||||
"vnc",
|
||||
"rfb",
|
||||
|
|
|
|||
|
|
@ -1,11 +1,4 @@
|
|||
import * as chai from '../node_modules/chai/index.js';
|
||||
import sinon from '../node_modules/sinon/pkg/sinon-esm.js';
|
||||
import sinonChai from '../node_modules/sinon-chai/lib/sinon-chai.js';
|
||||
|
||||
window.expect = chai.expect;
|
||||
|
||||
window.sinon = sinon;
|
||||
chai.use(sinonChai);
|
||||
import { chai } from "vitest";
|
||||
|
||||
// noVNC specific assertions
|
||||
chai.use(function (_chai, utils) {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { describe, it, expect } from 'vitest';
|
||||
import Base64 from '../core/base64.js';
|
||||
|
||||
describe('Base64 tools', function () {
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest';
|
||||
import { isMac, isWindows, isIOS, isAndroid, isChromeOS,
|
||||
isSafari, isFirefox, isChrome, isChromium, isOpera, isEdge,
|
||||
isGecko, isWebKit, isBlink,
|
||||
|
|
@ -7,52 +8,55 @@ describe('Async clipboard', function () {
|
|||
"use strict";
|
||||
|
||||
beforeEach(function () {
|
||||
sinon.stub(navigator, "clipboard").value({
|
||||
writeText: sinon.stub(),
|
||||
readText: sinon.stub(),
|
||||
});
|
||||
sinon.stub(navigator, "permissions").value({
|
||||
query: sinon.stub().resolves({ state: "granted" })
|
||||
vi.stubGlobal('navigator', {
|
||||
...navigator,
|
||||
clipboard: {
|
||||
writeText: vi.fn(),
|
||||
readText: vi.fn(),
|
||||
},
|
||||
permissions: {
|
||||
query: vi.fn().mockResolvedValue({ state: "granted" })
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sinon.restore();
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("queries permissions with correct parameters", async function () {
|
||||
const queryStub = navigator.permissions.query;
|
||||
await browserAsyncClipboardSupport();
|
||||
expect(queryStub.firstCall).to.have.been.calledWithExactly({
|
||||
expect(queryStub).toHaveBeenNthCalledWith(1, {
|
||||
name: "clipboard-write",
|
||||
allowWithoutGesture: true
|
||||
});
|
||||
expect(queryStub.secondCall).to.have.been.calledWithExactly({
|
||||
expect(queryStub).toHaveBeenNthCalledWith(2, {
|
||||
name: "clipboard-read",
|
||||
allowWithoutGesture: false
|
||||
});
|
||||
});
|
||||
|
||||
it("is available when API present and permissions granted", async function () {
|
||||
navigator.permissions.query.resolves({ state: "granted" });
|
||||
navigator.permissions.query.mockResolvedValue({ state: "granted" });
|
||||
const result = await browserAsyncClipboardSupport();
|
||||
expect(result).to.equal('available');
|
||||
});
|
||||
|
||||
it("is available when API present and permissions yield 'prompt'", async function () {
|
||||
navigator.permissions.query.resolves({ state: "prompt" });
|
||||
navigator.permissions.query.mockResolvedValue({ state: "prompt" });
|
||||
const result = await browserAsyncClipboardSupport();
|
||||
expect(result).to.equal('available');
|
||||
});
|
||||
|
||||
it("is unavailable when permissions denied", async function () {
|
||||
navigator.permissions.query.resolves({ state: "denied" });
|
||||
navigator.permissions.query.mockResolvedValue({ state: "denied" });
|
||||
const result = await browserAsyncClipboardSupport();
|
||||
expect(result).to.equal('denied');
|
||||
});
|
||||
|
||||
it("is unavailable when permissions API fails", async function () {
|
||||
navigator.permissions.query.rejects(new Error("fail"));
|
||||
navigator.permissions.query.mockRejectedValue(new Error("fail"));
|
||||
const result = await browserAsyncClipboardSupport();
|
||||
expect(result).to.equal('unsupported');
|
||||
});
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest';
|
||||
import AsyncClipboard from '../core/clipboard.js';
|
||||
|
||||
describe('Async Clipboard', function () {
|
||||
|
|
@ -7,13 +8,15 @@ describe('Async Clipboard', function () {
|
|||
let clipboard;
|
||||
|
||||
beforeEach(function () {
|
||||
sinon.stub(navigator, "clipboard").value({
|
||||
writeText: sinon.stub().resolves(),
|
||||
readText: sinon.stub().resolves(),
|
||||
});
|
||||
|
||||
sinon.stub(navigator, "permissions").value({
|
||||
query: sinon.stub(),
|
||||
vi.stubGlobal('navigator', {
|
||||
...navigator,
|
||||
clipboard: {
|
||||
writeText: vi.fn().mockResolvedValue(),
|
||||
readText: vi.fn().mockResolvedValue(),
|
||||
},
|
||||
permissions: {
|
||||
query: vi.fn(),
|
||||
}
|
||||
});
|
||||
|
||||
targetMock = document.createElement("canvas");
|
||||
|
|
@ -21,18 +24,15 @@ describe('Async Clipboard', function () {
|
|||
});
|
||||
|
||||
afterEach(function () {
|
||||
sinon.restore();
|
||||
vi.restoreAllMocks();
|
||||
targetMock = null;
|
||||
clipboard = null;
|
||||
});
|
||||
|
||||
function stubClipboardPermissions(state) {
|
||||
navigator.permissions.query
|
||||
.withArgs({ name: 'clipboard-write', allowWithoutGesture: true })
|
||||
.resolves({ state: state });
|
||||
navigator.permissions.query
|
||||
.withArgs({ name: 'clipboard-read', allowWithoutGesture: false })
|
||||
.resolves({ state: state });
|
||||
navigator.permissions.query.mockImplementation(args =>
|
||||
Promise.resolve({ state: state })
|
||||
);
|
||||
}
|
||||
|
||||
function nextTick() {
|
||||
|
|
@ -42,30 +42,30 @@ describe('Async Clipboard', function () {
|
|||
it('grab() adds listener if permissions granted', async function () {
|
||||
stubClipboardPermissions('granted');
|
||||
|
||||
const addListenerSpy = sinon.spy(targetMock, 'addEventListener');
|
||||
const addListenerSpy = vi.spyOn(targetMock, 'addEventListener');
|
||||
clipboard.grab();
|
||||
|
||||
await nextTick();
|
||||
|
||||
expect(addListenerSpy.calledWith('focus')).to.be.true;
|
||||
expect(addListenerSpy).toHaveBeenCalledWith('focus', expect.any(Function));
|
||||
});
|
||||
|
||||
it('grab() does not add listener if permissions denied', async function () {
|
||||
stubClipboardPermissions('denied');
|
||||
|
||||
const addListenerSpy = sinon.spy(targetMock, 'addEventListener');
|
||||
const addListenerSpy = vi.spyOn(targetMock, 'addEventListener');
|
||||
clipboard.grab();
|
||||
|
||||
await nextTick();
|
||||
|
||||
expect(addListenerSpy.calledWith('focus')).to.be.false;
|
||||
expect(addListenerSpy).not.toHaveBeenCalledWith('focus', expect.any(Function));
|
||||
});
|
||||
|
||||
it('focus event triggers onpaste() if permissions granted', async function () {
|
||||
stubClipboardPermissions('granted');
|
||||
|
||||
const text = 'hello clipboard world';
|
||||
navigator.clipboard.readText.resolves(text);
|
||||
navigator.clipboard.readText.mockResolvedValue(text);
|
||||
|
||||
const spyPromise = new Promise(resolve => clipboard.onpaste = resolve);
|
||||
|
||||
|
|
@ -83,9 +83,9 @@ describe('Async Clipboard', function () {
|
|||
stubClipboardPermissions('denied');
|
||||
|
||||
const text = 'should not read';
|
||||
navigator.clipboard.readText.resolves(text);
|
||||
navigator.clipboard.readText.mockResolvedValue(text);
|
||||
|
||||
clipboard.onpaste = sinon.spy();
|
||||
clipboard.onpaste = vi.fn();
|
||||
|
||||
clipboard.grab();
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ describe('Async Clipboard', function () {
|
|||
|
||||
targetMock.dispatchEvent(new Event('focus'));
|
||||
|
||||
expect(clipboard.onpaste.called).to.be.false;
|
||||
expect(clipboard.onpaste).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('writeClipboard() calls navigator.clipboard.writeText() if permissions granted', async function () {
|
||||
|
|
@ -103,8 +103,8 @@ describe('Async Clipboard', function () {
|
|||
const text = 'writing to clipboard';
|
||||
const result = clipboard.writeClipboard(text);
|
||||
|
||||
expect(navigator.clipboard.writeText.calledWith(text)).to.be.true;
|
||||
expect(result).to.be.true;
|
||||
expect(navigator.clipboard.writeText).toHaveBeenCalledWith(text);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('writeClipboard() does not call navigator.clipboard.writeText() if permissions denied', async function () {
|
||||
|
|
@ -114,8 +114,8 @@ describe('Async Clipboard', function () {
|
|||
const text = 'should not write';
|
||||
const result = clipboard.writeClipboard(text);
|
||||
|
||||
expect(navigator.clipboard.writeText.called).to.be.false;
|
||||
expect(result).to.be.false;
|
||||
expect(navigator.clipboard.writeText).not.toHaveBeenCalled();
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
});
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest';
|
||||
import Websock from '../core/websock.js';
|
||||
import Display from '../core/display.js';
|
||||
|
||||
|
|
@ -33,8 +34,8 @@ describe('CopyRect decoder', function () {
|
|||
let decoder;
|
||||
let display;
|
||||
|
||||
before(FakeWebSocket.replace);
|
||||
after(FakeWebSocket.restore);
|
||||
beforeAll(FakeWebSocket.replace);
|
||||
afterAll(FakeWebSocket.restore);
|
||||
|
||||
beforeEach(function () {
|
||||
decoder = new CopyRectDecoder();
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import { describe, it, expect } from 'vitest';
|
||||
import { inflateInit, inflate } from "../vendor/pako/lib/zlib/inflate.js";
|
||||
import ZStream from "../vendor/pako/lib/zlib/zstream.js";
|
||||
import Deflator from "../core/deflator.js";
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest';
|
||||
import Base64 from '../core/base64.js';
|
||||
import Display from '../core/display.js';
|
||||
|
||||
|
|
@ -71,15 +72,15 @@ describe('Display/Canvas helper', function () {
|
|||
});
|
||||
|
||||
it('should redraw when moving the viewport', function () {
|
||||
display.flip = sinon.spy();
|
||||
display.flip = vi.fn();
|
||||
display.viewportChangePos(-1, 1);
|
||||
expect(display.flip).to.have.been.calledOnce;
|
||||
expect(display.flip).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it('should redraw when resizing the viewport', function () {
|
||||
display.flip = sinon.spy();
|
||||
display.flip = vi.fn();
|
||||
display.viewportChangeSize(2, 2);
|
||||
expect(display.flip).to.have.been.calledOnce;
|
||||
expect(display.flip).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it('should show the entire framebuffer when disabling the viewport', function () {
|
||||
|
|
@ -322,37 +323,37 @@ describe('Display/Canvas helper', function () {
|
|||
beforeEach(function () {
|
||||
display = new Display(document.createElement('canvas'));
|
||||
display.resize(4, 4);
|
||||
sinon.spy(display, '_scanRenderQ');
|
||||
vi.spyOn(display, '_scanRenderQ');
|
||||
});
|
||||
|
||||
it('should try to process an item when it is pushed on, if nothing else is on the queue', function () {
|
||||
display._renderQPush({ type: 'noop' }); // does nothing
|
||||
expect(display._scanRenderQ).to.have.been.calledOnce;
|
||||
expect(display._scanRenderQ).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it('should not try to process an item when it is pushed on if we are waiting for other items', function () {
|
||||
display._renderQ.length = 2;
|
||||
display._renderQPush({ type: 'noop' });
|
||||
expect(display._scanRenderQ).to.not.have.been.called;
|
||||
expect(display._scanRenderQ).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should wait until an image is loaded to attempt to draw it and the rest of the queue', function () {
|
||||
const img = { complete: false, width: 4, height: 4, addEventListener: sinon.spy() };
|
||||
const img = { complete: false, width: 4, height: 4, addEventListener: vi.fn() };
|
||||
display._renderQ = [{ type: 'img', x: 3, y: 4, width: 4, height: 4, img: img },
|
||||
{ type: 'fill', x: 1, y: 2, width: 3, height: 4, color: 5 }];
|
||||
display.drawImage = sinon.spy();
|
||||
display.fillRect = sinon.spy();
|
||||
display.drawImage = vi.fn();
|
||||
display.fillRect = vi.fn();
|
||||
|
||||
display._scanRenderQ();
|
||||
expect(display.drawImage).to.not.have.been.called;
|
||||
expect(display.fillRect).to.not.have.been.called;
|
||||
expect(img.addEventListener).to.have.been.calledOnce;
|
||||
expect(display.drawImage).not.toHaveBeenCalled();
|
||||
expect(display.fillRect).not.toHaveBeenCalled();
|
||||
expect(img.addEventListener).toHaveBeenCalledOnce();
|
||||
|
||||
display._renderQ[0].img.complete = true;
|
||||
display._scanRenderQ();
|
||||
expect(display.drawImage).to.have.been.calledOnce;
|
||||
expect(display.fillRect).to.have.been.calledOnce;
|
||||
expect(img.addEventListener).to.have.been.calledOnce;
|
||||
expect(display.drawImage).toHaveBeenCalledOnce();
|
||||
expect(display.fillRect).toHaveBeenCalledOnce();
|
||||
expect(img.addEventListener).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it('should resolve promise when queue is flushed', async function () {
|
||||
|
|
@ -363,32 +364,32 @@ describe('Display/Canvas helper', function () {
|
|||
});
|
||||
|
||||
it('should draw a blit image on type "blit"', function () {
|
||||
display.blitImage = sinon.spy();
|
||||
display.blitImage = vi.fn();
|
||||
display._renderQPush({ type: 'blit', x: 3, y: 4, width: 5, height: 6, data: [7, 8, 9] });
|
||||
expect(display.blitImage).to.have.been.calledOnce;
|
||||
expect(display.blitImage).to.have.been.calledWith(3, 4, 5, 6, [7, 8, 9], 0);
|
||||
expect(display.blitImage).toHaveBeenCalledOnce();
|
||||
expect(display.blitImage).toHaveBeenCalledWith(3, 4, 5, 6, [7, 8, 9], 0, true);
|
||||
});
|
||||
|
||||
it('should copy a region on type "copy"', function () {
|
||||
display.copyImage = sinon.spy();
|
||||
display.copyImage = vi.fn();
|
||||
display._renderQPush({ type: 'copy', x: 3, y: 4, width: 5, height: 6, oldX: 7, oldY: 8 });
|
||||
expect(display.copyImage).to.have.been.calledOnce;
|
||||
expect(display.copyImage).to.have.been.calledWith(7, 8, 3, 4, 5, 6);
|
||||
expect(display.copyImage).toHaveBeenCalledOnce();
|
||||
expect(display.copyImage).toHaveBeenCalledWith(7, 8, 3, 4, 5, 6, true);
|
||||
});
|
||||
|
||||
it('should fill a rect with a given color on type "fill"', function () {
|
||||
display.fillRect = sinon.spy();
|
||||
display.fillRect = vi.fn();
|
||||
display._renderQPush({ type: 'fill', x: 3, y: 4, width: 5, height: 6, color: [7, 8, 9]});
|
||||
expect(display.fillRect).to.have.been.calledOnce;
|
||||
expect(display.fillRect).to.have.been.calledWith(3, 4, 5, 6, [7, 8, 9]);
|
||||
expect(display.fillRect).toHaveBeenCalledOnce();
|
||||
expect(display.fillRect).toHaveBeenCalledWith(3, 4, 5, 6, [7, 8, 9], true);
|
||||
});
|
||||
|
||||
it('should draw an image from an image object on type "img" (if complete)', function () {
|
||||
const img = { complete: true };
|
||||
display.drawImage = sinon.spy();
|
||||
display.drawImage = vi.fn();
|
||||
display._renderQPush({ type: 'img', x: 3, y: 4, img: img });
|
||||
expect(display.drawImage).to.have.been.calledOnce;
|
||||
expect(display.drawImage).to.have.been.calledWith(img, 3, 4);
|
||||
expect(display.drawImage).toHaveBeenCalledOnce();
|
||||
expect(display.drawImage).toHaveBeenCalledWith(img, 3, 4);
|
||||
});
|
||||
});
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,3 +1,4 @@
|
|||
import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest';
|
||||
import Websock from '../core/websock.js';
|
||||
import Display from '../core/display.js';
|
||||
|
||||
|
|
@ -133,9 +134,9 @@ describe('H.264 parser', function () {
|
|||
describe('H.264 decoder unit test', function () {
|
||||
let decoder;
|
||||
|
||||
beforeEach(function () {
|
||||
beforeEach(function ({ skip }) {
|
||||
if (!supportsWebCodecsH264Decode) {
|
||||
this.skip();
|
||||
skip();
|
||||
return;
|
||||
}
|
||||
decoder = new H264Decoder();
|
||||
|
|
@ -185,12 +186,12 @@ describe('H.264 decoder functional test', function () {
|
|||
let decoder;
|
||||
let display;
|
||||
|
||||
before(FakeWebSocket.replace);
|
||||
after(FakeWebSocket.restore);
|
||||
beforeAll(FakeWebSocket.replace);
|
||||
afterAll(FakeWebSocket.restore);
|
||||
|
||||
beforeEach(function () {
|
||||
beforeEach(function ({ skip }) {
|
||||
if (!supportsWebCodecsH264Decode) {
|
||||
this.skip();
|
||||
skip();
|
||||
return;
|
||||
}
|
||||
decoder = new H264Decoder();
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
||||
import keysyms from '../core/input/keysymdef.js';
|
||||
import * as KeyboardUtil from "../core/input/util.js";
|
||||
|
||||
|
|
@ -140,8 +141,8 @@ describe('Helpers', function () {
|
|||
it('should handle Windows key with incorrect location', function () {
|
||||
expect(KeyboardUtil.getKeysym({key: 'Meta', location: 0})).to.be.equal(0xFFEC);
|
||||
});
|
||||
it('should handle Clear/NumLock key with incorrect location', function () {
|
||||
this.skip(); // Broken because of Clear/NumLock override
|
||||
it('should handle Clear/NumLock key with incorrect location', function ({ skip }) {
|
||||
skip(); // Broken because of Clear/NumLock override
|
||||
expect(KeyboardUtil.getKeysym({key: 'Clear', code: 'NumLock', location: 3})).to.be.equal(0xFF0B);
|
||||
});
|
||||
it('should handle Meta/Windows distinction', function () {
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest';
|
||||
import Websock from '../core/websock.js';
|
||||
import Display from '../core/display.js';
|
||||
|
||||
|
|
@ -40,8 +41,8 @@ describe('Hextile decoder', function () {
|
|||
let decoder;
|
||||
let display;
|
||||
|
||||
before(FakeWebSocket.replace);
|
||||
after(FakeWebSocket.restore);
|
||||
beforeAll(FakeWebSocket.replace);
|
||||
afterAll(FakeWebSocket.restore);
|
||||
|
||||
beforeEach(function () {
|
||||
decoder = new HextileDecoder();
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import { describe, it, expect } from 'vitest';
|
||||
import { deflateInit, deflate, Z_FULL_FLUSH } from "../vendor/pako/lib/zlib/deflate.js";
|
||||
import ZStream from "../vendor/pako/lib/zlib/zstream.js";
|
||||
import Inflator from "../core/inflator.js";
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import { describe, it, expect } from 'vitest';
|
||||
import { toUnsigned32bit, toSigned32bit } from '../core/util/int.js';
|
||||
|
||||
describe('Integer casting', function () {
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest';
|
||||
import Websock from '../core/websock.js';
|
||||
import Display from '../core/display.js';
|
||||
|
||||
|
|
@ -33,8 +34,8 @@ describe('JPEG decoder', function () {
|
|||
let decoder;
|
||||
let display;
|
||||
|
||||
before(FakeWebSocket.replace);
|
||||
after(FakeWebSocket.restore);
|
||||
beforeAll(FakeWebSocket.replace);
|
||||
afterAll(FakeWebSocket.restore);
|
||||
|
||||
beforeEach(function () {
|
||||
decoder = new JPEGDecoder();
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest';
|
||||
import Keyboard from '../core/input/keyboard.js';
|
||||
|
||||
describe('Key event handling', function () {
|
||||
|
|
@ -10,8 +11,8 @@ describe('Key event handling', function () {
|
|||
for (let key in KeyboardEventInit) {
|
||||
e[key] = KeyboardEventInit[key];
|
||||
}
|
||||
e.stopPropagation = sinon.spy();
|
||||
e.preventDefault = sinon.spy();
|
||||
e.stopPropagation = vi.fn();
|
||||
e.preventDefault = vi.fn();
|
||||
e.getModifierState = function (key) {
|
||||
return e[key];
|
||||
};
|
||||
|
|
@ -20,66 +21,74 @@ describe('Key event handling', function () {
|
|||
}
|
||||
|
||||
describe('Decode keyboard events', function () {
|
||||
it('should decode keydown events', function (done) {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('KeyA');
|
||||
expect(down).to.be.equal(true);
|
||||
done();
|
||||
};
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'a'}));
|
||||
});
|
||||
it('should decode keyup events', function (done) {
|
||||
let calls = 0;
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('KeyA');
|
||||
if (calls++ === 1) {
|
||||
expect(down).to.be.equal(false);
|
||||
it('should decode keydown events', function () {
|
||||
return new Promise((done) => {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('KeyA');
|
||||
expect(down).to.be.equal(true);
|
||||
done();
|
||||
}
|
||||
};
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'a'}));
|
||||
kbd._handleKeyUp(keyevent('keyup', {code: 'KeyA', key: 'a'}));
|
||||
};
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'a'}));
|
||||
});
|
||||
});
|
||||
it('should decode keyup events', function () {
|
||||
return new Promise((done) => {
|
||||
let calls = 0;
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('KeyA');
|
||||
if (calls++ === 1) {
|
||||
expect(down).to.be.equal(false);
|
||||
done();
|
||||
}
|
||||
};
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'a'}));
|
||||
kbd._handleKeyUp(keyevent('keyup', {code: 'KeyA', key: 'a'}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Fake keyup', function () {
|
||||
it('should fake keyup events for virtual keyboards', function (done) {
|
||||
let count = 0;
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
switch (count++) {
|
||||
case 0:
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('Unidentified');
|
||||
expect(down).to.be.equal(true);
|
||||
break;
|
||||
case 1:
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('Unidentified');
|
||||
expect(down).to.be.equal(false);
|
||||
done();
|
||||
}
|
||||
};
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'Unidentified', key: 'a'}));
|
||||
it('should fake keyup events for virtual keyboards', function () {
|
||||
return new Promise((done) => {
|
||||
let count = 0;
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
switch (count++) {
|
||||
case 0:
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('Unidentified');
|
||||
expect(down).to.be.equal(true);
|
||||
break;
|
||||
case 1:
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('Unidentified');
|
||||
expect(down).to.be.equal(false);
|
||||
done();
|
||||
}
|
||||
};
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'Unidentified', key: 'a'}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Track key state', function () {
|
||||
it('should send release using the same keysym as the press', function (done) {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('KeyA');
|
||||
if (!down) {
|
||||
done();
|
||||
}
|
||||
};
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'a'}));
|
||||
kbd._handleKeyUp(keyevent('keyup', {code: 'KeyA', key: 'b'}));
|
||||
it('should send release using the same keysym as the press', function () {
|
||||
return new Promise((done) => {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('KeyA');
|
||||
if (!down) {
|
||||
done();
|
||||
}
|
||||
};
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'a'}));
|
||||
kbd._handleKeyUp(keyevent('keyup', {code: 'KeyA', key: 'b'}));
|
||||
});
|
||||
});
|
||||
it('should send the same keysym for multiple presses', function () {
|
||||
let count = 0;
|
||||
|
|
@ -96,23 +105,25 @@ describe('Key event handling', function () {
|
|||
});
|
||||
it('should do nothing on keyup events if no keys are down', function () {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
kbd._handleKeyUp(keyevent('keyup', {code: 'KeyA', key: 'a'}));
|
||||
expect(kbd.onkeyevent).to.not.have.been.called;
|
||||
expect(kbd.onkeyevent).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('Legacy events', function () {
|
||||
it('should track keys using keyCode if no code', function (done) {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('Platform65');
|
||||
if (!down) {
|
||||
done();
|
||||
}
|
||||
};
|
||||
kbd._handleKeyDown(keyevent('keydown', {keyCode: 65, key: 'a'}));
|
||||
kbd._handleKeyUp(keyevent('keyup', {keyCode: 65, key: 'b'}));
|
||||
it('should track keys using keyCode if no code', function () {
|
||||
return new Promise((done) => {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('Platform65');
|
||||
if (!down) {
|
||||
done();
|
||||
}
|
||||
};
|
||||
kbd._handleKeyDown(keyevent('keydown', {keyCode: 65, key: 'a'}));
|
||||
kbd._handleKeyUp(keyevent('keyup', {keyCode: 65, key: 'b'}));
|
||||
});
|
||||
});
|
||||
it('should ignore compositing code', function () {
|
||||
const kbd = new Keyboard(document);
|
||||
|
|
@ -122,17 +133,19 @@ describe('Key event handling', function () {
|
|||
};
|
||||
kbd._handleKeyDown(keyevent('keydown', {keyCode: 229, key: 'a'}));
|
||||
});
|
||||
it('should track keys using keyIdentifier if no code', function (done) {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('Platform65');
|
||||
if (!down) {
|
||||
done();
|
||||
}
|
||||
};
|
||||
kbd._handleKeyDown(keyevent('keydown', {keyIdentifier: 'U+0041', key: 'a'}));
|
||||
kbd._handleKeyUp(keyevent('keyup', {keyIdentifier: 'U+0041', key: 'b'}));
|
||||
it('should track keys using keyIdentifier if no code', function () {
|
||||
return new Promise((done) => {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0x61);
|
||||
expect(code).to.be.equal('Platform65');
|
||||
if (!down) {
|
||||
done();
|
||||
}
|
||||
};
|
||||
kbd._handleKeyDown(keyevent('keydown', {keyIdentifier: 'U+0041', key: 'a'}));
|
||||
kbd._handleKeyUp(keyevent('keyup', {keyIdentifier: 'U+0041', key: 'b'}));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -171,29 +184,33 @@ describe('Key event handling', function () {
|
|||
kbd._handleKeyDown(keyevent('keydown', {code: 'AltRight', key: 'Alt', location: 2}));
|
||||
expect(count).to.be.equal(2);
|
||||
});
|
||||
it('should change left Super to Alt', function (done) {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0xFFE9);
|
||||
expect(code).to.be.equal('MetaLeft');
|
||||
done();
|
||||
};
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'MetaLeft', key: 'Meta', location: 1}));
|
||||
it('should change left Super to Alt', function () {
|
||||
return new Promise((done) => {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0xFFE9);
|
||||
expect(code).to.be.equal('MetaLeft');
|
||||
done();
|
||||
};
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'MetaLeft', key: 'Meta', location: 1}));
|
||||
});
|
||||
});
|
||||
it('should change right Super to left Super', function (done) {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0xFFEB);
|
||||
expect(code).to.be.equal('MetaRight');
|
||||
done();
|
||||
};
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'MetaRight', key: 'Meta', location: 2}));
|
||||
it('should change right Super to left Super', function () {
|
||||
return new Promise((done) => {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = (keysym, code, down) => {
|
||||
expect(keysym).to.be.equal(0xFFEB);
|
||||
expect(code).to.be.equal('MetaRight');
|
||||
done();
|
||||
};
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'MetaRight', key: 'Meta', location: 2}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Meta key combination on iOS and macOS', function () {
|
||||
let origNavigator;
|
||||
beforeEach(function () {
|
||||
beforeEach(function ({ skip }) {
|
||||
// window.navigator is a protected read-only property in many
|
||||
// environments, so we need to redefine it whilst running these
|
||||
// tests.
|
||||
|
|
@ -203,7 +220,7 @@ describe('Key event handling', function () {
|
|||
if (window.navigator.platform !== undefined) {
|
||||
// Object.defineProperty() doesn't work properly in old
|
||||
// versions of Chrome
|
||||
this.skip();
|
||||
skip();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -216,39 +233,39 @@ describe('Key event handling', function () {
|
|||
it('should send keyup when meta key is pressed on iOS', function () {
|
||||
window.navigator.platform = "iPad";
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'MetaRight', key: 'Meta', location: 2, metaKey: true}));
|
||||
expect(kbd.onkeyevent).to.have.been.calledOnce;
|
||||
kbd.onkeyevent.resetHistory();
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledOnce();
|
||||
kbd.onkeyevent.mockClear();
|
||||
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'a', metaKey: true}));
|
||||
expect(kbd.onkeyevent).to.have.been.calledTwice;
|
||||
expect(kbd.onkeyevent).to.have.been.calledWith(0x61, "KeyA", true);
|
||||
expect(kbd.onkeyevent).to.have.been.calledWith(0x61, "KeyA", false);
|
||||
kbd.onkeyevent.resetHistory();
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledTimes(2);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(1, 0x61, "KeyA", true, null, null);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(2, 0x61, "KeyA", false, null, null);
|
||||
kbd.onkeyevent.mockClear();
|
||||
|
||||
kbd._handleKeyUp(keyevent('keyup', {code: 'MetaRight', key: 'Meta', location: 2, metaKey: true}));
|
||||
expect(kbd.onkeyevent).to.have.been.calledOnce;
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it('should send keyup when meta key is pressed on macOS', function () {
|
||||
window.navigator.platform = "Mac";
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'MetaRight', key: 'Meta', location: 2, metaKey: true}));
|
||||
expect(kbd.onkeyevent).to.have.been.calledOnce;
|
||||
kbd.onkeyevent.resetHistory();
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledOnce();
|
||||
kbd.onkeyevent.mockClear();
|
||||
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'a', metaKey: true}));
|
||||
expect(kbd.onkeyevent).to.have.been.calledTwice;
|
||||
expect(kbd.onkeyevent).to.have.been.calledWith(0x61, "KeyA", true);
|
||||
expect(kbd.onkeyevent).to.have.been.calledWith(0x61, "KeyA", false);
|
||||
kbd.onkeyevent.resetHistory();
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledTimes(2);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(1, 0x61, "KeyA", true, null, null);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(2, 0x61, "KeyA", false, null, null);
|
||||
kbd.onkeyevent.mockClear();
|
||||
|
||||
kbd._handleKeyUp(keyevent('keyup', {code: 'MetaRight', key: 'Meta', location: 2, metaKey: true}));
|
||||
expect(kbd.onkeyevent).to.have.been.calledOnce;
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledOnce();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -270,45 +287,45 @@ describe('Key event handling', function () {
|
|||
it('should toggle caps lock on key press on iOS', function () {
|
||||
window.navigator.platform = "iPad";
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'CapsLock', key: 'CapsLock'}));
|
||||
|
||||
expect(kbd.onkeyevent).to.have.been.calledTwice;
|
||||
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0xFFE5, "CapsLock", true);
|
||||
expect(kbd.onkeyevent.secondCall).to.have.been.calledWith(0xFFE5, "CapsLock", false);
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledTimes(2);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(1, 0xFFE5, "CapsLock", true, null, null);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(2, 0xFFE5, "CapsLock", false, null, null);
|
||||
});
|
||||
|
||||
it('should toggle caps lock on key press on mac', function () {
|
||||
window.navigator.platform = "Mac";
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'CapsLock', key: 'CapsLock'}));
|
||||
|
||||
expect(kbd.onkeyevent).to.have.been.calledTwice;
|
||||
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0xFFE5, "CapsLock", true);
|
||||
expect(kbd.onkeyevent.secondCall).to.have.been.calledWith(0xFFE5, "CapsLock", false);
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledTimes(2);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(1, 0xFFE5, "CapsLock", true, null, null);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(2, 0xFFE5, "CapsLock", false, null, null);
|
||||
});
|
||||
|
||||
it('should toggle caps lock on key release on iOS', function () {
|
||||
window.navigator.platform = "iPad";
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
kbd._handleKeyUp(keyevent('keyup', {code: 'CapsLock', key: 'CapsLock'}));
|
||||
|
||||
expect(kbd.onkeyevent).to.have.been.calledTwice;
|
||||
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0xFFE5, "CapsLock", true);
|
||||
expect(kbd.onkeyevent.secondCall).to.have.been.calledWith(0xFFE5, "CapsLock", false);
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledTimes(2);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(1, 0xFFE5, "CapsLock", true, null, null);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(2, 0xFFE5, "CapsLock", false, null, null);
|
||||
});
|
||||
|
||||
it('should toggle caps lock on key release on mac', function () {
|
||||
window.navigator.platform = "Mac";
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
kbd._handleKeyUp(keyevent('keyup', {code: 'CapsLock', key: 'CapsLock'}));
|
||||
|
||||
expect(kbd.onkeyevent).to.have.been.calledTwice;
|
||||
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0xFFE5, "CapsLock", true);
|
||||
expect(kbd.onkeyevent.secondCall).to.have.been.calledWith(0xFFE5, "CapsLock", false);
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledTimes(2);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(1, 0xFFE5, "CapsLock", true, null, null);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(2, 0xFFE5, "CapsLock", false, null, null);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -329,30 +346,30 @@ describe('Key event handling', function () {
|
|||
|
||||
it('should provide caps lock state', function () {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'A', NumLock: false, CapsLock: true}));
|
||||
|
||||
expect(kbd.onkeyevent).to.have.been.calledOnce;
|
||||
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0x41, "KeyA", true, false, true);
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledOnce();
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledWith(0x41, "KeyA", true, false, true);
|
||||
});
|
||||
|
||||
it('should provide num lock state', function () {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'A', NumLock: true, CapsLock: false}));
|
||||
|
||||
expect(kbd.onkeyevent).to.have.been.calledOnce;
|
||||
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0x41, "KeyA", true, true, false);
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledOnce();
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledWith(0x41, "KeyA", true, true, false);
|
||||
});
|
||||
|
||||
it('should have no num lock state on mac', function () {
|
||||
window.navigator.platform = "Mac";
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'A', NumLock: false, CapsLock: true}));
|
||||
|
||||
expect(kbd.onkeyevent).to.have.been.calledOnce;
|
||||
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0x41, "KeyA", true, null, true);
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledOnce();
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledWith(0x41, "KeyA", true, null, true);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -379,18 +396,20 @@ describe('Key event handling', function () {
|
|||
for (let [key, keysym] of Object.entries(keys)) {
|
||||
it(`should fake key release for ${key} on Windows`, function () {
|
||||
let kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'FakeIM', key: key}));
|
||||
|
||||
expect(kbd.onkeyevent).to.have.been.calledTwice;
|
||||
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(keysym, "FakeIM", true);
|
||||
expect(kbd.onkeyevent.secondCall).to.have.been.calledWith(keysym, "FakeIM", false);
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledTimes(2);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(1, keysym, "FakeIM", true, null, null);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(2, keysym, "FakeIM", false, null, null);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('Escape AltGraph on Windows', function () {
|
||||
let origNavigator;
|
||||
let clock;
|
||||
|
||||
beforeEach(function () {
|
||||
// window.navigator is a protected read-only property in many
|
||||
// environments, so we need to redefine it whilst running these
|
||||
|
|
@ -400,181 +419,183 @@ describe('Key event handling', function () {
|
|||
Object.defineProperty(window, "navigator", {value: {}});
|
||||
window.navigator.platform = "Windows x86_64";
|
||||
|
||||
this.clock = sinon.useFakeTimers();
|
||||
clock = vi.useFakeTimers();
|
||||
});
|
||||
afterEach(function () {
|
||||
Object.defineProperty(window, "navigator", origNavigator);
|
||||
if (this.clock !== undefined) {
|
||||
this.clock.restore();
|
||||
if (clock !== undefined) {
|
||||
clock.restoreAllMocks();
|
||||
}
|
||||
});
|
||||
|
||||
it('should supress ControlLeft until it knows if it is AltGr', function () {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control', location: 1}));
|
||||
expect(kbd.onkeyevent).to.not.have.been.called;
|
||||
expect(kbd.onkeyevent).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not trigger on repeating ControlLeft', function () {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control', location: 1}));
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control', location: 1}));
|
||||
expect(kbd.onkeyevent).to.have.been.calledTwice;
|
||||
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0xffe3, "ControlLeft", true);
|
||||
expect(kbd.onkeyevent.secondCall).to.have.been.calledWith(0xffe3, "ControlLeft", true);
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledTimes(2);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(1, 0xffe3, "ControlLeft", true, null, null);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(2, 0xffe3, "ControlLeft", true, null, null);
|
||||
});
|
||||
|
||||
it('should not supress ControlRight', function () {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'ControlRight', key: 'Control', location: 2}));
|
||||
expect(kbd.onkeyevent).to.have.been.calledOnce;
|
||||
expect(kbd.onkeyevent).to.have.been.calledWith(0xffe4, "ControlRight", true);
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledOnce();
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledWith(0xffe4, "ControlRight", true, null, null);
|
||||
});
|
||||
|
||||
it('should release ControlLeft after 100 ms', function () {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control', location: 1}));
|
||||
expect(kbd.onkeyevent).to.not.have.been.called;
|
||||
this.clock.tick(100);
|
||||
expect(kbd.onkeyevent).to.have.been.calledOnce;
|
||||
expect(kbd.onkeyevent).to.have.been.calledWith(0xffe3, "ControlLeft", true);
|
||||
expect(kbd.onkeyevent).not.toHaveBeenCalled();
|
||||
clock.advanceTimersByTime(100);
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledOnce();
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledWith(0xffe3, "ControlLeft", true, null, null);
|
||||
});
|
||||
|
||||
it('should release ControlLeft on other key press', function () {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control', location: 1}));
|
||||
expect(kbd.onkeyevent).to.not.have.been.called;
|
||||
expect(kbd.onkeyevent).not.toHaveBeenCalled();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'a'}));
|
||||
expect(kbd.onkeyevent).to.have.been.calledTwice;
|
||||
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0xffe3, "ControlLeft", true);
|
||||
expect(kbd.onkeyevent.secondCall).to.have.been.calledWith(0x61, "KeyA", true);
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledTimes(2);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(1, 0xffe3, "ControlLeft", true, null, null);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(2, 0x61, "KeyA", true, null, null);
|
||||
|
||||
// Check that the timer is properly dead
|
||||
kbd.onkeyevent.resetHistory();
|
||||
this.clock.tick(100);
|
||||
expect(kbd.onkeyevent).to.not.have.been.called;
|
||||
kbd.onkeyevent.mockClear();
|
||||
clock.advanceTimersByTime(100);
|
||||
expect(kbd.onkeyevent).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should release ControlLeft on other key release', function () {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'KeyA', key: 'a'}));
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control', location: 1}));
|
||||
expect(kbd.onkeyevent).to.have.been.calledOnce;
|
||||
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0x61, "KeyA", true);
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledOnce();
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledWith(0x61, "KeyA", true, null, null);
|
||||
kbd._handleKeyUp(keyevent('keyup', {code: 'KeyA', key: 'a'}));
|
||||
expect(kbd.onkeyevent).to.have.been.calledThrice;
|
||||
expect(kbd.onkeyevent.secondCall).to.have.been.calledWith(0xffe3, "ControlLeft", true);
|
||||
expect(kbd.onkeyevent.thirdCall).to.have.been.calledWith(0x61, "KeyA", false);
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledTimes(3);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(2, 0xffe3, "ControlLeft", true, null, null);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(3, 0x61, "KeyA", false, null, null);
|
||||
|
||||
// Check that the timer is properly dead
|
||||
kbd.onkeyevent.resetHistory();
|
||||
this.clock.tick(100);
|
||||
expect(kbd.onkeyevent).to.not.have.been.called;
|
||||
kbd.onkeyevent.mockClear();
|
||||
clock.advanceTimersByTime(100);
|
||||
expect(kbd.onkeyevent).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should release ControlLeft on blur', function () {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control', location: 1}));
|
||||
expect(kbd.onkeyevent).to.not.have.been.called;
|
||||
expect(kbd.onkeyevent).not.toHaveBeenCalled();
|
||||
kbd._allKeysUp();
|
||||
expect(kbd.onkeyevent).to.have.been.calledTwice;
|
||||
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0xffe3, "ControlLeft", true);
|
||||
expect(kbd.onkeyevent.secondCall).to.have.been.calledWith(0xffe3, "ControlLeft", false);
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledTimes(2);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(1, 0xffe3, "ControlLeft", true, null, null);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(2, 0xffe3, "ControlLeft", false, null, null);
|
||||
|
||||
// Check that the timer is properly dead
|
||||
kbd.onkeyevent.resetHistory();
|
||||
this.clock.tick(100);
|
||||
expect(kbd.onkeyevent).to.not.have.been.called;
|
||||
kbd.onkeyevent.mockClear();
|
||||
clock.advanceTimersByTime(100);
|
||||
expect(kbd.onkeyevent).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should generate AltGraph for quick Ctrl+Alt sequence', function () {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control', location: 1, timeStamp: Date.now()}));
|
||||
this.clock.tick(20);
|
||||
clock.advanceTimersByTime(20);
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'AltRight', key: 'Alt', location: 2, timeStamp: Date.now()}));
|
||||
expect(kbd.onkeyevent).to.have.been.calledOnce;
|
||||
expect(kbd.onkeyevent).to.have.been.calledWith(0xfe03, 'AltRight', true);
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledOnce();
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledWith(0xfe03, 'AltRight', true, null, null);
|
||||
|
||||
// Check that the timer is properly dead
|
||||
kbd.onkeyevent.resetHistory();
|
||||
this.clock.tick(100);
|
||||
expect(kbd.onkeyevent).to.not.have.been.called;
|
||||
kbd.onkeyevent.mockClear();
|
||||
clock.advanceTimersByTime(100);
|
||||
expect(kbd.onkeyevent).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should generate Ctrl, Alt for slow Ctrl+Alt sequence', function () {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control', location: 1, timeStamp: Date.now()}));
|
||||
this.clock.tick(60);
|
||||
clock.advanceTimersByTime(60);
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'AltRight', key: 'Alt', location: 2, timeStamp: Date.now()}));
|
||||
expect(kbd.onkeyevent).to.have.been.calledTwice;
|
||||
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0xffe3, "ControlLeft", true);
|
||||
expect(kbd.onkeyevent.secondCall).to.have.been.calledWith(0xffea, "AltRight", true);
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledTimes(2);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(1, 0xffe3, "ControlLeft", true, null, null);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(2, 0xffea, "AltRight", true, null, null);
|
||||
|
||||
// Check that the timer is properly dead
|
||||
kbd.onkeyevent.resetHistory();
|
||||
this.clock.tick(100);
|
||||
expect(kbd.onkeyevent).to.not.have.been.called;
|
||||
kbd.onkeyevent.mockClear();
|
||||
clock.advanceTimersByTime(100);
|
||||
expect(kbd.onkeyevent).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should generate AltGraph for quick Ctrl+AltGraph sequence', function () {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control', location: 1, timeStamp: Date.now()}));
|
||||
this.clock.tick(20);
|
||||
clock.advanceTimersByTime(20);
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'AltRight', key: 'AltGraph', location: 2, timeStamp: Date.now()}));
|
||||
expect(kbd.onkeyevent).to.have.been.calledOnce;
|
||||
expect(kbd.onkeyevent).to.have.been.calledWith(0xfe03, 'AltRight', true);
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledOnce();
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledWith(0xfe03, 'AltRight', true, null, null);
|
||||
|
||||
// Check that the timer is properly dead
|
||||
kbd.onkeyevent.resetHistory();
|
||||
this.clock.tick(100);
|
||||
expect(kbd.onkeyevent).to.not.have.been.called;
|
||||
kbd.onkeyevent.mockClear();
|
||||
clock.advanceTimersByTime(100);
|
||||
expect(kbd.onkeyevent).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should generate Ctrl, AltGraph for slow Ctrl+AltGraph sequence', function () {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'ControlLeft', key: 'Control', location: 1, timeStamp: Date.now()}));
|
||||
this.clock.tick(60);
|
||||
clock.advanceTimersByTime(60);
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'AltRight', key: 'AltGraph', location: 2, timeStamp: Date.now()}));
|
||||
expect(kbd.onkeyevent).to.have.been.calledTwice;
|
||||
expect(kbd.onkeyevent.firstCall).to.have.been.calledWith(0xffe3, "ControlLeft", true);
|
||||
expect(kbd.onkeyevent.secondCall).to.have.been.calledWith(0xfe03, "AltRight", true);
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledTimes(2);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(1, 0xffe3, "ControlLeft", true, null, null);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(2, 0xfe03, "AltRight", true, null, null);
|
||||
|
||||
// Check that the timer is properly dead
|
||||
kbd.onkeyevent.resetHistory();
|
||||
this.clock.tick(100);
|
||||
expect(kbd.onkeyevent).to.not.have.been.called;
|
||||
kbd.onkeyevent.mockClear();
|
||||
clock.advanceTimersByTime(100);
|
||||
expect(kbd.onkeyevent).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should pass through single Alt', function () {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'AltRight', key: 'Alt', location: 2}));
|
||||
expect(kbd.onkeyevent).to.have.been.calledOnce;
|
||||
expect(kbd.onkeyevent).to.have.been.calledWith(0xffea, 'AltRight', true);
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledOnce();
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledWith(0xffea, 'AltRight', true, null, null);
|
||||
});
|
||||
|
||||
it('should pass through single AltGr', function () {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'AltRight', key: 'AltGraph', location: 2}));
|
||||
expect(kbd.onkeyevent).to.have.been.calledOnce;
|
||||
expect(kbd.onkeyevent).to.have.been.calledWith(0xfe03, 'AltRight', true);
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledOnce();
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledWith(0xfe03, 'AltRight', true, null, null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Missing Shift keyup on Windows', function () {
|
||||
let origNavigator;
|
||||
let clock;
|
||||
|
||||
beforeEach(function () {
|
||||
// window.navigator is a protected read-only property in many
|
||||
// environments, so we need to redefine it whilst running these
|
||||
|
|
@ -584,53 +605,53 @@ describe('Key event handling', function () {
|
|||
Object.defineProperty(window, "navigator", {value: {}});
|
||||
window.navigator.platform = "Windows x86_64";
|
||||
|
||||
this.clock = sinon.useFakeTimers();
|
||||
clock = vi.useFakeTimers();
|
||||
});
|
||||
afterEach(function () {
|
||||
Object.defineProperty(window, "navigator", origNavigator);
|
||||
if (this.clock !== undefined) {
|
||||
this.clock.restore();
|
||||
if (clock !== undefined) {
|
||||
clock.restoreAllMocks();
|
||||
}
|
||||
});
|
||||
|
||||
it('should fake a left Shift keyup', function () {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'ShiftLeft', key: 'Shift', location: 1}));
|
||||
expect(kbd.onkeyevent).to.have.been.calledOnce;
|
||||
expect(kbd.onkeyevent).to.have.been.calledWith(0xffe1, 'ShiftLeft', true);
|
||||
kbd.onkeyevent.resetHistory();
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledOnce();
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledWith(0xffe1, 'ShiftLeft', true, null, null);
|
||||
kbd.onkeyevent.mockClear();
|
||||
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'ShiftRight', key: 'Shift', location: 2}));
|
||||
expect(kbd.onkeyevent).to.have.been.calledOnce;
|
||||
expect(kbd.onkeyevent).to.have.been.calledWith(0xffe2, 'ShiftRight', true);
|
||||
kbd.onkeyevent.resetHistory();
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledOnce();
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledWith(0xffe2, 'ShiftRight', true, null, null);
|
||||
kbd.onkeyevent.mockClear();
|
||||
|
||||
kbd._handleKeyUp(keyevent('keyup', {code: 'ShiftLeft', key: 'Shift', location: 1}));
|
||||
expect(kbd.onkeyevent).to.have.been.calledTwice;
|
||||
expect(kbd.onkeyevent).to.have.been.calledWith(0xffe2, 'ShiftRight', false);
|
||||
expect(kbd.onkeyevent).to.have.been.calledWith(0xffe1, 'ShiftLeft', false);
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledTimes(2);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(1, 0xffe1, 'ShiftLeft', false, null, null);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(2, 0xffe2, 'ShiftRight', false, null, null);
|
||||
});
|
||||
|
||||
it('should fake a right Shift keyup', function () {
|
||||
const kbd = new Keyboard(document);
|
||||
kbd.onkeyevent = sinon.spy();
|
||||
kbd.onkeyevent = vi.fn();
|
||||
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'ShiftLeft', key: 'Shift', location: 1}));
|
||||
expect(kbd.onkeyevent).to.have.been.calledOnce;
|
||||
expect(kbd.onkeyevent).to.have.been.calledWith(0xffe1, 'ShiftLeft', true);
|
||||
kbd.onkeyevent.resetHistory();
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledOnce();
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledWith(0xffe1, 'ShiftLeft', true, null, null);
|
||||
kbd.onkeyevent.mockClear();
|
||||
|
||||
kbd._handleKeyDown(keyevent('keydown', {code: 'ShiftRight', key: 'Shift', location: 2}));
|
||||
expect(kbd.onkeyevent).to.have.been.calledOnce;
|
||||
expect(kbd.onkeyevent).to.have.been.calledWith(0xffe2, 'ShiftRight', true);
|
||||
kbd.onkeyevent.resetHistory();
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledOnce();
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledWith(0xffe2, 'ShiftRight', true, null, null);
|
||||
kbd.onkeyevent.mockClear();
|
||||
|
||||
kbd._handleKeyUp(keyevent('keyup', {code: 'ShiftRight', key: 'Shift', location: 2}));
|
||||
expect(kbd.onkeyevent).to.have.been.calledTwice;
|
||||
expect(kbd.onkeyevent).to.have.been.calledWith(0xffe2, 'ShiftRight', false);
|
||||
expect(kbd.onkeyevent).to.have.been.calledWith(0xffe1, 'ShiftLeft', false);
|
||||
expect(kbd.onkeyevent).toHaveBeenCalledTimes(2);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(1, 0xffe2, 'ShiftRight', false, null, null);
|
||||
expect(kbd.onkeyevent).toHaveBeenNthCalledWith(2, 0xffe1, 'ShiftLeft', false, null, null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest';
|
||||
import _, { Localizer, l10n } from '../app/localization.js';
|
||||
|
||||
describe('Localization', function () {
|
||||
|
|
@ -15,11 +16,11 @@ describe('Localization', function () {
|
|||
Object.defineProperty(window, "navigator", {value: {}});
|
||||
window.navigator.languages = [];
|
||||
|
||||
fetch = sinon.stub(window, "fetch");
|
||||
fetch.resolves(new Response("{}"));
|
||||
fetch = vi.spyOn(window, "fetch");
|
||||
fetch.mockResolvedValue(new Response("{}"));
|
||||
});
|
||||
afterEach(function () {
|
||||
fetch.restore();
|
||||
vi.restoreAllMocks();
|
||||
|
||||
Object.defineProperty(window, "navigator", origNavigator);
|
||||
});
|
||||
|
|
@ -31,7 +32,7 @@ describe('Localization', function () {
|
|||
it('should export a singleton translation function', async function () {
|
||||
// FIXME: Can we use some spy instead?
|
||||
window.navigator.languages = ["de"];
|
||||
fetch.resolves(new Response(JSON.stringify({ "Foobar": "gazonk" })));
|
||||
fetch.mockResolvedValue(new Response(JSON.stringify({ "Foobar": "gazonk" })));
|
||||
await l10n.setup(["de"]);
|
||||
expect(_("Foobar")).to.equal("gazonk");
|
||||
});
|
||||
|
|
@ -103,35 +104,38 @@ describe('Localization', function () {
|
|||
window.navigator.languages = [];
|
||||
let lclz = new Localizer();
|
||||
await lclz.setup([]);
|
||||
expect(fetch).to.not.have.been.called;
|
||||
expect(fetch).not.toHaveBeenCalled();
|
||||
});
|
||||
it('should fetch dictionary relative base URL', async function () {
|
||||
window.navigator.languages = ["de", "fr"];
|
||||
fetch.resolves(new Response('{ "Foobar": "gazonk" }'));
|
||||
fetch.mockResolvedValue(new Response('{ "Foobar": "gazonk" }'));
|
||||
let lclz = new Localizer();
|
||||
await lclz.setup(["ru", "fr"], "/some/path/");
|
||||
expect(fetch).to.have.been.calledOnceWith("/some/path/fr.json");
|
||||
expect(fetch).toHaveBeenCalledOnce();
|
||||
expect(fetch).toHaveBeenCalledWith("/some/path/fr.json");
|
||||
expect(lclz.get("Foobar")).to.equal("gazonk");
|
||||
});
|
||||
it('should handle base URL without trailing slash', async function () {
|
||||
window.navigator.languages = ["de", "fr"];
|
||||
fetch.resolves(new Response('{ "Foobar": "gazonk" }'));
|
||||
fetch.mockResolvedValue(new Response('{ "Foobar": "gazonk" }'));
|
||||
let lclz = new Localizer();
|
||||
await lclz.setup(["ru", "fr"], "/some/path");
|
||||
expect(fetch).to.have.been.calledOnceWith("/some/path/fr.json");
|
||||
expect(fetch).toHaveBeenCalledOnce();
|
||||
expect(fetch).toHaveBeenCalledWith("/some/path/fr.json");
|
||||
expect(lclz.get("Foobar")).to.equal("gazonk");
|
||||
});
|
||||
it('should handle current base URL', async function () {
|
||||
window.navigator.languages = ["de", "fr"];
|
||||
fetch.resolves(new Response('{ "Foobar": "gazonk" }'));
|
||||
fetch.mockResolvedValue(new Response('{ "Foobar": "gazonk" }'));
|
||||
let lclz = new Localizer();
|
||||
await lclz.setup(["ru", "fr"]);
|
||||
expect(fetch).to.have.been.calledOnceWith("fr.json");
|
||||
expect(fetch).toHaveBeenCalledOnce();
|
||||
expect(fetch).toHaveBeenCalledWith("fr.json");
|
||||
expect(lclz.get("Foobar")).to.equal("gazonk");
|
||||
});
|
||||
it('should fail if dictionary cannot be found', async function () {
|
||||
window.navigator.languages = ["de", "fr"];
|
||||
fetch.resolves(new Response('{}', { status: 404 }));
|
||||
fetch.mockResolvedValue(new Response('{}', { status: 404 }));
|
||||
let lclz = new Localizer();
|
||||
let ok = false;
|
||||
try {
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest';
|
||||
import Websock from '../core/websock.js';
|
||||
import Display from '../core/display.js';
|
||||
|
||||
|
|
@ -33,8 +34,8 @@ describe('Raw decoder', function () {
|
|||
let decoder;
|
||||
let display;
|
||||
|
||||
before(FakeWebSocket.replace);
|
||||
after(FakeWebSocket.restore);
|
||||
beforeAll(FakeWebSocket.replace);
|
||||
afterAll(FakeWebSocket.restore);
|
||||
|
||||
beforeEach(function () {
|
||||
decoder = new RawDecoder();
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,3 +1,4 @@
|
|||
import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest';
|
||||
import Websock from '../core/websock.js';
|
||||
import Display from '../core/display.js';
|
||||
|
||||
|
|
@ -45,8 +46,8 @@ describe('RRE decoder', function () {
|
|||
let decoder;
|
||||
let display;
|
||||
|
||||
before(FakeWebSocket.replace);
|
||||
after(FakeWebSocket.restore);
|
||||
beforeAll(FakeWebSocket.replace);
|
||||
afterAll(FakeWebSocket.restore);
|
||||
|
||||
beforeEach(function () {
|
||||
decoder = new RREDecoder();
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,3 +1,4 @@
|
|||
import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest';
|
||||
import Websock from '../core/websock.js';
|
||||
import Display from '../core/display.js';
|
||||
|
||||
|
|
@ -33,8 +34,8 @@ describe('Tight decoder', function () {
|
|||
let decoder;
|
||||
let display;
|
||||
|
||||
before(FakeWebSocket.replace);
|
||||
after(FakeWebSocket.restore);
|
||||
beforeAll(FakeWebSocket.replace);
|
||||
afterAll(FakeWebSocket.restore);
|
||||
|
||||
beforeEach(function () {
|
||||
decoder = new TightDecoder();
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest';
|
||||
import Websock from '../core/websock.js';
|
||||
import Display from '../core/display.js';
|
||||
|
||||
|
|
@ -33,8 +34,8 @@ describe('TightPng decoder', function () {
|
|||
let decoder;
|
||||
let display;
|
||||
|
||||
before(FakeWebSocket.replace);
|
||||
after(FakeWebSocket.restore);
|
||||
beforeAll(FakeWebSocket.replace);
|
||||
afterAll(FakeWebSocket.restore);
|
||||
|
||||
beforeEach(function () {
|
||||
decoder = new TightPngDecoder();
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest';
|
||||
/* eslint-disable no-console */
|
||||
import * as Log from '../core/util/logging.js';
|
||||
import { encodeUTF8, decodeUTF8 } from '../core/util/strings.js';
|
||||
|
|
@ -7,19 +8,19 @@ describe('Utils', function () {
|
|||
|
||||
describe('logging functions', function () {
|
||||
beforeEach(function () {
|
||||
sinon.spy(console, 'log');
|
||||
sinon.spy(console, 'debug');
|
||||
sinon.spy(console, 'warn');
|
||||
sinon.spy(console, 'error');
|
||||
sinon.spy(console, 'info');
|
||||
vi.spyOn(console, 'log');
|
||||
vi.spyOn(console, 'debug');
|
||||
vi.spyOn(console, 'warn');
|
||||
vi.spyOn(console, 'error');
|
||||
vi.spyOn(console, 'info');
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
console.log.restore();
|
||||
console.debug.restore();
|
||||
console.warn.restore();
|
||||
console.error.restore();
|
||||
console.info.restore();
|
||||
console.log.mockRestore();
|
||||
console.debug.mockRestore();
|
||||
console.warn.mockRestore();
|
||||
console.error.mockRestore();
|
||||
console.info.mockRestore();
|
||||
Log.initLogging();
|
||||
});
|
||||
|
||||
|
|
@ -27,33 +28,33 @@ describe('Utils', function () {
|
|||
Log.initLogging('warn');
|
||||
Log.Debug('hi');
|
||||
Log.Info('hello');
|
||||
expect(console.log).to.not.have.been.called;
|
||||
expect(console.log).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should use console.debug for Debug', function () {
|
||||
Log.initLogging('debug');
|
||||
Log.Debug('dbg');
|
||||
expect(console.debug).to.have.been.calledWith('dbg');
|
||||
expect(console.debug).toHaveBeenCalledWith('dbg');
|
||||
});
|
||||
|
||||
it('should use console.info for Info', function () {
|
||||
Log.initLogging('debug');
|
||||
Log.Info('inf');
|
||||
expect(console.info).to.have.been.calledWith('inf');
|
||||
expect(console.info).toHaveBeenCalledWith('inf');
|
||||
});
|
||||
|
||||
it('should use console.warn for Warn', function () {
|
||||
Log.initLogging('warn');
|
||||
Log.Warn('wrn');
|
||||
expect(console.warn).to.have.been.called;
|
||||
expect(console.warn).to.have.been.calledWith('wrn');
|
||||
expect(console.warn).toHaveBeenCalled();
|
||||
expect(console.warn).toHaveBeenCalledWith('wrn');
|
||||
});
|
||||
|
||||
it('should use console.error for Error', function () {
|
||||
Log.initLogging('error');
|
||||
Log.Error('err');
|
||||
expect(console.error).to.have.been.called;
|
||||
expect(console.error).to.have.been.calledWith('err');
|
||||
expect(console.error).toHaveBeenCalled();
|
||||
expect(console.error).toHaveBeenCalledWith('err');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import { vi, describe, it, expect, beforeAll, afterAll, beforeEach, afterEach } from 'vitest';
|
||||
import Websock from '../core/websock.js';
|
||||
import FakeWebSocket from './fake.websocket.js';
|
||||
|
||||
|
|
@ -352,7 +353,7 @@ describe('Websock', function () {
|
|||
|
||||
describe('lifecycle methods', function () {
|
||||
let oldWS;
|
||||
before(function () {
|
||||
beforeAll(function () {
|
||||
oldWS = WebSocket;
|
||||
});
|
||||
|
||||
|
|
@ -360,7 +361,11 @@ describe('Websock', function () {
|
|||
beforeEach(function () {
|
||||
sock = new Websock();
|
||||
// eslint-disable-next-line no-global-assign
|
||||
WebSocket = sinon.spy(FakeWebSocket);
|
||||
WebSocket = vi.fn(FakeWebSocket);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe('opening', function () {
|
||||
|
|
@ -370,7 +375,7 @@ describe('Websock', function () {
|
|||
|
||||
it('should open the actual websocket', function () {
|
||||
sock.open('ws://localhost:8675', 'binary');
|
||||
expect(WebSocket).to.have.been.calledWith('ws://localhost:8675', 'binary');
|
||||
expect(WebSocket).toHaveBeenCalledWith('ws://localhost:8675', 'binary');
|
||||
});
|
||||
|
||||
// it('should initialize the event handlers')?
|
||||
|
|
@ -380,79 +385,79 @@ describe('Websock', function () {
|
|||
it('should attach to an existing websocket', function () {
|
||||
let ws = new FakeWebSocket('ws://localhost:8675');
|
||||
sock.attach(ws);
|
||||
expect(WebSocket).to.not.have.been.called;
|
||||
expect(WebSocket).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('closing', function () {
|
||||
beforeEach(function () {
|
||||
sock.open('ws://localhost');
|
||||
sock._websocket.close = sinon.spy();
|
||||
sock._websocket.close = vi.fn();
|
||||
});
|
||||
|
||||
it('should close the actual websocket if it is open', function () {
|
||||
sock._websocket.readyState = WebSocket.OPEN;
|
||||
sock.close();
|
||||
expect(sock._websocket.close).to.have.been.calledOnce;
|
||||
expect(sock._websocket.close).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it('should close the actual websocket if it is connecting', function () {
|
||||
sock._websocket.readyState = WebSocket.CONNECTING;
|
||||
sock.close();
|
||||
expect(sock._websocket.close).to.have.been.calledOnce;
|
||||
expect(sock._websocket.close).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it('should not try to close the actual websocket if closing', function () {
|
||||
sock._websocket.readyState = WebSocket.CLOSING;
|
||||
sock.close();
|
||||
expect(sock._websocket.close).not.to.have.been.called;
|
||||
expect(sock._websocket.close).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not try to close the actual websocket if closed', function () {
|
||||
sock._websocket.readyState = WebSocket.CLOSED;
|
||||
sock.close();
|
||||
expect(sock._websocket.close).not.to.have.been.called;
|
||||
expect(sock._websocket.close).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should reset onmessage to not call _recvMessage', function () {
|
||||
sinon.spy(sock, '_recvMessage');
|
||||
vi.spyOn(sock, '_recvMessage');
|
||||
sock.close();
|
||||
sock._websocket.onmessage(null);
|
||||
try {
|
||||
expect(sock._recvMessage).not.to.have.been.called;
|
||||
expect(sock._recvMessage).not.toHaveBeenCalled();
|
||||
} finally {
|
||||
sock._recvMessage.restore();
|
||||
sock._recvMessage.mockRestore();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('event handlers', function () {
|
||||
beforeEach(function () {
|
||||
sock._recvMessage = sinon.spy();
|
||||
sock.on('open', sinon.spy());
|
||||
sock.on('close', sinon.spy());
|
||||
sock.on('error', sinon.spy());
|
||||
sock._recvMessage = vi.fn();
|
||||
sock.on('open', vi.fn());
|
||||
sock.on('close', vi.fn());
|
||||
sock.on('error', vi.fn());
|
||||
sock.open('ws://localhost');
|
||||
});
|
||||
|
||||
it('should call _recvMessage on a message', function () {
|
||||
sock._websocket.onmessage(null);
|
||||
expect(sock._recvMessage).to.have.been.calledOnce;
|
||||
expect(sock._recvMessage).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it('should call the open event handler on opening', function () {
|
||||
sock._websocket.onopen();
|
||||
expect(sock._eventHandlers.open).to.have.been.calledOnce;
|
||||
expect(sock._eventHandlers.open).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it('should call the close event handler on closing', function () {
|
||||
sock._websocket.onclose();
|
||||
expect(sock._eventHandlers.close).to.have.been.calledOnce;
|
||||
expect(sock._eventHandlers.close).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it('should call the error event handler on error', function () {
|
||||
sock._websocket.onerror();
|
||||
expect(sock._eventHandlers.error).to.have.been.calledOnce;
|
||||
expect(sock._eventHandlers.error).toHaveBeenCalledOnce();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -543,7 +548,7 @@ describe('Websock', function () {
|
|||
});
|
||||
});
|
||||
|
||||
after(function () {
|
||||
afterAll(function () {
|
||||
// eslint-disable-next-line no-global-assign
|
||||
WebSocket = oldWS;
|
||||
});
|
||||
|
|
@ -563,19 +568,19 @@ describe('Websock', function () {
|
|||
});
|
||||
|
||||
it('should call the message event handler if present', function () {
|
||||
sock._eventHandlers.message = sinon.spy();
|
||||
sock._eventHandlers.message = vi.fn();
|
||||
const msg = { data: new Uint8Array([1, 2, 3]).buffer };
|
||||
sock._mode = 'binary';
|
||||
sock._recvMessage(msg);
|
||||
expect(sock._eventHandlers.message).to.have.been.calledOnce;
|
||||
expect(sock._eventHandlers.message).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it('should not call the message event handler if there is nothing in the receive queue', function () {
|
||||
sock._eventHandlers.message = sinon.spy();
|
||||
sock._eventHandlers.message = vi.fn();
|
||||
const msg = { data: new Uint8Array([]).buffer };
|
||||
sock._mode = 'binary';
|
||||
sock._recvMessage(msg);
|
||||
expect(sock._eventHandlers.message).not.to.have.been.called;
|
||||
expect(sock._eventHandlers.message).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should compact the receive queue when fully read', function () {
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
/* jshint expr: true */
|
||||
|
||||
import { vi, describe, it, expect, beforeAll, afterAll, beforeEach, afterEach } from 'vitest';
|
||||
import * as WebUtil from '../app/webutil.js';
|
||||
|
||||
describe('WebUtil', function () {
|
||||
|
|
@ -52,19 +53,17 @@ describe('WebUtil', function () {
|
|||
});
|
||||
});
|
||||
|
||||
describe('cookies', function () {
|
||||
// TODO
|
||||
});
|
||||
describe.todo('cookies');
|
||||
|
||||
describe('settings', function () {
|
||||
|
||||
describe('localStorage', function () {
|
||||
let chrome = window.chrome;
|
||||
before(function () {
|
||||
beforeAll(function () {
|
||||
chrome = window.chrome;
|
||||
window.chrome = null;
|
||||
});
|
||||
after(function () {
|
||||
afterAll(function () {
|
||||
window.chrome = chrome;
|
||||
});
|
||||
|
||||
|
|
@ -74,9 +73,9 @@ describe('WebUtil', function () {
|
|||
|
||||
Object.defineProperty(window, "localStorage", {value: {}});
|
||||
|
||||
window.localStorage.setItem = sinon.stub();
|
||||
window.localStorage.getItem = sinon.stub();
|
||||
window.localStorage.removeItem = sinon.stub();
|
||||
window.localStorage.setItem = vi.fn();
|
||||
window.localStorage.getItem = vi.fn();
|
||||
window.localStorage.removeItem = vi.fn();
|
||||
|
||||
return WebUtil.initSettings();
|
||||
});
|
||||
|
|
@ -87,12 +86,12 @@ describe('WebUtil', function () {
|
|||
describe('writeSetting', function () {
|
||||
it('should save the setting value to local storage', function () {
|
||||
WebUtil.writeSetting('test', 'value');
|
||||
expect(window.localStorage.setItem).to.have.been.calledWithExactly('test', 'value');
|
||||
expect(window.localStorage.setItem).toHaveBeenCalledWith('test', 'value');
|
||||
expect(WebUtil.readSetting('test')).to.equal('value');
|
||||
});
|
||||
|
||||
it('should not crash when local storage save fails', function () {
|
||||
localStorage.setItem.throws(new DOMException());
|
||||
localStorage.setItem.mockImplementation(() => { throw new DOMException(); });
|
||||
expect(WebUtil.writeSetting('test', 'value')).to.not.throw;
|
||||
});
|
||||
});
|
||||
|
|
@ -100,14 +99,14 @@ describe('WebUtil', function () {
|
|||
describe('setSetting', function () {
|
||||
it('should update the setting but not save to local storage', function () {
|
||||
WebUtil.setSetting('test', 'value');
|
||||
expect(window.localStorage.setItem).to.not.have.been.called;
|
||||
expect(window.localStorage.setItem).not.toHaveBeenCalled();
|
||||
expect(WebUtil.readSetting('test')).to.equal('value');
|
||||
});
|
||||
});
|
||||
|
||||
describe('readSetting', function () {
|
||||
it('should read the setting value from local storage', function () {
|
||||
localStorage.getItem.returns('value');
|
||||
localStorage.getItem.mockReturnValue('value');
|
||||
expect(WebUtil.readSetting('test')).to.equal('value');
|
||||
});
|
||||
|
||||
|
|
@ -116,33 +115,33 @@ describe('WebUtil', function () {
|
|||
});
|
||||
|
||||
it('should return the cached value even if local storage changed', function () {
|
||||
localStorage.getItem.returns('value');
|
||||
localStorage.getItem.mockReturnValue('value');
|
||||
expect(WebUtil.readSetting('test')).to.equal('value');
|
||||
localStorage.getItem.returns('something else');
|
||||
localStorage.getItem.mockReturnValue('something else');
|
||||
expect(WebUtil.readSetting('test')).to.equal('value');
|
||||
});
|
||||
|
||||
it('should cache the value even if it is not initially in local storage', function () {
|
||||
expect(WebUtil.readSetting('test')).to.be.null;
|
||||
localStorage.getItem.returns('value');
|
||||
localStorage.getItem.mockReturnValue('value');
|
||||
expect(WebUtil.readSetting('test')).to.be.null;
|
||||
});
|
||||
|
||||
it('should return the default value always if the first read was not in local storage', function () {
|
||||
expect(WebUtil.readSetting('test', 'default')).to.equal('default');
|
||||
localStorage.getItem.returns('value');
|
||||
localStorage.getItem.mockReturnValue('value');
|
||||
expect(WebUtil.readSetting('test', 'another default')).to.equal('another default');
|
||||
});
|
||||
|
||||
it('should return the last local written value', function () {
|
||||
localStorage.getItem.returns('value');
|
||||
localStorage.getItem.mockReturnValue('value');
|
||||
expect(WebUtil.readSetting('test')).to.equal('value');
|
||||
WebUtil.writeSetting('test', 'something else');
|
||||
expect(WebUtil.readSetting('test')).to.equal('something else');
|
||||
});
|
||||
|
||||
it('should not crash when local storage read fails', function () {
|
||||
localStorage.getItem.throws(new DOMException());
|
||||
localStorage.getItem.mockImplementation(() => { throw new DOMException(); });
|
||||
expect(WebUtil.readSetting('test')).to.not.throw;
|
||||
});
|
||||
});
|
||||
|
|
@ -151,11 +150,11 @@ describe('WebUtil', function () {
|
|||
describe('eraseSetting', function () {
|
||||
it('should remove the setting from local storage', function () {
|
||||
WebUtil.eraseSetting('test');
|
||||
expect(window.localStorage.removeItem).to.have.been.calledWithExactly('test');
|
||||
expect(window.localStorage.removeItem).toHaveBeenCalledWith('test');
|
||||
});
|
||||
|
||||
it('should not crash when local storage remove fails', function () {
|
||||
localStorage.removeItem.throws(new DOMException());
|
||||
localStorage.removeItem.mockImplementation(() => { throw new DOMException(); });
|
||||
expect(WebUtil.eraseSetting('test')).to.not.throw;
|
||||
});
|
||||
});
|
||||
|
|
@ -164,7 +163,7 @@ describe('WebUtil', function () {
|
|||
describe('chrome.storage', function () {
|
||||
let chrome = window.chrome;
|
||||
let settings = {};
|
||||
before(function () {
|
||||
beforeAll(function () {
|
||||
chrome = window.chrome;
|
||||
window.chrome = {
|
||||
storage: {
|
||||
|
|
@ -176,25 +175,25 @@ describe('WebUtil', function () {
|
|||
}
|
||||
};
|
||||
});
|
||||
after(function () {
|
||||
afterAll(function () {
|
||||
window.chrome = chrome;
|
||||
});
|
||||
|
||||
beforeEach(function () {
|
||||
settings = {};
|
||||
sinon.spy(window.chrome.storage.sync, 'set');
|
||||
sinon.spy(window.chrome.storage.sync, 'remove');
|
||||
vi.spyOn(window.chrome.storage.sync, 'set');
|
||||
vi.spyOn(window.chrome.storage.sync, 'remove');
|
||||
return WebUtil.initSettings();
|
||||
});
|
||||
afterEach(function () {
|
||||
window.chrome.storage.sync.set.restore();
|
||||
window.chrome.storage.sync.remove.restore();
|
||||
window.chrome.storage.sync.set.mockRestore();
|
||||
window.chrome.storage.sync.remove.mockRestore();
|
||||
});
|
||||
|
||||
describe('writeSetting', function () {
|
||||
it('should save the setting value to chrome storage', function () {
|
||||
WebUtil.writeSetting('test', 'value');
|
||||
expect(window.chrome.storage.sync.set).to.have.been.calledWithExactly(sinon.match({ test: 'value' }));
|
||||
expect(window.chrome.storage.sync.set).toHaveBeenCalledWith(expect.objectContaining({ test: 'value' }));
|
||||
expect(WebUtil.readSetting('test')).to.equal('value');
|
||||
});
|
||||
});
|
||||
|
|
@ -202,7 +201,7 @@ describe('WebUtil', function () {
|
|||
describe('setSetting', function () {
|
||||
it('should update the setting but not save to chrome storage', function () {
|
||||
WebUtil.setSetting('test', 'value');
|
||||
expect(window.chrome.storage.sync.set).to.not.have.been.called;
|
||||
expect(window.chrome.storage.sync.set).not.toHaveBeenCalled();
|
||||
expect(WebUtil.readSetting('test')).to.equal('value');
|
||||
});
|
||||
});
|
||||
|
|
@ -229,7 +228,7 @@ describe('WebUtil', function () {
|
|||
describe('eraseSetting', function () {
|
||||
it('should remove the setting from chrome storage', function () {
|
||||
WebUtil.eraseSetting('test');
|
||||
expect(window.chrome.storage.sync.remove).to.have.been.calledWithExactly('test');
|
||||
expect(window.chrome.storage.sync.remove).toHaveBeenCalledWith('test');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest';
|
||||
import Websock from '../core/websock.js';
|
||||
import Display from '../core/display.js';
|
||||
|
||||
|
|
@ -33,8 +34,8 @@ describe('Zlib decoder', function () {
|
|||
let decoder;
|
||||
let display;
|
||||
|
||||
before(FakeWebSocket.replace);
|
||||
after(FakeWebSocket.restore);
|
||||
beforeAll(FakeWebSocket.replace);
|
||||
afterAll(FakeWebSocket.restore);
|
||||
|
||||
beforeEach(function () {
|
||||
decoder = new ZlibDecoder();
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest';
|
||||
import Websock from '../core/websock.js';
|
||||
import Display from '../core/display.js';
|
||||
|
||||
|
|
@ -33,8 +34,8 @@ describe('ZRLE decoder', function () {
|
|||
let decoder;
|
||||
let display;
|
||||
|
||||
before(FakeWebSocket.replace);
|
||||
after(FakeWebSocket.restore);
|
||||
beforeAll(FakeWebSocket.replace);
|
||||
afterAll(FakeWebSocket.restore);
|
||||
|
||||
beforeEach(function () {
|
||||
decoder = new ZRLEDecoder();
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { defineConfig } from 'vitest/config';
|
||||
import { playwright } from '@vitest/browser-playwright';
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
setupFiles: "./tests/assertions.js",
|
||||
browser: {
|
||||
enabled: true,
|
||||
provider: playwright(),
|
||||
// https://vitest.dev/guide/browser/playwright
|
||||
instances: [
|
||||
{ browser: 'chromium' },
|
||||
{ browser: 'firefox' },
|
||||
{ browser: 'webkit' },
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
Loading…
Reference in New Issue