@cull/imap
Version:
A simple, configurable javascript interface exposing mailboxes and messages via IMAP.
210 lines (196 loc) • 5.11 kB
text/typescript
import test, { ExecutionContext } from 'ava';
import Client, { Preferences } from './client';
import Mailbox from './mailbox';
import { State } from './connection';
import { Status, ServerStatus } from './response';
import Command from './command';
/**
* Credentials for a fake, functional imap server.
* @link https://ethereal.email
*/
export let testPreferences = {
host: 'imap.ethereal.email',
user: 'manuel22@ethereal.email',
pass: 'RZPfRRKZNnrptYDGmX'
};
export let testClient = (t: ExecutionContext, preferences: Preferences = testPreferences) => {
let client = new Client(preferences);
client.on('error', (...args) => {
t.fail(...args);
});
return client;
};
test('Client id is generated when unspecified.', t => {
let c = new Client({
host: '',
port: 0,
user: '',
pass: ''
});
t.truthy(typeof c.id === 'string');
t.truthy(c.id !== '');
t.truthy(c.id !== null);
});
test('Client id can be specified.', t => {
let c = new Client({
id: 'foo',
host: '',
port: 0,
user: '',
pass: ''
});
t.is(c.id, 'foo');
});
test('Client can establish an authenticated connection to an IMAP server.', async t => {
let c = testClient(t);
let connected = await c.connect();
t.true(connected);
await c.disconnect();
});
test('Client can store CAPABILITY data received from the server.', async t => {
let c = testClient(t);
try {
await c.connect();
t.is(c.connection.state, State.Authenticated);
t.true([...c.capabilities].length > 0);
c.capabilities = new Set();
let command = new Command('capability');
let response = await c.connection.exchange(command);
t.is(response.status, Status.OK);
let capabilityResponse = c.connection.responses.find(r => {
return r.data[ServerStatus.CAPABILITY] !== undefined && r.received > command.sent!;
});
if (capabilityResponse) {
t.deepEqual(c.capabilities, new Set(capabilityResponse.data[ServerStatus.CAPABILITY]));
} else {
t.fail(`Expected a CAPABILITY response.`);
}
} catch (error) {
t.fail(error);
} finally {
await c.disconnect();
}
});
test('Client can list mailboxes.', async t => {
let c = testClient(t);
try {
await c.connect();
let m = await c.mailboxes('', true, true);
let expected: Mailbox[] = [
{
attributes: ['\\HasNoChildren'],
delimiter: '/',
name: 'INBOX'
},
{
attributes: ['\\HasNoChildren', '\\Drafts'],
delimiter: '/',
name: 'Drafts'
},
{
attributes: ['\\HasNoChildren', '\\Junk'],
delimiter: '/',
name: 'Junk'
},
{
attributes: ['\\HasNoChildren', '\\Sent'],
delimiter: '/',
name: 'Sent Mail'
},
{
attributes: ['\\HasNoChildren', '\\Trash'],
delimiter: '/',
name: 'Trash'
}
];
t.deepEqual([...m.values()], expected);
} catch (error) {
t.fail(error);
} finally {
await c.disconnect();
}
});
test('Client can get a mailbox.', async t => {
let c = testClient(t);
try {
await c.connect();
let m = await c.mailbox('INBOX');
let expected: Mailbox = {
attributes: ['\\HasNoChildren'],
delimiter: '/',
name: 'INBOX'
};
t.deepEqual(m, expected);
} catch (error) {
t.fail(error);
} finally {
await c.disconnect();
}
});
test('Client can select a mailbox.', async t => {
let c = testClient(t);
try {
await c.connect();
let m = await c.select('INBOX');
t.deepEqual(m, c.selected);
} catch (error) {
t.fail(error);
} finally {
await c.disconnect();
}
});
/**
* @todo interface with a server/mock for legitimate, predictable scenario
*/
test('Client can list all envelopes for a mailbox.', async t => {
let c = testClient(t);
try {
await c.connect();
let e = await c.envelopes();
t.is([...e.values()].length, 0);
} catch (error) {
t.log(error);
t.fail('An unexpected error has occurred.');
} finally {
await c.disconnect();
}
});
test('Client can list all messages for a mailbox.', async t => {
let c = testClient(t);
try {
await c.connect();
let m = await c.messages('inbox', '1:*', ['UID']);
t.is([...m.values()].length, 0);
} catch (error) {
t.log(error);
t.fail('An unexpected error has occurred.');
} finally {
await c.disconnect();
}
});
test('Client can list all headers for a mailbox.', async t => {
let c = testClient(t);
try {
await c.connect();
let h = await c.headers('inbox', '1:*');
t.is([...h.values()].length, 0);
} catch (error) {
t.log(error);
t.fail('An unexpected error has occurred.');
} finally {
await c.disconnect();
}
});
test('Client resets selected mailbo and capabilities on disconnect.', async t => {
let c = testClient(t);
try {
await c.connect();
await c.select('INBOX');
t.is(c.selected?.name, 'INBOX');
await c.disconnect();
t.falsy(c.selected);
} catch (error) {
t.log(error);
t.fail('An unexpected error has occurred.');
}
});