Skip to content

Commit

Permalink
Merge pull request #1134 from vector-im/invite/implement-invite-command
Browse files Browse the repository at this point in the history
Invite - PR [1/2] - Add command /invite to message composer
  • Loading branch information
MidhunSureshR authored Sep 4, 2023
2 parents 363ea20 + a89a901 commit 0cad1e5
Show file tree
Hide file tree
Showing 11 changed files with 165 additions and 25 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/codechecks.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:

strategy:
matrix:
node-version: [14.x]
node-version: [18.1.0]

steps:
- name: Checkout source
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"escodegen": "^2.0.0",
"eslint": "^7.32.0",
"fake-indexeddb": "^3.1.2",
"fs-extra": "^11.1.1",
"impunity": "^1.0.9",
"mdn-polyfills": "^5.20.0",
"merge-options": "^3.0.4",
Expand Down
4 changes: 1 addition & 3 deletions playwright/plugins/dex/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,13 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

/// <reference types="cypress" />

import * as path from "path";
import * as os from "os";
import * as fse from "fs-extra";

import {dockerRun, dockerStop } from "../docker";

// A cypress plugins to add command to start & stop dex instances
// A plugin that adds command to start & stop dex instances

interface DexConfig {
configDir: string;
Expand Down
23 changes: 14 additions & 9 deletions playwright/plugins/docker/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

/// <reference types="cypress" />

import * as os from "os";
import * as childProcess from "child_process";
import * as fse from "fs-extra";
Expand All @@ -36,7 +34,8 @@ export function dockerRun(args: {
}

return new Promise<string>((resolve, reject) => {
childProcess.execFile('docker', [
childProcess.execFile('sudo', [
"docker",
"run",
"--name", args.containerName,
"-d",
Expand All @@ -57,7 +56,8 @@ export function dockerExec(args: {
params: string[];
}): Promise<void> {
return new Promise<void>((resolve, reject) => {
childProcess.execFile("docker", [
childProcess.execFile("sudo", [
"docker",
"exec", args.containerId,
...args.params,
], { encoding: 'utf8' }, (err, stdout, stderr) => {
Expand All @@ -79,10 +79,12 @@ export function dockerCreateNetwork(args: {
networkName: string;
}): Promise<void> {
return new Promise<void>((resolve, reject) => {
childProcess.execFile("docker", [
childProcess.execFile("sudo", [
"docker",
"network",
"create",
args.networkName
args.networkName,
"--subnet", "172.18.0.0/16"
], { encoding: 'utf8' }, (err, stdout, stderr) => {
if(err) {
if (stderr.includes(`network with name ${args.networkName} already exists`)) {
Expand All @@ -106,7 +108,8 @@ export async function dockerLogs(args: {
const stderrFile = args.stderrFile ? await fse.open(args.stderrFile, "w") : "ignore";

await new Promise<void>((resolve) => {
childProcess.spawn("docker", [
childProcess.spawn("sudo", [
"docker",
"logs",
args.containerId,
], {
Expand All @@ -122,7 +125,8 @@ export function dockerStop(args: {
containerId: string;
}): Promise<void> {
return new Promise<void>((resolve, reject) => {
childProcess.execFile('docker', [
childProcess.execFile('sudo', [
"docker",
"stop",
args.containerId,
], err => {
Expand All @@ -138,7 +142,8 @@ export function dockerRm(args: {
containerId: string;
}): Promise<void> {
return new Promise<void>((resolve, reject) => {
childProcess.execFile('docker', [
childProcess.execFile('sudo', [
"docker",
"rm",
args.containerId,
], err => {
Expand Down
4 changes: 1 addition & 3 deletions playwright/plugins/synapsedocker/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

/// <reference types="cypress" />

import * as path from "path";
import * as os from "os";
import * as crypto from "crypto";
Expand All @@ -25,7 +23,7 @@ import {dockerCreateNetwork, dockerExec, dockerLogs, dockerRun, dockerStop} from
import {request} from "@playwright/test";


// A cypress plugins to add command to start & stop synapses in
// A plugin to add command to start & stop synapses in
// docker with preset templates.

interface SynapseConfig {
Expand Down
86 changes: 86 additions & 0 deletions playwright/tests/invite.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
Copyright 2023 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import {test} from '@playwright/test';
import {synapseStart, synapseStop, registerUser} from "../plugins/synapsedocker";
import type {SynapseInstance} from "../plugins/synapsedocker";

test.describe("Login", () => {
let synapse: SynapseInstance;

test.beforeEach(async () => {
synapse = await synapseStart("default");
});

test.afterEach(async () => {
await synapseStop(synapse.synapseId);
});

test("Invite user using /invite command from composer", async ({ page }) => {
const user1 = ["foobaraccount", "password123"] as const;
const user2 = ["foobaraccount2", "password123"] as const;
await registerUser(synapse, ...user1);
const { userId } = await registerUser(synapse, ...user2);
await page.goto("/");
await page.locator("#homeserver").fill("");
await page.locator("#homeserver").type(synapse.baseUrl);
const [username, password] = user1;
await page.locator("#username").type(username);
await page.locator("#password").type(password);
await page.getByText("Log In", { exact: true }).click();
await page.locator(".SessionView").waitFor();
// Create the room
await page.getByLabel("Create room").click();
await page.getByText("Create Room").click();
await page.locator("#name").type("My Room");
await page.locator(".CreateRoomView_detailsForm")
.getByRole("button", { name: "Create room" })
.click();
await page.locator(".RoomList")
.locator("li")
.first()
.click();
await page.locator(".MessageComposer_input textarea").type(`/invite ${userId}`);
await page.keyboard.press("Enter");
await page.locator(".AnnouncementView").last().getByText("was invited to the room").waitFor();
});

test("Error is shown when using /invite command from composer", async ({ page }) => {
const user1 = ["foobaraccount", "password123"] as const;
await registerUser(synapse, ...user1);
await page.goto("/");
await page.locator("#homeserver").fill("");
await page.locator("#homeserver").type(synapse.baseUrl);
const [username, password] = user1;
await page.locator("#username").type(username);
await page.locator("#password").type(password);
await page.getByText("Log In", { exact: true }).click();
await page.locator(".SessionView").waitFor();
// Create the room
await page.getByLabel("Create room").click();
await page.getByText("Create Room").click();
await page.locator("#name").type("My Room");
await page.locator(".CreateRoomView_detailsForm")
.getByRole("button", { name: "Create room" })
.click();
await page.locator(".RoomList")
.locator("li")
.first()
.click();
await page.locator(".MessageComposer_input textarea").type("/invite foobar");
await page.keyboard.press("Enter");
await page.locator(".RoomView").locator(".ErrorView").waitFor();
});
});
2 changes: 1 addition & 1 deletion scripts/test-app.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash

# Make sure docker is available
if ! docker info > /dev/null 2>&1; then
if ! docker --version > /dev/null 2>&1; then
echo "You need to intall docker before you can run the tests!"
exit 1
fi
Expand Down
8 changes: 8 additions & 0 deletions src/domain/session/room/RoomViewModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,14 @@ export class RoomViewModel extends ErrorReportViewModel {
this.reportError(new Error("join syntax: /join <room-id>"));
}
break;
case "invite":
if (args.length === 1) {
const userId = args[0];
await this._room.inviteUser(userId);
} else {
this.reportError(new Error("invite syntax: /invite <user-id>"));
}
break;
case "shrug":
message = "¯\\_(ツ)_/¯ " + args.join(" ");
msgtype = "m.text";
Expand Down
9 changes: 9 additions & 0 deletions src/matrix/net/HomeServerApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,15 @@ export class HomeServerApi {
return this._get("/pushers", undefined, undefined, options);
}

invite(roomId: string, userId: string, reason?: string, options?: BaseRequestOptions): IHomeServerRequest {
return this._post(
`/rooms/${encodeURIComponent(roomId)}/invite`,
{},
{ user_id: userId, reason },
options
);
}

join(roomId: string, options?: BaseRequestOptions): IHomeServerRequest {
return this._post(`/rooms/${encodeURIComponent(roomId)}/join`, {}, {}, options);
}
Expand Down
7 changes: 7 additions & 0 deletions src/matrix/room/Room.js
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,13 @@ export class Room extends BaseRoom {
});
}

async inviteUser(userId, reason) {
if (!userId) {
throw new Error("userId is null/undefined");
}
await this._hsApi.invite(this.id, userId, reason).response();
}

/* called by BaseRoom to pass pendingEvents when opening the timeline */
_getPendingEvents() {
return this._sendQueue.pendingEvents;
Expand Down
44 changes: 36 additions & 8 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,12 @@
fastq "^1.6.0"

"@playwright/test@^1.27.1":
version "1.32.1"
resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.32.1.tgz#749c9791adb048c266277a39ba0f7e33fe593ffe"
integrity sha512-FTwjCuhlm1qHUGf4hWjfr64UMJD/z0hXYbk+O387Ioe6WdyZQ+0TBDAc6P+pHjx2xCv1VYNgrKbYrNixFWy4Dg==
version "1.37.1"
resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.37.1.tgz#e7f44ae0faf1be52d6360c6bbf689fd0057d9b6f"
integrity sha512-bq9zTli3vWJo8S3LwB91U0qDNQDpEXnw7knhxLM0nwDvexQAwx9tO8iKDZSqqneVq+URd/WIoz+BALMqUTgdSg==
dependencies:
"@types/node" "*"
playwright-core "1.32.1"
playwright-core "1.37.1"
optionalDependencies:
fsevents "2.3.2"

Expand Down Expand Up @@ -1000,6 +1000,15 @@ flatted@^3.1.0:
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469"
integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==

fs-extra@^11.1.1:
version "11.1.1"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.1.tgz#da69f7c39f3b002378b0954bb6ae7efdc0876e2d"
integrity sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==
dependencies:
graceful-fs "^4.2.0"
jsonfile "^6.0.1"
universalify "^2.0.0"

fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
Expand Down Expand Up @@ -1065,6 +1074,11 @@ globby@^11.0.3:
merge2 "^1.3.0"
slash "^3.0.0"

graceful-fs@^4.1.6, graceful-fs@^4.2.0:
version "4.2.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==

has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
Expand Down Expand Up @@ -1199,6 +1213,15 @@ json-stable-stringify-without-jsonify@^1.0.1:
resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=

jsonfile@^6.0.1:
version "6.1.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
dependencies:
universalify "^2.0.0"
optionalDependencies:
graceful-fs "^4.1.6"

levn@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
Expand Down Expand Up @@ -1384,10 +1407,10 @@ picomatch@^2.2.3:
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==

playwright-core@1.32.1:
version "1.32.1"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.32.1.tgz#5a10c32403323b07d75ea428ebeed866a80b76a1"
integrity sha512-KZYUQC10mXD2Am1rGlidaalNGYk3LU1vZqqNk0gT4XPty1jOqgup8KDP8l2CUlqoNKhXM5IfGjWgW37xvGllBA==
playwright-core@1.37.1:
version "1.37.1"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.37.1.tgz#cb517d52e2e8cb4fa71957639f1cd105d1683126"
integrity sha512-17EuQxlSIYCmEMwzMqusJ2ztDgJePjrbttaefgdsiqeLWidjYz9BxXaTaZWxH1J95SHGk6tjE+dwgWILJoUZfA==

postcss-css-variables@^0.18.0:
version "0.18.0"
Expand Down Expand Up @@ -1714,6 +1737,11 @@ typeson@^6.0.0:
resolved "https://registry.yarnpkg.com/typeson/-/typeson-6.1.0.tgz#5b2a53705a5f58ff4d6f82f965917cabd0d7448b"
integrity sha512-6FTtyGr8ldU0pfbvW/eOZrEtEkczHRUtduBnA90Jh9kMPCiFNnXIon3vF41N0S4tV1HHQt4Hk1j4srpESziCaA==

universalify@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==

uri-js@^4.2.2:
version "4.4.1"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
Expand Down

0 comments on commit 0cad1e5

Please sign in to comment.