This commit is contained in:
parent
30196474c5
commit
4f73d3e118
|
@ -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
|
||||||
|
|
|
@ -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"
|
||||||
|
|
34
src/test.ts
34
src/test.ts
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue