feat(cron): enable WeChat as a supported delivery channel (#789)
This commit is contained in:
committed by
GitHub
Unverified
parent
97d29ab23c
commit
3021ad5089
@@ -158,7 +158,7 @@ describe('handleCronRoutes', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('rejects WeChat scheduled delivery because the plugin requires a live context token', async () => {
|
||||
it('allows WeChat scheduled delivery', async () => {
|
||||
parseJsonBodyMock.mockResolvedValue({
|
||||
name: 'WeChat delivery',
|
||||
message: 'Send update',
|
||||
@@ -172,7 +172,17 @@ describe('handleCronRoutes', () => {
|
||||
enabled: true,
|
||||
});
|
||||
|
||||
const rpc = vi.fn();
|
||||
const rpc = vi.fn().mockResolvedValue({
|
||||
id: 'job-wechat',
|
||||
name: 'WeChat delivery',
|
||||
enabled: true,
|
||||
createdAtMs: 1,
|
||||
updatedAtMs: 2,
|
||||
schedule: { kind: 'cron', expr: '0 10 * * *' },
|
||||
payload: { kind: 'agentTurn', message: 'Send update' },
|
||||
delivery: { mode: 'announce', channel: 'openclaw-weixin', to: 'wechat:wxid_target', accountId: 'wechat-bot' },
|
||||
state: {},
|
||||
});
|
||||
|
||||
const { handleCronRoutes } = await import('@electron/api/routes/cron');
|
||||
const handled = await handleCronRoutes(
|
||||
@@ -185,13 +195,14 @@ describe('handleCronRoutes', () => {
|
||||
);
|
||||
|
||||
expect(handled).toBe(true);
|
||||
expect(rpc).not.toHaveBeenCalled();
|
||||
expect(rpc).toHaveBeenCalledWith('cron.add', expect.objectContaining({
|
||||
delivery: expect.objectContaining({ mode: 'announce', to: 'wechat:wxid_target' }),
|
||||
}));
|
||||
expect(sendJsonMock).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
400,
|
||||
200,
|
||||
expect.objectContaining({
|
||||
success: false,
|
||||
error: expect.stringContaining('WeChat scheduled delivery is not supported'),
|
||||
id: 'job-wechat',
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import {
|
||||
getGatewayStartupRecoveryAction,
|
||||
hasInvalidConfigFailureSignal,
|
||||
isInvalidConfigSignal,
|
||||
shouldAttemptConfigAutoRepair,
|
||||
@@ -50,3 +51,62 @@ describe('gateway startup recovery heuristics', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('getGatewayStartupRecoveryAction', () => {
|
||||
const configInvalidStderr = ['Config invalid', 'Run: openclaw doctor --fix'];
|
||||
const transientError = new Error('Gateway process exited before becoming ready (code=1)');
|
||||
|
||||
it('returns repair on first config-invalid failure', () => {
|
||||
const action = getGatewayStartupRecoveryAction({
|
||||
startupError: transientError,
|
||||
startupStderrLines: configInvalidStderr,
|
||||
configRepairAttempted: false,
|
||||
attempt: 1,
|
||||
maxAttempts: 3,
|
||||
});
|
||||
expect(action).toBe('repair');
|
||||
});
|
||||
|
||||
it('returns retry when repair was attempted but error is still transient', () => {
|
||||
const action = getGatewayStartupRecoveryAction({
|
||||
startupError: transientError,
|
||||
startupStderrLines: configInvalidStderr,
|
||||
configRepairAttempted: true,
|
||||
attempt: 1,
|
||||
maxAttempts: 3,
|
||||
});
|
||||
expect(action).toBe('retry');
|
||||
});
|
||||
|
||||
it('returns retry for transient errors after successful repair (no config signal)', () => {
|
||||
const action = getGatewayStartupRecoveryAction({
|
||||
startupError: transientError,
|
||||
startupStderrLines: ['Gateway process exited (code=1, expected=no)'],
|
||||
configRepairAttempted: true,
|
||||
attempt: 1,
|
||||
maxAttempts: 3,
|
||||
});
|
||||
expect(action).toBe('retry');
|
||||
});
|
||||
|
||||
it('returns fail when max attempts exceeded even for transient errors', () => {
|
||||
const action = getGatewayStartupRecoveryAction({
|
||||
startupError: transientError,
|
||||
startupStderrLines: [],
|
||||
configRepairAttempted: false,
|
||||
attempt: 3,
|
||||
maxAttempts: 3,
|
||||
});
|
||||
expect(action).toBe('fail');
|
||||
});
|
||||
|
||||
it('returns fail for non-transient, non-config errors', () => {
|
||||
const action = getGatewayStartupRecoveryAction({
|
||||
startupError: new Error('Unknown fatal error'),
|
||||
startupStderrLines: [],
|
||||
configRepairAttempted: false,
|
||||
attempt: 1,
|
||||
maxAttempts: 3,
|
||||
});
|
||||
expect(action).toBe('fail');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user