Skip to content
This repository was archived by the owner on Oct 21, 2019. It is now read-only.

Commit 5e8a3db

Browse files
authored
Merge pull request #16 from matrix-org/bwindels/lltests
Test timeline messages have correct display name with lazy loading
2 parents 58d52f9 + e843d53 commit 5e8a3db

File tree

15 files changed

+597
-69
lines changed

15 files changed

+597
-69
lines changed

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@
99
"author": "",
1010
"license": "ISC",
1111
"dependencies": {
12+
"cheerio": "^1.0.0-rc.2",
1213
"commander": "^2.17.1",
13-
"puppeteer": "^1.6.0"
14+
"puppeteer": "^1.6.0",
15+
"request": "^2.88.0",
16+
"request-promise-native": "^1.0.5",
17+
"uuid": "^3.3.2"
1418
}
1519
}

src/rest/consent.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
Copyright 2018 New Vector Ltd
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
const request = require('request-promise-native');
18+
const cheerio = require('cheerio');
19+
const url = require("url");
20+
21+
module.exports.approveConsent = async function(consentUrl) {
22+
const body = await request.get(consentUrl);
23+
const doc = cheerio.load(body);
24+
const v = doc("input[name=v]").val();
25+
const u = doc("input[name=u]").val();
26+
const h = doc("input[name=h]").val();
27+
const formAction = doc("form").attr("action");
28+
const absAction = url.resolve(consentUrl, formAction);
29+
await request.post(absAction).form({v, u, h});
30+
};

src/rest/creator.js

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
Copyright 2018 New Vector Ltd
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
const util = require('util');
18+
const exec = util.promisify(require('child_process').exec);
19+
const request = require('request-promise-native');
20+
const RestSession = require('./session');
21+
const RestMultiSession = require('./multi');
22+
23+
module.exports = class RestSessionCreator {
24+
constructor(synapseSubdir, hsUrl, cwd) {
25+
this.synapseSubdir = synapseSubdir;
26+
this.hsUrl = hsUrl;
27+
this.cwd = cwd;
28+
}
29+
30+
async createSessionRange(usernames, password) {
31+
const sessionPromises = usernames.map((username) => this.createSession(username, password));
32+
const sessions = await Promise.all(sessionPromises);
33+
return new RestMultiSession(sessions);
34+
}
35+
36+
async createSession(username, password) {
37+
await this._register(username, password);
38+
const authResult = await this._authenticate(username, password);
39+
return new RestSession(authResult);
40+
}
41+
42+
_register(username, password) {
43+
const registerArgs = [
44+
'-c homeserver.yaml',
45+
`-u ${username}`,
46+
`-p ${password}`,
47+
// '--regular-user',
48+
'-a', //until PR gets merged
49+
this.hsUrl
50+
];
51+
const registerCmd = `./scripts/register_new_matrix_user ${registerArgs.join(' ')}`;
52+
const allCmds = [
53+
`cd ${this.synapseSubdir}`,
54+
"source env/bin/activate",
55+
registerCmd
56+
].join(';');
57+
58+
return exec(allCmds, {cwd: this.cwd, encoding: 'utf-8'}).catch((result) => {
59+
const lines = result.stdout.trim().split('\n');
60+
const failureReason = lines[lines.length - 1];
61+
throw new Error(`creating user ${username} failed: ${failureReason}`);
62+
});
63+
}
64+
65+
async _authenticate(username, password) {
66+
const requestBody = {
67+
"type": "m.login.password",
68+
"identifier": {
69+
"type": "m.id.user",
70+
"user": username
71+
},
72+
"password": password
73+
};
74+
const url = `${this.hsUrl}/_matrix/client/r0/login`;
75+
const responseBody = await request.post({url, json: true, body: requestBody});
76+
return {
77+
accessToken: responseBody.access_token,
78+
homeServer: responseBody.home_server,
79+
userId: responseBody.user_id,
80+
deviceId: responseBody.device_id,
81+
hsUrl: this.hsUrl,
82+
};
83+
}
84+
}

