Remove `matrix-bot-sdk` usage in tests (#15)
Remove `matrix-bot-sdk` usage in tests because it didn't have timestamp massaging `?ts` and it's not really necessary to rely on since we can just call the API directly 🤷. `matrix-bot-sdk` is also very annoying having to build rust crypto packages. We're now using direct `fetch` requests against the Matrix API and lightweight `client` object. All 3 current tests pass ✅
This commit is contained in:
parent
7dfe8cabc9
commit
9fc71a3412
File diff suppressed because it is too large
Load Diff
|
@ -31,8 +31,6 @@
|
|||
"express": "^4.17.2",
|
||||
"hydrogen-view-sdk": "^0.0.4",
|
||||
"linkedom": "^0.14.1",
|
||||
"matrix-bot-sdk": "^0.5.19",
|
||||
"matrix-js-sdk": "^15.5.2",
|
||||
"matrix-public-archive-shared": "file:./shared/",
|
||||
"nconf": "^0.11.3",
|
||||
"node-fetch": "^2.6.7",
|
||||
|
|
|
@ -16,7 +16,7 @@ assert(matrixServerUrl);
|
|||
// Consider this scenario: dayStart(fromTs) <---- msg1 <- msg2 <-- msg3 <---- dayEnd(toTs)
|
||||
// - ❌ If we start from dayStart and look backwards, we will find nothing.
|
||||
// - ❌ If we start from dayStart and look forwards, we will find msg1, but federated backfill won't be able to paginate forwards
|
||||
// - ✅ If we start from dayEnd and look backwards, we will msg3
|
||||
// - ✅ If we start from dayEnd and look backwards, we will find msg3
|
||||
// - ❌ If we start from dayEnd and look forwards, we will find nothing
|
||||
//
|
||||
// Returns events in reverse-chronological order.
|
||||
|
|
|
@ -20,7 +20,7 @@ function configureNodeEnv() {
|
|||
}
|
||||
|
||||
const nodeEnv = configureNodeEnv();
|
||||
console.log('nodeEnv', nodeEnv);
|
||||
console.log(`Config is using nodeEnv=${nodeEnv}`);
|
||||
const configDir = path.join(__dirname, '../../config');
|
||||
|
||||
nconf.argv().env('__');
|
||||
|
|
|
@ -33,6 +33,7 @@ async function fetchEndpoint(endpoint, options = {}) {
|
|||
const res = await fetch(endpoint, {
|
||||
method,
|
||||
headers,
|
||||
body: options.body,
|
||||
});
|
||||
await checkResponseStatus(res);
|
||||
|
||||
|
@ -49,11 +50,16 @@ async function fetchEndpointAsJson(endpoint, options) {
|
|||
const opts = {
|
||||
...options,
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
...(options.headers || {}),
|
||||
},
|
||||
};
|
||||
|
||||
if (options.body) {
|
||||
opts.body = JSON.stringify(options.body);
|
||||
}
|
||||
|
||||
const res = await fetchEndpoint(endpoint, opts);
|
||||
const data = await res.json();
|
||||
return data;
|
||||
|
|
|
@ -174,7 +174,7 @@ async function mountHydrogen() {
|
|||
const memberEvent = workingStateEventMap[event.user_id];
|
||||
return makeEventEntryFromEventJson(event, memberEvent);
|
||||
});
|
||||
console.log('eventEntries', eventEntries.length);
|
||||
//console.log('eventEntries', eventEntries.length);
|
||||
|
||||
// Map of `event_id` to `EventEntry`
|
||||
const eventEntriesByEventId = eventEntries.reduce((currentMap, eventEntry) => {
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
```
|
||||
```sh
|
||||
$ docker pull matrixdotorg/synapse:latest
|
||||
$ docker build -t matrix-public-archive-test-homeserver -f test/dockerfiles/Synapse.Dockerfile test/dockerfiles/
|
||||
```
|
||||
|
||||
```
|
||||
docker-compose -f test/docker-compose.yml up -d --no-recreate
|
||||
```sh
|
||||
$ docker-compose --project-name matrix_public_archive_test -f test/docker-compose.yml up -d --no-recreate
|
||||
```
|
||||
|
||||
```
|
||||
```sh
|
||||
$ docker ps --all | grep test_hs
|
||||
$ docker logs test_hs1_1
|
||||
$ docker logs test_hs2_1
|
||||
$ docker logs -f --tail 10 matrix_public_archive_test_hs1_1
|
||||
$ docker logs -f --tail 10 matrix_public_archive_test_hs2_1
|
||||
|
||||
$ docker stop test_hs1_1 test_hs2_1
|
||||
$ docker rm test_hs1_1 test_hs2_1
|
||||
$ docker stop matrix_public_archive_test_hs1_1 matrix_public_archive_test_hs2_1
|
||||
$ docker rm matrix_public_archive_test_hs1_1 matrix_public_archive_test_hs2_1
|
||||
```
|
||||
|
|
|
@ -0,0 +1,211 @@
|
|||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
const { URLSearchParams } = require('url');
|
||||
const urlJoin = require('url-join');
|
||||
const { fetchEndpointAsJson, fetchEndpoint } = require('../server/lib/fetch-endpoint');
|
||||
|
||||
const config = require('../server/lib/config');
|
||||
const matrixAccessToken = config.get('matrixAccessToken');
|
||||
assert(matrixAccessToken);
|
||||
|
||||
let txnCount = 0;
|
||||
function getTxnId() {
|
||||
txnCount++;
|
||||
return `${new Date().getTime()}--${txnCount}`;
|
||||
}
|
||||
|
||||
// Get client to act with for all of the client methods. This will use the
|
||||
// application service access token and client methods will append `?user_id`
|
||||
// for the specific user to act upon so we can use the `?ts` message timestamp
|
||||
// massaging when sending.
|
||||
async function getTestClientForHs(testMatrixServerUrl) {
|
||||
// Register the virtual user
|
||||
const username = `user-t${new Date().getTime()}-r${Math.floor(Math.random() * 1000000000)}`;
|
||||
const registerResponse = await fetchEndpointAsJson(
|
||||
urlJoin(testMatrixServerUrl, '/_matrix/client/v3/register'),
|
||||
{
|
||||
method: 'POST',
|
||||
body: {
|
||||
type: 'm.login.application_service',
|
||||
username,
|
||||
},
|
||||
accessToken: matrixAccessToken,
|
||||
}
|
||||
);
|
||||
|
||||
const userId = registerResponse['user_id'];
|
||||
assert(userId);
|
||||
|
||||
return {
|
||||
homeserverUrl: testMatrixServerUrl,
|
||||
// We use the application service AS token because we need to be able to use
|
||||
// the `?ts` timestamp massaging when sending events
|
||||
accessToken: matrixAccessToken,
|
||||
userId: userId,
|
||||
};
|
||||
}
|
||||
|
||||
// Create a public room to test in
|
||||
async function createTestRoom(client) {
|
||||
let qs = new URLSearchParams();
|
||||
if (client.userId) {
|
||||
qs.append('user_id', client.userId);
|
||||
}
|
||||
|
||||
const createRoomResponse = await fetchEndpointAsJson(
|
||||
urlJoin(client.homeserverUrl, `/_matrix/client/v3/createRoom?${qs.toString()}`),
|
||||
{
|
||||
method: 'POST',
|
||||
body: {
|
||||
preset: 'public_chat',
|
||||
name: 'the hangout spot',
|
||||
initial_state: [
|
||||
{
|
||||
type: 'm.room.history_visibility',
|
||||
state_key: '',
|
||||
content: {
|
||||
history_visibility: 'world_readable',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
accessToken: client.accessToken,
|
||||
}
|
||||
);
|
||||
|
||||
const roomId = createRoomResponse['room_id'];
|
||||
assert(roomId);
|
||||
return roomId;
|
||||
}
|
||||
|
||||
async function joinRoom({ client, roomId, viaServers }) {
|
||||
let qs = new URLSearchParams();
|
||||
if (viaServers) {
|
||||
[].concat(viaServers).forEach((viaServer) => {
|
||||
qs.append('server_name', viaServer);
|
||||
});
|
||||
}
|
||||
|
||||
if (client.userId) {
|
||||
qs.append('user_id', client.userId);
|
||||
}
|
||||
|
||||
const joinRoomResponse = await fetchEndpointAsJson(
|
||||
urlJoin(client.homeserverUrl, `/_matrix/client/v3/join/${roomId}?${qs.toString()}`),
|
||||
{
|
||||
method: 'POST',
|
||||
accessToken: client.accessToken,
|
||||
}
|
||||
);
|
||||
|
||||
const joinedRoomId = joinRoomResponse['room_id'];
|
||||
assert(joinedRoomId);
|
||||
return joinedRoomId;
|
||||
}
|
||||
|
||||
async function sendEvent({ client, roomId, eventType, content, timestamp }) {
|
||||
assert(client);
|
||||
assert(roomId);
|
||||
assert(content);
|
||||
|
||||
let qs = new URLSearchParams();
|
||||
if (timestamp) {
|
||||
assert(
|
||||
timestamp && client.userId,
|
||||
'We can only do `?ts` massaging from an application service access token. ' +
|
||||
'Expected `client.userId` to be defined so we can act on behalf of that user'
|
||||
);
|
||||
|
||||
qs.append('ts', timestamp);
|
||||
}
|
||||
|
||||
if (client.userId) {
|
||||
qs.append('user_id', client.userId);
|
||||
}
|
||||
|
||||
const sendResponse = await fetchEndpointAsJson(
|
||||
urlJoin(
|
||||
client.homeserverUrl,
|
||||
`/_matrix/client/v3/rooms/${roomId}/send/${eventType}/${getTxnId()}?${qs.toString()}`
|
||||
),
|
||||
{
|
||||
method: 'PUT',
|
||||
body: content,
|
||||
accessToken: client.accessToken,
|
||||
}
|
||||
);
|
||||
|
||||
const eventId = sendResponse['event_id'];
|
||||
assert(eventId);
|
||||
return eventId;
|
||||
}
|
||||
|
||||
async function sendMessage({ client, roomId, content, timestamp }) {
|
||||
return sendEvent({ client, roomId, eventType: 'm.room.message', content, timestamp });
|
||||
}
|
||||
|
||||
// Create a number of messages in the given room
|
||||
async function createMessagesInRoom({ client, roomId, numMessages, prefix, timestamp }) {
|
||||
let eventIds = [];
|
||||
for (let i = 0; i < numMessages; i++) {
|
||||
const eventId = await sendMessage({
|
||||
client,
|
||||
roomId,
|
||||
content: {
|
||||
msgtype: 'm.text',
|
||||
body: `${prefix} - message${i}`,
|
||||
},
|
||||
timestamp,
|
||||
});
|
||||
eventIds.push(eventId);
|
||||
}
|
||||
|
||||
return eventIds;
|
||||
}
|
||||
|
||||
// Uploads the given data Buffer and returns the MXC URI of the uploaded content
|
||||
async function uploadContent({ client, roomId, data, fileName, contentType }) {
|
||||
assert(client);
|
||||
assert(roomId);
|
||||
assert(data);
|
||||
|
||||
let qs = new URLSearchParams();
|
||||
if (client.userId) {
|
||||
qs.append('user_id', client.userId);
|
||||
}
|
||||
|
||||
if (fileName) {
|
||||
qs.append('filename', fileName);
|
||||
}
|
||||
|
||||
// We don't want to use `fetchEndpointAsJson` here because it will
|
||||
// `JSON.stringify(...)` the body data
|
||||
const uploadResponse = await fetchEndpoint(
|
||||
urlJoin(client.homeserverUrl, `/_matrix/media/v3/upload`),
|
||||
{
|
||||
method: 'POST',
|
||||
body: data,
|
||||
headers: {
|
||||
'Content-Type': contentType || 'application/octet-stream',
|
||||
},
|
||||
accessToken: client.accessToken,
|
||||
}
|
||||
);
|
||||
|
||||
const uploadResponseData = await uploadResponse.json();
|
||||
|
||||
const mxcUri = uploadResponseData['content_uri'];
|
||||
assert(mxcUri);
|
||||
return mxcUri;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getTestClientForHs,
|
||||
createTestRoom,
|
||||
joinRoom,
|
||||
sendEvent,
|
||||
sendMessage,
|
||||
createMessagesInRoom,
|
||||
uploadContent,
|
||||
};
|
|
@ -24,7 +24,7 @@ COPY keys/* /ca/
|
|||
RUN openssl genrsa -out /conf/server.tls.key 2048
|
||||
|
||||
# generate a signing key
|
||||
RUN generate_signing_key.py -o /conf/server.signing.key
|
||||
RUN generate_signing_key -o /conf/server.signing.key
|
||||
|
||||
WORKDIR /data
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ report_stats: False
|
|||
signing_key_path: /conf/server.signing.key
|
||||
trusted_key_servers: []
|
||||
enable_registration: true
|
||||
enable_registration_without_verification: true
|
||||
|
||||
## Listeners ##
|
||||
|
||||
|
@ -94,6 +95,13 @@ rc_joins:
|
|||
|
||||
federation_rr_transactions_per_room_per_second: 9999
|
||||
|
||||
## Media Store ##
|
||||
|
||||
# Whether to generate new thumbnails on the fly. This lets the image thumbnails
|
||||
# load in the tests.
|
||||
#
|
||||
dynamic_thumbnails: true
|
||||
|
||||
## API Configuration ##
|
||||
|
||||
# A list of application service config files to use
|
||||
|
|
|
@ -3,16 +3,26 @@
|
|||
process.env.NODE_ENV = 'test';
|
||||
|
||||
const assert = require('assert');
|
||||
const path = require('path');
|
||||
const urlJoin = require('url-join');
|
||||
const escapeStringRegexp = require('escape-string-regexp');
|
||||
const { MatrixAuth } = require('matrix-bot-sdk');
|
||||
const { parseHTML } = require('linkedom');
|
||||
|
||||
const { fetchEndpointAsText, fetchEndpointAsJson } = require('../server/lib/fetch-endpoint');
|
||||
const { readFile } = require('fs').promises;
|
||||
|
||||
const MatrixPublicArchiveURLCreator = require('matrix-public-archive-shared/lib/url-creator');
|
||||
|
||||
const { fetchEndpointAsText, fetchEndpointAsJson } = require('../server/lib/fetch-endpoint');
|
||||
const config = require('../server/lib/config');
|
||||
|
||||
const {
|
||||
getTestClientForHs,
|
||||
createTestRoom,
|
||||
joinRoom,
|
||||
sendEvent,
|
||||
sendMessage,
|
||||
createMessagesInRoom,
|
||||
uploadContent,
|
||||
} = require('./client-utils');
|
||||
|
||||
const testMatrixServerUrl1 = config.get('testMatrixServerUrl1');
|
||||
const testMatrixServerUrl2 = config.get('testMatrixServerUrl2');
|
||||
assert(testMatrixServerUrl1);
|
||||
|
@ -28,48 +38,6 @@ const HOMESERVER_URL_TO_PRETTY_NAME_MAP = {
|
|||
[testMatrixServerUrl2]: 'hs2',
|
||||
};
|
||||
|
||||
async function getTestClientForHs(testMatrixServerUrl) {
|
||||
const auth = new MatrixAuth(testMatrixServerUrl);
|
||||
|
||||
const client = await auth.passwordRegister(
|
||||
`user-t${new Date().getTime()}-r${Math.floor(Math.random() * 1000000000)}`,
|
||||
'password'
|
||||
);
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
async function createMessagesInRoom(client, roomId, numMessages, prefix) {
|
||||
let eventIds = [];
|
||||
for (let i = 0; i < numMessages; i++) {
|
||||
const eventId = await client.sendMessage(roomId, {
|
||||
msgtype: 'm.text',
|
||||
body: `${prefix} - message${i}`,
|
||||
});
|
||||
eventIds.push(eventId);
|
||||
}
|
||||
|
||||
return eventIds;
|
||||
}
|
||||
|
||||
async function createTestRoom(client) {
|
||||
const roomId = await client.createRoom({
|
||||
preset: 'public_chat',
|
||||
name: 'the hangout spot',
|
||||
initial_state: [
|
||||
{
|
||||
type: 'm.room.history_visibility',
|
||||
state_key: '',
|
||||
content: {
|
||||
history_visibility: 'world_readable',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
return roomId;
|
||||
}
|
||||
|
||||
describe('matrix-public-archive', () => {
|
||||
let server;
|
||||
before(() => {
|
||||
|
@ -83,24 +51,28 @@ describe('matrix-public-archive', () => {
|
|||
}
|
||||
});
|
||||
|
||||
// Sanity check that our test homeservers can actually federate with each
|
||||
// other. The rest of the tests won't work properly if this isn't working.
|
||||
it('Test federation between fixture homeservers', async () => {
|
||||
try {
|
||||
describe('Test fixture homeservers', () => {
|
||||
// Sanity check that our test homeservers can actually federate with each
|
||||
// other. The rest of the tests won't work properly if this isn't working.
|
||||
it('Test federation between fixture homeservers', async () => {
|
||||
const hs1Client = await getTestClientForHs(testMatrixServerUrl1);
|
||||
const hs2Client = await getTestClientForHs(testMatrixServerUrl2);
|
||||
|
||||
// Create a room on hs2
|
||||
const hs2RoomId = await createTestRoom(hs2Client);
|
||||
const room2EventIds = await createMessagesInRoom(
|
||||
hs2Client,
|
||||
hs2RoomId,
|
||||
10,
|
||||
HOMESERVER_URL_TO_PRETTY_NAME_MAP[hs2Client.homeserverUrl]
|
||||
);
|
||||
const room2EventIds = await createMessagesInRoom({
|
||||
client: hs2Client,
|
||||
roomId: hs2RoomId,
|
||||
numMessages: 10,
|
||||
prefix: HOMESERVER_URL_TO_PRETTY_NAME_MAP[hs2Client.homeserverUrl],
|
||||
});
|
||||
|
||||
// Join hs1 to a room on hs2 (federation)
|
||||
await hs1Client.joinRoom(hs2RoomId, 'hs2');
|
||||
await joinRoom({
|
||||
client: hs1Client,
|
||||
roomId: hs2RoomId,
|
||||
viaServers: 'hs2',
|
||||
});
|
||||
|
||||
// From, hs1, make sure we can fetch messages from hs2
|
||||
const messagesEndpoint = urlJoin(
|
||||
|
@ -129,31 +101,59 @@ describe('matrix-public-archive', () => {
|
|||
}") to be in room on hs2=${JSON.stringify(room2EventIds)}`
|
||||
);
|
||||
});
|
||||
} catch (err) {
|
||||
if (err.body) {
|
||||
// FIXME: Remove this try/catch once the matrix-bot-sdk no longer throws
|
||||
// huge response objects as errors, see
|
||||
// https://github.com/turt2live/matrix-bot-sdk/pull/158
|
||||
throw new Error(
|
||||
`Error occured in matrix-bot-sdk (this new error is to stop it from logging the huge response) statusCode=${
|
||||
err.statusCode
|
||||
} body=${JSON.stringify(err.body)}`
|
||||
);
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('shows all events in a given day', async () => {
|
||||
try {
|
||||
describe('Archive', () => {
|
||||
// Use a fixed date at the start of the UTC day so that the tests are
|
||||
// consistent. Otherwise, the tests could fail when they start close to
|
||||
// midnight and it rolls over to the next day.
|
||||
const archiveDate = new Date(Date.UTC(2022, 0, 3));
|
||||
let archiveUrl;
|
||||
let numMessagesSent = 0;
|
||||
afterEach(() => {
|
||||
if (interactive) {
|
||||
console.log('Interactive URL for test', archiveUrl);
|
||||
}
|
||||
|
||||
// Reset `numMessagesSent` between tests so each test starts from the
|
||||
// beginning of the day and we don't run out of minutes in the day to send
|
||||
// messages in (we space messages out by a minute so the timestamp visibly
|
||||
// changes in the UI).
|
||||
numMessagesSent = 0;
|
||||
});
|
||||
|
||||
// Sends a message and makes sure that a timestamp was provided
|
||||
async function sendMessageOnArchiveDate(options) {
|
||||
const minute = 1000 * 60;
|
||||
// Adjust the timestamp by a minute each time so there is some visual difference.
|
||||
options.timestamp = archiveDate.getTime() + minute * numMessagesSent;
|
||||
numMessagesSent++;
|
||||
|
||||
return sendMessage(options);
|
||||
}
|
||||
|
||||
// Sends a message and makes sure that a timestamp was provided
|
||||
async function sendEventOnArchiveDate(options) {
|
||||
const minute = 1000 * 60;
|
||||
// Adjust the timestamp by a minute each time so there is some visual difference.
|
||||
options.timestamp = archiveDate.getTime() + minute * numMessagesSent;
|
||||
numMessagesSent++;
|
||||
|
||||
return sendEvent(options);
|
||||
}
|
||||
|
||||
it('shows all events in a given day', async () => {
|
||||
const client = await getTestClientForHs(testMatrixServerUrl1);
|
||||
const roomId = await createTestRoom(client);
|
||||
|
||||
const archiveUrl = matrixPublicArchiveURLCreator.archiveUrlForDate(roomId, new Date());
|
||||
// Just render the page initially so that the archiver user is already joined to the page.
|
||||
// We don't want their join event masking the one-off problem where we're missing the latest message in the room.
|
||||
await fetchEndpointAsText(archiveUrl);
|
||||
// Just render the page initially so that the archiver user is already
|
||||
// joined to the page. We don't want their join event masking the one-off
|
||||
// problem where we're missing the latest message in the room. We just use the date now
|
||||
// because it will find whatever events backwards no matter when they were sent.
|
||||
await fetchEndpointAsText(
|
||||
matrixPublicArchiveURLCreator.archiveUrlForDate(roomId, new Date())
|
||||
);
|
||||
|
||||
const messageTextList = [
|
||||
`Amontons' First Law: The force of friction is directly proportional to the applied load.`,
|
||||
|
@ -164,9 +164,13 @@ describe('matrix-public-archive', () => {
|
|||
|
||||
const eventIds = [];
|
||||
for (const messageText of messageTextList) {
|
||||
const eventId = await client.sendMessage(roomId, {
|
||||
msgtype: 'm.text',
|
||||
body: messageText,
|
||||
const eventId = await sendMessageOnArchiveDate({
|
||||
client,
|
||||
roomId,
|
||||
content: {
|
||||
msgtype: 'm.text',
|
||||
body: messageText,
|
||||
},
|
||||
});
|
||||
eventIds.push(eventId);
|
||||
}
|
||||
|
@ -174,10 +178,7 @@ describe('matrix-public-archive', () => {
|
|||
// Sanity check that we actually sent some messages
|
||||
assert.strictEqual(eventIds.length, 3);
|
||||
|
||||
if (interactive) {
|
||||
console.log('Interactive URL for test', archiveUrl);
|
||||
}
|
||||
|
||||
archiveUrl = matrixPublicArchiveURLCreator.archiveUrlForDate(roomId, archiveDate);
|
||||
const archivePageHtml = await fetchEndpointAsText(archiveUrl);
|
||||
|
||||
const dom = parseHTML(archivePageHtml);
|
||||
|
@ -191,25 +192,10 @@ describe('matrix-public-archive', () => {
|
|||
new RegExp(`.*${escapeStringRegexp(eventText)}.*`)
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
if (err.body) {
|
||||
// FIXME: Remove this try/catch once the matrix-bot-sdk no longer throws
|
||||
// huge response objects as errors, see
|
||||
// https://github.com/turt2live/matrix-bot-sdk/pull/158
|
||||
throw new Error(
|
||||
`Error occured in matrix-bot-sdk (this new error is to stop it from logging the huge response) statusCode=${
|
||||
err.statusCode
|
||||
} body=${JSON.stringify(err.body)}`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
|
||||
// eslint-disable-next-line max-statements
|
||||
it('can render diverse messages', async () => {
|
||||
try {
|
||||
// eslint-disable-next-line max-statements
|
||||
it('can render diverse messages', async () => {
|
||||
const client = await getTestClientForHs(testMatrixServerUrl1);
|
||||
const roomId = await createTestRoom(client);
|
||||
|
||||
|
@ -218,84 +204,102 @@ describe('matrix-public-archive', () => {
|
|||
// TODO: Set avatar of room
|
||||
|
||||
// Test image
|
||||
const mxcUri = await client.uploadContentFromUrl(
|
||||
'https://en.wikipedia.org/wiki/Friction#/media/File:Friction_between_surfaces.jpg'
|
||||
// via https://en.wikipedia.org/wiki/Friction#/media/File:Friction_between_surfaces.jpg (CaoHao)
|
||||
const imageBuffer = await readFile(
|
||||
path.resolve(__dirname, './fixtures/friction_between_surfaces.jpg')
|
||||
);
|
||||
const imageEventId = await client.sendMessage(roomId, {
|
||||
body: 'Friction_between_surfaces.jpeg',
|
||||
info: {
|
||||
size: 396644,
|
||||
mimetype: 'image/jpeg',
|
||||
thumbnail_info: {
|
||||
w: 800,
|
||||
h: 390,
|
||||
const imageFileName = 'friction_between_surfaces.jpg';
|
||||
const mxcUri = await uploadContent({
|
||||
client,
|
||||
roomId,
|
||||
data: imageBuffer,
|
||||
fileName: imageFileName,
|
||||
});
|
||||
const imageEventId = await sendMessageOnArchiveDate({
|
||||
client,
|
||||
roomId,
|
||||
content: {
|
||||
body: imageFileName,
|
||||
info: {
|
||||
size: 17471,
|
||||
mimetype: 'image/jpeg',
|
||||
size: 126496,
|
||||
w: 640,
|
||||
h: 312,
|
||||
'xyz.amorgan.blurhash': 'LkR3G|IU?w%NbxbIemae_NxuD$M{',
|
||||
},
|
||||
w: 1894,
|
||||
h: 925,
|
||||
'xyz.amorgan.blurhash': 'LkR3G|IU?w%NbwbIemae_NxuD$M{',
|
||||
// TODO: How to get a proper thumnail URL that will load?
|
||||
thumbnail_url: mxcUri,
|
||||
msgtype: 'm.image',
|
||||
url: mxcUri,
|
||||
},
|
||||
msgtype: 'm.image',
|
||||
url: mxcUri,
|
||||
});
|
||||
|
||||
// A normal text message
|
||||
const normalMessageText1 =
|
||||
'^ Figure 1: Simulated blocks with fractal rough surfaces, exhibiting static frictional interactions';
|
||||
const normalMessageEventId1 = await client.sendMessage(roomId, {
|
||||
msgtype: 'm.text',
|
||||
body: normalMessageText1,
|
||||
const normalMessageEventId1 = await sendMessageOnArchiveDate({
|
||||
client,
|
||||
roomId,
|
||||
content: {
|
||||
msgtype: 'm.text',
|
||||
body: normalMessageText1,
|
||||
},
|
||||
});
|
||||
|
||||
// Another normal text message
|
||||
const normalMessageText2 =
|
||||
'The topography of the Moon has been measured with laser altimetry and stereo image analysis.';
|
||||
const normalMessageEventId2 = await client.sendMessage(roomId, {
|
||||
msgtype: 'm.text',
|
||||
body: normalMessageText2,
|
||||
const normalMessageEventId2 = await sendMessageOnArchiveDate({
|
||||
client,
|
||||
roomId,
|
||||
content: {
|
||||
msgtype: 'm.text',
|
||||
body: normalMessageText2,
|
||||
},
|
||||
});
|
||||
|
||||
// Test replies
|
||||
const replyMessageText = `The concentration of maria on the near side likely reflects the substantially thicker crust of the highlands of the Far Side, which may have formed in a slow-velocity impact of a second moon of Earth a few tens of millions of years after the Moon's formation.`;
|
||||
const replyMessageEventId = await client.sendMessage(roomId, {
|
||||
'org.matrix.msc1767.message': [
|
||||
{
|
||||
body: '> <@ericgittertester:my.synapse.server> ${normalMessageText2}',
|
||||
mimetype: 'text/plain',
|
||||
},
|
||||
{
|
||||
body: `<mx-reply><blockquote><a href="https://matrix.to/#/${roomId}/${normalMessageEventId2}?via=my.synapse.server">In reply to</a> <a href="https://matrix.to/#/@ericgittertester:my.synapse.server">@ericgittertester:my.synapse.server</a><br>${normalMessageText2}</blockquote></mx-reply>${replyMessageText}`,
|
||||
mimetype: 'text/html',
|
||||
},
|
||||
],
|
||||
body: `> <@ericgittertester:my.synapse.server> ${normalMessageText2}\n\n${replyMessageText}`,
|
||||
msgtype: 'm.text',
|
||||
format: 'org.matrix.custom.html',
|
||||
formatted_body: `<mx-reply><blockquote><a href="https://matrix.to/#/${roomId}/${normalMessageEventId2}?via=my.synapse.server">In reply to</a> <a href="https://matrix.to/#/@ericgittertester:my.synapse.server">@ericgittertester:my.synapse.server</a><br>${normalMessageText2}</blockquote></mx-reply>${replyMessageText}`,
|
||||
'm.relates_to': {
|
||||
'm.in_reply_to': {
|
||||
event_id: normalMessageEventId2,
|
||||
const replyMessageEventId = await sendMessageOnArchiveDate({
|
||||
client,
|
||||
roomId,
|
||||
content: {
|
||||
'org.matrix.msc1767.message': [
|
||||
{
|
||||
body: '> <@ericgittertester:my.synapse.server> ${normalMessageText2}',
|
||||
mimetype: 'text/plain',
|
||||
},
|
||||
{
|
||||
body: `<mx-reply><blockquote><a href="https://matrix.to/#/${roomId}/${normalMessageEventId2}?via=my.synapse.server">In reply to</a> <a href="https://matrix.to/#/@ericgittertester:my.synapse.server">@ericgittertester:my.synapse.server</a><br>${normalMessageText2}</blockquote></mx-reply>${replyMessageText}`,
|
||||
mimetype: 'text/html',
|
||||
},
|
||||
],
|
||||
body: `> <@ericgittertester:my.synapse.server> ${normalMessageText2}\n\n${replyMessageText}`,
|
||||
msgtype: 'm.text',
|
||||
format: 'org.matrix.custom.html',
|
||||
formatted_body: `<mx-reply><blockquote><a href="https://matrix.to/#/${roomId}/${normalMessageEventId2}?via=my.synapse.server">In reply to</a> <a href="https://matrix.to/#/@ericgittertester:my.synapse.server">@ericgittertester:my.synapse.server</a><br>${normalMessageText2}</blockquote></mx-reply>${replyMessageText}`,
|
||||
'm.relates_to': {
|
||||
'm.in_reply_to': {
|
||||
event_id: normalMessageEventId2,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Test reactions
|
||||
const reactionText = '😅';
|
||||
await client.sendEvent(roomId, 'm.reaction', {
|
||||
'm.relates_to': {
|
||||
rel_type: 'm.annotation',
|
||||
event_id: replyMessageEventId,
|
||||
key: reactionText,
|
||||
await sendEventOnArchiveDate({
|
||||
client,
|
||||
roomId,
|
||||
eventType: 'm.reaction',
|
||||
content: {
|
||||
'm.relates_to': {
|
||||
rel_type: 'm.annotation',
|
||||
event_id: replyMessageEventId,
|
||||
key: reactionText,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const archiveUrl = matrixPublicArchiveURLCreator.archiveUrlForDate(roomId, new Date());
|
||||
if (interactive) {
|
||||
console.log('Interactive URL for test', archiveUrl);
|
||||
}
|
||||
archiveUrl = matrixPublicArchiveURLCreator.archiveUrlForDate(roomId, archiveDate);
|
||||
|
||||
const archivePageHtml = await fetchEndpointAsText(archiveUrl);
|
||||
|
||||
|
@ -305,7 +309,7 @@ describe('matrix-public-archive', () => {
|
|||
const imageElement = dom.document.querySelector(`[data-event-id="${imageEventId}"] img`);
|
||||
assert(imageElement);
|
||||
assert.match(imageElement.getAttribute('src'), new RegExp(`^http://.*`));
|
||||
assert.strictEqual(imageElement.getAttribute('alt'), 'Friction_between_surfaces.jpeg');
|
||||
assert.strictEqual(imageElement.getAttribute('alt'), imageFileName);
|
||||
|
||||
// Make sure the normal message is visible
|
||||
assert.match(
|
||||
|
@ -337,29 +341,16 @@ describe('matrix-public-archive', () => {
|
|||
replyMessageElement.outerHTML,
|
||||
new RegExp(`.*${escapeStringRegexp(reactionText)}.*`)
|
||||
);
|
||||
} catch (err) {
|
||||
if (err.body) {
|
||||
// FIXME: Remove this try/catch once the matrix-bot-sdk no longer throws
|
||||
// huge response objects as errors, see
|
||||
// https://github.com/turt2live/matrix-bot-sdk/pull/158
|
||||
throw new Error(
|
||||
`Error occured in matrix-bot-sdk (this new error is to stop it from logging the huge response) statusCode=${
|
||||
err.statusCode
|
||||
} body=${JSON.stringify(err.body)}`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
throw err;
|
||||
}
|
||||
it(`can render day back in time from room on remote homeserver we haven't backfilled from`);
|
||||
|
||||
it(`will redirect to hour pagination when there are too many messages`);
|
||||
|
||||
it(`will render a room with only a day of messages`);
|
||||
|
||||
it(
|
||||
`will render a room with a sparse amount of messages (a few per day) with no contamination between days`
|
||||
);
|
||||
});
|
||||
|
||||
it(`can render day back in time from room on remote homeserver we haven't backfilled from`);
|
||||
|
||||
it(`will redirect to hour pagination when there are too many messages`);
|
||||
|
||||
it(`will render a room with only a day of messages`);
|
||||
|
||||
it(
|
||||
`will render a room with a sparse amount of messages (a few per day) with no contamination between days`
|
||||
);
|
||||
});
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
Loading…
Reference in New Issue