trypost/tests/Feature
Paulo Castellano 6496588bbc
Defuse links in X posts to avoid the link-post fee (#308)
X bills a post containing a URL at a much higher rate than a plain post, and
its algorithm demotes link posts. The X version of a post now rewrites every
URL non-clickable (https://example.com/post becomes example(.)com/post):
scheme and www. dropped, every dot of the host replaced with (.).

Leaving a single dot intact would still leave a resolvable domain for X to
detect, so all of them are broken. A scheme or www. proves a token is a URL on
its own; a bare host only counts when its last label is a delegated TLD, which
is the one thing telling acme.com apart from Node.js. That check runs against
App\Support\LinkTlds, generated from the whole IANA root zone in every form a
TLD can appear in a post -- ASCII, punycode and the Unicode it decodes to --
because whatever X links is what X bills, so a hand-picked subset would leave
us paying for its gaps. If the regex engine bails out on pathological input the
original content is returned instead of crashing the publisher.

The transform lives in the Platform::X arm of ContentSanitizer, so it reaches
publishing and the app/API/MCP previews from one place and cannot touch any
other network. Off by default; opt in with X_DEFUSE_LINKS.

The editor counts characters and renders its preview client-side and cannot ask
the server on every keystroke, so the rewrite is mirrored in TypeScript. PHP
stays the source of truth: a parity test fails if the two TLD sets drift, and a
browser test drives the real editor so the mirror is covered rather than
assumed. Without it the composer promised text the network never receives.

Character limits now measure the text a reader will see: sanitized, then with
markup resolved away. Measuring the raw draft blocked saving posts that publish
fine and let through posts the network rejects, and counted the editor's HTML
toward the limit. Measuring the sanitized form alone would have counted
Telegram's escaped entities, rejecting messages Telegram accepts.

Empty content is handled once inside the sanitizer instead of by a guard
repeated at every call site.
2026-08-29 15:31:05 -03:00
..
Actions feat: fire signup/checkout PostHog events from the backend (#277) 2026-08-12 11:47:47 -03:00
Ai Fix OpenRouter via laravel/ai default provider (revises #216) (#220) 2026-08-10 21:38:50 -03:00
Api Make the test suite pass on MySQL (#307) 2026-08-29 11:05:33 -03:00
App/Post refactor(posts): return the card display domain from the backend 2026-07-17 16:24:23 -03:00
Auth Allow multiple social accounts per network via env (#286) 2026-08-25 07:28:14 -03:00
Automation Make the test suite pass on MySQL (#307) 2026-08-29 11:05:33 -03:00
Billing Make Stripe Checkout configurable via billing env knobs (#252) 2026-08-07 21:25:32 -03:00
Brand Structure brand voice and make generated copy platform-aware 2026-06-12 17:09:39 -03:00
Commands Allow multiple social accounts per network via env (#286) 2026-08-25 07:28:14 -03:00
Database test(auth): cover remaining surfaces of the registration gate 2026-05-19 12:03:41 -03:00
Discord fix(channels): restrict Discord picker to postable channels the bot can use 2026-06-16 16:34:02 -03:00
Image Harden automations module: full-post generation, reliable runs, editor UX 2026-06-10 20:45:01 -03:00
Jobs Make the test suite pass on MySQL (#307) 2026-08-29 11:05:33 -03:00
Listeners feat: fire signup/checkout PostHog events from the backend (#277) 2026-08-12 11:47:47 -03:00
Mail feat: proactive connection check for at-risk posts + SocialAccount name centralization (#256) 2026-08-09 11:10:39 -03:00
Mcp Make the test suite pass on MySQL (#307) 2026-08-29 11:05:33 -03:00
Middleware Activation checklist + MCP OAuth authorize UX (#239) (#250) 2026-08-07 20:34:43 -03:00
Migrations Activation checklist + MCP OAuth authorize UX (#239) (#250) 2026-08-07 20:34:43 -03:00
Models Allow multiple social accounts per network via env (#286) 2026-08-25 07:28:14 -03:00
Observers Allow multiple social accounts per network via env (#286) 2026-08-25 07:28:14 -03:00
Onboarding Activation checklist + MCP OAuth authorize UX (#239) (#250) 2026-08-07 20:34:43 -03:00
Passport fix: stop reporting client-error OAuth exceptions to Nightwatch (#261) 2026-08-09 12:01:12 -03:00
Permissions Allow account owners to delete workspaces (#208) 2026-08-01 13:00:38 -04:00
Services Defuse links in X posts to avoid the link-post fee (#308) 2026-08-29 15:31:05 -03:00
Settings Add Ukrainian as a supported platform language (#219) 2026-08-05 19:45:30 -03:00
Social Connect the Pages a login only reaches through a Business Portfolio (#301) 2026-08-26 10:42:59 -03:00
SocialAccount Make the test suite pass on MySQL (#307) 2026-08-29 11:05:33 -03:00
Welcome Add social connect step to welcome before Stripe (#293) 2026-08-17 19:37:43 -03:00
Workspace feat: @mentions in comments, AI Action layer + MCP tools, settings tabs 2026-05-01 20:59:03 -03:00
AcceptInviteControllerTest.php Allow account owners to delete workspaces (#208) 2026-08-01 13:00:38 -04:00
AccountControllerTest.php refactor: reorganize settings UI, migrate post templates to a file-based registry, and remove legacy video generation features 2026-05-03 13:44:13 -03:00
AiUsageLogTest.php feat: per-workspace pricing, onboarding, and billing overhaul 2026-06-21 20:40:03 -03:00
AnalyticsResilienceTest.php Remove the X API reads that buy nothing (#299) 2026-08-20 17:58:16 -03:00
ApiKeyControllerTest.php Scope MCP OAuth tokens to user + workspace (#222) (#245) 2026-08-06 21:59:34 -03:00
AssetControllerTest.php Use whereLike for search so MySQL works alongside PostgreSQL (#302) 2026-08-26 10:59:31 -03:00
BackfillMcpOAuthWorkspaceTest.php Scope MCP OAuth tokens to user + workspace (#222) (#245) 2026-08-06 21:59:34 -03:00
BillingControllerTest.php feat: fire signup/checkout PostHog events from the backend (#277) 2026-08-12 11:47:47 -03:00
ChunkedAssetReceiverTest.php fix: chunked upload session collision + workspace name i18n (#263) 2026-08-09 14:06:47 -03:00
ChunkedCloudUploadTest.php fix: chunked upload session collision + workspace name i18n (#263) 2026-08-09 14:06:47 -03:00
ChunkedUploadFilenameEncodingTest.php fix: chunked upload session collision + workspace name i18n (#263) 2026-08-09 14:06:47 -03:00
ContentTypeMediaRulesShareTest.php Restore media-rule parity and release failed MCP upload tokens. 2026-07-24 22:37:57 -03:00
ExampleTest.php refactor: settings redesign, Spanish translations, language system, strict_types 2026-03-30 00:20:43 -03:00
GitHubAuthToggleTest.php feat: fire signup/checkout PostHog events from the backend (#277) 2026-08-12 11:47:47 -03:00
GoogleAuthToggleTest.php feat: fire signup/checkout PostHog events from the backend (#277) 2026-08-12 11:47:47 -03:00
InstagramFacebookIntegrationTest.php Allow multiple social accounts per network via env (#286) 2026-08-25 07:28:14 -03:00
InvitePermissionTest.php refactor: address code review for per-workspace pricing 2026-06-21 21:28:47 -03:00
LocalizationParityTest.php Allow account owners to delete workspaces (#208) 2026-08-01 13:00:38 -04:00
McpOAuthWorkspaceBindingTest.php Activation checklist + MCP OAuth authorize UX (#239) (#250) 2026-08-07 20:34:43 -03:00
McpSettingsControllerTest.php Make the test suite pass on MySQL (#307) 2026-08-29 11:05:33 -03:00
NotificationControllerTest.php refactor: remove onboarding flow, implement brand analysis services, and replace setup middleware with account readiness checks 2026-04-16 23:05:51 -03:00
PlanSeederTest.php feat: per-workspace pricing, onboarding, and billing overhaul 2026-06-21 20:40:03 -03:00
PlanTest.php chore: remove legacy plan tiers (starter/plus/pro/max) 2026-06-22 15:31:32 -03:00
PostCommentControllerTest.php feat: @mentions in comments, AI Action layer + MCP tools, settings tabs 2026-05-01 20:59:03 -03:00
PostControllerTest.php Defuse links in X posts to avoid the link-post fee (#308) 2026-08-29 15:31:05 -03:00
PostMediaAltTextValidationTest.php Harden per-image alt text across publishers, validation, and attach paths 2026-07-16 13:55:33 -03:00
PostSearchTest.php refactor: remove onboarding flow, implement brand analysis services, and replace setup middleware with account readiness checks 2026-04-16 23:05:51 -03:00
SocialAccountModelTest.php Allow multiple social accounts per network via env (#286) 2026-08-25 07:28:14 -03:00
SocialAccountToggleTest.php refactor: remove onboarding flow, implement brand analysis services, and replace setup middleware with account readiness checks 2026-04-16 23:05:51 -03:00
SocialControllerTest.php Allow multiple social accounts per network via env (#286) 2026-08-25 07:28:14 -03:00
SocialLoginControllerTest.php feat: fire signup/checkout PostHog events from the backend (#277) 2026-08-12 11:47:47 -03:00
TikTokI18nStringsTest.php fix(tiktok): align UX strings and render processing notice for app review 2026-05-29 10:16:04 -03:00
UpdatePostRequestTest.php Add optional Pinterest pin title and destination link (#232) 2026-08-05 18:15:50 -03:00
UsageControllerTest.php refactor: reorganize settings UI, migrate post templates to a file-based registry, and remove legacy video generation features 2026-05-03 13:44:13 -03:00
VerifyWorkspaceConnectionsTest.php Remove the X API reads that buy nothing (#299) 2026-08-20 17:58:16 -03:00
WorkspaceBillingTest.php Welcome: pre-subscription funnel and member subscription-required screen (#243) 2026-08-06 11:34:50 -03:00
WorkspaceControllerTest.php Fix OpenRouter via laravel/ai default provider (revises #216) (#220) 2026-08-10 21:38:50 -03:00
WorkspaceInviteControllerTest.php Make the test suite pass on MySQL (#307) 2026-08-29 11:05:33 -03:00
WorkspaceInviteGuardTest.php Allow account owners to delete workspaces (#208) 2026-08-01 13:00:38 -04:00
WorkspaceLabelControllerTest.php Use whereLike for search so MySQL works alongside PostgreSQL (#302) 2026-08-26 10:59:31 -03:00
WorkspaceSignatureControllerTest.php Use whereLike for search so MySQL works alongside PostgreSQL (#302) 2026-08-26 10:59:31 -03:00
XAnalyticsTest.php Remove the X API reads that buy nothing (#299) 2026-08-20 17:58:16 -03:00
YouTubeAnalyticsTest.php feat: proactive connection check for at-risk posts + SocialAccount name centralization (#256) 2026-08-09 11:10:39 -03:00