trash-cleaner
Version:
Finds and deletes trash email in the mailbox
126 lines (104 loc) • 4.22 kB
text/typescript
import fs from 'fs';
import path from 'path';
import os from 'os';
import sinon from 'sinon';
import { assert } from 'chai';
import { HtmlProgressReporter } from '../../lib/reporter/html-progress-reporter.js';
import { Email } from '../../lib/client/email-client.js';
describe('HtmlProgressReporter', () => {
let reporter: HtmlProgressReporter, tmpDir: string, outputPath: string;
beforeEach(() => {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'trash-cleaner-html-'));
outputPath = path.join(tmpDir, 'report.html');
reporter = new HtmlProgressReporter(outputPath);
sinon.stub(console, 'log');
});
afterEach(() => {
(console.log as sinon.SinonStub).restore();
fs.rmSync(tmpDir, { recursive: true, force: true });
});
it('writes HTML file on stop', () => {
reporter.onStart(false);
reporter.onUnreadEmailsRetrieved(new Array(5));
reporter.onTrashEmailsIdentified([]);
reporter.onStop();
assert.isTrue(fs.existsSync(outputPath));
});
it('includes email count in report', () => {
reporter.onStart(false);
reporter.onUnreadEmailsRetrieved(new Array(10));
reporter.onTrashEmailsIdentified([]);
reporter.onStop();
const html = fs.readFileSync(outputPath, 'utf8');
assert.include(html, '10');
assert.include(html, 'Unread emails');
});
it('includes trash email details in table', () => {
const email = new Email();
email.id = '1';
email.from = 'spammer@test.com';
email.subject = 'Win big!';
email.labels = ['spam'];
(email as any)._action = 'delete';
reporter.onStart(false);
reporter.onUnreadEmailsRetrieved(new Array(5));
reporter.onTrashEmailsIdentified([email]);
reporter.onStop();
const html = fs.readFileSync(outputPath, 'utf8');
assert.include(html, 'spammer@test.com');
assert.include(html, 'Win big!');
assert.include(html, 'delete');
});
it('shows dry-run badge when in dry-run mode', () => {
reporter.onStart(true /* dryRun */);
reporter.onUnreadEmailsRetrieved([]);
reporter.onTrashEmailsIdentified([]);
reporter.onStop();
const html = fs.readFileSync(outputPath, 'utf8');
assert.include(html, 'Dry-run mode');
});
it('escapes HTML in email fields', () => {
const email = new Email();
email.id = '1';
email.from = '<script>alert("xss")</script>';
email.subject = 'Test & "subject"';
email.labels = ['inbox'];
(email as any)._action = 'delete';
reporter.onStart(false);
reporter.onUnreadEmailsRetrieved([email]);
reporter.onTrashEmailsIdentified([email]);
reporter.onStop();
const html = fs.readFileSync(outputPath, 'utf8');
assert.include(html, '<script>');
assert.include(html, '&');
assert.include(html, '"subject"');
assert.notInclude(html, '<script>alert');
});
it('shows action breakdown stats', () => {
const email1 = new Email();
(email1 as any)._action = 'delete';
email1.from = 'a@test.com';
email1.subject = 'spam';
email1.labels = ['spam'];
const email2 = new Email();
(email2 as any)._action = 'archive';
email2.from = 'b@test.com';
email2.subject = 'news';
email2.labels = ['inbox'];
reporter.onStart(false);
reporter.onUnreadEmailsRetrieved(new Array(10));
reporter.onTrashEmailsIdentified([email1, email2]);
reporter.onStop();
const html = fs.readFileSync(outputPath, 'utf8');
assert.include(html, 'Deleted');
assert.include(html, 'Archived');
});
it('logs output path to console', () => {
reporter.onStart(false);
reporter.onUnreadEmailsRetrieved([]);
reporter.onTrashEmailsIdentified([]);
reporter.onStop();
sinon.assert.calledOnce(console.log as sinon.SinonStub);
assert.include((console.log as sinon.SinonStub).firstCall.args[0], 'HTML report written to');
});
});