From 91a1483709db83c8d62191a366dce369a2e0d704 Mon Sep 17 00:00:00 2001 From: Deepak Jain Date: Mon, 17 Aug 2026 15:56:53 -0700 Subject: [PATCH 1/7] fix(e2e): require active Telegram configuration Fixes #9361 Signed-off-by: Deepak Jain --- test/e2e/live/channels-add-remove.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/e2e/live/channels-add-remove.test.ts b/test/e2e/live/channels-add-remove.test.ts index 2da28db1352..147c022c805 100644 --- a/test/e2e/live/channels-add-remove.test.ts +++ b/test/e2e/live/channels-add-remove.test.ts @@ -291,7 +291,9 @@ async function openClawHasTelegram(sandbox: SandboxClient, artifactName: string) [ "import json", "data=json.load(open('/sandbox/.openclaw/openclaw.json'))", - "print('yes' if 'telegram' in data.get('channels', {}) else 'no')", + "channel=data.get('channels', {}).get('telegram', {})", + "plugin=data.get('plugins', {}).get('entries', {}).get('telegram', {})", + "print('yes' if channel.get('enabled') is True and plugin.get('enabled') is True else 'no')", ].join("; "), ], { From 5cf326d44570f4036c0e4ece02250d55f4f06523 Mon Sep 17 00:00:00 2001 From: Deepak Jain Date: Mon, 17 Aug 2026 16:20:48 -0700 Subject: [PATCH 2/7] docs(e2e): describe Telegram activation probe Signed-off-by: Deepak Jain --- test/e2e/live/channels-add-remove.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/e2e/live/channels-add-remove.test.ts b/test/e2e/live/channels-add-remove.test.ts index 147c022c805..4b1bbff4baa 100644 --- a/test/e2e/live/channels-add-remove.test.ts +++ b/test/e2e/live/channels-add-remove.test.ts @@ -282,6 +282,7 @@ async function expectProvider( } } +/** Report whether both OpenClaw Telegram activation gates are enabled. */ async function openClawHasTelegram(sandbox: SandboxClient, artifactName: string): Promise { const result = await sandbox.exec( SANDBOX_NAME, From 20ffdf79c3e73e6e2cdc908dd146c8d9a9288769 Mon Sep 17 00:00:00 2001 From: Deepak Jain Date: Mon, 17 Aug 2026 16:48:54 -0700 Subject: [PATCH 3/7] docs(e2e): describe Telegram state assertion Signed-off-by: Deepak Jain --- test/e2e/live/channels-add-remove.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/e2e/live/channels-add-remove.test.ts b/test/e2e/live/channels-add-remove.test.ts index 4b1bbff4baa..63ad804deef 100644 --- a/test/e2e/live/channels-add-remove.test.ts +++ b/test/e2e/live/channels-add-remove.test.ts @@ -311,6 +311,7 @@ async function openClawHasTelegram(sandbox: SandboxClient, artifactName: string) return verdict === "yes"; } +/** Assert the active Telegram state recorded inside the OpenClaw sandbox. */ async function expectOpenClawTelegram( sandbox: SandboxClient, expected: boolean, From 55276e2fb916212000eb031b60a901ccba4aabee Mon Sep 17 00:00:00 2001 From: Deepak Jain Date: Mon, 17 Aug 2026 17:49:32 -0700 Subject: [PATCH 4/7] docs(e2e): describe active policy matcher Signed-off-by: Deepak Jain --- test/e2e/live/channels-add-remove.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/e2e/live/channels-add-remove.test.ts b/test/e2e/live/channels-add-remove.test.ts index 63ad804deef..a52730ed6f7 100644 --- a/test/e2e/live/channels-add-remove.test.ts +++ b/test/e2e/live/channels-add-remove.test.ts @@ -320,6 +320,7 @@ async function expectOpenClawTelegram( await expect(openClawHasTelegram(sandbox, artifactName)).resolves.toBe(expected); } +/** Detect an active policy preset in the human-readable policy listing. */ function policyListHasActivePreset(output: string, preset: string): boolean { const activePreset = new RegExp(`^\\s*\\u25cf\\s+${escapeRegex(preset)}\\b`, "im"); return activePreset.test(stripAnsi(output)); From 55ac75272a2b41bce5e7751f6184c98eda482e1b Mon Sep 17 00:00:00 2001 From: Aaron Erickson Date: Mon, 17 Aug 2026 21:41:37 -0500 Subject: [PATCH 5/7] test(e2e): require Telegram entries removed Signed-off-by: Aaron Erickson --- test/e2e/live/channels-add-remove.test.ts | 32 ++++++++++++++++++----- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/test/e2e/live/channels-add-remove.test.ts b/test/e2e/live/channels-add-remove.test.ts index a52730ed6f7..40a3b550b81 100644 --- a/test/e2e/live/channels-add-remove.test.ts +++ b/test/e2e/live/channels-add-remove.test.ts @@ -282,8 +282,16 @@ async function expectProvider( } } -/** Report whether both OpenClaw Telegram activation gates are enabled. */ -async function openClawHasTelegram(sandbox: SandboxClient, artifactName: string): Promise { +/** Report whether the OpenClaw Telegram entries match the requested probe. */ +async function openClawTelegramMatches( + sandbox: SandboxClient, + artifactName: string, + probe: "active" | "present", +): Promise { + const predicate = + probe === "active" + ? "channel.get('enabled') is True and plugin.get('enabled') is True" + : "'telegram' in channels or 'telegram' in plugins"; const result = await sandbox.exec( SANDBOX_NAME, [ @@ -292,9 +300,11 @@ async function openClawHasTelegram(sandbox: SandboxClient, artifactName: string) [ "import json", "data=json.load(open('/sandbox/.openclaw/openclaw.json'))", - "channel=data.get('channels', {}).get('telegram', {})", - "plugin=data.get('plugins', {}).get('entries', {}).get('telegram', {})", - "print('yes' if channel.get('enabled') is True and plugin.get('enabled') is True else 'no')", + "channels=data.get('channels', {})", + "plugins=data.get('plugins', {}).get('entries', {})", + "channel=channels.get('telegram', {})", + "plugin=plugins.get('telegram', {})", + `print('yes' if ${predicate} else 'no')`, ].join("; "), ], { @@ -317,7 +327,15 @@ async function expectOpenClawTelegram( expected: boolean, artifactName: string, ): Promise { - await expect(openClawHasTelegram(sandbox, artifactName)).resolves.toBe(expected); + await expect(openClawTelegramMatches(sandbox, artifactName, "active")).resolves.toBe(expected); +} + +/** Assert that neither OpenClaw Telegram configuration entry remains. */ +async function expectOpenClawTelegramRemoved( + sandbox: SandboxClient, + artifactName: string, +): Promise { + await expect(openClawTelegramMatches(sandbox, artifactName, "present")).resolves.toBe(false); } /** Detect an active policy preset in the human-readable policy listing. */ @@ -556,7 +574,7 @@ test( }); progress.phase("validate Telegram removal"); - await expectOpenClawTelegram(sandbox, false, "phase-6-openclaw-json-after-remove"); + await expectOpenClawTelegramRemoved(sandbox, "phase-6-openclaw-json-after-remove"); await expectProvider(host, "absent", "phase-6-provider-get-after-remove"); await expectPolicyPreset(host, "telegram", "not-applied", "phase-6-policy-list-after-remove"); expectHostTelegramPlan("removed", "after remove+rebuild"); From 2080bb94660060448b4cefec365653468d876ca2 Mon Sep 17 00:00:00 2001 From: Aaron Erickson Date: Mon, 17 Aug 2026 21:58:14 -0500 Subject: [PATCH 6/7] test(e2e): require enabled Telegram account Signed-off-by: Aaron Erickson --- test/e2e/live/channels-add-remove.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/e2e/live/channels-add-remove.test.ts b/test/e2e/live/channels-add-remove.test.ts index 40a3b550b81..ad071d3b4d4 100644 --- a/test/e2e/live/channels-add-remove.test.ts +++ b/test/e2e/live/channels-add-remove.test.ts @@ -290,7 +290,7 @@ async function openClawTelegramMatches( ): Promise { const predicate = probe === "active" - ? "channel.get('enabled') is True and plugin.get('enabled') is True" + ? "channel.get('enabled') is True and plugin.get('enabled') is True and isinstance(accounts, dict) and any(isinstance(account, dict) and account.get('enabled') is True for account in accounts.values())" : "'telegram' in channels or 'telegram' in plugins"; const result = await sandbox.exec( SANDBOX_NAME, @@ -304,6 +304,7 @@ async function openClawTelegramMatches( "plugins=data.get('plugins', {}).get('entries', {})", "channel=channels.get('telegram', {})", "plugin=plugins.get('telegram', {})", + "accounts=channel.get('accounts', {})", `print('yes' if ${predicate} else 'no')`, ].join("; "), ], From 5bfbe6296956eebaad9d986ef87af494e4aeeab4 Mon Sep 17 00:00:00 2001 From: Deepak Jain Date: Mon, 17 Aug 2026 20:05:08 -0700 Subject: [PATCH 7/7] test(e2e): expose Telegram activation state Signed-off-by: Deepak Jain --- test/e2e/live/channels-add-remove.test.ts | 63 +++++++++++++++-------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/test/e2e/live/channels-add-remove.test.ts b/test/e2e/live/channels-add-remove.test.ts index a52730ed6f7..ae9fccd39ba 100644 --- a/test/e2e/live/channels-add-remove.test.ts +++ b/test/e2e/live/channels-add-remove.test.ts @@ -282,8 +282,11 @@ async function expectProvider( } } -/** Report whether both OpenClaw Telegram activation gates are enabled. */ -async function openClawHasTelegram(sandbox: SandboxClient, artifactName: string): Promise { +/** Read non-secret Telegram activation state from the rendered OpenClaw config. */ +async function readOpenClawTelegramState( + sandbox: SandboxClient, + artifactName: string, +): Promise { const result = await sandbox.exec( SANDBOX_NAME, [ @@ -292,9 +295,12 @@ async function openClawHasTelegram(sandbox: SandboxClient, artifactName: string) [ "import json", "data=json.load(open('/sandbox/.openclaw/openclaw.json'))", - "channel=data.get('channels', {}).get('telegram', {})", + "channels=data.get('channels', {})", + "channel=channels.get('telegram', {})", "plugin=data.get('plugins', {}).get('entries', {}).get('telegram', {})", - "print('yes' if channel.get('enabled') is True and plugin.get('enabled') is True else 'no')", + "accounts=channel.get('accounts', {})", + "state={'channelPresent': 'telegram' in channels, 'channelEnabled': channel.get('enabled') is True, 'pluginEnabled': plugin.get('enabled') is True, 'accountEnabled': any(isinstance(account, dict) and account.get('enabled') is True for account in accounts.values())}", + "print(json.dumps(state))", ].join("; "), ], { @@ -304,20 +310,8 @@ async function openClawHasTelegram(sandbox: SandboxClient, artifactName: string) }, ); assertExitZero(result, "read /sandbox/.openclaw/openclaw.json"); - const verdict = stripAnsi(result.stdout).trim().split(/\r?\n/).at(-1); - expect(["yes", "no"], `unexpected openclaw.json verdict:\n${resultText(result)}`).toContain( - verdict, - ); - return verdict === "yes"; -} - -/** Assert the active Telegram state recorded inside the OpenClaw sandbox. */ -async function expectOpenClawTelegram( - sandbox: SandboxClient, - expected: boolean, - artifactName: string, -): Promise { - await expect(openClawHasTelegram(sandbox, artifactName)).resolves.toBe(expected); + const output = stripAnsi(result.stdout).trim().split(/\r?\n/).at(-1) ?? ""; + return JSON.parse(output) as JsonRecord; } /** Detect an active policy preset in the human-readable policy listing. */ @@ -470,7 +464,16 @@ test( progress.phase("verify baseline channel absence"); await expectProvider(host, "absent", "phase-2-provider-get-baseline"); - await expectOpenClawTelegram(sandbox, false, "phase-2-openclaw-json-baseline"); + const baselineTelegram = await readOpenClawTelegramState( + sandbox, + "phase-2-openclaw-json-baseline", + ); + expect(baselineTelegram).toEqual({ + accountEnabled: false, + channelEnabled: false, + channelPresent: true, + pluginEnabled: false, + }); await expectPolicyPreset(host, "telegram", "not-applied", "phase-2-policy-list-baseline"); progress.phase("add Telegram and rebuild sandbox"); @@ -512,7 +515,16 @@ test( progress.phase("validate active Telegram integration"); await expectPolicyPreset(host, "telegram", "applied", "phase-4-policy-list-after-add"); - await expectOpenClawTelegram(sandbox, true, "phase-4-openclaw-json-after-add"); + const activeTelegram = await readOpenClawTelegramState( + sandbox, + "phase-4-openclaw-json-after-add", + ); + expect(activeTelegram).toEqual({ + accountEnabled: true, + channelEnabled: true, + channelPresent: true, + pluginEnabled: true, + }); await expectProvider(host, "present", "phase-4-provider-get-after-add"); expectHostTelegramConfig("after add+rebuild"); expectHostTelegramPlan("active", "after add+rebuild"); @@ -556,7 +568,16 @@ test( }); progress.phase("validate Telegram removal"); - await expectOpenClawTelegram(sandbox, false, "phase-6-openclaw-json-after-remove"); + const removedTelegram = await readOpenClawTelegramState( + sandbox, + "phase-6-openclaw-json-after-remove", + ); + expect(removedTelegram).toEqual({ + accountEnabled: false, + channelEnabled: false, + channelPresent: false, + pluginEnabled: false, + }); await expectProvider(host, "absent", "phase-6-provider-get-after-remove"); await expectPolicyPreset(host, "telegram", "not-applied", "phase-6-policy-list-after-remove"); expectHostTelegramPlan("removed", "after remove+rebuild");