mirror of https://github.com/vector-im/riot-web
Add a Cypress Test 🌲 (#8295)
* A first, maybe working cypress test Plus cypress plugins to manage synapses in docker containers * Fix yaml * This file is important * try & find where it's put the artifact * Download artifact to a directory * pics or it didn't happen * Add conditional, otherwise no artifacts on failure... * Try increasing timeout also actually give the test a name * Try in chrome * Get docker logs to see why it's failing also document the chrome setting * Try changing mode on homeserver.yaml * debug * More debugging * more file permissions debugging * ARGH * more debug * sigh * Eugh, that's not how arguments work * Add the option to really allow open registration and remove debug logging / comment fixes * failure to yaml * Upload docker logs as artifacts and temporarily remove contional to test * Put the conditional back * Upgrade types in end to end tests to be compatible with fs-extra types * Try reducing timeout a bit also make password more... sensible * Hex is not octal * Remove file mode Seems to be unnecessary since the signing key is perfectly fine * Give the log files extensions * Rename workflow file now it also does tests * Add cypress scripts * copyright headers * Use ? operator Co-authored-by: Travis Ralston <travisr@matrix.org> * Use develop synapse image * Tidy up any remaining synapses after each spec run Also: * Move the synapseStart / synapseStop functions out to the top level so they can be reused * Add a tsconfig file * Give the containers names * Don't upload video on test pass We don't upload it anyway so tell cypress not to so it can not bother encoding them * Enable linting on cypress files and fix existing lint errors * Type check cypress files and make it pass the type checks, specifically: * Upgrade sinon fake timers to a version that has the right types * Set module resolution * Type check cypress files separately * Rename workflow file again Probably better to just call it an element web build * Don't plus + characters in container name * Fix yaml * Stream logs to file * Add note to end to end tester to sya what's been ported * Put docker rm in finally block Co-authored-by: Travis Ralston <travisr@matrix.org>pull/21833/head
parent
bcb45f1447
commit
b8013fc52a
|
@ -92,6 +92,7 @@ module.exports = {
|
||||||
files: [
|
files: [
|
||||||
"src/**/*.{ts,tsx}",
|
"src/**/*.{ts,tsx}",
|
||||||
"test/**/*.{ts,tsx}",
|
"test/**/*.{ts,tsx}",
|
||||||
|
"cypress/**/*.ts",
|
||||||
],
|
],
|
||||||
extends: [
|
extends: [
|
||||||
"plugin:matrix-org/typescript",
|
"plugin:matrix-org/typescript",
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
# Produce a build of element-web with this version of react-sdk
|
||||||
|
# and any matching branches of element-web and js-sdk, output it
|
||||||
|
# as an artifact and run integration tests.
|
||||||
|
name: Element Web - Build and Test
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
# This must be set for fetchdep.sh to get the right branch
|
||||||
|
PR_NUMBER: ${{github.event.number}}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Build
|
||||||
|
run: scripts/ci/layered.sh && cd element-web && cp element.io/develop/config.json config.json && CI_PACKAGE=true yarn build
|
||||||
|
- name: Upload Artifact
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: previewbuild
|
||||||
|
path: element-web/webapp
|
||||||
|
# We'll only use this in a triggered job, then we're done with it
|
||||||
|
retention-days: 1
|
||||||
|
cypress:
|
||||||
|
needs: build
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Download build
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: previewbuild
|
||||||
|
path: webapp
|
||||||
|
- name: Run Cypress tests
|
||||||
|
uses: cypress-io/github-action@v2
|
||||||
|
with:
|
||||||
|
# The built in Electron runner seems to grind to a halt trying
|
||||||
|
# to run the tests, so use chrome.
|
||||||
|
browser: chrome
|
||||||
|
start: npx serve -p 8080 webapp
|
||||||
|
- name: Upload Artifact
|
||||||
|
if: failure()
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: cypress-results
|
||||||
|
path: |
|
||||||
|
cypress/screenshots
|
||||||
|
cypress/videos
|
||||||
|
cypress/dockerlogs
|
|
@ -1,23 +0,0 @@
|
||||||
# Produce a 'layered build' (a build of element-web with this version of
|
|
||||||
# react-sdk) and output it as an artifact
|
|
||||||
name: Layered Preview Build
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
# This must be set for fetchdep.sh to get the right branch
|
|
||||||
PR_NUMBER: ${{github.event.number}}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Build
|
|
||||||
run: scripts/ci/layered.sh && cd element-web && cp element.io/develop/config.json config.json && CI_PACKAGE=true yarn build
|
|
||||||
- name: Upload Artifact
|
|
||||||
uses: actions/upload-artifact@v2
|
|
||||||
with:
|
|
||||||
name: previewbuild
|
|
||||||
path: element-web/webapp
|
|
||||||
# We'll only use this in a triggered job, then we're done with it
|
|
||||||
retention-days: 1
|
|
||||||
|
|
|
@ -19,3 +19,11 @@ package-lock.json
|
||||||
|
|
||||||
.vscode
|
.vscode
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|
||||||
|
/cypress/videos
|
||||||
|
/cypress/downloads
|
||||||
|
/cypress/screenshots
|
||||||
|
/cypress/synapselogs
|
||||||
|
# These could have files in them but don't currently
|
||||||
|
# Cypress will still auto-create them though...
|
||||||
|
/cypress/fixtures
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"baseUrl": "http://localhost:8080",
|
||||||
|
"videoUploadOnPasses": false
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
Copyright 2022 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// <reference types="cypress" />
|
||||||
|
|
||||||
|
import { SynapseInstance } from "../../plugins/synapsedocker/index";
|
||||||
|
|
||||||
|
describe("Registration", () => {
|
||||||
|
let synapseId;
|
||||||
|
let synapsePort;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.task<SynapseInstance>("synapseStart", "consent").then(result => {
|
||||||
|
synapseId = result.synapseId;
|
||||||
|
synapsePort = result.port;
|
||||||
|
});
|
||||||
|
cy.visit("/#/register");
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
cy.task("synapseStop", synapseId);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("registers an account and lands on the home screen", () => {
|
||||||
|
cy.get(".mx_ServerPicker_change", { timeout: 15000 }).click();
|
||||||
|
cy.get(".mx_ServerPickerDialog_otherHomeserver").type(`http://localhost:${synapsePort}`);
|
||||||
|
cy.get(".mx_ServerPickerDialog_continue").click();
|
||||||
|
// wait for the dialog to go away
|
||||||
|
cy.get('.mx_ServerPickerDialog').should('not.exist');
|
||||||
|
cy.get("#mx_RegistrationForm_username").type("alice");
|
||||||
|
cy.get("#mx_RegistrationForm_password").type("totally a great password");
|
||||||
|
cy.get("#mx_RegistrationForm_passwordConfirm").type("totally a great password");
|
||||||
|
cy.get(".mx_Login_submit").click();
|
||||||
|
cy.get(".mx_RegistrationEmailPromptDialog button.mx_Dialog_primary").click();
|
||||||
|
cy.get(".mx_InteractiveAuthEntryComponents_termsPolicy input").click();
|
||||||
|
cy.get(".mx_InteractiveAuthEntryComponents_termsSubmit").click();
|
||||||
|
cy.url().should('contain', '/#/home');
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
Copyright 2022 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// <reference types="cypress" />
|
||||||
|
|
||||||
|
import { synapseDocker } from "./synapsedocker/index";
|
||||||
|
|
||||||
|
export default function(on, config) {
|
||||||
|
synapseDocker(on, config);
|
||||||
|
}
|
|
@ -0,0 +1,212 @@
|
||||||
|
/*
|
||||||
|
Copyright 2022 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// <reference types="cypress" />
|
||||||
|
|
||||||
|
import * as path from "path";
|
||||||
|
import * as os from "os";
|
||||||
|
import * as crypto from "crypto";
|
||||||
|
import * as childProcess from "child_process";
|
||||||
|
import * as fse from "fs-extra";
|
||||||
|
|
||||||
|
// A cypress plugins to add command to start & stop synapses in
|
||||||
|
// docker with preset templates.
|
||||||
|
|
||||||
|
interface SynapseConfig {
|
||||||
|
configDir: string;
|
||||||
|
registrationSecret: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SynapseInstance extends SynapseConfig {
|
||||||
|
synapseId: string;
|
||||||
|
port: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const synapses = new Map<string, SynapseInstance>();
|
||||||
|
|
||||||
|
function randB64Bytes(numBytes: number): string {
|
||||||
|
return crypto.randomBytes(numBytes).toString("base64").replace(/=*$/, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
async function cfgDirFromTemplate(template: string): Promise<SynapseConfig> {
|
||||||
|
const templateDir = path.join(__dirname, "templates", template);
|
||||||
|
|
||||||
|
const stats = await fse.stat(templateDir);
|
||||||
|
if (!stats?.isDirectory) {
|
||||||
|
throw new Error(`No such template: ${template}`);
|
||||||
|
}
|
||||||
|
const tempDir = await fse.mkdtemp(path.join(os.tmpdir(), 'react-sdk-synapsedocker-'));
|
||||||
|
|
||||||
|
// change permissions on the temp directory so the docker container can see its contents
|
||||||
|
await fse.chmod(tempDir, 0o777);
|
||||||
|
|
||||||
|
// copy the contents of the template dir, omitting homeserver.yaml as we'll template that
|
||||||
|
console.log(`Copy ${templateDir} -> ${tempDir}`);
|
||||||
|
await fse.copy(templateDir, tempDir, { filter: f => path.basename(f) !== 'homeserver.yaml' });
|
||||||
|
|
||||||
|
const registrationSecret = randB64Bytes(16);
|
||||||
|
const macaroonSecret = randB64Bytes(16);
|
||||||
|
const formSecret = randB64Bytes(16);
|
||||||
|
|
||||||
|
// now copy homeserver.yaml, applying sustitutions
|
||||||
|
console.log(`Gen ${path.join(templateDir, "homeserver.yaml")}`);
|
||||||
|
let hsYaml = await fse.readFile(path.join(templateDir, "homeserver.yaml"), "utf8");
|
||||||
|
hsYaml = hsYaml.replace(/{{REGISTRATION_SECRET}}/g, registrationSecret);
|
||||||
|
hsYaml = hsYaml.replace(/{{MACAROON_SECRET_KEY}}/g, macaroonSecret);
|
||||||
|
hsYaml = hsYaml.replace(/{{FORM_SECRET}}/g, formSecret);
|
||||||
|
await fse.writeFile(path.join(tempDir, "homeserver.yaml"), hsYaml);
|
||||||
|
|
||||||
|
// now generate a signing key (we could use synapse's config generation for
|
||||||
|
// this, or we could just do this...)
|
||||||
|
// NB. This assumes the homeserver.yaml specifies the key in this location
|
||||||
|
const signingKey = randB64Bytes(32);
|
||||||
|
console.log(`Gen ${path.join(templateDir, "localhost.signing.key")}`);
|
||||||
|
await fse.writeFile(path.join(tempDir, "localhost.signing.key"), `ed25519 x ${signingKey}`);
|
||||||
|
|
||||||
|
return {
|
||||||
|
configDir: tempDir,
|
||||||
|
registrationSecret,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start a synapse instance: the template must be the name of
|
||||||
|
// one of the templates in the cypress/plugins/synapsedocker/templates
|
||||||
|
// directory
|
||||||
|
async function synapseStart(template: string): Promise<SynapseInstance> {
|
||||||
|
const synCfg = await cfgDirFromTemplate(template);
|
||||||
|
|
||||||
|
console.log(`Starting synapse with config dir ${synCfg.configDir}...`);
|
||||||
|
|
||||||
|
const containerName = `react-sdk-cypress-synapse-${crypto.randomBytes(4).toString("hex")}`;
|
||||||
|
|
||||||
|
const synapseId = await new Promise<string>((resolve, reject) => {
|
||||||
|
childProcess.execFile('docker', [
|
||||||
|
"run",
|
||||||
|
"--name", containerName,
|
||||||
|
"-d",
|
||||||
|
"-v", `${synCfg.configDir}:/data`,
|
||||||
|
"-p", "8008/tcp",
|
||||||
|
"matrixdotorg/synapse:develop",
|
||||||
|
"run",
|
||||||
|
], (err, stdout) => {
|
||||||
|
if (err) reject(err);
|
||||||
|
resolve(stdout.trim());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get the port that docker allocated: specifying only one
|
||||||
|
// port above leaves docker to just grab a free one, although
|
||||||
|
// in hindsight we need to put the port in public_baseurl in the
|
||||||
|
// config really, so this will probably need changing to use a fixed
|
||||||
|
// / configured port.
|
||||||
|
const port = await new Promise<number>((resolve, reject) => {
|
||||||
|
childProcess.execFile('docker', [
|
||||||
|
"port", synapseId, "8008",
|
||||||
|
], { encoding: 'utf8' }, (err, stdout) => {
|
||||||
|
if (err) reject(err);
|
||||||
|
resolve(Number(stdout.trim().split(":")[1]));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
synapses.set(synapseId, Object.assign({
|
||||||
|
port,
|
||||||
|
synapseId,
|
||||||
|
}, synCfg));
|
||||||
|
|
||||||
|
console.log(`Started synapse with id ${synapseId} on port ${port}.`);
|
||||||
|
return synapses.get(synapseId);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function synapseStop(id) {
|
||||||
|
const synCfg = synapses.get(id);
|
||||||
|
|
||||||
|
if (!synCfg) throw new Error("Unknown synapse ID");
|
||||||
|
|
||||||
|
try {
|
||||||
|
const synapseLogsPath = path.join("cypress", "synapselogs", id);
|
||||||
|
await fse.ensureDir(synapseLogsPath);
|
||||||
|
|
||||||
|
const stdoutFile = await fse.open(path.join(synapseLogsPath, "stdout.log"), "w");
|
||||||
|
const stderrFile = await fse.open(path.join(synapseLogsPath, "stderr.log"), "w");
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
childProcess.spawn('docker', [
|
||||||
|
"logs",
|
||||||
|
id,
|
||||||
|
], {
|
||||||
|
stdio: ["ignore", stdoutFile, stderrFile],
|
||||||
|
}).once('close', resolve);
|
||||||
|
});
|
||||||
|
await fse.close(stdoutFile);
|
||||||
|
await fse.close(stderrFile);
|
||||||
|
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
childProcess.execFile('docker', [
|
||||||
|
"stop",
|
||||||
|
id,
|
||||||
|
], err => {
|
||||||
|
if (err) reject(err);
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
childProcess.execFile('docker', [
|
||||||
|
"rm",
|
||||||
|
id,
|
||||||
|
], err => {
|
||||||
|
if (err) reject(err);
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await fse.remove(synCfg.configDir);
|
||||||
|
|
||||||
|
synapses.delete(id);
|
||||||
|
|
||||||
|
console.log(`Stopped synapse id ${id}.`);
|
||||||
|
// cypres deliberately fails if you return 'undefined', so
|
||||||
|
// return null to signal all is well and we've handled the task.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Cypress.PluginConfig}
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
export function synapseDocker(on, config) {
|
||||||
|
on("task", {
|
||||||
|
synapseStart, synapseStop,
|
||||||
|
});
|
||||||
|
|
||||||
|
on("after:spec", async (spec) => {
|
||||||
|
// Cleans up any remaining synapse instances after a spec run
|
||||||
|
// This is on the theory that we should avoid re-using synapse
|
||||||
|
// instances between spec runs: they should be cheap enough to
|
||||||
|
// start that we can have a separate one for each spec run or even
|
||||||
|
// test. If we accidentally re-use synapses, we could inadvertantly
|
||||||
|
// make our tests depend on each other.
|
||||||
|
for (const synId of synapses.keys()) {
|
||||||
|
console.warn(`Cleaning up synapse ID ${synId} after ${spec.name}`);
|
||||||
|
await synapseStop(synId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
on("before:run", async () => {
|
||||||
|
// tidy up old synapse log files before each run
|
||||||
|
await fse.emptyDir(path.join("cypress", "synapselogs"));
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Meta-template for synapse templates
|
||||||
|
|
||||||
|
To make another template, you can copy this directory
|
|
@ -0,0 +1,72 @@
|
||||||
|
server_name: "localhost"
|
||||||
|
pid_file: /data/homeserver.pid
|
||||||
|
# XXX: This won't actually be right: it lets docker allocate an ephemeral port,
|
||||||
|
# so we have a chicken-and-egg problem
|
||||||
|
public_baseurl: http://localhost:8008/
|
||||||
|
# Listener is always port 8008 (configured in the container)
|
||||||
|
listeners:
|
||||||
|
- port: 8008
|
||||||
|
tls: false
|
||||||
|
bind_addresses: ['::']
|
||||||
|
type: http
|
||||||
|
x_forwarded: true
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- names: [client, federation, consent]
|
||||||
|
compress: false
|
||||||
|
|
||||||
|
# An sqlite in-memory database is fast & automatically wipes each time
|
||||||
|
database:
|
||||||
|
name: "sqlite3"
|
||||||
|
args:
|
||||||
|
database: ":memory:"
|
||||||
|
|
||||||
|
# Needs to be configured to log to the console like a good docker process
|
||||||
|
log_config: "/data/log.config"
|
||||||
|
|
||||||
|
rc_messages_per_second: 10000
|
||||||
|
rc_message_burst_count: 10000
|
||||||
|
rc_registration:
|
||||||
|
per_second: 10000
|
||||||
|
burst_count: 10000
|
||||||
|
|
||||||
|
rc_login:
|
||||||
|
address:
|
||||||
|
per_second: 10000
|
||||||
|
burst_count: 10000
|
||||||
|
account:
|
||||||
|
per_second: 10000
|
||||||
|
burst_count: 10000
|
||||||
|
failed_attempts:
|
||||||
|
per_second: 10000
|
||||||
|
burst_count: 10000
|
||||||
|
|
||||||
|
media_store_path: "/data/media_store"
|
||||||
|
uploads_path: "/data/uploads"
|
||||||
|
enable_registration: true
|
||||||
|
enable_registration_without_verification: true
|
||||||
|
disable_msisdn_registration: false
|
||||||
|
# These placeholders will be be replaced with values generated at start
|
||||||
|
registration_shared_secret: "{{REGISTRATION_SECRET}}"
|
||||||
|
report_stats: false
|
||||||
|
macaroon_secret_key: "{{MACAROON_SECRET_KEY}}"
|
||||||
|
form_secret: "{{FORM_SECRET}}"
|
||||||
|
# Signing key must be here: it will be generated to this file
|
||||||
|
signing_key_path: "/data/localhost.signing.key"
|
||||||
|
email:
|
||||||
|
enable_notifs: false
|
||||||
|
smtp_host: "localhost"
|
||||||
|
smtp_port: 25
|
||||||
|
smtp_user: "exampleusername"
|
||||||
|
smtp_pass: "examplepassword"
|
||||||
|
require_transport_security: False
|
||||||
|
notif_from: "Your Friendly %(app)s homeserver <noreply@example.com>"
|
||||||
|
app_name: Matrix
|
||||||
|
notif_template_html: notif_mail.html
|
||||||
|
notif_template_text: notif_mail.txt
|
||||||
|
notif_for_new_users: True
|
||||||
|
client_base_url: "http://localhost/element"
|
||||||
|
|
||||||
|
trusted_key_servers:
|
||||||
|
- server_name: "matrix.org"
|
||||||
|
suppress_key_server_warning: true
|
|
@ -0,0 +1,50 @@
|
||||||
|
# Log configuration for Synapse.
|
||||||
|
#
|
||||||
|
# This is a YAML file containing a standard Python logging configuration
|
||||||
|
# dictionary. See [1] for details on the valid settings.
|
||||||
|
#
|
||||||
|
# Synapse also supports structured logging for machine readable logs which can
|
||||||
|
# be ingested by ELK stacks. See [2] for details.
|
||||||
|
#
|
||||||
|
# [1]: https://docs.python.org/3.7/library/logging.config.html#configuration-dictionary-schema
|
||||||
|
# [2]: https://matrix-org.github.io/synapse/latest/structured_logging.html
|
||||||
|
|
||||||
|
version: 1
|
||||||
|
|
||||||
|
formatters:
|
||||||
|
precise:
|
||||||
|
format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s'
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
# A handler that writes logs to stderr. Unused by default, but can be used
|
||||||
|
# instead of "buffer" and "file" in the logger handlers.
|
||||||
|
console:
|
||||||
|
class: logging.StreamHandler
|
||||||
|
formatter: precise
|
||||||
|
|
||||||
|
loggers:
|
||||||
|
synapse.storage.SQL:
|
||||||
|
# beware: increasing this to DEBUG will make synapse log sensitive
|
||||||
|
# information such as access tokens.
|
||||||
|
level: INFO
|
||||||
|
|
||||||
|
twisted:
|
||||||
|
# We send the twisted logging directly to the file handler,
|
||||||
|
# to work around https://github.com/matrix-org/synapse/issues/3471
|
||||||
|
# when using "buffer" logger. Use "console" to log to stderr instead.
|
||||||
|
handlers: [console]
|
||||||
|
propagate: false
|
||||||
|
|
||||||
|
root:
|
||||||
|
level: INFO
|
||||||
|
|
||||||
|
# Write logs to the `buffer` handler, which will buffer them together in memory,
|
||||||
|
# then write them to a file.
|
||||||
|
#
|
||||||
|
# Replace "buffer" with "console" to log to stderr instead. (Note that you'll
|
||||||
|
# also need to update the configuration for the `twisted` logger above, in
|
||||||
|
# this case.)
|
||||||
|
#
|
||||||
|
handlers: [console]
|
||||||
|
|
||||||
|
disable_existing_loggers: false
|
|
@ -0,0 +1 @@
|
||||||
|
A synapse configured with user privacy consent enabled
|
|
@ -0,0 +1,84 @@
|
||||||
|
server_name: "localhost"
|
||||||
|
pid_file: /data/homeserver.pid
|
||||||
|
public_baseurl: http://localhost:5005/
|
||||||
|
listeners:
|
||||||
|
- port: 8008
|
||||||
|
tls: false
|
||||||
|
bind_addresses: ['::']
|
||||||
|
type: http
|
||||||
|
x_forwarded: true
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- names: [client, federation, consent]
|
||||||
|
compress: false
|
||||||
|
|
||||||
|
database:
|
||||||
|
name: "sqlite3"
|
||||||
|
args:
|
||||||
|
database: ":memory:"
|
||||||
|
|
||||||
|
log_config: "/data/log.config"
|
||||||
|
|
||||||
|
rc_messages_per_second: 10000
|
||||||
|
rc_message_burst_count: 10000
|
||||||
|
rc_registration:
|
||||||
|
per_second: 10000
|
||||||
|
burst_count: 10000
|
||||||
|
|
||||||
|
rc_login:
|
||||||
|
address:
|
||||||
|
per_second: 10000
|
||||||
|
burst_count: 10000
|
||||||
|
account:
|
||||||
|
per_second: 10000
|
||||||
|
burst_count: 10000
|
||||||
|
failed_attempts:
|
||||||
|
per_second: 10000
|
||||||
|
burst_count: 10000
|
||||||
|
|
||||||
|
media_store_path: "/data/media_store"
|
||||||
|
uploads_path: "/data/uploads"
|
||||||
|
enable_registration: true
|
||||||
|
enable_registration_without_verification: true
|
||||||
|
disable_msisdn_registration: false
|
||||||
|
registration_shared_secret: "{{REGISTRATION_SECRET}}"
|
||||||
|
report_stats: false
|
||||||
|
macaroon_secret_key: "{{MACAROON_SECRET_KEY}}"
|
||||||
|
form_secret: "{{FORM_SECRET}}"
|
||||||
|
signing_key_path: "/data/localhost.signing.key"
|
||||||
|
email:
|
||||||
|
enable_notifs: false
|
||||||
|
smtp_host: "localhost"
|
||||||
|
smtp_port: 25
|
||||||
|
smtp_user: "exampleusername"
|
||||||
|
smtp_pass: "examplepassword"
|
||||||
|
require_transport_security: False
|
||||||
|
notif_from: "Your Friendly %(app)s homeserver <noreply@example.com>"
|
||||||
|
app_name: Matrix
|
||||||
|
notif_template_html: notif_mail.html
|
||||||
|
notif_template_text: notif_mail.txt
|
||||||
|
notif_for_new_users: True
|
||||||
|
client_base_url: "http://localhost/element"
|
||||||
|
|
||||||
|
user_consent:
|
||||||
|
template_dir: /data/res/templates/privacy
|
||||||
|
version: 1.0
|
||||||
|
server_notice_content:
|
||||||
|
msgtype: m.text
|
||||||
|
body: >-
|
||||||
|
To continue using this homeserver you must review and agree to the
|
||||||
|
terms and conditions at %(consent_uri)s
|
||||||
|
send_server_notice_to_guests: True
|
||||||
|
block_events_error: >-
|
||||||
|
To continue using this homeserver you must review and agree to the
|
||||||
|
terms and conditions at %(consent_uri)s
|
||||||
|
require_at_registration: true
|
||||||
|
|
||||||
|
server_notices:
|
||||||
|
system_mxid_localpart: notices
|
||||||
|
system_mxid_display_name: "Server Notices"
|
||||||
|
system_mxid_avatar_url: "mxc://localhost:5005/oumMVlgDnLYFaPVkExemNVVZ"
|
||||||
|
room_name: "Server Notices"
|
||||||
|
trusted_key_servers:
|
||||||
|
- server_name: "matrix.org"
|
||||||
|
suppress_key_server_warning: true
|
|
@ -0,0 +1,50 @@
|
||||||
|
# Log configuration for Synapse.
|
||||||
|
#
|
||||||
|
# This is a YAML file containing a standard Python logging configuration
|
||||||
|
# dictionary. See [1] for details on the valid settings.
|
||||||
|
#
|
||||||
|
# Synapse also supports structured logging for machine readable logs which can
|
||||||
|
# be ingested by ELK stacks. See [2] for details.
|
||||||
|
#
|
||||||
|
# [1]: https://docs.python.org/3.7/library/logging.config.html#configuration-dictionary-schema
|
||||||
|
# [2]: https://matrix-org.github.io/synapse/latest/structured_logging.html
|
||||||
|
|
||||||
|
version: 1
|
||||||
|
|
||||||
|
formatters:
|
||||||
|
precise:
|
||||||
|
format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s'
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
# A handler that writes logs to stderr. Unused by default, but can be used
|
||||||
|
# instead of "buffer" and "file" in the logger handlers.
|
||||||
|
console:
|
||||||
|
class: logging.StreamHandler
|
||||||
|
formatter: precise
|
||||||
|
|
||||||
|
loggers:
|
||||||
|
synapse.storage.SQL:
|
||||||
|
# beware: increasing this to DEBUG will make synapse log sensitive
|
||||||
|
# information such as access tokens.
|
||||||
|
level: INFO
|
||||||
|
|
||||||
|
twisted:
|
||||||
|
# We send the twisted logging directly to the file handler,
|
||||||
|
# to work around https://github.com/matrix-org/synapse/issues/3471
|
||||||
|
# when using "buffer" logger. Use "console" to log to stderr instead.
|
||||||
|
handlers: [console]
|
||||||
|
propagate: false
|
||||||
|
|
||||||
|
root:
|
||||||
|
level: INFO
|
||||||
|
|
||||||
|
# Write logs to the `buffer` handler, which will buffer them together in memory,
|
||||||
|
# then write them to a file.
|
||||||
|
#
|
||||||
|
# Replace "buffer" with "console" to log to stderr instead. (Note that you'll
|
||||||
|
# also need to update the configuration for the `twisted` logger above, in
|
||||||
|
# this case.)
|
||||||
|
#
|
||||||
|
handlers: [console]
|
||||||
|
|
||||||
|
disable_existing_loggers: false
|
|
@ -0,0 +1,23 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Test Privacy policy</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{% if has_consented %}
|
||||||
|
<p>
|
||||||
|
Thank you, you've already accepted the license.
|
||||||
|
</p>
|
||||||
|
{% else %}
|
||||||
|
<p>
|
||||||
|
Please accept the license!
|
||||||
|
</p>
|
||||||
|
<form method="post" action="consent">
|
||||||
|
<input type="hidden" name="v" value="{{version}}"/>
|
||||||
|
<input type="hidden" name="u" value="{{user}}"/>
|
||||||
|
<input type="hidden" name="h" value="{{userhmac}}"/>
|
||||||
|
<input type="submit" value="Sure thing!"/>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Test Privacy policy</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>Danke schon</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,3 @@
|
||||||
|
// Empty file to prevent cypress from recreating a helpful example
|
||||||
|
// file on every run (their example file doesn't use semicolons and
|
||||||
|
// so fails our lint rules).
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2016",
|
||||||
|
"lib": ["es2020", "dom"],
|
||||||
|
"types": ["cypress"],
|
||||||
|
"moduleResolution": "node"
|
||||||
|
},
|
||||||
|
"include": ["**/*.ts"]
|
||||||
|
}
|
13
package.json
13
package.json
|
@ -44,11 +44,13 @@
|
||||||
"start:all": "echo THIS IS FOR LEGACY PURPOSES ONLY. && yarn start:build",
|
"start:all": "echo THIS IS FOR LEGACY PURPOSES ONLY. && yarn start:build",
|
||||||
"start:build": "babel src -w -s -d lib --verbose --extensions \".ts,.js\"",
|
"start:build": "babel src -w -s -d lib --verbose --extensions \".ts,.js\"",
|
||||||
"lint": "yarn lint:types && yarn lint:js && yarn lint:style",
|
"lint": "yarn lint:types && yarn lint:js && yarn lint:style",
|
||||||
"lint:js": "eslint --max-warnings 0 src test",
|
"lint:js": "eslint --max-warnings 0 src test cypress",
|
||||||
"lint:js-fix": "eslint --fix src test",
|
"lint:js-fix": "eslint --fix src test cypress",
|
||||||
"lint:types": "tsc --noEmit --jsx react",
|
"lint:types": "tsc --noEmit --jsx react && tsc --noEmit -p cypress",
|
||||||
"lint:style": "stylelint \"res/css/**/*.scss\"",
|
"lint:style": "stylelint \"res/css/**/*.scss\"",
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
|
"test:cypress": "cypress run",
|
||||||
|
"test:cypress:open": "cypress open",
|
||||||
"test:e2e": "./test/end-to-end-tests/run.sh --app-url http://localhost:8080",
|
"test:e2e": "./test/end-to-end-tests/run.sh --app-url http://localhost:8080",
|
||||||
"coverage": "yarn test --coverage"
|
"coverage": "yarn test --coverage"
|
||||||
},
|
},
|
||||||
|
@ -132,7 +134,7 @@
|
||||||
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.8.tgz",
|
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.8.tgz",
|
||||||
"@peculiar/webcrypto": "^1.1.4",
|
"@peculiar/webcrypto": "^1.1.4",
|
||||||
"@sentry/types": "^6.10.0",
|
"@sentry/types": "^6.10.0",
|
||||||
"@sinonjs/fake-timers": "^7.0.2",
|
"@sinonjs/fake-timers": "^9.1.2",
|
||||||
"@types/classnames": "^2.2.11",
|
"@types/classnames": "^2.2.11",
|
||||||
"@types/commonmark": "^0.27.4",
|
"@types/commonmark": "^0.27.4",
|
||||||
"@types/counterpart": "^0.18.1",
|
"@types/counterpart": "^0.18.1",
|
||||||
|
@ -142,6 +144,7 @@
|
||||||
"@types/escape-html": "^1.0.1",
|
"@types/escape-html": "^1.0.1",
|
||||||
"@types/file-saver": "^2.0.3",
|
"@types/file-saver": "^2.0.3",
|
||||||
"@types/flux": "^3.1.9",
|
"@types/flux": "^3.1.9",
|
||||||
|
"@types/fs-extra": "^9.0.13",
|
||||||
"@types/jest": "^26.0.20",
|
"@types/jest": "^26.0.20",
|
||||||
"@types/lodash": "^4.14.168",
|
"@types/lodash": "^4.14.168",
|
||||||
"@types/modernizr": "^3.5.3",
|
"@types/modernizr": "^3.5.3",
|
||||||
|
@ -163,6 +166,7 @@
|
||||||
"babel-jest": "^26.6.3",
|
"babel-jest": "^26.6.3",
|
||||||
"blob-polyfill": "^6.0.20211015",
|
"blob-polyfill": "^6.0.20211015",
|
||||||
"chokidar": "^3.5.1",
|
"chokidar": "^3.5.1",
|
||||||
|
"cypress": "^9.5.4",
|
||||||
"enzyme": "^3.11.0",
|
"enzyme": "^3.11.0",
|
||||||
"enzyme-to-json": "^3.6.2",
|
"enzyme-to-json": "^3.6.2",
|
||||||
"eslint": "8.9.0",
|
"eslint": "8.9.0",
|
||||||
|
@ -172,6 +176,7 @@
|
||||||
"eslint-plugin-matrix-org": "^0.4.0",
|
"eslint-plugin-matrix-org": "^0.4.0",
|
||||||
"eslint-plugin-react": "^7.28.0",
|
"eslint-plugin-react": "^7.28.0",
|
||||||
"eslint-plugin-react-hooks": "^4.3.0",
|
"eslint-plugin-react-hooks": "^4.3.0",
|
||||||
|
"fs-extra": "^10.0.1",
|
||||||
"glob": "^7.1.6",
|
"glob": "^7.1.6",
|
||||||
"jest": "^27.4.0",
|
"jest": "^27.4.0",
|
||||||
"jest-canvas-mock": "^2.3.0",
|
"jest-canvas-mock": "^2.3.0",
|
||||||
|
|
|
@ -43,6 +43,7 @@ export async function scenario(createSession: (s: string) => Promise<ElementSess
|
||||||
console.log(`running tests on ${await session.browser.version()} ...`);
|
console.log(`running tests on ${await session.browser.version()} ...`);
|
||||||
firstUser = false;
|
firstUser = false;
|
||||||
}
|
}
|
||||||
|
// ported to cyprus (registration test)
|
||||||
await signup(session, session.username, 'testsarefun!!!', session.hsUrl);
|
await signup(session, session.username, 'testsarefun!!!', session.hsUrl);
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,14 +3,14 @@
|
||||||
|
|
||||||
|
|
||||||
"@types/node@*":
|
"@types/node@*":
|
||||||
version "11.12.1"
|
version "17.0.23"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-11.12.1.tgz#d90123f6c61fdf2f7cddd286ddae891586dd3488"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.23.tgz#3b41a6e643589ac6442bdbd7a4a3ded62f33f7da"
|
||||||
integrity sha512-sKDlqv6COJrR7ar0+GqqhrXQDzQlMcqMnF2iEU6m9hLo8kxozoAGUazwPyELHlRVmjsbvlnGXjnzyptSXVmceA==
|
integrity sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==
|
||||||
|
|
||||||
"@types/puppeteer@^5.4.4":
|
"@types/puppeteer@^5.4.4":
|
||||||
version "5.4.4"
|
version "5.4.5"
|
||||||
resolved "https://registry.yarnpkg.com/@types/puppeteer/-/puppeteer-5.4.4.tgz#e92abeccc4f46207c3e1b38934a1246be080ccd0"
|
resolved "https://registry.yarnpkg.com/@types/puppeteer/-/puppeteer-5.4.5.tgz#154e3850a77bfd3967f036680de8ddc88eb3a12b"
|
||||||
integrity sha512-3Nau+qi69CN55VwZb0ATtdUAlYlqOOQ3OfQfq0Hqgc4JMFXiQT/XInlwQ9g6LbicDslE6loIFsXFklGh5XmI6Q==
|
integrity sha512-lxCjpDEY+DZ66+W3x5Af4oHnEmUXt0HuaRzkBGE2UZiZEp/V1d3StpLPlmNVu/ea091bdNmVPl44lu8Wy/0ZCA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue