This commit is contained in:
Leandro Facchinetti 2020-03-21 11:58:28 -04:00
parent 30196474c5
commit 4f73d3e118
3 changed files with 26 additions and 23 deletions

View File

@ -2,7 +2,14 @@
<h1><a href="https://www.kill-the-newsletter.com">Kill the Newsletter!</a></h1> <h1><a href="https://www.kill-the-newsletter.com">Kill the Newsletter!</a></h1>
<p><strong>Convert email newsletters into Atom feeds</strong></p> <p><strong>Convert email newsletters into Atom feeds</strong></p>
<p><img alt="Convert email newsletters into Atom feeds" src="static/logo.png" width="150" /></p> <p><img alt="Convert email newsletters into Atom feeds" src="static/logo.png" width="150" /></p>
<p><strong><a href="https://github.com/leafac/www.kill-the-newsletter.com">Source</a></strong><img alt=".github/workflows/main.yml" src="https://github.com/leafac/www.kill-the-newsletter.com/workflows/.github/workflows/main.yml/badge.svg" /></p> <p>
<a href="https://github.com/leafac/www.kill-the-newsletter.com">
<img alt="Source" src="https://img.shields.io/badge/Source---" />
</a>
<a href="https://github.com/leafac/www.kill-the-newsletter.com/actions">
<img alt=".github/workflows/main.yml" src="https://github.com/leafac/www.kill-the-newsletter.com/workflows/.github/workflows/main.yml/badge.svg" />
</a>
</p>
</div> </div>
# Running Locally # Running Locally

View File

@ -21,7 +21,7 @@ export const webServer = express()
) )
.post("/", (req, res) => { .post("/", (req, res) => {
const name = req.body.name; const name = req.body.name;
const identifier = newIdentifier(); const identifier = createIdentifier();
fs.writeFileSync( fs.writeFileSync(
feedPath(identifier), feedPath(identifier),
renderXML(Feed({ name, identifier })) renderXML(Feed({ name, identifier }))
@ -224,7 +224,7 @@ function Entry({
}) { }) {
return { return {
entry: { entry: {
id: urn(newIdentifier()), id: urn(createIdentifier()),
title, title,
author: { name: author }, author: { name: author },
updated: now(), updated: now(),
@ -233,7 +233,7 @@ function Entry({
}; };
} }
function newIdentifier(): string { function createIdentifier(): string {
return cryptoRandomString({ return cryptoRandomString({
length: 20, length: 20,
characters: "1234567890qwertyuiopasdfghjklzxcvbnm" characters: "1234567890qwertyuiopasdfghjklzxcvbnm"

View File

@ -6,25 +6,19 @@ import qs from "qs";
test("create feed", async () => { test("create feed", async () => {
const identifier = await createFeed(); const identifier = await createFeed();
expect(await readFeed(identifier)).toMatch("My Feed"); expect(await getFeed(identifier)).toMatch("My Feed");
}); });
describe("receive email", () => { describe("receive email", () => {
const transporter = nodemailer.createTransport({
host: "localhost",
port: 2525,
tls: { rejectUnauthorized: false }
});
test("HTML content", async () => { test("HTML content", async () => {
const identifier = await createFeed(); const identifier = await createFeed();
await transporter.sendMail({ await emailClient.sendMail({
from: "publisher@example.com", from: "publisher@example.com",
to: `${identifier}@kill-the-newsletter.com`, to: `${identifier}@kill-the-newsletter.com`,
subject: "New Message", subject: "New Message",
html: "<p>HTML content</p>" html: "<p>HTML content</p>"
}); });
const feed = await readFeed(identifier); const feed = await getFeed(identifier);
expect(feed).toMatch("publisher@example.com"); expect(feed).toMatch("publisher@example.com");
expect(feed).toMatch("New Message"); expect(feed).toMatch("New Message");
expect(feed).toMatch("HTML content"); expect(feed).toMatch("HTML content");
@ -32,29 +26,29 @@ describe("receive email", () => {
test("text content", async () => { test("text content", async () => {
const identifier = await createFeed(); const identifier = await createFeed();
await transporter.sendMail({ await emailClient.sendMail({
from: "publisher@example.com", from: "publisher@example.com",
to: `${identifier}@kill-the-newsletter.com`, to: `${identifier}@kill-the-newsletter.com`,
subject: "New Message", subject: "New Message",
text: "TEXT content" text: "TEXT content"
}); });
const feed = await readFeed(identifier); const feed = await getFeed(identifier);
expect(feed).toMatch("TEXT content"); expect(feed).toMatch("TEXT content");
}); });
test("truncation", async () => { test("truncation", async () => {
const identifier = await createFeed(); const identifier = await createFeed();
for (const repetition of [...new Array(4).keys()]) for (const repetition of [...new Array(4).keys()])
await transporter.sendMail({ await emailClient.sendMail({
from: "publisher@example.com", from: "publisher@example.com",
to: `${identifier}@kill-the-newsletter.com`, to: `${identifier}@kill-the-newsletter.com`,
subject: "New Message", subject: "New Message",
text: `REPETITION ${repetition} `.repeat(10_000) text: `REPETITION ${repetition} `.repeat(10_000)
}); });
const feed = await readFeed(identifier); const feed = await getFeed(identifier);
expect(feed).toMatch("REPETITION 3"); expect(feed).toMatch("REPETITION 3");
expect(feed).not.toMatch("REPETITION 0"); expect(feed).not.toMatch("REPETITION 0");
}, 10_000); });
}); });
afterAll(() => { afterAll(() => {
@ -63,10 +57,13 @@ afterAll(() => {
emailServer.close(() => {}); emailServer.close(() => {});
}); });
const webClient = axios.create({ baseURL: "http://localhost:8000" });
const emailClient = nodemailer.createTransport("smtp://localhost:2525");
async function createFeed(): Promise<string> { async function createFeed(): Promise<string> {
return ( return (
await axios.post( await webClient.post(
"http://localhost:8000", "/",
qs.stringify({ qs.stringify({
name: "My Feed" name: "My Feed"
}) })
@ -74,7 +71,6 @@ async function createFeed(): Promise<string> {
).data.match(/(\w{20}).xml/)![1]; ).data.match(/(\w{20}).xml/)![1];
} }
async function readFeed(identifier: string): Promise<string> { async function getFeed(identifier: string): Promise<string> {
return (await axios.get(`http://localhost:8000/feeds/${identifier}.xml`)) return (await webClient.get(`/feeds/${identifier}.xml`)).data;
.data;
} }