koishi-test-utils
Version:
Test utilities for Koishi
807 lines (797 loc) • 31.3 kB
JavaScript
var __create = Object.create;
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
var __export = (target, all) => {
__markAsModule(target);
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __reExport = (target, module2, desc) => {
if (module2 && typeof module2 === "object" || typeof module2 === "function") {
for (let key of __getOwnPropNames(module2))
if (!__hasOwnProp.call(target, key) && key !== "default")
__defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
}
return target;
};
var __toModule = (module2) => {
return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
};
// packages/koishi-test-utils/src/index.ts
__export(exports, {
App: () => MockedApp,
BASE_SELF_ID: () => BASE_SELF_ID,
MockedApp: () => MockedApp,
TestSession: () => TestSession,
Tests: () => Tests,
createArray: () => createArray,
default: () => src_default
});
// packages/koishi-test-utils/src/memory.ts
var memory_exports = {};
__export(memory_exports, {
MemoryDatabase: () => MemoryDatabase,
apply: () => apply
});
var import_koishi_core = __toModule(require("koishi-core"));
var import_koishi_utils = __toModule(require("koishi-utils"));
var MemoryDatabase = class {
constructor(app, config) {
this.app = app;
this.config = config;
this.$store = {};
this.memory = this;
}
$table(table) {
var _a;
return (_a = this.$store)[table] || (_a[table] = []);
}
$count(table, field = "id") {
return new Set(this.$table(table).map((data) => data[field])).size;
}
};
MemoryDatabase.tables = {};
var queryOperators = {
$eq: (query, data) => data.valueOf() === query.valueOf(),
$ne: (query, data) => data.valueOf() !== query.valueOf(),
$gt: (query, data) => data.valueOf() > query.valueOf(),
$gte: (query, data) => data.valueOf() >= query.valueOf(),
$lt: (query, data) => data.valueOf() < query.valueOf(),
$lte: (query, data) => data.valueOf() <= query.valueOf(),
$in: (query, data) => query.includes(data),
$nin: (query, data) => !query.includes(data),
$regex: (query, data) => query.test(data),
$regexFor: (query, data) => new RegExp(data, "i").test(query),
$bitsAllSet: (query, data) => (query & data) === query,
$bitsAllClear: (query, data) => (query & data) === 0,
$bitsAnySet: (query, data) => (query & data) !== 0,
$bitsAnyClear: (query, data) => (query & data) !== query,
$el: (query, data) => data.some((item) => executeFieldQuery(query, item)),
$size: (query, data) => data.length === query
};
var evalOperators = {
$add: (args, data) => args.reduce((prev, curr) => prev + executeEval(curr, data), 0),
$multiply: (args, data) => args.reduce((prev, curr) => prev * executeEval(curr, data), 1),
$subtract: ([left, right], data) => executeEval(left, data) - executeEval(right, data),
$divide: ([left, right], data) => executeEval(left, data) - executeEval(right, data),
$eq: ([left, right], data) => executeEval(left, data).valueOf() === executeEval(right, data).valueOf(),
$ne: ([left, right], data) => executeEval(left, data).valueOf() !== executeEval(right, data).valueOf(),
$gt: ([left, right], data) => executeEval(left, data).valueOf() > executeEval(right, data).valueOf(),
$gte: ([left, right], data) => executeEval(left, data).valueOf() >= executeEval(right, data).valueOf(),
$lt: ([left, right], data) => executeEval(left, data).valueOf() < executeEval(right, data).valueOf(),
$lte: ([left, right], data) => executeEval(left, data).valueOf() <= executeEval(right, data).valueOf(),
$sum: (expr, table) => table.reduce((prev, curr) => prev + executeEval(expr, curr), 0),
$avg: (expr, table) => table.reduce((prev, curr) => prev + executeEval(expr, curr), 0) / table.length,
$min: (expr, table) => Math.min(...table.map((data) => executeEval(expr, data))),
$max: (expr, table) => Math.max(...table.map((data) => executeEval(expr, data))),
$count: (expr, table) => new Set(table.map((data) => executeEval(expr, data))).size
};
function executeFieldQuery(query, data) {
if (Array.isArray(query)) {
return query.includes(data);
} else if (query instanceof RegExp) {
return query.test(data);
} else if (typeof query === "string" || typeof query === "number" || query instanceof Date) {
return data.valueOf() === query.valueOf();
}
for (const key in queryOperators) {
const value = query[key];
if (value === void 0)
continue;
if (!queryOperators[key](value, data))
return false;
}
return true;
}
function executeQuery(query, data) {
const entries = Object.entries(query);
return entries.every(([key, value]) => {
if (key === "$and") {
return value.reduce((prev, query2) => prev && executeQuery(query2, data), true);
} else if (key === "$or") {
return value.reduce((prev, query2) => prev || executeQuery(query2, data), false);
} else if (key === "$not") {
return !executeQuery(value, data);
} else if (key === "$expr") {
return executeEval(value, data);
}
try {
if (!(key in data))
return false;
return executeFieldQuery(value, data[key]);
} catch {
return false;
}
});
}
function executeEval(expr, data) {
if (typeof expr === "string") {
return data[expr];
} else if (typeof expr === "number" || typeof expr === "boolean") {
return expr;
}
for (const key in expr) {
if (key in evalOperators) {
return evalOperators[key](expr[key], data);
}
}
}
import_koishi_core.Database.extend(MemoryDatabase, {
async drop(name) {
if (name) {
delete this.$store[name];
} else {
this.$store = {};
}
},
async get(name, query, modifier) {
const expr = import_koishi_core.Query.resolve(name, query);
const { fields, limit = Infinity, offset = 0 } = import_koishi_core.Query.resolveModifier(modifier);
return this.$table(name).filter((row) => executeQuery(expr, row)).map((row) => (0, import_koishi_utils.clone)((0, import_koishi_utils.pick)(row, fields))).slice(offset, offset + limit);
},
async remove(name, query) {
const entries = Object.entries(import_koishi_core.Query.resolve(name, query));
this.$store[name] = this.$table(name).filter((row) => !entries.every(([key, value]) => value.includes(row[key])));
},
async create(table, data) {
const store = this.$table(table);
const { primary = "id" } = MemoryDatabase.tables[table] || {};
if (!data[primary]) {
const max = store.length ? Math.max(...store.map((row) => +row[primary])) : 0;
data[primary] = max + 1;
}
store.push(data);
return data;
},
async update(table, data, key) {
if (key)
key = (MemoryDatabase.tables[table] || {}).primary || "id";
for (const item of data) {
const row = this.$table(table).find((row2) => row2[key] === item[key]);
Object.assign(row, (0, import_koishi_utils.clone)(item));
}
},
async aggregate(name, fields, query) {
const expr = import_koishi_core.Query.resolve(name, query);
const table = this.$table(name).filter((row) => executeQuery(expr, row));
return Object.fromEntries(Object.entries(fields).map(([key, expr2]) => [key, executeEval(expr2, table)]));
},
async getUser(type, id, fields) {
if (Array.isArray(id)) {
return this.get("user", { [type]: id }, fields);
} else {
return (await this.get("user", { [type]: [id] }, fields))[0];
}
},
async setUser(type, id, data) {
const table = this.$table("user");
const index = table.findIndex((row) => row[type] === id);
if (index < 0)
return;
Object.assign(table[index], (0, import_koishi_utils.clone)(data));
},
async createUser(type, id, data) {
const table = this.$table("user");
const index = table.findIndex((row) => row[type] === id);
if (index >= 0)
return;
const user = await this.create("user", __spreadValues(__spreadValues({}, import_koishi_core.User.create(type, id)), (0, import_koishi_utils.clone)(data)));
user.id = "" + user.id;
},
async getChannel(type, id, fields) {
if (Array.isArray(id)) {
return this.get("channel", id.map((id2) => `${type}:${id2}`), fields);
} else {
return (await this.get("channel", [`${type}:${id}`], fields))[0];
}
},
async getAssignedChannels(fields, assignMap = this.app.getSelfIds()) {
return this.$table("channel").filter((row) => {
var _a;
const [type] = row.id.split(":");
return (_a = assignMap[type]) == null ? void 0 : _a.includes(row.assignee);
}).map((row) => (0, import_koishi_utils.clone)((0, import_koishi_utils.pick)(row, fields)));
},
async setChannel(type, id, data) {
const table = this.$table("channel");
const index = table.findIndex((row) => row.id === `${type}:${id}`);
if (index < 0)
return;
Object.assign(table[index], (0, import_koishi_utils.clone)(data));
},
async createChannel(type, id, data) {
const table = this.$table("channel");
const index = table.findIndex((row) => row.id === `${type}:${id}`);
if (index >= 0)
return;
table.push(__spreadValues(__spreadValues({}, import_koishi_core.Channel.create(type, id)), (0, import_koishi_utils.clone)(data)));
}
});
function apply(app, config = {}) {
app.database = new MemoryDatabase(app, config);
}
// packages/koishi-test-utils/src/app.ts
var import_koishi_core2 = __toModule(require("koishi-core"));
var import_chai = __toModule(require("chai"));
var import_net = __toModule(require("net"));
var import_util = __toModule(require("util"));
var http = __toModule(require("http"));
var import_koishi_utils2 = __toModule(require("koishi-utils"));
var BASE_SELF_ID = "514";
var MockedBot = class extends import_koishi_core2.Bot {
constructor() {
super(...arguments);
this.status = import_koishi_core2.Bot.Status.GOOD;
}
async getMessage(channelId, messageId) {
return {
messageId,
channelId,
content: "",
time: 0,
subtype: null,
messageType: null,
author: { userId: this.selfId }
};
}
};
var MockedServer = class extends import_koishi_core2.Adapter {
constructor(app) {
super(app, MockedBot);
}
stop() {
}
async start() {
}
get(path, headers) {
return this.receive("GET", path, headers, "");
}
post(path, body, headers) {
return this.receive("POST", path, __spreadProps(__spreadValues({}, headers), {
"content-type": "application/json"
}), JSON.stringify(body));
}
receive(method, path, headers, content) {
const socket = new import_net.Socket();
const req = new http.IncomingMessage(socket);
req.url = path;
req.method = method;
Object.assign(req.headers, headers);
req.headers["content-length"] = "" + content.length;
return new Promise((resolve) => {
const res = new http.ServerResponse(req);
let body = "";
res.write = (chunk) => {
body += chunk;
return true;
};
res.end = (chunk) => {
res.write(chunk);
const code = res.statusCode;
const headers2 = res.getHeaders();
resolve({ code, body, headers: headers2 });
};
this.app._httpServer.emit("request", req, res);
req.emit("data", content);
req.emit("end");
});
}
};
import_koishi_core2.Adapter.types.mock = MockedServer;
var MockedApp = class extends import_koishi_core2.App {
constructor(options = {}) {
super(__spreadValues({
type: "mock",
selfId: BASE_SELF_ID,
channelCacheAge: Number.EPSILON,
userCacheAge: Number.EPSILON
}, options));
this.server = this.adapters.mock;
if (options.mockStart !== false)
this.status = import_koishi_core2.App.Status.open;
if (options.mockDatabase)
this.plugin(memory_exports);
}
get selfId() {
return this.bots[0].selfId;
}
receive(meta) {
const session = new import_koishi_core2.Session(this, meta);
this.adapters.mock.dispatch(session);
return session.id;
}
session(userId, channelId) {
return new TestSession(this, userId, channelId);
}
async initUser(id, authority = 1) {
await this.database.createUser("mock", id, { authority });
}
async initChannel(id, assignee = this.selfId) {
await this.database.createChannel("mock", id, { assignee });
}
};
var TestSession = class {
constructor(app, userId, channelId) {
this.app = app;
this.userId = userId;
this.channelId = channelId;
this.replies = [];
this.meta = {
platform: "mock",
type: "message",
selfId: app.selfId,
userId,
author: {
userId,
username: "" + userId
}
};
if (channelId) {
this.meta.groupId = channelId;
this.meta.channelId = channelId;
this.meta.subtype = "group";
} else {
this.meta.channelId = "private:" + userId;
this.meta.subtype = "private";
}
}
async receive(content, count) {
return new Promise((resolve) => {
let resolved = false;
const _resolve = () => {
if (resolved)
return;
resolved = true;
dispose();
resolve(this.replies);
this.replies = [];
};
const send = async (content2) => {
if (!content2)
return;
const session = this.app.bots[0].createSession((0, import_koishi_utils2.pick)(this.meta, ["userId", "channelId", "groupId"]));
session.content = content2;
this.app.emit(session, "before-send", session);
const length = this.replies.push(content2);
if (length >= count)
_resolve();
};
const dispose = this.app.on("middleware", (session) => {
if (session.id === uuid)
process.nextTick(_resolve);
});
const uuid = this.app.receive(__spreadProps(__spreadValues({}, this.meta), { send, content }));
});
}
async shouldReply(message, reply) {
if (!reply) {
const result2 = await this.receive(message);
return import_chai.assert.ok(result2.length, (0, import_util.format)(RECEIVED_NOTHING, message));
}
if (!Array.isArray(reply))
reply = [reply];
const result = await this.receive(message, reply.length);
for (const index in reply) {
const expected = reply[index];
const actual = result[index];
import_chai.assert.ok(actual, (0, import_util.format)(RECEIVED_NOTHING, message));
if (typeof expected === "string") {
import_chai.assert.strictEqual(actual, expected, (0, import_util.format)(RECEIVED_OTHERWISE, message, `"${expected}"`, actual));
} else {
import_chai.assert.match(actual, expected, (0, import_util.format)(RECEIVED_OTHERWISE, message, expected.toString(), actual));
}
}
}
async shouldNotReply(message) {
const result = await this.receive(message);
import_chai.assert.ok(!result.length, `expected "${message}" to have no reply but received "${result[0]}"`);
}
};
var RECEIVED_NOTHING = 'expected "%s" to be replied but received nothing';
var RECEIVED_OTHERWISE = 'expected "%s" to be replied with %s but received "%s"';
// packages/koishi-test-utils/src/tests/builtin.ts
var import_koishi_core3 = __toModule(require("koishi-core"));
var import_chai3 = __toModule(require("chai"));
// packages/koishi-test-utils/chai/src/index.ts
var import_chai2 = __toModule(require("chai"));
var import_util2 = __toModule(require("util"));
(0, import_chai2.use)(({ Assertion }) => {
function checkShape(expect3, actual, path) {
if (actual === expect3 || Number.isNaN(expect3) && Number.isNaN(actual))
return;
function formatError(expect4, actual2) {
return `expected to have ${expect4} but got ${actual2} at path ${path}`;
}
if (!expect3 || ["string", "number", "boolean", "bigint"].includes(typeof expect3)) {
return formatError((0, import_util2.inspect)(expect3), (0, import_util2.inspect)(actual));
}
if (expect3 instanceof Date) {
if (!(actual instanceof Date) || +expect3 !== +actual) {
return formatError((0, import_util2.inspect)(expect3), (0, import_util2.inspect)(actual));
}
return;
}
if (actual === null) {
const type = Object.prototype.toString.call(expect3).slice(8, -1).toLowerCase();
return formatError(`a ${type}`, "null");
}
for (const prop in expect3) {
if (typeof actual[prop] === "undefined" && typeof expect3[prop] !== "undefined") {
return `expected "${prop}" field to be defined at path ${path}`;
}
const message = checkShape(expect3[prop], actual[prop], `${path}${prop}/`);
if (message)
return message;
}
}
Assertion.addMethod("shape", function(expect3) {
const message = checkShape(expect3, this._obj, "/");
if (message)
this.assert(false, message, void 0, expect3, this._obj);
});
});
(0, import_chai2.use)(require("chai-as-promised"));
// packages/koishi-test-utils/src/tests/builtin.ts
function BuiltinMethods(app) {
const { database: db } = app;
it("user operations", async () => {
await db.setUser("mock", "A", import_koishi_core3.User.create("mock", "A"));
await (0, import_chai3.expect)(db.getUser("mock", "A")).eventually.not.to.be.ok;
await db.createUser("mock", "A", { authority: 1 });
await (0, import_chai3.expect)(db.getUser("mock", "A")).eventually.to.have.shape({ authority: 1 });
await db.setUser("mock", "A", { authority: 2 });
await (0, import_chai3.expect)(db.getUser("mock", "A")).eventually.to.have.shape({ authority: 2 });
await db.remove("user", { mock: ["A"] });
await (0, import_chai3.expect)(db.getUser("mock", ["A"])).eventually.to.deep.equal([]);
});
it("channel operations", async () => {
await db.setChannel("mock", "A", import_koishi_core3.Channel.create("mock", "A"));
await (0, import_chai3.expect)(db.getChannel("mock", "A")).eventually.not.to.be.ok;
await db.createChannel("mock", "A", { assignee: "123" });
await (0, import_chai3.expect)(db.getChannel("mock", "A")).eventually.to.have.shape({ assignee: "123" });
await db.setChannel("mock", "A", { assignee: "321" });
await (0, import_chai3.expect)(db.getChannel("mock", "A")).eventually.to.have.shape({ assignee: "321" });
await db.createChannel("mock", "B", { assignee: app.bots[0].selfId });
await db.createChannel("mock", "C", { assignee: app.bots[0].selfId });
await (0, import_chai3.expect)(db.getAssignedChannels(null)).eventually.to.have.length(2);
await (0, import_chai3.expect)(db.getAssignedChannels(null, { mock: ["321"] })).eventually.to.have.length(1);
await db.remove("channel", { id: ["mock:A"] });
await (0, import_chai3.expect)(db.getChannel("mock", ["A"])).eventually.to.deep.equal([]);
});
}
// packages/koishi-test-utils/src/tests/query.ts
var import_koishi_core4 = __toModule(require("koishi-core"));
var import_chai5 = __toModule(require("chai"));
import_koishi_core4.Tables.extend("foo", {
type: "incremental",
fields: {
id: "unsigned",
text: "string",
value: "integer",
list: "list",
date: "timestamp"
}
});
var QueryOperators;
(function(QueryOperators2) {
QueryOperators2.name = "QueryOperators";
QueryOperators2.comparison = function Comparison(app) {
const db = app.database;
before(async () => {
await db.remove("foo", {});
await db.create("foo", { text: "awesome foo", date: new Date("2000-01-01") });
await db.create("foo", { text: "awesome bar" });
await db.create("foo", { text: "awesome baz" });
});
it("compile expr query", async () => {
await (0, import_chai5.expect)(db.get("foo", {
id: { $eq: 2 }
})).eventually.to.have.length(1).with.nested.property("0.text").equal("awesome bar");
await (0, import_chai5.expect)(db.get("foo", {
id: { $ne: 3 }
})).eventually.to.have.length(2).with.nested.property("0.text").equal("awesome foo");
await (0, import_chai5.expect)(db.get("foo", {
id: { $gt: 1 }
})).eventually.to.have.length(2).with.nested.property("1.text").equal("awesome baz");
await (0, import_chai5.expect)(db.get("foo", {
id: { $gte: 3 }
})).eventually.to.have.length(1).with.nested.property("0.text").equal("awesome baz");
await (0, import_chai5.expect)(db.get("foo", {
id: { $lt: 1 }
})).eventually.to.have.length(0);
await (0, import_chai5.expect)(db.get("foo", {
id: { $lte: 2 }
})).eventually.to.have.length(2).with.nested.property("0.text").equal("awesome foo");
});
it("date comparisons", async () => {
await (0, import_chai5.expect)(db.get("foo", {
date: { $gt: new Date("1999-01-01") }
})).eventually.to.have.length(1).with.nested.property("0.text").equal("awesome foo");
await (0, import_chai5.expect)(db.get("foo", {
date: { $lte: new Date("1999-01-01") }
})).eventually.to.have.length(0);
});
it("shorthand syntax", async () => {
await (0, import_chai5.expect)(db.get("foo", {
id: 2
})).eventually.to.have.length(1).with.nested.property("0.text").equal("awesome bar");
await (0, import_chai5.expect)(db.get("foo", {
date: new Date("2000-01-01")
})).eventually.to.have.length(1).with.nested.property("0.text").equal("awesome foo");
});
};
QueryOperators2.membership = function Membership(app) {
const db = app.database;
before(async () => {
await db.remove("foo", {});
await db.create("foo", { value: 3 });
await db.create("foo", { value: 4 });
await db.create("foo", { value: 7 });
});
it("should verify empty array", async () => {
await (0, import_chai5.expect)(db.get("foo", {
value: { $in: [] }
})).eventually.to.have.length(0);
await (0, import_chai5.expect)(db.get("foo", {
value: { $nin: [] }
})).eventually.to.have.length(3);
});
it("filter data by include", async () => {
await (0, import_chai5.expect)(db.get("foo", {
value: { $in: [3, 4] }
})).eventually.to.have.length(2);
await (0, import_chai5.expect)(db.get("foo", {
value: { $nin: [4] }
})).eventually.to.have.length(2);
});
};
QueryOperators2.regexp = function RegularExpression(app) {
const db = app.database;
before(async () => {
await db.remove("foo", {});
await db.create("foo", { text: "awesome foo" });
await db.create("foo", { text: "awesome bar" });
await db.create("foo", { text: "awesome foo bar" });
});
it("filter data by regex", async () => {
await (0, import_chai5.expect)(db.get("foo", {
text: /^.*foo$/
})).eventually.to.have.nested.property("[0].text").equal("awesome foo");
await (0, import_chai5.expect)(db.get("foo", {
text: { $regex: /^.*foo$/ }
})).eventually.to.have.nested.property("[0].text").equal("awesome foo");
await (0, import_chai5.expect)(db.get("foo", {
text: /^.*foo.*$/
})).eventually.to.have.length(2);
});
};
QueryOperators2.bitwise = function Bitwise(app) {
const db = app.database;
before(async () => {
await db.remove("foo", {});
await db.create("foo", { value: 3 });
await db.create("foo", { value: 4 });
await db.create("foo", { value: 7 });
});
it("filter data by bits", async () => {
await (0, import_chai5.expect)(db.get("foo", {
value: { $bitsAllSet: 3 }
})).eventually.to.have.shape([{ value: 3 }, { value: 7 }]);
await (0, import_chai5.expect)(db.get("foo", {
value: { $bitsAllClear: 9 }
})).eventually.to.have.shape([{ value: 4 }]);
await (0, import_chai5.expect)(db.get("foo", {
value: { $bitsAnySet: 4 }
})).eventually.to.have.shape([{ value: 4 }, { value: 7 }]);
await (0, import_chai5.expect)(db.get("foo", {
value: { $bitsAnyClear: 6 }
})).eventually.to.have.shape([{ value: 3 }, { value: 4 }]);
});
};
QueryOperators2.list = function List(app, options = {}) {
const db = app.database;
const { size = true, element = true, elementQuery = element } = options;
before(async () => {
await db.remove("foo", {});
await db.create("foo", { id: 1, list: [] });
await db.create("foo", { id: 2, list: [23] });
await db.create("foo", { id: 3, list: [233] });
await db.create("foo", { id: 4, list: [233, 332] });
});
size && it("$size", async () => {
await (0, import_chai5.expect)(db.get("foo", {
list: { $size: 1 }
})).eventually.to.have.length(2).with.shape([{ id: 2 }, { id: 3 }]);
});
element && it("$el shorthand", async () => {
await (0, import_chai5.expect)(db.get("foo", {
list: { $el: 233 }
})).eventually.to.have.length(2).with.shape([{ id: 3 }, { id: 4 }]);
});
elementQuery && it("$el with field query", async () => {
await (0, import_chai5.expect)(db.get("foo", {
list: { $el: { $lt: 50 } }
})).eventually.to.have.shape([{ id: 2 }]);
});
};
QueryOperators2.evaluation = function Evaluation(app) {
const db = app.database;
before(async () => {
await db.remove("foo", {});
await db.create("foo", { id: 1, value: 8 });
await db.create("foo", { id: 2, value: 7 });
await db.create("foo", { id: 3, value: 9 });
});
it("arithmetic operators", async () => {
await (0, import_chai5.expect)(db.get("foo", {
$expr: { $eq: [9, { $add: ["id", "value"] }] }
})).eventually.to.have.length(2).with.shape([{ id: 1 }, { id: 2 }]);
});
};
QueryOperators2.logical = function Logical(app) {
const db = app.database;
before(async () => {
await db.remove("foo", {});
await db.create("foo", { id: 1, text: "awesome foo", value: 3, list: [], date: new Date("2000-01-01") });
await db.create("foo", { id: 2, text: "awesome bar", value: 4, list: [1] });
await db.create("foo", { id: 3, text: "awesome foo bar", value: 7, list: [100] });
});
it("edge cases", async () => {
await (0, import_chai5.expect)(db.get("foo", {})).eventually.to.have.length(3);
await (0, import_chai5.expect)(db.get("foo", { $and: [] })).eventually.to.have.length(3);
await (0, import_chai5.expect)(db.get("foo", { $or: [] })).eventually.to.have.length(0);
await (0, import_chai5.expect)(db.get("foo", { $not: {} })).eventually.to.have.length(0);
await (0, import_chai5.expect)(db.get("foo", { $not: { $and: [] } })).eventually.to.have.length(0);
await (0, import_chai5.expect)(db.get("foo", { $not: { $or: [] } })).eventually.to.have.length(3);
});
it("should verify `$or`, `$and` and `$not`", async () => {
await (0, import_chai5.expect)(db.get("foo", {
$or: [{
id: [1, 2]
}, {
id: [1, 3]
}]
})).eventually.to.have.length(3);
await (0, import_chai5.expect)(db.get("foo", {
$or: [{
id: [2]
}, {
text: /.*foo.*/
}]
})).eventually.to.have.length(3);
await (0, import_chai5.expect)(db.get("foo", {
$or: [{
id: { $gt: 1 }
}, {
text: /.*foo$/
}]
})).eventually.to.have.length(3);
await (0, import_chai5.expect)(db.get("foo", {
$or: [{ text: /.*foo/ }, { text: /foo.*/ }]
})).eventually.to.have.length(2);
await (0, import_chai5.expect)(db.get("foo", {
$and: [{ text: /.*foo$/ }, { text: /foo.*/ }]
})).eventually.to.have.length(1);
await (0, import_chai5.expect)(db.get("foo", {
$not: { $and: [{ text: /.*foo$/ }, { text: /foo.*/ }] }
})).eventually.to.have.length(2);
await (0, import_chai5.expect)(db.get("foo", {
$not: { $or: [{ text: /.*foo/ }, { text: /foo.*/ }] }
})).eventually.to.have.length(1);
});
it("should verify `$or` and other key", async () => {
await (0, import_chai5.expect)(db.get("foo", {
text: /.*foo.*/,
$or: [{
text: /.*foo/
}]
})).eventually.to.have.length(2);
await (0, import_chai5.expect)(db.get("foo", {
text: /.*foo.*/,
$or: [{
text: /foo.+/
}]
})).eventually.to.have.length(1);
});
};
})(QueryOperators || (QueryOperators = {}));
var query_default = QueryOperators;
// packages/koishi-test-utils/src/tests/index.ts
var Tests;
(function(Tests2) {
const Keywords = ["name"];
function createUnit(target, root = false) {
const test = (app, options = {}) => {
function callback() {
if (typeof target === "function") {
target(app, options);
}
for (const key in target) {
if (options[key] === false || Keywords.includes(key))
continue;
test[key](app, options[key]);
}
}
const title = target["name"];
if (!root && title) {
describe(title.replace(/(?=[A-Z])/g, " ").trimStart(), callback);
} else {
callback();
}
};
for (const key in target) {
if (Keywords.includes(key))
continue;
test[key] = createUnit(target[key]);
}
return test;
}
function DatabaseTests(app) {
before(() => app.start());
after(async () => {
await app.database.drop();
await app.stop();
});
}
(function(DatabaseTests2) {
DatabaseTests2.builtin = BuiltinMethods;
DatabaseTests2.query = query_default;
})(DatabaseTests || (DatabaseTests = {}));
Tests2.database = createUnit(DatabaseTests, true);
})(Tests || (Tests = {}));
// packages/koishi-test-utils/src/index.ts
var src_default = MemoryDatabase;
function createArray(length, create) {
return [...new Array(length).keys()].map(create);
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
App,
BASE_SELF_ID,
MockedApp,
TestSession,
Tests,
createArray
});
//# sourceMappingURL=index.js.map