Migrate timeline.spec.ts from Cypress to Playwright (#12025)
* Migrate timeline.spec.ts from Cypress to Playwright Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Monospace font for timestamps Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * More expects Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * delint Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
BIN
cypress/fixtures/element.png
Normal file
After Width: | Height: | Size: 17 KiB |
|
@ -26,7 +26,10 @@ export default defineConfig<TestOptions>({
|
||||||
ignoreHTTPSErrors: true,
|
ignoreHTTPSErrors: true,
|
||||||
video: "retain-on-failure",
|
video: "retain-on-failure",
|
||||||
baseURL,
|
baseURL,
|
||||||
permissions: ["clipboard-write", "clipboard-read"],
|
permissions: ["clipboard-write", "clipboard-read", "microphone"],
|
||||||
|
launchOptions: {
|
||||||
|
args: ["--use-fake-ui-for-media-stream", "--use-fake-device-for-media-stream", "--mute-audio"],
|
||||||
|
},
|
||||||
trace: "on-first-retry",
|
trace: "on-first-retry",
|
||||||
},
|
},
|
||||||
webServer: {
|
webServer: {
|
||||||
|
|
1130
playwright/e2e/timeline/timeline.spec.ts
Normal file
|
@ -250,6 +250,10 @@ export const expect = baseExpect.extend({
|
||||||
.mx_ReplyChain {
|
.mx_ReplyChain {
|
||||||
border-left-color: var(--cpd-color-blue-1200) !important;
|
border-left-color: var(--cpd-color-blue-1200) !important;
|
||||||
}
|
}
|
||||||
|
/* Use monospace font for timestamp for consistent mask width */
|
||||||
|
.mx_MessageTimestamp {
|
||||||
|
font-family: Inconsolata !important;
|
||||||
|
}
|
||||||
${options?.css ?? ""}
|
${options?.css ?? ""}
|
||||||
`,
|
`,
|
||||||
})) as ElementHandle<Element>;
|
})) as ElementHandle<Element>;
|
||||||
|
|
|
@ -105,6 +105,14 @@ export class ElementAppPage {
|
||||||
return this.page.locator(`${panelClass} .mx_MessageComposer`);
|
return this.page.locator(`${panelClass} .mx_MessageComposer`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the composer input field
|
||||||
|
* @param isRightPanel whether to select the right panel composer, otherwise the main timeline composer
|
||||||
|
*/
|
||||||
|
public getComposerField(isRightPanel?: boolean): Locator {
|
||||||
|
return this.getComposer(isRightPanel).locator("[contenteditable]");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the message composer kebab menu
|
* Open the message composer kebab menu
|
||||||
* @param isRightPanel whether to select the right panel composer, otherwise the main timeline composer
|
* @param isRightPanel whether to select the right panel composer, otherwise the main timeline composer
|
||||||
|
@ -155,4 +163,10 @@ export class ElementAppPage {
|
||||||
await spotlight.open();
|
await spotlight.open();
|
||||||
return spotlight;
|
return spotlight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async scrollToBottom(page: Page): Promise<void> {
|
||||||
|
await page
|
||||||
|
.locator(".mx_ScrollPanel")
|
||||||
|
.evaluate((scrollPanel) => scrollPanel.scrollTo(0, scrollPanel.scrollHeight));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@ import type {
|
||||||
IRoomDirectoryOptions,
|
IRoomDirectoryOptions,
|
||||||
KnockRoomOpts,
|
KnockRoomOpts,
|
||||||
Visibility,
|
Visibility,
|
||||||
|
UploadOpts,
|
||||||
|
Upload,
|
||||||
} from "matrix-js-sdk/src/matrix";
|
} from "matrix-js-sdk/src/matrix";
|
||||||
import { Credentials } from "../plugins/homeserver";
|
import { Credentials } from "../plugins/homeserver";
|
||||||
|
|
||||||
|
@ -293,6 +295,46 @@ export class Client {
|
||||||
}, options);
|
}, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} name
|
||||||
|
* @param {module:client.callback} callback Optional.
|
||||||
|
* @return {Promise} Resolves: {} an empty object.
|
||||||
|
* @return {module:http-api.MatrixError} Rejects: with an error response.
|
||||||
|
*/
|
||||||
|
public async setDisplayName(name: string): Promise<{}> {
|
||||||
|
const client = await this.prepareClient();
|
||||||
|
return client.evaluate(async (cli: MatrixClient, name) => cli.setDisplayName(name), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} url
|
||||||
|
* @param {module:client.callback} callback Optional.
|
||||||
|
* @return {Promise} Resolves: {} an empty object.
|
||||||
|
* @return {module:http-api.MatrixError} Rejects: with an error response.
|
||||||
|
*/
|
||||||
|
public async setAvatarUrl(url: string): Promise<{}> {
|
||||||
|
const client = await this.prepareClient();
|
||||||
|
return client.evaluate(async (cli: MatrixClient, url) => cli.setAvatarUrl(url), url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload a file to the media repository on the homeserver.
|
||||||
|
*
|
||||||
|
* @param {object} file The object to upload. On a browser, something that
|
||||||
|
* can be sent to XMLHttpRequest.send (typically a File). Under node.js,
|
||||||
|
* a Buffer, String or ReadStream.
|
||||||
|
*/
|
||||||
|
public async uploadContent(file: Buffer, opts?: UploadOpts): Promise<Awaited<Upload["promise"]>> {
|
||||||
|
const client = await this.prepareClient();
|
||||||
|
return client.evaluate(
|
||||||
|
async (cli: MatrixClient, { file, opts }) => cli.uploadContent(new Uint8Array(file), opts),
|
||||||
|
{
|
||||||
|
file: [...file],
|
||||||
|
opts,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Boostraps cross-signing.
|
* Boostraps cross-signing.
|
||||||
*/
|
*/
|
||||||
|
|
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 7.5 KiB |
After Width: | Height: | Size: 8 KiB |
After Width: | Height: | Size: 9.1 KiB |
After Width: | Height: | Size: 8.2 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 49 KiB |
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 54 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 49 KiB |
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 92 KiB |
After Width: | Height: | Size: 91 KiB |
After Width: | Height: | Size: 100 KiB |
After Width: | Height: | Size: 5 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 10 KiB |