feat: Initial clean release of CHM
一些检查失败了
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
一些检查失败了
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
这个提交包含在:
@@ -0,0 +1,79 @@
|
||||
import { expect, Locator } from '@playwright/test';
|
||||
|
||||
const extendedExpect = expect.extend({
|
||||
async toBeSeekableMediaElement(videoLocator: Locator, seeksTo: number, playsUntil: number) {
|
||||
let pass = true;
|
||||
|
||||
let nextAssertionStep = '';
|
||||
const assertionName = 'toBeSeekableMediaElement';
|
||||
let resultMessage = () => `${assertionName}: Passed`;
|
||||
|
||||
try {
|
||||
await extendedExpect(videoLocator).toBeVisible();
|
||||
|
||||
const getDuration = () => {
|
||||
return videoLocator.evaluate((video) => {
|
||||
if (!(video instanceof HTMLMediaElement)) {
|
||||
throw new Error('Not a media element');
|
||||
}
|
||||
|
||||
return video.duration;
|
||||
});
|
||||
};
|
||||
|
||||
nextAssertionStep = 'Media should be long enough to seek and play';
|
||||
await extendedExpect.poll(getDuration).toBeGreaterThanOrEqual(Math.max(seeksTo, playsUntil));
|
||||
|
||||
nextAssertionStep = 'Should not have a loading error';
|
||||
await extendedExpect(videoLocator).toHaveJSProperty('error', null);
|
||||
|
||||
nextAssertionStep = `Should seek to ${this.utils.printExpected(seeksTo)}`;
|
||||
await videoLocator.evaluate((video: HTMLMediaElement, playsFrom: number) => {
|
||||
video.pause();
|
||||
video.currentTime = playsFrom;
|
||||
}, seeksTo);
|
||||
|
||||
const getCurrentTime = () => {
|
||||
return videoLocator.evaluate((video: HTMLVideoElement) => {
|
||||
return video.currentTime;
|
||||
});
|
||||
};
|
||||
await extendedExpect.poll(getCurrentTime).toBeCloseTo(seeksTo);
|
||||
|
||||
nextAssertionStep = `Should play until ${this.utils.printExpected(playsUntil)}`;
|
||||
await videoLocator.evaluate((video: HTMLMediaElement) => video.play());
|
||||
await extendedExpect.poll(getCurrentTime).toBeGreaterThan(playsUntil);
|
||||
} catch (error) {
|
||||
pass = false;
|
||||
resultMessage = () => error.toString();
|
||||
}
|
||||
|
||||
return {
|
||||
pass,
|
||||
message: () => `${assertionName}: ${nextAssertionStep}:\n ${resultMessage()}`,
|
||||
name: assertionName,
|
||||
};
|
||||
},
|
||||
|
||||
async toBeSelected(locator: Locator) {
|
||||
let pass = true;
|
||||
|
||||
const assertionName = 'toBeSelected';
|
||||
let resultMessage = () => `${assertionName}: Passed`;
|
||||
|
||||
try {
|
||||
await extendedExpect(locator).toHaveJSProperty('ariaSelected', 'true');
|
||||
} catch (error) {
|
||||
pass = false;
|
||||
resultMessage = () => error.toString();
|
||||
}
|
||||
|
||||
return {
|
||||
pass,
|
||||
message: () => `${assertionName}: ${resultMessage()}`,
|
||||
name: assertionName,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export default extendedExpect;
|
||||
在新工单中引用
屏蔽一个用户