chore: archive mac mini automation baseline
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
import { dateFromInput, plainTextToNoteHtml } from "../src/apple-events.js";
|
||||
|
||||
test("plainTextToNoteHtml escapes input and preserves line breaks", () => {
|
||||
assert.equal(
|
||||
plainTextToNoteHtml("R&D <today>", 'First\n"second"'),
|
||||
"<h1>R&D <today></h1><div>First<br>"second"</div>",
|
||||
);
|
||||
});
|
||||
|
||||
test("dateFromInput accepts valid datetimes and rejects invalid input", () => {
|
||||
assert.equal(dateFromInput("2026-05-26T10:00:00-04:00", "start").toISOString(), "2026-05-26T14:00:00.000Z");
|
||||
assert.throws(() => dateFromInput("not-a-date", "start"), /valid ISO-8601/);
|
||||
});
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
import {
|
||||
listMailAccounts,
|
||||
listMailboxes,
|
||||
listMailMessages,
|
||||
readMailMessage,
|
||||
} from "../src/integrations/mail.js";
|
||||
|
||||
const enabled = process.env.RUN_APPLE_INTEGRATION_TESTS === "1";
|
||||
|
||||
test("Apple Mail read-only integration: enumerate accounts and read a selected inbox message", { skip: !enabled }, async () => {
|
||||
const accounts = await listMailAccounts();
|
||||
assert.ok(accounts.length > 0, "Apple Mail must have at least one configured account");
|
||||
|
||||
const mailboxes = await listMailboxes({ accountId: accounts[0].id });
|
||||
const inbox = mailboxes.find((mailbox) => mailbox.role === "inbox");
|
||||
assert.ok(inbox, "Apple Mail must expose a global inbox");
|
||||
|
||||
let accountWithMessage = null;
|
||||
for (const account of accounts) {
|
||||
const messages = await listMailMessages({ accountId: account.id, mailbox: inbox.name, limit: 1 });
|
||||
if (messages.length) {
|
||||
accountWithMessage = account;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert.ok(accountWithMessage, "At least one configured account must contain an inbox message");
|
||||
|
||||
const messages = await listMailMessages({ accountId: accountWithMessage.id, mailbox: inbox.name, limit: 1 });
|
||||
assert.equal(messages.length, 1);
|
||||
const message = await readMailMessage({ accountId: accountWithMessage.id, mailbox: inbox.name, id: messages[0].id });
|
||||
assert.equal(message.id, messages[0].id);
|
||||
assert.equal(message.accountId, accountWithMessage.id);
|
||||
assert.equal(typeof message.body, "string");
|
||||
});
|
||||
@@ -0,0 +1,81 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
import { createMailClient } from "../src/integrations/mail.js";
|
||||
|
||||
function fakeRunJxa(result) {
|
||||
const calls = [];
|
||||
return {
|
||||
calls,
|
||||
client: createMailClient(async (script, input) => {
|
||||
calls.push({ script, input });
|
||||
return result;
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
test("mail_accounts returns normalized account identities without message data", async () => {
|
||||
const { client, calls } = fakeRunJxa([
|
||||
{ id: "acct-personal", name: "Personal", emailAddresses: ["me@example.com"] },
|
||||
{ id: "acct-emi", name: "EMI", emailAddresses: ["info@emmint.com"] },
|
||||
]);
|
||||
|
||||
const result = await client.accounts();
|
||||
|
||||
assert.deepEqual(result, [
|
||||
{ id: "acct-personal", name: "Personal", emailAddresses: ["me@example.com"] },
|
||||
{ id: "acct-emi", name: "EMI", emailAddresses: ["info@emmint.com"] },
|
||||
]);
|
||||
assert.equal(calls.length, 1);
|
||||
assert.deepEqual(calls[0].input, {});
|
||||
});
|
||||
|
||||
test("mail_list_messages scopes the request to an account mailbox and bounded limit", async () => {
|
||||
const { client, calls } = fakeRunJxa([
|
||||
{
|
||||
id: "message-1",
|
||||
accountId: "acct-emi",
|
||||
account: "EMI",
|
||||
mailbox: "INBOX",
|
||||
subject: "Board update",
|
||||
sender: "Board <board@example.org>",
|
||||
dateSent: "2026-08-03T12:00:00.000Z",
|
||||
read: false,
|
||||
},
|
||||
]);
|
||||
|
||||
const result = await client.listMessages({ accountId: "acct-emi", mailbox: "INBOX", limit: 5, unreadOnly: true });
|
||||
|
||||
assert.equal(result.length, 1);
|
||||
assert.equal(result[0].subject, "Board update");
|
||||
assert.deepEqual(calls[0].input, { accountId: "acct-emi", mailbox: "INBOX", limit: 5, unreadOnly: true });
|
||||
assert.match(calls[0].script, /input\.limit/);
|
||||
});
|
||||
|
||||
test("mail_read_message requires the selected message ID and never returns data from another message", async () => {
|
||||
const { client, calls } = fakeRunJxa({
|
||||
id: "message-1",
|
||||
accountId: "acct-personal",
|
||||
mailbox: "INBOX",
|
||||
subject: "Receipt",
|
||||
sender: "Store <sales@example.org>",
|
||||
dateSent: "2026-08-03T12:00:00.000Z",
|
||||
read: true,
|
||||
body: "Thanks for your order.",
|
||||
});
|
||||
|
||||
const result = await client.readMessage({ accountId: "acct-personal", mailbox: "INBOX", id: "message-1" });
|
||||
|
||||
assert.equal(result.id, "message-1");
|
||||
assert.equal(result.body, "Thanks for your order.");
|
||||
assert.deepEqual(calls[0].input, { accountId: "acct-personal", mailbox: "INBOX", id: "message-1" });
|
||||
});
|
||||
|
||||
test("mail_list_messages rejects out-of-range limits before asking Mail", async () => {
|
||||
const { client, calls } = fakeRunJxa([]);
|
||||
|
||||
assert.throws(
|
||||
() => client.listMessages({ accountId: "acct-emi", mailbox: "INBOX", limit: 51, unreadOnly: false }),
|
||||
/limit must be between 1 and 50/,
|
||||
);
|
||||
assert.equal(calls.length, 0);
|
||||
});
|
||||
Reference in New Issue
Block a user