一些检查失败了
automerge / automerge (push) Has been cancelled
react-native-android-build-apk / AssembleRelease (push) Has been cancelled
Build macOS M1 / Main (push) Has been cancelled
Joplin Continuous Integration / Main (macos-15-intel) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-11-vs2026-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-2025) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04-arm) (push) Has been cancelled
Joplin UI tests / Main (ubuntu-22.04) (push) Has been cancelled
Joplin UI tests / Main (windows-2025) (push) Has been cancelled
Joplin UI tests / Mobile (push) Has been cancelled
Close stale issues / ProcessStaleIssues (push) Has been cancelled
113 行
3.4 KiB
TypeScript
113 行
3.4 KiB
TypeScript
/**
|
|
* @jest-environment jsdom
|
|
*/
|
|
|
|
import createEventHandlingAttrs, { createEventHandlingListeners, Options } from './createEventHandlingAttrs';
|
|
import { describe, beforeAll, it, jest, expect, test } from '@jest/globals';
|
|
|
|
describe('createEventHandlingAttrs', () => {
|
|
let lastMessage: string|undefined = undefined;
|
|
const postMessageFn = (message: string) => {
|
|
lastMessage = message;
|
|
};
|
|
|
|
beforeAll(() => {
|
|
lastMessage = undefined;
|
|
|
|
jest.useFakeTimers();
|
|
});
|
|
|
|
it('should not create listeners to handle long-press when long press is disabled', () => {
|
|
const options: Options = {
|
|
enableLongPress: false,
|
|
postMessageSyntax: 'postMessageFn',
|
|
enableEditPopup: false,
|
|
};
|
|
const listeners = createEventHandlingListeners('someresourceid', options, 'postMessage("click")');
|
|
|
|
// Should not add touchstart/mouseenter/leave listeners when not creating
|
|
// an edit popup or long-pressing.
|
|
expect(listeners.onmouseenter).toBe('');
|
|
expect(listeners.onmouseleave).toBe('');
|
|
expect(listeners.ontouchstart).toBe('');
|
|
expect(listeners.ontouchmove).toBe('');
|
|
expect(listeners.ontouchend).toBe('');
|
|
expect(listeners.ontouchcancel).toBe('');
|
|
});
|
|
|
|
it('should create click listener for given click action', () => {
|
|
const options: Options = {
|
|
enableLongPress: false,
|
|
postMessageSyntax: 'postMessageFn',
|
|
enableEditPopup: false,
|
|
};
|
|
const clickAction = 'postMessageFn("click")';
|
|
const listeners = createEventHandlingListeners('someresourceid', options, clickAction);
|
|
expect(listeners.onclick).toContain(clickAction);
|
|
|
|
postMessageFn('test');
|
|
eval(listeners.onclick);
|
|
expect(lastMessage).toBe('click');
|
|
});
|
|
|
|
it('should create ontouch listeners for long press', () => {
|
|
const options: Options = {
|
|
enableLongPress: true,
|
|
postMessageSyntax: 'postMessageFn',
|
|
enableEditPopup: false,
|
|
};
|
|
const clickAction: null|string = null;
|
|
const listeners = createEventHandlingListeners('resourceidhere', options, clickAction);
|
|
|
|
expect(listeners.onclick).toBe('');
|
|
expect(listeners.ontouchstart).not.toBe('');
|
|
|
|
// Clear lastMessage
|
|
postMessageFn('test');
|
|
|
|
eval(listeners.ontouchstart);
|
|
jest.advanceTimersByTime(1000 * 4);
|
|
|
|
expect(lastMessage).toBe('longclick:resourceidhere');
|
|
});
|
|
|
|
it('motion during a long press should cancel the timeout', () => {
|
|
const options: Options = {
|
|
enableLongPress: true,
|
|
postMessageSyntax: 'postMessageFn',
|
|
enableEditPopup: false,
|
|
};
|
|
const listeners = createEventHandlingListeners('id', options, null);
|
|
|
|
lastMessage = '';
|
|
eval(listeners.ontouchstart);
|
|
jest.advanceTimersByTime(100);
|
|
eval(listeners.ontouchmove);
|
|
jest.advanceTimersByTime(1000 * 100);
|
|
|
|
// Message handler should not have been called.
|
|
expect(lastMessage).toBe('');
|
|
});
|
|
|
|
test.each([
|
|
'"',
|
|
'"',
|
|
'"',
|
|
])('should not allow an entity sequence in the click action to break out of the attribute (case %#)', (entity) => {
|
|
const options: Options = {
|
|
enableLongPress: true,
|
|
postMessageSyntax: 'postMessageFn',
|
|
enableEditPopup: false,
|
|
};
|
|
const clickAction = `postMessageFn("joplin://resourceid#${entity});canary=1;//")`;
|
|
const attrs = createEventHandlingAttrs('resourceid', options, clickAction);
|
|
|
|
const container = document.createElement('div');
|
|
container.innerHTML = `<a ${attrs}>link</a>`;
|
|
const onclick = container.querySelector('a').getAttribute('onclick');
|
|
|
|
expect(onclick).not.toContain('");canary=1');
|
|
expect(onclick).toContain(entity);
|
|
});
|
|
});
|