Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 102 additions & 1 deletion test/business-adapter.test.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import assert from 'node:assert/strict';
import { execFile } from 'node:child_process';
import { mkdtemp, readFile, readdir, rm, stat } from 'node:fs/promises';
import { mkdir, mkdtemp, readFile, readdir, rm, stat, writeFile } from 'node:fs/promises';
import http from 'node:http';
import os from 'node:os';
import path from 'node:path';
Expand Down Expand Up @@ -130,3 +130,104 @@ test('bundled Business adapter atomically replaces a shared session under concur
assert.equal((await stat(sessionFile)).mode & 0o777, 0o600);
assert.deepEqual((await readdir(stateDir)).filter((entry) => entry.endsWith('.tmp')), []);
});

test('bundled Business adapter sends repeated local attachments through the workspace operation', async (t) => {
const stateHome = await mkdtemp(path.join(os.tmpdir(), 'mere-business-bundled-attachments-'));
t.after(() => rm(stateHome, { recursive: true, force: true }));

const markdownPath = path.join(stateHome, 'approval-packet.md');
const jsonPath = path.join(stateHome, 'receipt.json');
await writeFile(markdownPath, '# Approval packet\n', 'utf8');
await writeFile(jsonPath, '{"ok":true}\n', 'utf8');

let received;
const server = http.createServer(async (request, response) => {
if (request.method !== 'POST' || request.url !== '/api/cli/v2') {
response.writeHead(404).end();
return;
}
received = {
authorization: request.headers.authorization,
body: JSON.parse(await readBody(request)),
};
response.writeHead(200, { 'content-type': 'application/json' });
response.end(JSON.stringify({ ok: true, data: { threadId: 'thread_1', messageId: 'message_1' } }));
});
await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
t.after(() => new Promise((resolve) => server.close(resolve)));

const address = server.address();
assert.ok(address && typeof address === 'object');
const workspaceUrl = `http://127.0.0.1:${address.port}`;
const session = sessionPayload('attachments');
session.workspace.host = workspaceUrl;
session.workspaces[0].host = workspaceUrl;
const stateDir = path.join(stateHome, 'mere-business');
await mkdir(stateDir, { recursive: true });
await writeFile(
path.join(stateDir, 'session.json'),
`${JSON.stringify({ ...session, version: 1, baseUrl: workspaceUrl })}\n`,
'utf8',
);

const env = {
...process.env,
HOME: stateHome,
XDG_STATE_HOME: stateHome,
MERE_ROOT: path.join(stateHome, 'missing-mere-root'),
MERE_CLI_SOURCE: 'bundled',
};
const result = await execFileAsync(
process.execPath,
[
rootCli,
'business',
'mail',
'send',
'--mailbox-id',
'mb_1',
'--to',
'director@example.com',
'--subject',
'Approval packet',
'--body',
'Attached.',
'--attach',
markdownPath,
'--attach',
jsonPath,
'--yes',
'--json',
],
{ cwd: repoRoot, env },
);

assert.equal(result.stderr, '');
assert.deepEqual(JSON.parse(result.stdout), { messageId: 'message_1', threadId: 'thread_1' });
assert.deepEqual(received, {
authorization: 'Bearer fake-access-attachments',
body: {
op: 'mail.send',
input: {
mailboxId: 'mb_1',
to: ['director@example.com'],
cc: [],
bcc: [],
attachments: [
{
filename: 'approval-packet.md',
mimeType: 'text/markdown; charset=utf-8',
contentBase64: Buffer.from('# Approval packet\n').toString('base64'),
},
{
filename: 'receipt.json',
mimeType: 'application/json; charset=utf-8',
contentBase64: Buffer.from('{"ok":true}\n').toString('base64'),
},
],
subject: 'Approval packet',
bodyText: 'Attached.',
},
},
});
});