aboutsummaryrefslogtreecommitdiffstats
path: root/test/format.test.js
diff options
context:
space:
mode:
authorElvis Claros Castro <elvis@claros.ar>2026-09-26 19:26:33 -0300
committerElvis Claros Castro <elvis@claros.ar>2026-09-26 19:26:33 -0300
commitd80640d01eeb84907e36ff4af33add9081eda17c (patch)
tree27698b34e06e28d111c2196700015d9c82f78274 /test/format.test.js
downloadwa-cli-d80640d01eeb84907e36ff4af33add9081eda17c.tar.gz
wa-cli-d80640d01eeb84907e36ff4af33add9081eda17c.zip
wa-cli: WhatsApp from the terminal, with a neomutt Maildir bridgeHEADmain
Diffstat (limited to 'test/format.test.js')
-rw-r--r--test/format.test.js66
1 files changed, 66 insertions, 0 deletions
diff --git a/test/format.test.js b/test/format.test.js
new file mode 100644
index 0000000..0eb5bf9
--- /dev/null
+++ b/test/format.test.js
@@ -0,0 +1,66 @@
+import assert from 'node:assert/strict';
+import { execFileSync } from 'node:child_process';
+import test from 'node:test';
+import { format } from '../src/format/index.js';
+import { messages } from './fixtures.js';
+
+// Validates with the Python mail parser (the same kind of strict parser MUAs use).
+function parseMbox(text) {
+ const py = `
+import sys, json, mailbox, email.policy, tempfile, os
+f = tempfile.NamedTemporaryFile('w', delete=False, suffix='.mbox'); f.write(sys.stdin.read()); f.close()
+out = []
+for m in mailbox.mbox(f.name, factory=lambda fp: email.message_from_binary_file(fp, policy=email.policy.default)):
+ body = m.get_body(('plain',))
+ atts = [(a.get_filename(), a.get_content_type(), len(a.get_content())) for a in m.iter_attachments()]
+ out.append({k: str(m[k]) for k in ('From','To','Reply-To','Subject','Message-ID','In-Reply-To','X-WA-Id','X-WA-Chat-Name')} | {'body': body.get_content(), 'atts': atts, 'defects': [str(d) for d in m.defects]})
+os.unlink(f.name)
+print(json.dumps(out))`;
+ return JSON.parse(execFileSync('python3', ['-c', py], { input: text, encoding: 'utf8' }));
+}
+
+test('mbox: headers, QP body, attachments and threads', () => {
+ const parsed = parseMbox(format(messages, 'mbox') + '\n');
+ assert.equal(parsed.length, 3);
+ const [a, b, c] = parsed;
+
+ assert.equal(a.From, 'Juan Pérez <5491122334455@c.us>');
+ assert.equal(a['Message-ID'], '<3EB0AAA1@wa>');
+ assert.equal(a.body.trimEnd(), messages[0].body); // QP round trip, including the "From " line
+ assert.match(a.Subject, /^Hola! ¿venís mañana\? 🎉$/);
+ assert.deepEqual(a.defects, []);
+
+ assert.equal(b['In-Reply-To'], '<3EB0AAA1@wa>');
+ assert.equal(b.To, 'Juan Pérez <5491122334455@c.us>');
+ assert.deepEqual(b.atts, [['captura año.png', 'image/png', 70]]);
+ assert.equal(b.body.trimEnd(), 'la foto');
+
+ assert.equal(c['Reply-To'], 'Familia <120363000000@g.us>');
+ assert.equal(c.From, '5491133334444@c.us');
+ assert.match(c.body, /attachment not downloaded: application\/pdf, 20 KB/);
+ assert.equal(c['X-WA-Id'], messages[2].id);
+});
+
+test('eml: a single message; with several it asks for mbox', () => {
+ assert.match(format(messages[0], 'eml'), /^From: =\?UTF-8\?B\?/);
+ assert.throws(() => format(messages, 'eml'), /use --format mbox/);
+ assert.throws(() => format([{ id: 1 }], 'mbox'), /only apply to messages/);
+});
+
+test('table / csv / yaml / text', () => {
+ process.stdout.columns = 80;
+ const t = format(messages, 'table', { columns: ['date', 'senderName', 'body'] });
+ assert.ok(t.split('\n').every((l) => l.length <= 80), t);
+ assert.match(t.split('\n')[0], /^DATE\s+SENDERNAME\s+BODY$/);
+
+ const csv = format([{ a: 'x,y', b: 'di "hola"', c: { d: 1 } }], 'csv', { columns: ['a', 'b', 'c.d'] });
+ assert.equal(csv, 'a,b,c.d\n"x,y","di ""hola""",1');
+
+ assert.equal(format({ a: 'yes', b: [1, { c: 'x: y' }], e: {} }, 'yaml'), 'a: "yes"\nb:\n - 1\n - c: "x: y"\ne: {}');
+
+ const txt = format(messages, 'text');
+ assert.match(txt, /\] Juan Pérez: Hola!/);
+ assert.match(txt, /\] me: ↩ \[image captura año.png\] la foto/);
+ assert.match(txt, /\] 5491133334444@c.us: \[document boleta.pdf\]/);
+ assert.equal(format({ x: 1 }, 'ndjson'), '{"x":1}');
+});