mirror of
https://github.com/chatmail/core.git
synced 2026-05-08 17:36:29 +03:00
improve test setup and code style
This commit is contained in:
committed by
Simon Laux
parent
bdd4aa0f10
commit
2f00b098ac
@@ -3,11 +3,11 @@ name = "deltachat-jsonrpc"
|
|||||||
version = "1.86.0"
|
version = "1.86.0"
|
||||||
authors = ["Delta Chat Developers (ML) <delta@codespeak.net>"]
|
authors = ["Delta Chat Developers (ML) <delta@codespeak.net>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
default-run = "webserver"
|
default-run = "deltachat-jsonrpc-server"
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "webserver"
|
name = "deltachat-jsonrpc-server"
|
||||||
path = "src/webserver.rs"
|
path = "src/webserver.rs"
|
||||||
required-features = ["webserver"]
|
required-features = ["webserver"]
|
||||||
|
|
||||||
@@ -36,6 +36,3 @@ tokio = { version = "1.19.2", features = ["full", "rt-multi-thread"] }
|
|||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
webserver = ["env_logger", "axum", "tokio/full", "yerpc/support-axum"]
|
webserver = ["env_logger", "axum", "tokio/full", "yerpc/support-axum"]
|
||||||
|
|
||||||
[profile.release]
|
|
||||||
lto = true
|
|
||||||
|
|||||||
@@ -9,14 +9,19 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"prettier:check": "prettier --check **.ts",
|
"prettier:check": "prettier --check **.ts",
|
||||||
"prettier:fix": "prettier --write **.ts",
|
"prettier:fix": "prettier --write **.ts",
|
||||||
"build": "npm run generate-bindings && tsc",
|
|
||||||
"bundle": "npm run build && esbuild --bundle dist/deltachat.js --outfile=dist/deltachat.bundle.js",
|
|
||||||
"generate-bindings": "cargo test",
|
"generate-bindings": "cargo test",
|
||||||
"example:build": "tsc && esbuild --bundle dist/example/example.js --outfile=dist/example.bundle.js",
|
"build": "run-s generate-bindings build:tsc build:bundle",
|
||||||
|
"build:tsc": "tsc",
|
||||||
|
"build:bundle": "esbuild --bundle dist/deltachat.js --outfile=dist/deltachat.bundle.js",
|
||||||
|
"example": "run-s build example:build example:start",
|
||||||
|
"example:build": "esbuild --bundle dist/example/example.js --outfile=dist/example.bundle.js",
|
||||||
"example:start": "http-server .",
|
"example:start": "http-server .",
|
||||||
"example:dev": "esbuild example/example.ts --bundle --outfile=dist/example.bundle.js --servedir=.",
|
"example:dev": "esbuild example/example.ts --bundle --outfile=dist/example.bundle.js --servedir=.",
|
||||||
"coverage": "tsc -b test && COVERAGE=1 NODE_OPTIONS=--enable-source-maps c8 --include \"dist/*\" -r text -r html -r json mocha test_dist && node report_api_coverage.mjs",
|
"test": "run-s test:prepare test:run-coverage test:report-coverage",
|
||||||
"test": "rm -rf dist && npm run build && npm run coverage && npm run prettier:check",
|
"test:prepare": "cargo build --features webserver --bin deltachat-jsonrpc-server",
|
||||||
|
"test:run": "mocha dist/test",
|
||||||
|
"test:run-coverage": "COVERAGE=1 NODE_OPTIONS=--enable-source-maps c8 --include 'dist/*' -r text -r html -r json mocha dist/test",
|
||||||
|
"test:report-coverage": "node report_api_coverage.mjs",
|
||||||
"docs": "typedoc --out docs deltachat.ts"
|
"docs": "typedoc --out docs deltachat.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -34,8 +39,10 @@
|
|||||||
"chai": "^4.3.4",
|
"chai": "^4.3.4",
|
||||||
"chai-as-promised": "^7.1.1",
|
"chai-as-promised": "^7.1.1",
|
||||||
"esbuild": "^0.14.11",
|
"esbuild": "^0.14.11",
|
||||||
|
"http-server": "^14.1.1",
|
||||||
"mocha": "^9.1.1",
|
"mocha": "^9.1.1",
|
||||||
"node-fetch": "^2.6.1",
|
"node-fetch": "^2.6.1",
|
||||||
|
"npm-run-all": "^4.1.5",
|
||||||
"prettier": "^2.6.2",
|
"prettier": "^2.6.2",
|
||||||
"typedoc": "^0.23.2",
|
"typedoc": "^0.23.2",
|
||||||
"typescript": "^4.5.5",
|
"typescript": "^4.5.5",
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { readFileSync } from "fs";
|
import { readFileSync } from "fs";
|
||||||
// only checks for the coverge of the api functions in bindings.ts for now
|
// only checks for the coverge of the api functions in bindings.ts for now
|
||||||
const generated_file = "typescript/generated/client.ts";
|
const generatedFile = "typescript/generated/client.ts";
|
||||||
const json = JSON.parse(readFileSync("./coverage/coverage-final.json"));
|
const json = JSON.parse(readFileSync("./coverage/coverage-final.json"));
|
||||||
const jsonCoverage =
|
const jsonCoverage =
|
||||||
json[Object.keys(json).find((k) => k.includes(generated_file))];
|
json[Object.keys(json).find((k) => k.includes(generatedFile))];
|
||||||
const fnMap = Object.keys(jsonCoverage.fnMap).map(
|
const fnMap = Object.keys(jsonCoverage.fnMap).map(
|
||||||
(key) => jsonCoverage.fnMap[key]
|
(key) => jsonCoverage.fnMap[key]
|
||||||
);
|
);
|
||||||
const htmlCoverage = readFileSync(
|
const htmlCoverage = readFileSync(
|
||||||
"./coverage/" + generated_file + ".html",
|
"./coverage/" + generatedFile + ".html",
|
||||||
"utf8"
|
"utf8"
|
||||||
);
|
);
|
||||||
const uncoveredLines = htmlCoverage
|
const uncoveredLines = htmlCoverage
|
||||||
@@ -22,7 +22,7 @@ console.log(
|
|||||||
uncoveredFunctions
|
uncoveredFunctions
|
||||||
.map((uF) => fnMap.find(({ name }) => name === uF))
|
.map((uF) => fnMap.find(({ name }) => name === uF))
|
||||||
.map(
|
.map(
|
||||||
({ name, line }) => `.${name.padEnd(40)} (${generated_file}:${line})`
|
({ name, line }) => `.${name.padEnd(40)} (${generatedFile}:${line})`
|
||||||
)
|
)
|
||||||
.join("\n")
|
.join("\n")
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,59 +2,55 @@ import { strictEqual } from "assert";
|
|||||||
import chai, { assert, expect } from "chai";
|
import chai, { assert, expect } from "chai";
|
||||||
import chaiAsPromised from "chai-as-promised";
|
import chaiAsPromised from "chai-as-promised";
|
||||||
chai.use(chaiAsPromised);
|
chai.use(chaiAsPromised);
|
||||||
import { Deltachat } from "../dist/deltachat.js";
|
import { Deltachat } from "../deltachat.js";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CMD_API_Server_Handle,
|
RpcServerHandle,
|
||||||
CMD_API_SERVER_PORT,
|
startServer,
|
||||||
startCMD_API_Server,
|
|
||||||
} from "./test_base.js";
|
} from "./test_base.js";
|
||||||
|
|
||||||
describe("basic tests", () => {
|
describe("basic tests", () => {
|
||||||
let server_handle: CMD_API_Server_Handle;
|
let serverHandle: RpcServerHandle;
|
||||||
let dc: Deltachat;
|
let dc: Deltachat;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
server_handle = await startCMD_API_Server(CMD_API_SERVER_PORT);
|
serverHandle = await startServer();
|
||||||
// make sure server is up by the time we continue
|
// make sure server is up by the time we continue
|
||||||
await new Promise((res) => setTimeout(res, 100));
|
await new Promise((res) => setTimeout(res, 100));
|
||||||
|
dc = new Deltachat(serverHandle.url)
|
||||||
dc = new Deltachat({
|
// dc.on("ALL", (event) => {
|
||||||
url: "ws://localhost:" + CMD_API_SERVER_PORT + "/ws",
|
|
||||||
});
|
|
||||||
dc.on("ALL", (event) => {
|
|
||||||
//console.log("event", event);
|
//console.log("event", event);
|
||||||
});
|
// });
|
||||||
});
|
});
|
||||||
|
|
||||||
after(async () => {
|
after(async () => {
|
||||||
dc && dc.close();
|
dc && dc.close();
|
||||||
await server_handle.close();
|
await serverHandle.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("check email", async () => {
|
it("check email address validity", async () => {
|
||||||
const positive_test_cases = [
|
const validAddresses = [
|
||||||
"email@example.com",
|
"email@example.com",
|
||||||
"36aa165ae3406424e0c61af17700f397cad3fe8ab83d682d0bddf3338a5dd52e@yggmail@yggmail",
|
"36aa165ae3406424e0c61af17700f397cad3fe8ab83d682d0bddf3338a5dd52e@yggmail@yggmail",
|
||||||
];
|
];
|
||||||
const negative_test_cases = ["email@", "example.com", "emai221"];
|
const invalidAddresses = ["email@", "example.com", "emai221"];
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
positive_test_cases.map((email) => dc.rpc.checkEmailValidity(email))
|
validAddresses.map((email) => dc.rpc.checkEmailValidity(email))
|
||||||
)
|
)
|
||||||
).to.not.contain(false);
|
).to.not.contain(false);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
negative_test_cases.map((email) => dc.rpc.checkEmailValidity(email))
|
invalidAddresses.map((email) => dc.rpc.checkEmailValidity(email))
|
||||||
)
|
)
|
||||||
).to.not.contain(true);
|
).to.not.contain(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("system info", async () => {
|
it("system info", async () => {
|
||||||
const system_info = await dc.rpc.getSystemInfo();
|
const systemInfo = await dc.rpc.getSystemInfo();
|
||||||
expect(system_info).to.contain.keys([
|
expect(systemInfo).to.contain.keys([
|
||||||
"arch",
|
"arch",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"deltachat_core_version",
|
"deltachat_core_version",
|
||||||
@@ -64,7 +60,8 @@ describe("basic tests", () => {
|
|||||||
|
|
||||||
describe("account managment", () => {
|
describe("account managment", () => {
|
||||||
it("should create account", async () => {
|
it("should create account", async () => {
|
||||||
await dc.rpc.addAccount();
|
const res = await dc.rpc.addAccount();
|
||||||
|
console.log('res', res)
|
||||||
assert((await dc.rpc.getAllAccountIds()).length === 1);
|
assert((await dc.rpc.getAllAccountIds()).length === 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -83,55 +80,55 @@ describe("basic tests", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("contact managment", function () {
|
describe("contact managment", function () {
|
||||||
let acc: number;
|
let accountId: number;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
acc = await dc.rpc.addAccount();
|
accountId = await dc.rpc.addAccount();
|
||||||
});
|
});
|
||||||
it("block and unblock contact", async function () {
|
it("should block and unblock contact", async function () {
|
||||||
const contactId = await dc.rpc.contactsCreateContact(
|
const contactId = await dc.rpc.contactsCreateContact(
|
||||||
acc,
|
accountId,
|
||||||
"example@delta.chat",
|
"example@delta.chat",
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
expect((await dc.rpc.contactsGetContact(acc, contactId)).is_blocked).to.be
|
expect((await dc.rpc.contactsGetContact(accountId, contactId)).is_blocked).to.be
|
||||||
.false;
|
.false;
|
||||||
await dc.rpc.contactsBlock(acc, contactId);
|
await dc.rpc.contactsBlock(accountId, contactId);
|
||||||
expect((await dc.rpc.contactsGetContact(acc, contactId)).is_blocked).to.be
|
expect((await dc.rpc.contactsGetContact(accountId, contactId)).is_blocked).to.be
|
||||||
.true;
|
.true;
|
||||||
expect(await dc.rpc.contactsGetBlocked(acc)).to.have.length(1);
|
expect(await dc.rpc.contactsGetBlocked(accountId)).to.have.length(1);
|
||||||
await dc.rpc.contactsUnblock(acc, contactId);
|
await dc.rpc.contactsUnblock(accountId, contactId);
|
||||||
expect((await dc.rpc.contactsGetContact(acc, contactId)).is_blocked).to.be
|
expect((await dc.rpc.contactsGetContact(accountId, contactId)).is_blocked).to.be
|
||||||
.false;
|
.false;
|
||||||
expect(await dc.rpc.contactsGetBlocked(acc)).to.have.length(0);
|
expect(await dc.rpc.contactsGetBlocked(accountId)).to.have.length(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("configuration", function () {
|
describe("configuration", function () {
|
||||||
let acc: number;
|
let accountId: number;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
acc = await dc.rpc.addAccount();
|
accountId = await dc.rpc.addAccount();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("set and retrive", async function () {
|
it("set and retrive", async function () {
|
||||||
await dc.rpc.setConfig(acc, "addr", "valid@email");
|
await dc.rpc.setConfig(accountId, "addr", "valid@email");
|
||||||
assert((await dc.rpc.getConfig(acc, "addr")) == "valid@email");
|
assert((await dc.rpc.getConfig(accountId, "addr")) == "valid@email");
|
||||||
});
|
});
|
||||||
it("set invalid key should throw", async function () {
|
it("set invalid key should throw", async function () {
|
||||||
await expect(dc.rpc.setConfig(acc, "invalid_key", "some value")).to.be
|
await expect(dc.rpc.setConfig(accountId, "invalid_key", "some value")).to.be
|
||||||
.eventually.rejected;
|
.eventually.rejected;
|
||||||
});
|
});
|
||||||
it("get invalid key should throw", async function () {
|
it("get invalid key should throw", async function () {
|
||||||
await expect(dc.rpc.getConfig(acc, "invalid_key")).to.be.eventually
|
await expect(dc.rpc.getConfig(accountId, "invalid_key")).to.be.eventually
|
||||||
.rejected;
|
.rejected;
|
||||||
});
|
});
|
||||||
it("set and retrive ui.*", async function () {
|
it("set and retrive ui.*", async function () {
|
||||||
await dc.rpc.setConfig(acc, "ui.chat_bg", "color:red");
|
await dc.rpc.setConfig(accountId, "ui.chat_bg", "color:red");
|
||||||
assert((await dc.rpc.getConfig(acc, "ui.chat_bg")) == "color:red");
|
assert((await dc.rpc.getConfig(accountId, "ui.chat_bg")) == "color:red");
|
||||||
});
|
});
|
||||||
it("set and retrive (batch)", async function () {
|
it("set and retrive (batch)", async function () {
|
||||||
const config = { addr: "valid@email", mail_pw: "1234" };
|
const config = { addr: "valid@email", mail_pw: "1234" };
|
||||||
await dc.rpc.batchSetConfig(acc, config);
|
await dc.rpc.batchSetConfig(accountId, config);
|
||||||
const retrieved = await dc.rpc.batchGetConfig(acc, Object.keys(config));
|
const retrieved = await dc.rpc.batchGetConfig(accountId, Object.keys(config));
|
||||||
expect(retrieved).to.deep.equal(config);
|
expect(retrieved).to.deep.equal(config);
|
||||||
});
|
});
|
||||||
it("set and retrive ui.* (batch)", async function () {
|
it("set and retrive ui.* (batch)", async function () {
|
||||||
@@ -139,8 +136,8 @@ describe("basic tests", () => {
|
|||||||
"ui.chat_bg": "color:green",
|
"ui.chat_bg": "color:green",
|
||||||
"ui.enter_key_sends": "true",
|
"ui.enter_key_sends": "true",
|
||||||
};
|
};
|
||||||
await dc.rpc.batchSetConfig(acc, config);
|
await dc.rpc.batchSetConfig(accountId, config);
|
||||||
const retrieved = await dc.rpc.batchGetConfig(acc, Object.keys(config));
|
const retrieved = await dc.rpc.batchGetConfig(accountId, Object.keys(config));
|
||||||
expect(retrieved).to.deep.equal(config);
|
expect(retrieved).to.deep.equal(config);
|
||||||
});
|
});
|
||||||
it("set and retrive mixed(ui and core) (batch)", async function () {
|
it("set and retrive mixed(ui and core) (batch)", async function () {
|
||||||
@@ -150,8 +147,8 @@ describe("basic tests", () => {
|
|||||||
addr: "valid2@email",
|
addr: "valid2@email",
|
||||||
mail_pw: "123456",
|
mail_pw: "123456",
|
||||||
};
|
};
|
||||||
await dc.rpc.batchSetConfig(acc, config);
|
await dc.rpc.batchSetConfig(accountId, config);
|
||||||
const retrieved = await dc.rpc.batchGetConfig(acc, Object.keys(config));
|
const retrieved = await dc.rpc.batchGetConfig(accountId, Object.keys(config));
|
||||||
expect(retrieved).to.deep.equal(config);
|
expect(retrieved).to.deep.equal(config);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,18 +1,19 @@
|
|||||||
import { assert, expect } from "chai";
|
import { assert, expect } from "chai";
|
||||||
import { Deltachat, DeltachatEvent, EventTypeName } from "../dist/deltachat.js";
|
import { Deltachat, DeltachatEvent, EventTypeName } from "../deltachat.js";
|
||||||
import {
|
import {
|
||||||
CMD_API_Server_Handle,
|
RpcServerHandle,
|
||||||
CMD_API_SERVER_PORT,
|
|
||||||
createTempUser,
|
createTempUser,
|
||||||
startCMD_API_Server,
|
startServer,
|
||||||
} from "./test_base.js";
|
} from "./test_base.js";
|
||||||
|
|
||||||
|
const EVENT_TIMEOUT = 10000
|
||||||
|
|
||||||
describe("online tests", function () {
|
describe("online tests", function () {
|
||||||
let server_handle: CMD_API_Server_Handle;
|
let serverHandle: RpcServerHandle;
|
||||||
let dc: Deltachat;
|
let dc: Deltachat;
|
||||||
let account: { email: string; password: string };
|
let account1: { email: string; password: string };
|
||||||
let account2: { email: string; password: string };
|
let account2: { email: string; password: string };
|
||||||
let acc1: number, acc2: number;
|
let accountId1: number, accountId2: number;
|
||||||
|
|
||||||
before(async function () {
|
before(async function () {
|
||||||
this.timeout(12000)
|
this.timeout(12000)
|
||||||
@@ -29,17 +30,15 @@ describe("online tests", function () {
|
|||||||
);
|
);
|
||||||
this.skip();
|
this.skip();
|
||||||
}
|
}
|
||||||
server_handle = await startCMD_API_Server(CMD_API_SERVER_PORT);
|
serverHandle = await startServer();
|
||||||
dc = new Deltachat({
|
dc = new Deltachat(serverHandle.url)
|
||||||
url: "ws://localhost:" + CMD_API_SERVER_PORT + "/ws",
|
|
||||||
});
|
|
||||||
|
|
||||||
dc.on("ALL", ({ id, contextId }) => {
|
dc.on("ALL", ({ id, contextId }) => {
|
||||||
if (id !== "Info") console.log(contextId, id);
|
if (id !== "Info") console.log(contextId, id);
|
||||||
});
|
});
|
||||||
|
|
||||||
account = await createTempUser(process.env.DCC_NEW_TMP_EMAIL);
|
account1 = await createTempUser(process.env.DCC_NEW_TMP_EMAIL);
|
||||||
if (!account || !account.email || !account.password) {
|
if (!account1 || !account1.email || !account1.password) {
|
||||||
console.log(
|
console.log(
|
||||||
"We didn't got back an account from the api, skip intergration tests"
|
"We didn't got back an account from the api, skip intergration tests"
|
||||||
);
|
);
|
||||||
@@ -47,6 +46,7 @@ describe("online tests", function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
account2 = await createTempUser(process.env.DCC_NEW_TMP_EMAIL);
|
account2 = await createTempUser(process.env.DCC_NEW_TMP_EMAIL);
|
||||||
|
console.log({ account: account1, account2 })
|
||||||
if (!account2 || !account2.email || !account2.password) {
|
if (!account2 || !account2.email || !account2.password) {
|
||||||
console.log(
|
console.log(
|
||||||
"We didn't got back an account2 from the api, skip intergration tests"
|
"We didn't got back an account2 from the api, skip intergration tests"
|
||||||
@@ -57,108 +57,109 @@ describe("online tests", function () {
|
|||||||
|
|
||||||
after(async () => {
|
after(async () => {
|
||||||
dc && dc.close();
|
dc && dc.close();
|
||||||
server_handle && (await server_handle.close());
|
serverHandle && (await serverHandle.close());
|
||||||
});
|
});
|
||||||
|
|
||||||
let are_configured = false;
|
let accountsConfigured = false;
|
||||||
|
|
||||||
it("configure test accounts", async function () {
|
it("configure test accounts", async function () {
|
||||||
this.timeout(20000);
|
this.timeout(20000);
|
||||||
|
|
||||||
acc1 = await dc.rpc.addAccount();
|
accountId1 = await dc.rpc.addAccount();
|
||||||
await dc.rpc.setConfig(acc1, "addr", account.email);
|
await dc.rpc.setConfig(accountId1, "addr", account1.email);
|
||||||
await dc.rpc.setConfig(acc1, "mail_pw", account.password);
|
await dc.rpc.setConfig(accountId1, "mail_pw", account1.password);
|
||||||
let configure_promise = dc.rpc.configure(acc1);
|
console.log('config set')
|
||||||
|
await dc.rpc.configure(accountId1);
|
||||||
|
console.log('account configured')
|
||||||
|
|
||||||
acc2 = await dc.rpc.addAccount();
|
accountId2 = await dc.rpc.addAccount();
|
||||||
await dc.rpc.batchSetConfig(acc2, {
|
await dc.rpc.batchSetConfig(accountId2, {
|
||||||
addr: account2.email,
|
addr: account2.email,
|
||||||
mail_pw: account2.password,
|
mail_pw: account2.password,
|
||||||
});
|
});
|
||||||
|
await dc.rpc.configure(accountId2)
|
||||||
await Promise.all([configure_promise, dc.rpc.configure(acc2)]);
|
accountsConfigured = true;
|
||||||
are_configured = true;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("send and recieve text message", async function () {
|
it("send and recieve text message", async function () {
|
||||||
if (!are_configured) {
|
if (!accountsConfigured) {
|
||||||
this.skip();
|
this.skip();
|
||||||
}
|
}
|
||||||
this.timeout(15000);
|
this.timeout(15000);
|
||||||
|
|
||||||
const contactId = await dc.rpc.contactsCreateContact(
|
const contactId = await dc.rpc.contactsCreateContact(
|
||||||
acc1,
|
accountId1,
|
||||||
account2.email,
|
account2.email,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
const chatId = await dc.rpc.contactsCreateChatByContactId(acc1, contactId);
|
const chatId = await dc.rpc.contactsCreateChatByContactId(accountId1, contactId);
|
||||||
const eventPromise = Promise.race([
|
const eventPromise = Promise.race([
|
||||||
waitForEvent(dc, "MsgsChanged", acc2),
|
waitForEvent(dc, "MsgsChanged", accountId2),
|
||||||
waitForEvent(dc, "IncomingMsg", acc2),
|
waitForEvent(dc, "IncomingMsg", accountId2),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
dc.rpc.miscSendTextMessage(acc1, "Hello", chatId);
|
await dc.rpc.miscSendTextMessage(accountId1, "Hello", chatId);
|
||||||
const { field1: chatIdOnAccountB } = await eventPromise;
|
const { field1: chatIdOnAccountB } = await eventPromise;
|
||||||
await dc.rpc.acceptChat(acc2, chatIdOnAccountB);
|
await dc.rpc.acceptChat(accountId2, chatIdOnAccountB);
|
||||||
const messageList = await dc.rpc.messageListGetMessageIds(
|
const messageList = await dc.rpc.messageListGetMessageIds(
|
||||||
acc2,
|
accountId2,
|
||||||
chatIdOnAccountB,
|
chatIdOnAccountB,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(messageList).have.length(1);
|
expect(messageList).have.length(1);
|
||||||
const message = await dc.rpc.messageGetMessage(acc2, messageList[0]);
|
const message = await dc.rpc.messageGetMessage(accountId2, messageList[0]);
|
||||||
expect(message.text).equal("Hello");
|
expect(message.text).equal("Hello");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("send and recieve text message roundtrip, encrypted on answer onwards", async function () {
|
it("send and recieve text message roundtrip, encrypted on answer onwards", async function () {
|
||||||
if (!are_configured) {
|
if (!accountsConfigured) {
|
||||||
this.skip();
|
this.skip();
|
||||||
}
|
}
|
||||||
this.timeout(10000);
|
this.timeout(10000);
|
||||||
|
|
||||||
// send message from A to B
|
// send message from A to B
|
||||||
const contactId = await dc.rpc.contactsCreateContact(
|
const contactId = await dc.rpc.contactsCreateContact(
|
||||||
acc1,
|
accountId1,
|
||||||
account2.email,
|
account2.email,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
const chatId = await dc.rpc.contactsCreateChatByContactId(acc1, contactId);
|
const chatId = await dc.rpc.contactsCreateChatByContactId(accountId1, contactId);
|
||||||
const eventPromise = Promise.race([
|
const eventPromise = Promise.race([
|
||||||
waitForEvent(dc, "MsgsChanged", acc2),
|
waitForEvent(dc, "MsgsChanged", accountId2),
|
||||||
waitForEvent(dc, "IncomingMsg", acc2),
|
waitForEvent(dc, "IncomingMsg", accountId2),
|
||||||
]);
|
]);
|
||||||
dc.rpc.miscSendTextMessage(acc1, "Hello2", chatId);
|
dc.rpc.miscSendTextMessage(accountId1, "Hello2", chatId);
|
||||||
// wait for message from A
|
// wait for message from A
|
||||||
console.log("wait for message from A");
|
console.log("wait for message from A");
|
||||||
|
|
||||||
const event = await eventPromise;
|
const event = await eventPromise;
|
||||||
const { field1: chatIdOnAccountB } = event;
|
const { field1: chatIdOnAccountB } = event;
|
||||||
|
|
||||||
await dc.rpc.acceptChat(acc2, chatIdOnAccountB);
|
await dc.rpc.acceptChat(accountId2, chatIdOnAccountB);
|
||||||
const messageList = await dc.rpc.messageListGetMessageIds(
|
const messageList = await dc.rpc.messageListGetMessageIds(
|
||||||
acc2,
|
accountId2,
|
||||||
chatIdOnAccountB,
|
chatIdOnAccountB,
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
const message = await dc.rpc.messageGetMessage(
|
const message = await dc.rpc.messageGetMessage(
|
||||||
acc2,
|
accountId2,
|
||||||
messageList.reverse()[0]
|
messageList.reverse()[0]
|
||||||
);
|
);
|
||||||
expect(message.text).equal("Hello2");
|
expect(message.text).equal("Hello2");
|
||||||
// Send message back from B to A
|
// Send message back from B to A
|
||||||
const eventPromise2 = Promise.race([
|
const eventPromise2 = Promise.race([
|
||||||
waitForEvent(dc, "MsgsChanged", acc1),
|
waitForEvent(dc, "MsgsChanged", accountId1),
|
||||||
waitForEvent(dc, "IncomingMsg", acc1),
|
waitForEvent(dc, "IncomingMsg", accountId1),
|
||||||
]);
|
]);
|
||||||
dc.rpc.miscSendTextMessage(acc2, "super secret message", chatId);
|
dc.rpc.miscSendTextMessage(accountId2, "super secret message", chatId);
|
||||||
// Check if answer arives at A and if it is encrypted
|
// Check if answer arives at A and if it is encrypted
|
||||||
await eventPromise2;
|
await eventPromise2;
|
||||||
|
|
||||||
const messageId = (
|
const messageId = (
|
||||||
await dc.rpc.messageListGetMessageIds(acc1, chatId, 0)
|
await dc.rpc.messageListGetMessageIds(accountId1, chatId, 0)
|
||||||
).reverse()[0];
|
).reverse()[0];
|
||||||
const message2 = await dc.rpc.messageGetMessage(acc1, messageId);
|
const message2 = await dc.rpc.messageGetMessage(accountId1, messageId);
|
||||||
expect(message2.text).equal("super secret message");
|
expect(message2.text).equal("super secret message");
|
||||||
expect(message2.show_padlock).equal(true);
|
expect(message2.show_padlock).equal(true);
|
||||||
});
|
});
|
||||||
@@ -181,23 +182,24 @@ describe("online tests", function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
type event_data = {
|
|
||||||
contextId: number;
|
|
||||||
id: EventTypeName;
|
|
||||||
[key: string]: any;
|
|
||||||
};
|
|
||||||
async function waitForEvent(
|
async function waitForEvent(
|
||||||
dc: Deltachat,
|
dc: Deltachat,
|
||||||
event: EventTypeName,
|
eventType: EventTypeName,
|
||||||
accountId: number
|
accountId: number,
|
||||||
): Promise<event_data> {
|
timeout: number = EVENT_TIMEOUT
|
||||||
return new Promise((res, rej) => {
|
): Promise<DeltachatEvent> {
|
||||||
const callback = (ev: DeltachatEvent) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (ev.contextId == accountId) {
|
const rejectTimeout = setTimeout(
|
||||||
dc.off(event, callback);
|
() => reject(new Error('Timeout reached before event came in')),
|
||||||
res(ev);
|
timeout
|
||||||
|
)
|
||||||
|
const callback = (event: DeltachatEvent) => {
|
||||||
|
if (event.contextId == accountId) {
|
||||||
|
dc.off(eventType, callback);
|
||||||
|
clearTimeout(rejectTimeout)
|
||||||
|
resolve(event);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
dc.on(event, callback);
|
dc.on(eventType, callback);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,90 @@
|
|||||||
import { tmpdir } from "os";
|
import { tmpdir } from "os";
|
||||||
import { join } from "path";
|
import { join, resolve } from "path";
|
||||||
import { mkdtemp, rm } from "fs/promises";
|
import { mkdtemp, rm } from "fs/promises";
|
||||||
import { existsSync } from "fs";
|
import { existsSync } from "fs";
|
||||||
import { spawn, exec } from "child_process";
|
import { spawn, exec } from "child_process";
|
||||||
import { unwrapPromise } from "./ts_helpers.js";
|
|
||||||
import fetch from "node-fetch";
|
import fetch from "node-fetch";
|
||||||
/* port is not configurable yet */
|
|
||||||
|
|
||||||
|
export const RPC_SERVER_PORT = 20808;
|
||||||
|
|
||||||
|
export type RpcServerHandle = {
|
||||||
|
url: string,
|
||||||
|
close: () => Promise<void>
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function startServer(port: number = RPC_SERVER_PORT): Promise<RpcServerHandle> {
|
||||||
|
const tmpDir = await mkdtemp(join(tmpdir(), "deltachat-jsonrpc-test"));
|
||||||
|
|
||||||
|
const pathToServerBinary = resolve(join(await getTargetDir(), "debug/deltachat-jsonrpc-server"));
|
||||||
|
console.log('using server binary: ' + pathToServerBinary);
|
||||||
|
|
||||||
|
if (!existsSync(pathToServerBinary)) {
|
||||||
|
throw new Error(
|
||||||
|
"server executable does not exist, you need to build it first" +
|
||||||
|
"\nserver executable not found at " +
|
||||||
|
pathToServerBinary
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const server = spawn(pathToServerBinary, {
|
||||||
|
cwd: tmpDir,
|
||||||
|
env: {
|
||||||
|
RUST_LOG: process.env.RUST_LOG || "info",
|
||||||
|
DC_PORT: '' + port
|
||||||
|
},
|
||||||
|
});
|
||||||
|
let shouldClose = false;
|
||||||
|
|
||||||
|
server.on("exit", () => {
|
||||||
|
if (shouldClose) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new Error("Server quit");
|
||||||
|
});
|
||||||
|
|
||||||
|
server.stderr.pipe(process.stderr);
|
||||||
|
server.stdout.pipe(process.stdout)
|
||||||
|
|
||||||
|
const url = `ws://localhost:${port}/ws`
|
||||||
|
|
||||||
|
return {
|
||||||
|
url,
|
||||||
|
close: async () => {
|
||||||
|
shouldClose = true;
|
||||||
|
if (!server.kill()) {
|
||||||
|
console.log("server termination failed");
|
||||||
|
}
|
||||||
|
await rm(tmpDir, { recursive: true });
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function createTempUser(url: string) {
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"cache-control": "no-cache",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!response.ok) throw new Error('Received invalid response')
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
|
||||||
function getTargetDir(): Promise<string> {
|
function getTargetDir(): Promise<string> {
|
||||||
return new Promise((res, rej) => {
|
return new Promise((resolve, reject) => {
|
||||||
exec(
|
exec(
|
||||||
"cargo metadata --no-deps --format-version 1",
|
"cargo metadata --no-deps --format-version 1",
|
||||||
(error, stdout, stderr) => {
|
(error, stdout, _stderr) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
console.log("error", error);
|
console.log("error", error);
|
||||||
rej(error);
|
reject(error);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
const json = JSON.parse(stdout);
|
const json = JSON.parse(stdout);
|
||||||
res(json.target_directory);
|
resolve(json.target_directory);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("json error", error);
|
console.log("json error", error);
|
||||||
rej(error);
|
reject(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -30,66 +92,3 @@ function getTargetDir(): Promise<string> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CMD_API_SERVER_PORT = 20808;
|
|
||||||
export async function startCMD_API_Server(port: typeof CMD_API_SERVER_PORT) {
|
|
||||||
const tmp_dir = await mkdtemp(join(tmpdir(), "test_prefix"));
|
|
||||||
|
|
||||||
const path_of_server = join(await getTargetDir(), "debug/webserver");
|
|
||||||
console.log(path_of_server);
|
|
||||||
|
|
||||||
if (!existsSync(path_of_server)) {
|
|
||||||
throw new Error(
|
|
||||||
"server executable does not exist, you need to build it first" +
|
|
||||||
"\nserver executable not found at " +
|
|
||||||
path_of_server
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const server = spawn(path_of_server, {
|
|
||||||
cwd: tmp_dir,
|
|
||||||
env: {
|
|
||||||
RUST_LOG: "info",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
let should_close = false;
|
|
||||||
|
|
||||||
server.on("exit", () => {
|
|
||||||
if (should_close) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw new Error("Server quit");
|
|
||||||
});
|
|
||||||
|
|
||||||
server.stderr.pipe(process.stderr);
|
|
||||||
|
|
||||||
//server.stdout.pipe(process.stdout)
|
|
||||||
|
|
||||||
return {
|
|
||||||
close: async () => {
|
|
||||||
should_close = true;
|
|
||||||
if (!server.kill(9)) {
|
|
||||||
console.log("server termination failed");
|
|
||||||
}
|
|
||||||
await rm(tmp_dir, { recursive: true });
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export type CMD_API_Server_Handle = unwrapPromise<
|
|
||||||
ReturnType<typeof startCMD_API_Server>
|
|
||||||
>;
|
|
||||||
|
|
||||||
export async function createTempUser(url: string) {
|
|
||||||
async function postData(url = "") {
|
|
||||||
// Default options are marked with *
|
|
||||||
const response = await fetch(url, {
|
|
||||||
method: "POST", // *GET, POST, PUT, DELETE, etc.
|
|
||||||
headers: {
|
|
||||||
"cache-control": "no-cache",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return response.json(); // parses JSON response into native JavaScript objects
|
|
||||||
}
|
|
||||||
|
|
||||||
return await postData(url);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
export type unwrapPromise<T> = T extends Promise<infer U> ? U : never;
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"rootDir": ".",
|
|
||||||
"outDir": "../test_dist",
|
|
||||||
"target": "ES2020",
|
|
||||||
"module": "es2020",
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"declaration": false,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"noImplicitAny": true,
|
|
||||||
"isolatedModules": true,
|
|
||||||
"strictNullChecks": true,
|
|
||||||
"strict": true,
|
|
||||||
"sourceMap": true
|
|
||||||
},
|
|
||||||
"compileOnSave": true
|
|
||||||
}
|
|
||||||
@@ -8,13 +8,13 @@
|
|||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"lib": ["ES2017", "dom"],
|
"lib": ["ES2017", "dom"],
|
||||||
"target": "ES2017",
|
"target": "ES2017",
|
||||||
"module": "es2015",
|
"module": "es2020",
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"noImplicitAny": true,
|
"noImplicitAny": true,
|
||||||
"isolatedModules": true
|
"isolatedModules": true
|
||||||
},
|
},
|
||||||
"include": ["*.ts", "example/*.ts"],
|
"include": ["*.ts", "example/*.ts", "test/*.ts"],
|
||||||
"compileOnSave": false
|
"compileOnSave": false
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user