describe("resolveMSTeamsChannelAllowlist", () => {
it("resolves team/channel by team name + channel display name", async () => { // After the fix, listChannelsForTeam is called once and reused for both // General channel resolution and channel matching.
listTeamsByName.mockResolvedValueOnce([{ id: "team-guid-1", displayName: "Product Team" }]);
listChannelsForTeam.mockResolvedValueOnce([
{ id: "19:general-conv-id@thread.tacv2", displayName: "General" },
{ id: "19:roadmap-conv-id@thread.tacv2", displayName: "Roadmap" },
]);
// teamId is now the General channel's conversation ID — not the Graph GUID — // because that's what Bot Framework sends as channelData.team.id at runtime.
expect(result).toEqual({
input: "Product Team/Roadmap",
resolved: true,
teamId: "19:general-conv-id@thread.tacv2",
teamName: "Product Team",
channelId: "19:roadmap-conv-id@thread.tacv2",
channelName: "Roadmap",
note: "multiple channels; chose first",
});
});
it("uses General channel conversation ID as team key for team-only entry", async () => { // When no channel is specified we still resolve the General channel so the // stored key matches what Bot Framework sends as channelData.team.id.
listTeamsByName.mockResolvedValueOnce([{ id: "guid-engineering", displayName: "Engineering" }]);
listChannelsForTeam.mockResolvedValueOnce([
{ id: "19:eng-general@thread.tacv2", displayName: "General" },
{ id: "19:eng-standups@thread.tacv2", displayName: "Standups" },
]);
it("falls back to Graph GUID when listChannelsForTeam throws", async () => { // Edge case: API call fails (rate limit, network error). We fall back to // the Graph GUID as the team key — the pre-fix behavior — so resolution // still succeeds instead of propagating the error.
listTeamsByName.mockResolvedValueOnce([{ id: "guid-flaky", displayName: "Flaky Team" }]);
listChannelsForTeam.mockRejectedValueOnce(new Error("429 Too Many Requests"));
it("falls back to Graph GUID when General channel is not found", async () => { // Edge case: General channel was renamed or deleted. We fall back to the // Graph GUID so resolution still succeeds rather than silently breaking.
listTeamsByName.mockResolvedValueOnce([{ id: "guid-ops", displayName: "Operations" }]);
listChannelsForTeam.mockResolvedValueOnce([
{ id: "19:ops-announce@thread.tacv2", displayName: "Announcements" },
{ id: "19:ops-random@thread.tacv2", displayName: "Random" },
]);
describe("looksLikeMSTeamsTargetId", () => { // Regression suite for https://github.com/openclaw/openclaw/issues/58001: // cron announce delivery rejected valid Teams conversation ids because the // validator only matched the `conversation:`-prefixed and `@thread`-suffixed // forms. It must now accept every documented Bot Framework + Graph format.
it.each([ "conversation:19:abc@thread.tacv2", "conversation:a:1abc", "conversation:8:orgid:2d8c2d2c-1111-2222-3333-444444444444",
])("accepts conversation-prefixed ids (%s)", (raw) => {
expect(looksLikeMSTeamsTargetId(raw)).toBe(true);
});
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.