src/rest/multi.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
Copyright 2018 New Vector Ltd
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
const request = require('request-promise-native');
18+
const RestRoom = require('./room');
19+
const {approveConsent} = require('./consent');
20+
21+
module.exports = class RestMultiSession {
22+
constructor(sessions) {
23+
this.sessions = sessions;
24+
}
25+
26+
slice(start, end) {
27+
return new RestMultiSession(this.sessions.slice(start, end));
28+
}
29+
30+
pop(userName) {
31+
const idx = this.sessions.findIndex((s) => s.userName() === userName);
32+
if(idx === -1) {
33+
throw new Error(`user ${userName} not found`);
34+
}
35+
const session = this.sessions.splice(idx, 1)[0];
36+
return session;
37+
}
38+
39+
async setDisplayName(fn) {
40+
await Promise.all(this.sessions.map((s) => s.setDisplayName(fn(s))));
41+
}
42+
43+
async join(roomId) {
44+
const rooms = await Promise.all(this.sessions.map((s) => s.join(roomId)));
45+
return new RestMultiRoom(rooms);
46+
}
47+
}
48+
49+
class RestMultiRoom {
50+
constructor(rooms) {
51+
this.rooms = rooms;
52+
}
53+
54+
async talk(message) {
55+
await Promise.all(this.rooms.map((r) => r.talk(message)));
56+
}
57+
58+
async leave() {
59+
await Promise.all(this.rooms.map((r) => r.leave()));
60+
}
61+
}

src/rest/room.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
Copyright 2018 New Vector Ltd
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
const uuidv4 = require('uuid/v4');
18+
19+
/* no pun intented */
20+
module.exports = class RestRoom {
21+
constructor(session, roomId) {
22+
this.session = session;
23+
this._roomId = roomId;
24+
}
25+
26+
async talk(message) {
27+
const txId = uuidv4();
28+
await this.session._put(`/rooms/${this._roomId}/send/m.room.message/${txId}`, {
29+
"msgtype": "m.text",
30+
"body": message
31+
});
32+
return txId;
33+
}
34+
35+
async leave() {
36+
await this.session._post(`/rooms/${this._roomId}/leave`);
37+
}
38+
39+
roomId() {
40+
return this._roomId;
41+
}
42+
}

src/rest/session.js

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
Copyright 2018 New Vector Ltd
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
const request = require('request-promise-native');
18+
const RestRoom = require('./room');
19+
const {approveConsent} = require('./consent');
20+
21+
module.exports = class RestSession {
22+
constructor(credentials) {
23+
this._credentials = credentials;
24+
this._displayName = null;
25+
}
26+
27+
userId() {
28+
return this._credentials.userId;
29+
}
30+
31+
userName() {
32+
return this._credentials.userId.split(":")[0].substr(1);
33+
}
34+
35+
displayName() {
36+
return this._displayName;
37+
}
38+
39+
async setDisplayName(displayName) {
40+
this._displayName = displayName;
41+
await this._put(`/profile/${this._credentials.userId}/displayname`, {
42+
displayname: displayName
43+
});
44+
}
45+
46+
async join(roomIdOrAlias) {
47+
const {room_id} = await this._post(`/join/${encodeURIComponent(roomIdOrAlias)}`);
48+
return new RestRoom(this, room_id);
49+
}
50+
51+
async createRoom(name, options) {
52+
const body = {
53+
name,
54+
};
55+
if (options.invite) {
56+
body.invite = options.invite;
57+
}
58+
if (options.public) {
59+
body.visibility = "public";
60+
} else {
61+
body.visibility = "private";
62+
}
63+
if (options.dm) {
64+
body.is_direct = true;
65+
}
66+
if (options.topic) {
67+
body.topic = options.topic;
68+
}
69+
70+
const {room_id} = await this._post(`/createRoom`, body);
71+
return new RestRoom(this, room_id);
72+
}
73+
74+
_post(csApiPath, body) {
75+
return this._request("POST", csApiPath, body);
76+
}
77+
78+
_put(csApiPath, body) {
79+
return this._request("PUT", csApiPath, body);
80+
}
81+
82+
async _request(method, csApiPath, body) {
83+
try {
84+
const responseBody = await request({
85+
url: `${this._credentials.hsUrl}/_matrix/client/r0${csApiPath}`,
86+
method,
87+
headers: {
88+
"Authorization": `Bearer ${this._credentials.accessToken}`
89+
},
90+
json: true,
91+
body
92+
});
93+
return responseBody;
94+
95+
} catch(err) {
96+
const responseBody = err.response.body;
97+
if (responseBody.errcode === 'M_CONSENT_NOT_GIVEN') {
98+
await approveConsent(responseBody.consent_uri);
99+
return this._request(method, csApiPath, body);
100+
} else if(responseBody && responseBody.error) {
101+
throw new Error(`${method} ${csApiPath}: ${responseBody.error}`);
102+
} else {
103+
throw new Error(`${method} ${csApiPath}: ${err.response.statusCode}`);
104+
}
105+
}
106+
}
107+
}

0 commit comments

Comments
 (0)