11import { describe , expect , test } from "bun:test" ;
22
33import {
4- PRODUCT_GITHUB_LABEL ,
5- PRODUCT_GITHUB_URL ,
6- PRODUCT_SITE_LABEL ,
7- PRODUCT_SITE_URL ,
8- } from "../branding.js" ;
9- import { callbackPageHtml , humanizeIdentifier } from "./callback-page.js" ;
10- import { authorizationDoneHtml } from "./oauth/callback-server.js" ;
4+ authorizationDoneHtml ,
5+ callbackPageHtml ,
6+ humanizeIdentifier ,
7+ type CallbackPageCopy ,
8+ } from "./callback-page.js" ;
9+
10+ const copy : CallbackPageCopy = {
11+ productName : "Fixture Product" ,
12+ siteUrl : "https://fixture.example" ,
13+ siteLabel : "fixture.example" ,
14+ githubUrl : "https://github.com/fixture" ,
15+ githubLabel : "github.com/fixture" ,
16+ } ;
1117
1218describe ( "humanizeIdentifier" , ( ) => {
1319 test ( "machine identifiers lose their separators and lead with a capital" , ( ) => {
@@ -24,59 +30,57 @@ describe("humanizeIdentifier", () => {
2430
2531describe ( "callbackPageHtml" , ( ) => {
2632 test ( "success names the server that connected" , ( ) => {
27- const html = callbackPageHtml ( { subject : "linear" } ) ;
33+ const html = callbackPageHtml ( { subject : "linear" } , copy ) ;
2834 expect ( html ) . toContain ( "Linear connected successfully" ) ;
2935 expect ( html ) . not . toContain ( "access_denied" ) ;
3036 } ) ;
3137
3238 test ( "provider authorization waits for native setup before claiming connection" , ( ) => {
33- const html = authorizationDoneHtml ( "Codex" ) ;
39+ const html = authorizationDoneHtml ( "Codex" , copy ) ;
3440 expect ( html ) . toContain ( "Codex authorization received" ) ;
3541 expect ( html ) . toContain ( "finish setup" ) ;
3642 expect ( html ) . not . toContain ( "connected successfully" ) ;
3743 } ) ;
3844
3945 test ( "failure names the server and the humanized reason" , ( ) => {
40- const html = callbackPageHtml ( {
41- subject : "granola" ,
42- error : "access_denied" ,
43- } ) ;
46+ const html = callbackPageHtml (
47+ {
48+ subject : "granola" ,
49+ error : "access_denied" ,
50+ } ,
51+ copy ,
52+ ) ;
4453 expect ( html ) . toContain ( "Granola failed to connect" ) ;
4554 expect ( html ) . toContain ( "Access denied." ) ;
4655 expect ( html ) . not . toContain ( "access_denied" ) ;
4756 } ) ;
4857
4958 test ( "an unnamed authorization still renders both outcomes" , ( ) => {
50- expect ( callbackPageHtml ( ) ) . toContain ( "Authorization complete" ) ;
51- expect ( callbackPageHtml ( { error : "server_error" } ) ) . toContain (
59+ expect ( callbackPageHtml ( { } , copy ) ) . toContain ( "Authorization complete" ) ;
60+ expect ( callbackPageHtml ( { error : "server_error" } , copy ) ) . toContain (
5261 "Authorization did not complete" ,
5362 ) ;
5463 } ) ;
5564
5665 test ( "the subject is escaped rather than pasted into markup" , ( ) => {
57- expect ( callbackPageHtml ( { subject : "<script>x</script>" } ) ) . not . toContain (
58- "<script>x" ,
59- ) ;
66+ expect (
67+ callbackPageHtml ( { subject : "<script>x</script>" } , copy ) ,
68+ ) . not . toContain ( "<script>x" ) ;
6069 } ) ;
6170
62- test ( "the footer links to the product site and the GitHub org " , ( ) => {
63- const html = callbackPageHtml ( { subject : "linear" } ) ;
71+ test ( "the footer links to the injected site and GitHub copy " , ( ) => {
72+ const html = callbackPageHtml ( { subject : "linear" } , copy ) ;
6473 const link = ( url : string , label : string ) =>
6574 `<a href="${ url } " target="_blank" rel="noopener noreferrer">${ label } </a>` ;
66- expect ( html ) . toContain ( link ( PRODUCT_SITE_URL , PRODUCT_SITE_LABEL ) ) ;
67- expect ( html ) . toContain ( link ( PRODUCT_GITHUB_URL , PRODUCT_GITHUB_LABEL ) ) ;
68- } ) ;
69-
70- test ( "each footer label names the destination its URL actually points at" , ( ) => {
71- expect ( PRODUCT_SITE_URL ) . toContain ( PRODUCT_SITE_LABEL ) ;
72- expect ( PRODUCT_GITHUB_URL ) . toContain ( PRODUCT_GITHUB_LABEL ) ;
75+ expect ( html ) . toContain ( link ( copy . siteUrl , copy . siteLabel ) ) ;
76+ expect ( html ) . toContain ( link ( copy . githubUrl , copy . githubLabel ) ) ;
7377 } ) ;
7478
7579 // An allowlist rather than a shape match: an unexpected origin fails loudly
7680 // instead of passing because it happened to be wrapped in an anchor tag.
7781 const allowedOrigins = new Set ( [
78- PRODUCT_SITE_URL ,
79- PRODUCT_GITHUB_URL ,
82+ copy . siteUrl ,
83+ copy . githubUrl ,
8084 // The SVG namespace the wordmark declares; a URI, never fetched.
8185 "http://www.w3.org/2000/svg" ,
8286 ] ) ;
@@ -97,7 +101,7 @@ describe("callbackPageHtml", () => {
97101 [ "failure" , { subject : "linear" , error : "access_denied" } ] ,
98102 ] as const ) {
99103 test ( `the ${ outcome } page names no off-machine origin beyond the footer links` , ( ) => {
100- const html = callbackPageHtml ( page ) ;
104+ const html = callbackPageHtml ( page , copy ) ;
101105 expect ( offMachineOrigins ( html ) ) . toEqual ( [ ] ) ;
102106 expect ( html ) . not . toMatch (
103107 / \b (?: f e t c h | X M L H t t p R e q u e s t | W e b S o c k e t | E v e n t S o u r c e | s e n d B e a c o n | i m p o r t S c r i p t s ) \s * \( / ,
0 commit comments