Cypress test for QR code display (#11240)

This commit is contained in:
Richard van der Hoff 2023-07-13 14:56:15 +01:00 committed by GitHub
parent 2cfbd73cd3
commit 46c12a808f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 69 additions and 0 deletions

View file

@ -14,6 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import jsQR from "jsqr";
import type { VerificationRequest, Verifier } from "matrix-js-sdk/src/crypto-api/verification"; import type { VerificationRequest, Verifier } from "matrix-js-sdk/src/crypto-api/verification";
import { CypressBot } from "../../support/bot"; import { CypressBot } from "../../support/bot";
import { HomeserverInstance } from "../../plugins/utils/homeserver"; import { HomeserverInstance } from "../../plugins/utils/homeserver";
@ -21,6 +23,24 @@ import { emitPromise } from "../../support/util";
import { checkDeviceIsCrossSigned, doTwoWaySasVerification, logIntoElement, waitForVerificationRequest } from "./utils"; import { checkDeviceIsCrossSigned, doTwoWaySasVerification, logIntoElement, waitForVerificationRequest } from "./utils";
import { getToast } from "../../support/toasts"; import { getToast } from "../../support/toasts";
/** Render a data URL and return the rendered image data */
async function renderQRCode(dataUrl: string): Promise<ImageData> {
// create a new image and set the source to the data url
const img = new Image();
await new Promise((r) => {
img.onload = r;
img.src = dataUrl;
});
// draw the image on a canvas
const myCanvas = new OffscreenCanvas(256, 256);
const ctx = myCanvas.getContext("2d");
ctx.drawImage(img, 0, 0);
// read the image data
return ctx.getImageData(0, 0, myCanvas.width, myCanvas.height);
}
describe("Device verification", () => { describe("Device verification", () => {
let aliceBotClient: CypressBot; let aliceBotClient: CypressBot;
let homeserver: HomeserverInstance; let homeserver: HomeserverInstance;
@ -91,6 +111,49 @@ describe("Device verification", () => {
checkDeviceIsCrossSigned(); checkDeviceIsCrossSigned();
}); });
it("Verify device during login with QR code", () => {
logIntoElement(homeserver.baseUrl, aliceBotClient.getUserId(), aliceBotClient.__cypress_password);
// Launch the verification request between alice and the bot
initiateAliceVerificationRequest();
cy.get(".mx_InfoDialog").within(() => {
cy.get('[alt="QR Code"]').then((qrCode) => {
/* the bot scans the QR code */
cy.get<VerificationRequest>("@verificationRequest")
.then(async (request: VerificationRequest) => {
// because I don't know how to scrape the imagedata from the cypress browser window,
// we extract the data url and render it to a new canvas.
const imageData = await renderQRCode(qrCode.attr("src"));
// now we can decode the QR code...
const result = jsQR(imageData.data, imageData.width, imageData.height);
// ... and feed it into the verification request.
return await request.scanQRCode(new Uint8Array(result.binaryData));
})
.as("verifier");
});
// Confirm that the bot user scanned successfully
cy.findByText("Almost there! Is your other device showing the same shield?");
cy.findByRole("button", { name: "Yes" }).click();
cy.findByRole("button", { name: "Got it" }).click();
});
// wait for the bot to see we have finished
cy.get<Verifier>("@verifier").then(async (verifier) => {
await verifier.verify();
});
// the bot uploads the signatures asynchronously, so wait for that to happen
cy.wait(1000);
// Check that our device is now cross-signed
checkDeviceIsCrossSigned();
});
it("Verify device during login with Security Phrase", () => { it("Verify device during login with Security Phrase", () => {
logIntoElement(homeserver.baseUrl, aliceBotClient.getUserId(), aliceBotClient.__cypress_password); logIntoElement(homeserver.baseUrl, aliceBotClient.getUserId(), aliceBotClient.__cypress_password);

View file

@ -203,6 +203,7 @@
"jest-environment-jsdom": "^29.2.2", "jest-environment-jsdom": "^29.2.2",
"jest-mock": "^29.2.2", "jest-mock": "^29.2.2",
"jest-raw-loader": "^1.0.1", "jest-raw-loader": "^1.0.1",
"jsqr": "^1.4.0",
"matrix-mock-request": "^2.5.0", "matrix-mock-request": "^2.5.0",
"matrix-web-i18n": "^1.4.0", "matrix-web-i18n": "^1.4.0",
"mocha-junit-reporter": "^2.2.0", "mocha-junit-reporter": "^2.2.0",

View file

@ -6497,6 +6497,11 @@ jsprim@^2.0.2:
json-schema "0.4.0" json-schema "0.4.0"
verror "1.10.0" verror "1.10.0"
jsqr@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/jsqr/-/jsqr-1.4.0.tgz#8efb8d0a7cc6863cb6d95116b9069123ce9eb2d1"
integrity sha512-dxLob7q65Xg2DvstYkRpkYtmKm2sPJ9oFhrhmudT1dZvNFFTlroai3AWSpLey/w5vMcLBXRgOJsbXpdN9HzU/A==
"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.3: "jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.3:
version "3.3.3" version "3.3.3"
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz#76b3e6e6cece5c69d49a5792c3d01bd1a0cdc7ea" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz#76b3e6e6cece5c69d49a5792c3d01bd1a0cdc7ea"