Public: anyone can read this; the crew can change it.

A new issue's and pull's length limits live in one module, read by both forms #5605

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

mason/forge:mason/5587-a-new-issue-s-and-pull-s-length-limits-l → main 2 commits fork

  • Merged. mason/5587-a-new-issue-s-and-pull-s-length-limits-l was merged into main as e719cf6.

Review

Sign in to review this change.
4 files changed +48 −4
src/actions/thread_limits_words.ts added +11
@@ -0,0 +1,11 @@
1 /**
2 * What a new issue or pull says when its title or description is too long
3 * (#5587): one place, read by the issue form and the pull form alike, so the
4 * two never drift apart.
5 */
6
7 /** A title past MAX_TITLE in src/core/issues.ts. */
8 export const TITLE_TOO_LONG = "That title is too long (256 characters at most).";
9
10 /** A description past the body limit. */
11 export const BODY_TOO_LONG = "That description is too long (64 KB at most).";
src/web/pages/issues.ts +3 −2
@@ -13,6 +13,7 @@ import {
1313 import type { Issue } from "../../core/issues.ts";
1414 import { canRead, type Repo } from "../../core/repos.ts";
1515 import { privateRepoForSealed } from "../../actions/repos.ts";
16 import { BODY_TOO_LONG, TITLE_TOO_LONG } from "../../actions/thread_limits_words.ts";
1617 import { COMMENT_EMPTY, COMMENT_NOT_POSTED } from "../../actions/comment_words.ts";
1718 import { notePhase, takeSessionTime, timePhase } from "../../core/route_timing.ts";
1819 import type { Ctx } from "../../http/context.ts";
@@ -196,9 +197,9 @@ export async function newIssueSubmit(ctx: Ctx): Promise<Response> {
196197 (created.error === "empty_title"
197198 ? "An issue needs a title."
198199 : created.error === "title_too_long"
199 ? "That title is too long (256 characters at most)."
200 ? TITLE_TOO_LONG
200201 : created.error === "body_too_long"
201 ? "That description is too long (64 KB at most)."
202 ? BODY_TOO_LONG
202203 : "You cannot open an issue here.");
203204 return composePage(ctx, repo, values, message);
204205 }
src/web/pages/pulls.ts +3 −2
@@ -6,6 +6,7 @@
66 */
77
88 import { openPull } from "../../actions/pulls.ts";
9 import { BODY_TOO_LONG, TITLE_TOO_LONG } from "../../actions/thread_limits_words.ts";
910 import type { Label } from "../../core/issues.ts";
1011 import type { Pull } from "../../core/pulls.ts";
1112 import {
@@ -215,8 +216,8 @@ export async function newPullPage(ctx: Ctx): Promise<Response> {
215216
216217 const COMPOSE_ERRORS: Record<string, string> = {
217218 empty_title: "A title is required.",
218 title_too_long: "That title is too long (256 characters at most).",
219 body_too_long: "That description is too long (64 KB at most).",
219 title_too_long: TITLE_TOO_LONG,
220 body_too_long: BODY_TOO_LONG,
220221 same_branch: "Base and compare branches must differ.",
221222 unknown_base: "That base branch does not exist.",
222223 unknown_head: "That compare branch does not exist.",
test/thread-limits-words.test.ts added +31
@@ -0,0 +1,31 @@
1 /**
2 * A new issue's and pull's length limits are said from one module (#5587):
3 * the issue form and the pull form import the sentences, and neither types
4 * a copy back.
5 */
6
7 import { expect, test } from "bun:test";
8 import { readFileSync } from "node:fs";
9 import { join } from "node:path";
10 import * as words from "../src/actions/thread_limits_words.ts";
11
12 const sentences = Object.entries(words) as [string, string][];
13 const readers = ["src/web/pages/issues.ts", "src/web/pages/pulls.ts"];
14
15 test("each sentence is said, and not empty", () => {
16 expect(sentences.length).toBe(2);
17 for (const [name, sentence] of sentences) {
18 expect(typeof sentence, name).toBe("string");
19 expect(sentence.trim().length, name).toBeGreaterThan(0);
20 }
21 });
22
23 test("the forms import the sentences and type no copy of them", () => {
24 for (const file of readers) {
25 const source = readFileSync(join(import.meta.dir, "..", file), "utf8");
26 expect(source, file).toContain("actions/thread_limits_words.ts");
27 for (const [, sentence] of sentences) {
28 expect(source.includes(sentence), `${file}: ${sentence}`).toBe(false);
29 }
30 }
31 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs