@proteinjs/user-server 1.21.1 → 1.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/generated/index.d.ts.map +1 -1
- package/dist/generated/index.js +5 -1
- package/dist/generated/index.js.map +1 -1
- package/dist/src/routes/devMail.d.ts +4 -0
- package/dist/src/routes/devMail.d.ts.map +1 -0
- package/dist/src/routes/devMail.js +119 -0
- package/dist/src/routes/devMail.js.map +1 -0
- package/dist/test/DevMail.test.d.ts +2 -0
- package/dist/test/DevMail.test.d.ts.map +1 -0
- package/dist/test/DevMail.test.js +250 -0
- package/dist/test/DevMail.test.js.map +1 -0
- package/generated/index.ts +5 -1
- package/package.json +3 -3
- package/src/routes/devMail.ts +72 -0
- package/test/DevMail.test.ts +151 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
+
function step(op) {
|
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
+
switch (op[0]) {
|
|
21
|
+
case 0: case 1: t = op; break;
|
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
+
default:
|
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
+
if (t[2]) _.ops.pop();
|
|
31
|
+
_.trys.pop(); continue;
|
|
32
|
+
}
|
|
33
|
+
op = body.call(thisArg, _);
|
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.devMailMessage = exports.devMail = void 0;
|
|
40
|
+
var email_server_1 = require("@proteinjs/email-server");
|
|
41
|
+
/**
|
|
42
|
+
* DEV-ONLY mail door: reads the process's mail sink (`@proteinjs/email-server` MailSink — the
|
|
43
|
+
* messages a development sender recorded instead of transporting), so automated dev-loop testing
|
|
44
|
+
* reads an invite or reset link from the sink instead of needing a real inbox, and nothing a dev
|
|
45
|
+
* server composes ever has to reach a real address to be verified.
|
|
46
|
+
*
|
|
47
|
+
* GET /dev/mail[?n=<count>] the last n messages (default 20, at most MailSink.CAPACITY), newest
|
|
48
|
+
* first: id, at, from, to, subject, the body's first link, refused, url
|
|
49
|
+
* GET /dev/mail/<id> the rendered message — its html part, or its text part as text/plain
|
|
50
|
+
*
|
|
51
|
+
* Double-gated exactly like `/dev/login` (devLogin.ts), acting only when BOTH hold; otherwise the
|
|
52
|
+
* paths answer 404 as if unregistered:
|
|
53
|
+
* 1. `process.env.DEVELOPMENT` — the dev-server switch, never set in prod images.
|
|
54
|
+
* 2. `DEV_AUTO_LOGIN_EMAIL` — the explicit per-launch dev opt-in.
|
|
55
|
+
*/
|
|
56
|
+
var DEFAULT_COUNT = 20;
|
|
57
|
+
var gatesOpen = function () { var _a; return !!process.env.DEVELOPMENT && ((_a = process.env.DEV_AUTO_LOGIN_EMAIL) !== null && _a !== void 0 ? _a : '').trim().length > 0; };
|
|
58
|
+
exports.devMail = {
|
|
59
|
+
path: '/dev/mail',
|
|
60
|
+
method: 'get',
|
|
61
|
+
onRequest: function (request, response) { return __awaiter(void 0, void 0, void 0, function () {
|
|
62
|
+
var requested, count, messages;
|
|
63
|
+
var _a;
|
|
64
|
+
return __generator(this, function (_b) {
|
|
65
|
+
if (!gatesOpen()) {
|
|
66
|
+
response.status(404).send();
|
|
67
|
+
return [2 /*return*/];
|
|
68
|
+
}
|
|
69
|
+
requested = Number((_a = request.query) === null || _a === void 0 ? void 0 : _a.n);
|
|
70
|
+
count = Number.isInteger(requested) && requested > 0 ? Math.min(requested, email_server_1.MailSink.CAPACITY) : DEFAULT_COUNT;
|
|
71
|
+
messages = email_server_1.MailSink.get()
|
|
72
|
+
.list(count)
|
|
73
|
+
.map(function (_a) {
|
|
74
|
+
var id = _a.id, at = _a.at, from = _a.from, to = _a.to, subject = _a.subject, link = _a.link, refused = _a.refused;
|
|
75
|
+
return ({
|
|
76
|
+
id: id,
|
|
77
|
+
at: at,
|
|
78
|
+
from: from,
|
|
79
|
+
to: to,
|
|
80
|
+
subject: subject,
|
|
81
|
+
link: link,
|
|
82
|
+
refused: refused,
|
|
83
|
+
url: "/dev/mail/".concat(id),
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
response.status(200).json({ messages: messages });
|
|
87
|
+
return [2 /*return*/];
|
|
88
|
+
});
|
|
89
|
+
}); },
|
|
90
|
+
};
|
|
91
|
+
exports.devMailMessage = {
|
|
92
|
+
path: '/dev/mail/:id',
|
|
93
|
+
method: 'get',
|
|
94
|
+
onRequest: function (request, response) { return __awaiter(void 0, void 0, void 0, function () {
|
|
95
|
+
var record;
|
|
96
|
+
var _a, _b, _c;
|
|
97
|
+
return __generator(this, function (_d) {
|
|
98
|
+
if (!gatesOpen()) {
|
|
99
|
+
response.status(404).send();
|
|
100
|
+
return [2 /*return*/];
|
|
101
|
+
}
|
|
102
|
+
record = email_server_1.MailSink.get().get(String((_b = (_a = request.params) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : ''));
|
|
103
|
+
if (!record) {
|
|
104
|
+
response.status(404).send();
|
|
105
|
+
return [2 /*return*/];
|
|
106
|
+
}
|
|
107
|
+
if (record.html !== undefined) {
|
|
108
|
+
response.status(200).type('html').send(record.html);
|
|
109
|
+
return [2 /*return*/];
|
|
110
|
+
}
|
|
111
|
+
response
|
|
112
|
+
.status(200)
|
|
113
|
+
.type('text')
|
|
114
|
+
.send((_c = record.text) !== null && _c !== void 0 ? _c : '');
|
|
115
|
+
return [2 /*return*/];
|
|
116
|
+
});
|
|
117
|
+
}); },
|
|
118
|
+
};
|
|
119
|
+
//# sourceMappingURL=devMail.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devMail.js","sourceRoot":"","sources":["../../../src/routes/devMail.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,wDAAmD;AAEnD;;;;;;;;;;;;;;GAcG;AACH,IAAM,aAAa,GAAG,EAAE,CAAC;AAEzB,IAAM,SAAS,GAAG,sBAChB,OAAA,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,CAAC,MAAA,OAAO,CAAC,GAAG,CAAC,oBAAoB,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAA,EAAA,CAAC;AAE7E,QAAA,OAAO,GAAU;IAC5B,IAAI,EAAE,WAAW;IACjB,MAAM,EAAE,KAAK;IACb,SAAS,EAAE,UAAO,OAAO,EAAE,QAAQ;;;;YACjC,IAAI,CAAC,SAAS,EAAE,EAAE;gBAChB,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC5B,sBAAO;aACR;YACK,SAAS,GAAG,MAAM,CAAC,MAAA,OAAO,CAAC,KAAK,0CAAE,CAAC,CAAC,CAAC;YACrC,KAAK,GAAG,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,uBAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;YAC9G,QAAQ,GAAG,uBAAQ,CAAC,GAAG,EAAE;iBAC5B,IAAI,CAAC,KAAK,CAAC;iBACX,GAAG,CAAC,UAAC,EAA4C;oBAA1C,EAAE,QAAA,EAAE,EAAE,QAAA,EAAE,IAAI,UAAA,EAAE,EAAE,QAAA,EAAE,OAAO,aAAA,EAAE,IAAI,UAAA,EAAE,OAAO,aAAA;gBAAO,OAAA,CAAC;oBACtD,EAAE,IAAA;oBACF,EAAE,IAAA;oBACF,IAAI,MAAA;oBACJ,EAAE,IAAA;oBACF,OAAO,SAAA;oBACP,IAAI,MAAA;oBACJ,OAAO,SAAA;oBACP,GAAG,EAAE,oBAAa,EAAE,CAAE;iBACvB,CAAC;YATqD,CASrD,CAAC,CAAC;YACN,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,QAAQ,UAAA,EAAE,CAAC,CAAC;;;SACzC;CACF,CAAC;AAEW,QAAA,cAAc,GAAU;IACnC,IAAI,EAAE,eAAe;IACrB,MAAM,EAAE,KAAK;IACb,SAAS,EAAE,UAAO,OAAO,EAAE,QAAQ;;;;YACjC,IAAI,CAAC,SAAS,EAAE,EAAE;gBAChB,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC5B,sBAAO;aACR;YACK,MAAM,GAAG,uBAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,MAAA,MAAA,OAAO,CAAC,MAAM,0CAAE,EAAE,mCAAI,EAAE,CAAC,CAAC,CAAC;YACpE,IAAI,CAAC,MAAM,EAAE;gBACX,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;gBAC5B,sBAAO;aACR;YACD,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE;gBAC7B,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBACpD,sBAAO;aACR;YACD,QAAQ;iBACL,MAAM,CAAC,GAAG,CAAC;iBACX,IAAI,CAAC,MAAM,CAAC;iBACZ,IAAI,CAAC,MAAA,MAAM,CAAC,IAAI,mCAAI,EAAE,CAAC,CAAC;;;SAC5B;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DevMail.test.d.ts","sourceRoot":"","sources":["../../test/DevMail.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
+
function step(op) {
|
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
+
switch (op[0]) {
|
|
21
|
+
case 0: case 1: t = op; break;
|
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
+
default:
|
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
+
if (t[2]) _.ops.pop();
|
|
31
|
+
_.trys.pop(); continue;
|
|
32
|
+
}
|
|
33
|
+
op = body.call(thisArg, _);
|
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
var email_server_1 = require("@proteinjs/email-server");
|
|
40
|
+
var devMail_1 = require("../src/routes/devMail");
|
|
41
|
+
/**
|
|
42
|
+
* `GET /dev/mail` and `GET /dev/mail/<id>` — the dev-only door onto the mail sink, gated exactly
|
|
43
|
+
* like `/dev/login`: `DEVELOPMENT` AND `DEV_AUTO_LOGIN_EMAIL`, else 404 as if unregistered. With
|
|
44
|
+
* the gates open, the last invite a development sender recorded is readable — its link off the
|
|
45
|
+
* list, its rendered html off the message — so a lane never needs a real inbox. No database:
|
|
46
|
+
* the sink is the process's own ring.
|
|
47
|
+
*/
|
|
48
|
+
var ENV_EMAIL = 'dev@test.local';
|
|
49
|
+
var invoke = function (route, _a) {
|
|
50
|
+
var _b = _a === void 0 ? {} : _a, query = _b.query, params = _b.params;
|
|
51
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
|
52
|
+
var outcome, response;
|
|
53
|
+
return __generator(this, function (_c) {
|
|
54
|
+
switch (_c.label) {
|
|
55
|
+
case 0:
|
|
56
|
+
outcome = {};
|
|
57
|
+
response = {
|
|
58
|
+
status: function (code) {
|
|
59
|
+
outcome.status = code;
|
|
60
|
+
return this;
|
|
61
|
+
},
|
|
62
|
+
type: function (kind) {
|
|
63
|
+
outcome.type = kind;
|
|
64
|
+
return this;
|
|
65
|
+
},
|
|
66
|
+
send: function (body) {
|
|
67
|
+
outcome.body = body;
|
|
68
|
+
},
|
|
69
|
+
json: function (body) {
|
|
70
|
+
outcome.body = body;
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
return [4 /*yield*/, route.onRequest({ query: query !== null && query !== void 0 ? query : {}, params: params !== null && params !== void 0 ? params : {} }, response)];
|
|
74
|
+
case 1:
|
|
75
|
+
_c.sent();
|
|
76
|
+
return [2 /*return*/, outcome];
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
var INVITE_LINK = 'http://localhost:7985/auth/signup?token=abc123';
|
|
82
|
+
var INVITE_HTML = "<html><body><p>You are invited.</p><a href=\"".concat(INVITE_LINK, "\">Accept</a></body></html>");
|
|
83
|
+
/** The product's path onto the sink: a development sender with a real-looking SMTP config, no opt-in. */
|
|
84
|
+
var sendInviteThroughSender = function (to) { return __awaiter(void 0, void 0, void 0, function () {
|
|
85
|
+
return __generator(this, function (_a) {
|
|
86
|
+
switch (_a.label) {
|
|
87
|
+
case 0: return [4 /*yield*/, new email_server_1.EmailSender({
|
|
88
|
+
host: 'smtp.test.local',
|
|
89
|
+
port: 465,
|
|
90
|
+
secure: true,
|
|
91
|
+
auth: { user: 'mailbox@test.local', pass: 'unused' },
|
|
92
|
+
from: '"Example" <hi@example.com>',
|
|
93
|
+
}).sendEmail({ to: to, subject: "You're invited", text: "Accept your invite: ".concat(INVITE_LINK), html: INVITE_HTML })];
|
|
94
|
+
case 1:
|
|
95
|
+
_a.sent();
|
|
96
|
+
return [2 /*return*/];
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}); };
|
|
100
|
+
describe('devMail routes', function () {
|
|
101
|
+
var originalEnv = {
|
|
102
|
+
DEVELOPMENT: process.env.DEVELOPMENT,
|
|
103
|
+
DEV_AUTO_LOGIN_EMAIL: process.env.DEV_AUTO_LOGIN_EMAIL,
|
|
104
|
+
EMAIL_TRANSPORT: process.env.EMAIL_TRANSPORT,
|
|
105
|
+
EMAIL_ALLOW_REAL_SEND: process.env.EMAIL_ALLOW_REAL_SEND,
|
|
106
|
+
};
|
|
107
|
+
beforeEach(function () {
|
|
108
|
+
process.env.DEVELOPMENT = 'true';
|
|
109
|
+
process.env.DEV_AUTO_LOGIN_EMAIL = ENV_EMAIL;
|
|
110
|
+
delete process.env.EMAIL_TRANSPORT;
|
|
111
|
+
delete process.env.EMAIL_ALLOW_REAL_SEND;
|
|
112
|
+
email_server_1.MailSink.get().clear();
|
|
113
|
+
});
|
|
114
|
+
afterEach(function () {
|
|
115
|
+
for (var _i = 0, _a = Object.entries(originalEnv); _i < _a.length; _i++) {
|
|
116
|
+
var _b = _a[_i], key = _b[0], value = _b[1];
|
|
117
|
+
if (value === undefined) {
|
|
118
|
+
delete process.env[key];
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
process.env[key] = value;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
it("lists the last sent messages newest first — the invite's recipient, subject, first link and timestamp — and the message renders its html", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
126
|
+
var list, messages, message;
|
|
127
|
+
return __generator(this, function (_a) {
|
|
128
|
+
switch (_a.label) {
|
|
129
|
+
case 0: return [4 /*yield*/, sendInviteThroughSender('earlier@test.local')];
|
|
130
|
+
case 1:
|
|
131
|
+
_a.sent();
|
|
132
|
+
return [4 /*yield*/, sendInviteThroughSender('lane-after@test.local')];
|
|
133
|
+
case 2:
|
|
134
|
+
_a.sent();
|
|
135
|
+
return [4 /*yield*/, invoke(devMail_1.devMail)];
|
|
136
|
+
case 3:
|
|
137
|
+
list = _a.sent();
|
|
138
|
+
expect(list.status).toBe(200);
|
|
139
|
+
messages = list.body.messages;
|
|
140
|
+
expect(messages).toHaveLength(2);
|
|
141
|
+
expect(messages[0]).toMatchObject({
|
|
142
|
+
to: ['lane-after@test.local'],
|
|
143
|
+
subject: "You're invited",
|
|
144
|
+
link: INVITE_LINK,
|
|
145
|
+
from: 'hi@example.com',
|
|
146
|
+
refused: true,
|
|
147
|
+
});
|
|
148
|
+
expect(typeof messages[0].id).toBe('string');
|
|
149
|
+
expect(Date.parse(String(messages[0].at))).not.toBeNaN();
|
|
150
|
+
expect(messages[0].url).toBe("/dev/mail/".concat(messages[0].id));
|
|
151
|
+
expect(messages[1].to).toEqual(['earlier@test.local']);
|
|
152
|
+
return [4 /*yield*/, invoke(devMail_1.devMailMessage, { params: { id: String(messages[0].id) } })];
|
|
153
|
+
case 4:
|
|
154
|
+
message = _a.sent();
|
|
155
|
+
expect(message.status).toBe(200);
|
|
156
|
+
expect(message.type).toBe('html');
|
|
157
|
+
expect(message.body).toBe(INVITE_HTML);
|
|
158
|
+
return [2 /*return*/];
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}); });
|
|
162
|
+
it('?n= bounds the list; a text-only message renders as text; an unknown id is 404', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
163
|
+
var one, all, messages, plain, _a;
|
|
164
|
+
return __generator(this, function (_b) {
|
|
165
|
+
switch (_b.label) {
|
|
166
|
+
case 0:
|
|
167
|
+
process.env.EMAIL_TRANSPORT = 'sink';
|
|
168
|
+
return [4 /*yield*/, new email_server_1.EmailSender({ host: 'h', port: 465, secure: true, from: '"Example" <hi@example.com>' }).sendEmail({
|
|
169
|
+
to: 'a@test.local',
|
|
170
|
+
subject: 'Plain',
|
|
171
|
+
text: 'just text',
|
|
172
|
+
})];
|
|
173
|
+
case 1:
|
|
174
|
+
_b.sent();
|
|
175
|
+
return [4 /*yield*/, sendInviteThroughSender('b@test.local')];
|
|
176
|
+
case 2:
|
|
177
|
+
_b.sent();
|
|
178
|
+
return [4 /*yield*/, invoke(devMail_1.devMail, { query: { n: '1' } })];
|
|
179
|
+
case 3:
|
|
180
|
+
one = _b.sent();
|
|
181
|
+
expect(one.body.messages).toHaveLength(1);
|
|
182
|
+
return [4 /*yield*/, invoke(devMail_1.devMail, { query: { n: 'garbage' } })];
|
|
183
|
+
case 4:
|
|
184
|
+
all = _b.sent();
|
|
185
|
+
messages = all.body.messages;
|
|
186
|
+
expect(messages.map(function (m) { return m.subject; })).toEqual(["You're invited", 'Plain']);
|
|
187
|
+
expect(messages[1].refused).toBe(false);
|
|
188
|
+
return [4 /*yield*/, invoke(devMail_1.devMailMessage, { params: { id: messages[1].id } })];
|
|
189
|
+
case 5:
|
|
190
|
+
plain = _b.sent();
|
|
191
|
+
expect(plain.status).toBe(200);
|
|
192
|
+
expect(plain.type).toBe('text');
|
|
193
|
+
expect(plain.body).toBe('just text');
|
|
194
|
+
_a = expect;
|
|
195
|
+
return [4 /*yield*/, invoke(devMail_1.devMailMessage, { params: { id: 'nope' } })];
|
|
196
|
+
case 6:
|
|
197
|
+
_a.apply(void 0, [(_b.sent()).status]).toBe(404);
|
|
198
|
+
return [2 /*return*/];
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
}); });
|
|
202
|
+
it('DEVELOPMENT unset → 404 on both paths, even with messages in the sink', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
203
|
+
var record, _a, _b;
|
|
204
|
+
return __generator(this, function (_c) {
|
|
205
|
+
switch (_c.label) {
|
|
206
|
+
case 0: return [4 /*yield*/, sendInviteThroughSender('lane@test.local')];
|
|
207
|
+
case 1:
|
|
208
|
+
_c.sent();
|
|
209
|
+
record = email_server_1.MailSink.get().list()[0];
|
|
210
|
+
delete process.env.DEVELOPMENT;
|
|
211
|
+
_a = expect;
|
|
212
|
+
return [4 /*yield*/, invoke(devMail_1.devMail)];
|
|
213
|
+
case 2:
|
|
214
|
+
_a.apply(void 0, [(_c.sent()).status]).toBe(404);
|
|
215
|
+
_b = expect;
|
|
216
|
+
return [4 /*yield*/, invoke(devMail_1.devMailMessage, { params: { id: record.id } })];
|
|
217
|
+
case 3:
|
|
218
|
+
_b.apply(void 0, [(_c.sent()).status]).toBe(404);
|
|
219
|
+
return [2 /*return*/];
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
}); });
|
|
223
|
+
it('DEV_AUTO_LOGIN_EMAIL unset (or blank) → 404 on both paths', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
224
|
+
var record, _a, _b, _c;
|
|
225
|
+
return __generator(this, function (_d) {
|
|
226
|
+
switch (_d.label) {
|
|
227
|
+
case 0: return [4 /*yield*/, sendInviteThroughSender('lane@test.local')];
|
|
228
|
+
case 1:
|
|
229
|
+
_d.sent();
|
|
230
|
+
record = email_server_1.MailSink.get().list()[0];
|
|
231
|
+
delete process.env.DEV_AUTO_LOGIN_EMAIL;
|
|
232
|
+
_a = expect;
|
|
233
|
+
return [4 /*yield*/, invoke(devMail_1.devMail)];
|
|
234
|
+
case 2:
|
|
235
|
+
_a.apply(void 0, [(_d.sent()).status]).toBe(404);
|
|
236
|
+
_b = expect;
|
|
237
|
+
return [4 /*yield*/, invoke(devMail_1.devMailMessage, { params: { id: record.id } })];
|
|
238
|
+
case 3:
|
|
239
|
+
_b.apply(void 0, [(_d.sent()).status]).toBe(404);
|
|
240
|
+
process.env.DEV_AUTO_LOGIN_EMAIL = ' ';
|
|
241
|
+
_c = expect;
|
|
242
|
+
return [4 /*yield*/, invoke(devMail_1.devMail)];
|
|
243
|
+
case 4:
|
|
244
|
+
_c.apply(void 0, [(_d.sent()).status]).toBe(404);
|
|
245
|
+
return [2 /*return*/];
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
}); });
|
|
249
|
+
});
|
|
250
|
+
//# sourceMappingURL=DevMail.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DevMail.test.js","sourceRoot":"","sources":["../../test/DevMail.test.ts"],"names":[],"mappings":"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"}
|