"use strict"; const Promise = require("bluebird"); const tap = require("tap"); const pEvent = require("p-event"); const IMAP = require("../.."); const lines = require("../lines"); const createMockServer = require("../mock-server"); const fetch = require("../fetch"); tap.test("idle-with-delay", (test) => { return testIdle(test, true); }); tap.test("idle-without-delay", (test) => { return testIdle(test, false); }); function testIdle(test, withDelay) { let steps = [{ expected: 'A0 CAPABILITY', response: lines([ '* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA CHILDREN', 'A0 OK Thats all she wrote!', ]), }, { expected: 'A1 LOGIN "foo" "bar"', response: lines([ '* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA CHILDREN UIDPLUS MOVE', 'A1 OK authenticated (Success)', ]), }, { expected: 'A2 NAMESPACE', response: lines([ '* NAMESPACE (("" "/")) NIL NIL', 'A2 OK Success', ]), }, { expected: 'A3 LIST "" ""', response: lines([ '* LIST (\\Noselect) "/" "/"', 'A3 OK Success', ]), }, { expected: 'A4 EXAMINE "INBOX"', response: lines([ '* FLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen)', '* OK [PERMANENTFLAGS ()] Flags permitted.', '* OK [UIDVALIDITY 2] UIDs valid.', '* 685 EXISTS', '* 0 RECENT', '* OK [UIDNEXT 4422] Predicted next UID.', 'A4 OK [READ-ONLY] INBOX selected. (Success)' ]), }, { expected: 'A5 FETCH 1 (UID FLAGS INTERNALDATE BODY.PEEK[TEXT])', response: lines([ '* 1 FETCH (UID 1)', '* 1 FETCH (INTERNALDATE "05-Sep-2004 00:38:03 +0000" UID 1000)', '* 1 FETCH (BODY[TEXT] "IMAP is terrible")', '* 1 FETCH (FLAGS (\\Seen))', 'A5 OK Success', ]), }, { expected: 'A6 STATUS "test" (MESSAGES RECENT UNSEEN UIDVALIDITY UIDNEXT)', response: lines([ '* STATUS test (MESSAGES 231 RECENT 0 UNSEEN 0 UIDVALIDITY 123 UIDNEXT 442)', 'A6 OK STATUS completed', ]), }, { expected: 'A7 LOGOUT', response: lines([ '* BYE LOGOUT Requested', 'A7 OK good day (Success)', ]), }]; return Promise.try(() => { let continuationWasSent; return createMockServer({ steps: steps, test: test, // NOTE: Anything handled here is not matched against steps, nor is the counter incremented handle: function (line) { if (line === "IDLE IDLE") { continuationWasSent = true; return Promise.delay(100).then(() => { return lines([ "+ idling" ]); }); } else if (line === "DONE") { test.ok(continuationWasSent, "DONE seen before continuation sent"); continuationWasSent = false; return lines([ "IDLE ok" ]); } } }); }).then(({ server, port, finalize }) => { const client = new IMAP({ user: "foo", password: "bar", host: "127.0.0.1", port: port, keepalive: true // NOTE: Different in other tests! }); Promise.promisifyAll(client, { multiArgs: true }); client.connect(); return Promise.try(() => { return pEvent(client, "ready"); }).then(() => { server.close(); // Stop listening for new clients return client.openBoxAsync("INBOX", true); }).then(() => { return fetch( client, [ 1, { bodies: [ "TEXT" ] } ] ); }).tap(() => { return Promise.try(() => { if (withDelay) { return Promise.delay(500); } }).then(() => { return Promise.try(() => { return client.statusAsync("test"); }).then((_status) => { client.end(); return pEvent(client, "end"); }).timeout(500, "Timed out waiting for STATUS"); }); }).then(({ attributeResults, bodyInfoResults, bodies }) => { finalize(); test.same(attributeResults, [{ uid: 1, date: new Date('05-Sep-2004 00:38:03 +0000'), flags: [ '\\Seen' ] }]); test.same(bodies, [ Buffer.from('IMAP is terrible') ]); test.same(bodyInfoResults, [{ seqno: 1, which: 'TEXT', size: 16 }]); }); }); }