import { afterEach, beforeEach, describe, expect, it, vi } from
"vitest" ;
import { getMatrixScopedEnvVarNames } from
"../env-vars.js" ;
import type { CoreConfig } from
"../types.js" ;
import {
listMatrixAccountIds,
resolveConfiguredMatrixBotUserIds,
resolveDefaultMatrixAccountId,
resolveMatrixAccount,
} from
"./accounts.js" ;
import type { MatrixStoredCredentials } from
"./credentials-read.js" ;
const loadMatrixCredentialsMock = vi.hoisted(() =>
vi.fn<(env?: NodeJS.ProcessEnv, accountId?: string |
null ) => MatrixStoredCredentials |
null >(
() =>
null ,
),
);
vi.mock(
"./credentials-read.js" , () => ({
loadMatrixCredentials: (env?: NodeJS.ProcessEnv, accountId?: string |
null ) =>
loadMatrixCredentialsMock(env, accountId),
credentialsMatchConfig: () =>
false ,
}));
const envKeys = [
"MATRIX_HOMESERVER" ,
"MATRIX_USER_ID" ,
"MATRIX_ACCESS_TOKEN" ,
"MATRIX_PASSWORD" ,
"MATRIX_DEVICE_NAME" ,
"MATRIX_DEFAULT_HOMESERVER" ,
"MATRIX_DEFAULT_ACCESS_TOKEN" ,
getMatrixScopedEnvVarNames(
"team-ops" ).homeserver,
getMatrixScopedEnvVarNames(
"team-ops" ).accessToken,
];
type MatrixRoomScopeKey =
"groups" |
"rooms" ;
function createMatrixAccountConfig(accessToken: string) {
return {
homeserver:
"https://matrix.example.org ",
accessToken,
};
}
function createMatrixScopedEntriesConfig(scopeKey: MatrixRoomScopeKey): CoreConfig {
return {
channels: {
matrix: {
[scopeKey]: {
"!default-room:example.org" : {
enabled:
true ,
account:
"default" ,
},
"!axis-room:example.org" : {
enabled:
true ,
account:
"axis" ,
},
"!unassigned-room:example.org" : {
enabled:
true ,
},
},
accounts: {
default : createMatrixAccountConfig(
"default-token" ),
axis: createMatrixAccountConfig(
"axis-token" ),
},
},
},
} as unknown as CoreConfig;
}
function createMatrixTopLevelDefaultScopedEntriesConfig(scopeKey: MatrixRoomScopeK
ey): CoreConfig {
return {
channels: {
matrix: {
...createMatrixAccountConfig("default-token" ),
[scopeKey]: {
"!default-room:example.org" : {
enabled: true ,
account: "default" ,
},
"!ops-room:example.org" : {
enabled: true ,
account: "ops" ,
},
"!shared-room:example.org" : {
enabled: true ,
},
},
accounts: {
ops: createMatrixAccountConfig("ops-token" ),
},
},
},
} as unknown as CoreConfig;
}
function expectMatrixScopedEntries(
cfg: CoreConfig,
scopeKey: MatrixRoomScopeKey,
accountId: string,
expected: Record<string, { enabled: true ; account?: string }>,
): void {
expect(resolveMatrixAccount({ cfg, accountId }).config[scopeKey]).toEqual(expected);
}
function expectMultiAccountMatrixScopedEntries(
cfg: CoreConfig,
scopeKey: MatrixRoomScopeKey,
): void {
expectMatrixScopedEntries(cfg, scopeKey, "default" , {
"!default-room:example.org" : {
enabled: true ,
account: "default" ,
},
"!unassigned-room:example.org" : {
enabled: true ,
},
});
expectMatrixScopedEntries(cfg, scopeKey, "axis" , {
"!axis-room:example.org" : {
enabled: true ,
account: "axis" ,
},
"!unassigned-room:example.org" : {
enabled: true ,
},
});
}
function expectTopLevelDefaultMatrixScopedEntries(
cfg: CoreConfig,
scopeKey: MatrixRoomScopeKey,
): void {
expectMatrixScopedEntries(cfg, scopeKey, "default" , {
"!default-room:example.org" : {
enabled: true ,
account: "default" ,
},
"!shared-room:example.org" : {
enabled: true ,
},
});
expectMatrixScopedEntries(cfg, scopeKey, "ops" , {
"!ops-room:example.org" : {
enabled: true ,
account: "ops" ,
},
"!shared-room:example.org" : {
enabled: true ,
},
});
}
describe("resolveMatrixAccount" , () => {
let prevEnv: Record<string, string | undefined> = {};
beforeEach(() => {
loadMatrixCredentialsMock.mockReset().mockReturnValue(null );
prevEnv = {};
for (const key of envKeys) {
prevEnv[key] = process.env[key];
delete process.env[key];
}
});
afterEach(() => {
for (const key of envKeys) {
const value = prevEnv[key];
if (value === undefined) {
delete process.env[key];
} else {
process.env[key] = value;
}
}
});
it("treats access-token-only config as configured" , () => {
const cfg: CoreConfig = {
channels: {
matrix: {
homeserver: "https://matrix.example.org ",
accessToken: "tok-access" ,
},
},
};
const account = resolveMatrixAccount({ cfg });
expect(account.configured).toBe(true );
});
it("treats SecretRef access-token config as configured" , () => {
const cfg: CoreConfig = {
channels: {
matrix: {
homeserver: "https://matrix.example.org ",
accessToken: { source: "file" , provider: "matrix-file" , id: "value" },
},
},
secrets: {
providers: {
"matrix-file" : {
source: "file" ,
path: "/tmp/matrix-token" ,
},
},
},
};
const account = resolveMatrixAccount({ cfg });
expect(account.configured).toBe(true );
});
it("treats accounts.default SecretRef access-token config as configured" , () => {
const cfg: CoreConfig = {
channels: {
matrix: {
accounts: {
default : {
homeserver: "https://matrix.example.org ",
accessToken: { source: "file" , provider: "matrix-file" , id: "value" },
},
},
},
},
secrets: {
providers: {
"matrix-file" : {
source: "file" ,
path: "/tmp/matrix-token" ,
},
},
},
};
const account = resolveMatrixAccount({ cfg });
expect(account.configured).toBe(true );
});
it("treats accounts.default SecretRef password config as configured" , () => {
const cfg: CoreConfig = {
channels: {
matrix: {
accounts: {
default : {
homeserver: "https://matrix.example.org ",
userId: "@bot:example.org" ,
password: { source: "file" , provider: "matrix-file" , id: "value" },
},
},
},
},
secrets: {
providers: {
"matrix-file" : {
source: "file" ,
path: "/tmp/matrix-password" ,
},
},
},
};
const account = resolveMatrixAccount({ cfg });
expect(account.configured).toBe(true );
});
it("requires userId + password when no access token is set" , () => {
const cfg: CoreConfig = {
channels: {
matrix: {
homeserver: "https://matrix.example.org ",
userId: "@bot:example.org" ,
},
},
};
const account = resolveMatrixAccount({ cfg });
expect(account.configured).toBe(false );
});
it("marks password auth as configured when userId is present" , () => {
const cfg: CoreConfig = {
channels: {
matrix: {
homeserver: "https://matrix.example.org ",
userId: "@bot:example.org" ,
password: "secret" ,
},
},
};
const account = resolveMatrixAccount({ cfg });
expect(account.configured).toBe(true );
});
it("normalizes and de-duplicates configured account ids" , () => {
const cfg: CoreConfig = {
channels: {
matrix: {
defaultAccount: "Main Bot" ,
accounts: {
"Main Bot" : {
homeserver: "https://matrix.example.org ",
accessToken: "main-token" ,
},
"main-bot" : {
homeserver: "https://matrix.example.org ",
accessToken: "duplicate-token" ,
},
OPS: {
homeserver: "https://matrix.example.org ",
accessToken: "ops-token" ,
},
},
},
},
};
expect(listMatrixAccountIds(cfg)).toEqual(["main-bot" , "ops" ]);
expect(resolveDefaultMatrixAccountId(cfg)).toBe("main-bot" );
});
it("returns the only named account when no explicit default is set" , () => {
const cfg: CoreConfig = {
channels: {
matrix: {
accounts: {
ops: {
homeserver: "https://matrix.example.org ",
accessToken: "ops-token" ,
},
},
},
},
};
expect(resolveDefaultMatrixAccountId(cfg)).toBe("ops" );
});
it("uses configured defaultAccount when accountId is omitted" , () => {
const cfg: CoreConfig = {
channels: {
matrix: {
defaultAccount: "ops" ,
homeserver: "https://matrix.example.org ",
accessToken: "default-token" ,
accounts: {
ops: {
homeserver: "https://ops.example.org ",
accessToken: "ops-token" ,
},
},
},
},
};
const account = resolveMatrixAccount({ cfg });
expect(account.accountId).toBe("ops" );
expect(account.homeserver).toBe("https://ops.example.org ");
expect(account.configured).toBe(true );
});
it("includes env-backed named accounts in plugin account enumeration" , () => {
const keys = getMatrixScopedEnvVarNames("team-ops" );
process.env[keys.homeserver] = "https://matrix.example.org ";
process.env[keys.accessToken] = "ops-token" ;
const cfg: CoreConfig = {
channels: {
matrix: {},
},
};
expect(listMatrixAccountIds(cfg)).toEqual(["team-ops" ]);
expect(resolveDefaultMatrixAccountId(cfg)).toBe("team-ops" );
});
it("includes default accounts backed only by global env vars in plugin account enumeration" , () => {
process.env.MATRIX_HOMESERVER = "https://matrix.example.org ";
process.env.MATRIX_ACCESS_TOKEN = "default-token" ;
const cfg: CoreConfig = {};
expect(listMatrixAccountIds(cfg)).toEqual(["default" ]);
expect(resolveDefaultMatrixAccountId(cfg)).toBe("default" );
});
it("treats mixed default and named env-backed accounts as multi-account" , () => {
const keys = getMatrixScopedEnvVarNames("team-ops" );
process.env.MATRIX_HOMESERVER = "https://matrix.example.org ";
process.env.MATRIX_ACCESS_TOKEN = "default-token" ;
process.env[keys.homeserver] = "https://matrix.example.org ";
process.env[keys.accessToken] = "ops-token" ;
const cfg: CoreConfig = {
channels: {
matrix: {},
},
};
expect(listMatrixAccountIds(cfg)).toEqual(["default" , "team-ops" ]);
expect(resolveDefaultMatrixAccountId(cfg)).toBe("default" );
});
it("includes a top-level configured default account alongside named accounts" , () => {
const cfg: CoreConfig = {
channels: {
matrix: {
homeserver: "https://matrix.example.org ",
accessToken: "default-token" ,
accounts: {
ops: {
homeserver: "https://matrix.example.org ",
accessToken: "ops-token" ,
},
},
},
},
};
expect(listMatrixAccountIds(cfg)).toEqual(["default" , "ops" ]);
expect(resolveDefaultMatrixAccountId(cfg)).toBe("default" );
});
it("does not materialize a default account from shared top-level defaults alone" , () => {
const cfg: CoreConfig = {
channels: {
matrix: {
name: "Shared Defaults" ,
enabled: true ,
accounts: {
ops: {
homeserver: "https://matrix.example.org ",
accessToken: "ops-token" ,
},
},
},
},
};
expect(listMatrixAccountIds(cfg)).toEqual(["ops" ]);
expect(resolveDefaultMatrixAccountId(cfg)).toBe("ops" );
});
it('uses the synthetic "default" account when multiple named accounts need explicit selection' , () => {
const cfg: CoreConfig = {
channels: {
matrix: {
accounts: {
alpha: {
homeserver: "https://matrix.example.org ",
accessToken: "alpha-token" ,
},
beta: {
homeserver: "https://matrix.example.org ",
accessToken: "beta-token" ,
},
},
},
},
};
expect(resolveDefaultMatrixAccountId(cfg)).toBe("default" );
});
it("collects other configured Matrix account user ids for bot detection" , () => {
const cfg: CoreConfig = {
channels: {
matrix: {
userId: "@main:example.org" ,
homeserver: "https://matrix.example.org ",
accessToken: "main-token" ,
accounts: {
ops: {
homeserver: "https://matrix.example.org ",
userId: "@ops:example.org" ,
accessToken: "ops-token" ,
},
alerts: {
homeserver: "https://matrix.example.org ",
userId: "@alerts:example.org" ,
accessToken: "alerts-token" ,
},
},
},
},
};
expect(
Array.from(resolveConfiguredMatrixBotUserIds({ cfg, accountId: "ops" })).toSorted(),
).toEqual(["@alerts:example.org" , "@main:example.org" ]);
});
it("honors injected env when detecting configured bot accounts" , () => {
const env = {
MATRIX_HOMESERVER: "https://matrix.example.org ",
MATRIX_USER_ID: "@main:example.org" ,
MATRIX_ACCESS_TOKEN: "main-token" ,
MATRIX_ALERTS_HOMESERVER: "https://matrix.example.org ",
MATRIX_ALERTS_USER_ID: "@alerts:example.org" ,
MATRIX_ALERTS_ACCESS_TOKEN: "alerts-token" ,
} as NodeJS.ProcessEnv;
const cfg: CoreConfig = {
channels: {
matrix: {},
},
};
expect(
Array.from(resolveConfiguredMatrixBotUserIds({ cfg, accountId: "ops" , env })).toSorted(),
).toEqual(["@alerts:example.org" , "@main:example.org" ]);
});
it("falls back to stored credentials when an access-token-only account omits userId" , () => {
loadMatrixCredentialsMock.mockImplementation(
(env?: NodeJS.ProcessEnv, accountId?: string | null ) =>
accountId === "ops"
? {
homeserver: "https://matrix.example.org ",
userId: "@ops:example.org" ,
accessToken: "ops-token" ,
createdAt: "2026-03-19T00:00:00.000Z" ,
}
: null ,
);
const cfg: CoreConfig = {
channels: {
matrix: {
userId: "@main:example.org" ,
homeserver: "https://matrix.example.org ",
accessToken: "main-token" ,
accounts: {
ops: {
homeserver: "https://matrix.example.org ",
accessToken: "ops-token" ,
},
},
},
},
};
expect(Array.from(resolveConfiguredMatrixBotUserIds({ cfg, accountId: "default" }))).toEqual([
"@ops:example.org" ,
]);
});
it("preserves shared nested dm and actions config when an account overrides one field" , () => {
const account = resolveMatrixAccount({
cfg: {
channels: {
matrix: {
homeserver: "https://matrix.example.org ",
accessToken: "main-token" ,
dm: {
enabled: true ,
policy: "pairing" ,
},
actions: {
reactions: true ,
messages: true ,
},
accounts: {
ops: {
accessToken: "ops-token" ,
dm: {
allowFrom: ["@ops:example.org" ],
},
actions: {
messages: false ,
},
},
},
},
},
},
accountId: "ops" ,
});
expect(account.config.dm).toEqual({
enabled: true ,
policy: "pairing" ,
allowFrom: ["@ops:example.org" ],
});
expect(account.config.actions).toEqual({
reactions: true ,
messages: false ,
});
});
it("filters channel-level groups by room account in multi-account setups" , () => {
expectMultiAccountMatrixScopedEntries(createMatrixScopedEntriesConfig("groups" ), "groups" );
});
it("filters channel-level groups when the default account is configured at the top level" , () => {
expectTopLevelDefaultMatrixScopedEntries(
createMatrixTopLevelDefaultScopedEntriesConfig("groups" ),
"groups" ,
);
});
it("filters legacy channel-level rooms by room account in multi-account setups" , () => {
expectMultiAccountMatrixScopedEntries(createMatrixScopedEntriesConfig("rooms" ), "rooms" );
});
it("filters legacy channel-level rooms when the default account is configured at the top level" , () => {
expectTopLevelDefaultMatrixScopedEntries(
createMatrixTopLevelDefaultScopedEntriesConfig("rooms" ),
"rooms" ,
);
});
it("honors injected env when scoping room entries in multi-account setups" , () => {
const env = {
MATRIX_HOMESERVER: "https://matrix.example.org ",
MATRIX_ACCESS_TOKEN: "default-token" ,
MATRIX_OPS_HOMESERVER: "https://matrix.example.org ",
MATRIX_OPS_ACCESS_TOKEN: "ops-token" ,
} as NodeJS.ProcessEnv;
const cfg = {
channels: {
matrix: {
groups: {
"!default-room:example.org" : {
enabled: true ,
account: "default" ,
},
"!ops-room:example.org" : {
enabled: true ,
account: "ops" ,
},
"!shared-room:example.org" : {
enabled: true ,
},
},
},
},
} as unknown as CoreConfig;
expect(resolveMatrixAccount({ cfg, accountId: "ops" , env }).config.groups).toEqual({
"!ops-room:example.org" : {
enabled: true ,
account: "ops" ,
},
"!shared-room:example.org" : {
enabled: true ,
},
});
});
it("keeps scoped groups bound to their account even when only one account is active" , () => {
const cfg = {
channels: {
matrix: {
groups: {
"!default-room:example.org" : {
enabled: true ,
account: "default" ,
},
"!shared-room:example.org" : {
enabled: true ,
},
},
accounts: {
ops: {
homeserver: "https://matrix.example.org ",
accessToken: "ops-token" ,
},
},
},
},
} as unknown as CoreConfig;
expect(resolveMatrixAccount({ cfg, accountId: "ops" }).config.groups).toEqual({
"!shared-room:example.org" : {
enabled: true ,
},
});
});
it("keeps scoped legacy rooms bound to their account even when only one account is active" , () => {
const cfg = {
channels: {
matrix: {
rooms: {
"!default-room:example.org" : {
enabled: true ,
account: "default" ,
},
"!shared-room:example.org" : {
enabled: true ,
},
},
accounts: {
ops: {
homeserver: "https://matrix.example.org ",
accessToken: "ops-token" ,
},
},
},
},
} as unknown as CoreConfig;
expect(resolveMatrixAccount({ cfg, accountId: "ops" }).config.rooms).toEqual({
"!shared-room:example.org" : {
enabled: true ,
},
});
});
it("lets an account clear inherited groups with an explicit empty map" , () => {
const cfg = {
channels: {
matrix: {
groups: {
"!shared-room:example.org" : {
enabled: true ,
},
},
accounts: {
ops: {
homeserver: "https://matrix.example.org ",
accessToken: "ops-token" ,
groups: {},
},
},
},
},
} as unknown as CoreConfig;
expect(resolveMatrixAccount({ cfg, accountId: "ops" }).config.groups).toBeUndefined();
});
it("lets an account clear inherited legacy rooms with an explicit empty map" , () => {
const cfg = {
channels: {
matrix: {
rooms: {
"!shared-room:example.org" : {
enabled: true ,
},
},
accounts: {
ops: {
homeserver: "https://matrix.example.org ",
accessToken: "ops-token" ,
rooms: {},
},
},
},
},
} as unknown as CoreConfig;
expect(resolveMatrixAccount({ cfg, accountId: "ops" }).config.rooms).toBeUndefined();
});
});
Messung V0.5 in Prozent C=95 H=97 G=95
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet am 2026-06-08)
¤
*© Formatika GbR, Deutschland