22import { beforeEach , describe , expect , it } from "vitest" ;
33import type { PluginRuntime } from "../runtime-api.js" ;
44import {
5- buildMSTeamsAttachmentPlaceholder ,
65 buildMSTeamsGraphMessageUrl ,
76 buildMSTeamsMediaPayload ,
87 resolveMSTeamsInboundAttachmentPresentation ,
@@ -14,19 +13,10 @@ const TEST_HOST = "x";
1413const createUrlForHost = ( host : string , pathSegment : string ) => `https://${ host } /${ pathSegment } ` ;
1514const createTestUrl = ( pathSegment : string ) => createUrlForHost ( TEST_HOST , pathSegment ) ;
1615const TEST_URL_IMAGE = createTestUrl ( "img" ) ;
17- const TEST_URL_IMAGE_PNG = createTestUrl ( "img.png" ) ;
18- const TEST_URL_IMAGE_1_PNG = createTestUrl ( "1.png" ) ;
19- const TEST_URL_IMAGE_2_JPG = createTestUrl ( "2.jpg" ) ;
2016const TEST_URL_PDF = createTestUrl ( "x.pdf" ) ;
21- const TEST_URL_PDF_1 = createTestUrl ( "1.pdf" ) ;
22- const TEST_URL_PDF_2 = createTestUrl ( "2.pdf" ) ;
23- const TEST_URL_HTML_A = createTestUrl ( "a.png" ) ;
24- const TEST_URL_HTML_B = createTestUrl ( "b.png" ) ;
2517const CONTENT_TYPE_IMAGE_PNG = "image/png" ;
2618const CONTENT_TYPE_APPLICATION_PDF = "application/pdf" ;
2719const CONTENT_TYPE_TEXT_HTML = "text/html" ;
28- const CONTENT_TYPE_TEAMS_FILE_DOWNLOAD_INFO = "application/vnd.microsoft.teams.file.download.info" ;
29- type AttachmentPlaceholderInput = Parameters < typeof buildMSTeamsAttachmentPlaceholder > [ 0 ] ;
3020type GraphMessageUrlParams = Parameters < typeof buildMSTeamsGraphMessageUrl > [ 0 ] ;
3121type MSTeamsMediaPayload = ReturnType < typeof buildMSTeamsMediaPayload > ;
3222
@@ -39,10 +29,6 @@ const runtimeStub = {
3929} as unknown as PluginRuntime ;
4030const MEDIA_PLACEHOLDER_IMAGE = "<media:image>" ;
4131const MEDIA_PLACEHOLDER_DOCUMENT = "<media:document>" ;
42- const formatImagePlaceholder = ( count : number ) =>
43- count > 1 ? `${ MEDIA_PLACEHOLDER_IMAGE } (${ count } images)` : MEDIA_PLACEHOLDER_IMAGE ;
44- const formatDocumentPlaceholder = ( count : number ) =>
45- count > 1 ? `${ MEDIA_PLACEHOLDER_DOCUMENT } (${ count } files)` : MEDIA_PLACEHOLDER_DOCUMENT ;
4632const withLabel = < T extends object > ( label : string , fields : T ) : T & { label : string } => ( {
4733 label,
4834 ...fields ,
@@ -53,24 +39,6 @@ const buildAttachment = <T extends Record<string, unknown>>(contentType: string,
5339} ) ;
5440const createHtmlAttachment = ( content : string ) =>
5541 buildAttachment ( CONTENT_TYPE_TEXT_HTML , { content } ) ;
56- const buildHtmlImageTag = ( src : string ) => `<img src="${ src } " />` ;
57- const createHtmlImageAttachments = ( sources : string [ ] , prefix = "" ) => [
58- createHtmlAttachment ( `${ prefix } ${ sources . map ( buildHtmlImageTag ) . join ( "" ) } ` ) ,
59- ] ;
60- const createContentUrlAttachments = ( contentType : string , ...contentUrls : string [ ] ) =>
61- contentUrls . map ( ( contentUrl ) => buildAttachment ( contentType , { contentUrl } ) ) ;
62- const createImageAttachments = ( ...contentUrls : string [ ] ) =>
63- createContentUrlAttachments ( CONTENT_TYPE_IMAGE_PNG , ...contentUrls ) ;
64- const createPdfAttachments = ( ...contentUrls : string [ ] ) =>
65- createContentUrlAttachments ( CONTENT_TYPE_APPLICATION_PDF , ...contentUrls ) ;
66- const createTeamsFileDownloadInfoAttachments = (
67- downloadUrl = createTestUrl ( "dl" ) ,
68- fileType = "png" ,
69- ) => [
70- buildAttachment ( CONTENT_TYPE_TEAMS_FILE_DOWNLOAD_INFO , {
71- content : { downloadUrl, fileType } ,
72- } ) ,
73- ] ;
7442const createMediaEntriesWithType = ( contentType : string , ...paths : string [ ] ) =>
7543 paths . map ( ( path ) => ( { path, contentType } ) ) ;
7644const createImageMediaEntries = ( ...paths : string [ ] ) =>
@@ -88,59 +56,71 @@ const createChannelGraphMessageUrlParams = (
8856const GRAPH_CHANNEL_MESSAGES_ROOT =
8957 "https://graph.microsoft.com/v1.0/teams/team-id/channels/chan-id/messages" ;
9058
91- const expectMSTeamsMediaPayload = (
92- payload : MSTeamsMediaPayload ,
93- expected : { firstPath : string ; paths : string [ ] ; types : string [ ] } ,
94- ) => {
95- expect ( payload . MediaPath ) . toBe ( expected . firstPath ) ;
96- expect ( payload . MediaUrl ) . toBe ( expected . firstPath ) ;
97- expect ( payload . MediaPaths ) . toEqual ( expected . paths ) ;
98- expect ( payload . MediaUrls ) . toEqual ( expected . paths ) ;
99- expect ( payload . MediaTypes ) . toEqual ( expected . types ) ;
100- } ;
101-
102- const ATTACHMENT_PLACEHOLDER_CASES = [
103- withLabel ( "returns empty string when no attachments" , {
104- attachments : undefined as AttachmentPlaceholderInput ,
105- expected : "" ,
59+ const ATTACHMENT_PRESENTATION_CASES = [
60+ withLabel ( "returns empty presentation without attachments" , {
61+ attachments : undefined ,
62+ expected : { placeholder : "" , expectedMediaCount : 0 } ,
10663 } ) ,
107- withLabel ( "returns empty string when attachments are empty" , {
64+ withLabel ( "returns empty presentation for an empty attachment list " , {
10865 attachments : [ ] ,
109- expected : "" ,
66+ expected : { placeholder : "" , expectedMediaCount : 0 } ,
11067 } ) ,
111- withLabel ( "returns image placeholder for one image attachment " , {
112- attachments : createImageAttachments ( TEST_URL_IMAGE_PNG ) ,
113- expected : formatImagePlaceholder ( 1 ) ,
68+ withLabel ( "returns an image presentation for one image" , {
69+ attachments : [ { contentType : "image/png" , contentUrl : "https://x.test/image.png" } ] ,
70+ expected : { placeholder : "<media:image>" , expectedMediaCount : 1 } ,
11471 } ) ,
115- withLabel ( "returns image placeholder with count for many image attachments " , {
72+ withLabel ( "counts multiple images " , {
11673 attachments : [
117- ... createImageAttachments ( TEST_URL_IMAGE_1_PNG ) ,
118- { contentType : "image/jpeg" , contentUrl : TEST_URL_IMAGE_2_JPG } ,
74+ { contentType : "image/png" , contentUrl : "https://x.test/one.png" } ,
75+ { contentType : "image/jpeg" , contentUrl : "https://x.test/two.jpg" } ,
11976 ] ,
120- expected : formatImagePlaceholder ( 2 ) ,
77+ expected : { placeholder : "<media:image> (2 images)" , expectedMediaCount : 2 } ,
12178 } ) ,
122- withLabel ( "treats Teams file.download.info image attachments as images" , {
123- attachments : createTeamsFileDownloadInfoAttachments ( ) ,
124- expected : formatImagePlaceholder ( 1 ) ,
79+ withLabel ( "recognizes Teams download-info images" , {
80+ attachments : [
81+ {
82+ contentType : "application/vnd.microsoft.teams.file.download.info" ,
83+ content : { downloadUrl : "https://x.test/download" , fileType : "png" } ,
84+ } ,
85+ ] ,
86+ expected : { placeholder : "<media:image>" , expectedMediaCount : 1 } ,
12587 } ) ,
126- withLabel ( "returns document placeholder for non-image attachments " , {
127- attachments : createPdfAttachments ( TEST_URL_PDF ) ,
128- expected : formatDocumentPlaceholder ( 1 ) ,
88+ withLabel ( "returns a document presentation for one document " , {
89+ attachments : [ { contentType : "application/pdf" , contentUrl : "https://x.test/file.pdf" } ] ,
90+ expected : { placeholder : "<media:document>" , expectedMediaCount : 1 } ,
12991 } ) ,
130- withLabel ( "returns document placeholder with count for many non-image attachments" , {
131- attachments : createPdfAttachments ( TEST_URL_PDF_1 , TEST_URL_PDF_2 ) ,
132- expected : formatDocumentPlaceholder ( 2 ) ,
92+ withLabel ( "counts multiple documents" , {
93+ attachments : [
94+ { contentType : "application/pdf" , contentUrl : "https://x.test/one.pdf" } ,
95+ { contentType : "application/pdf" , contentUrl : "https://x.test/two.pdf" } ,
96+ ] ,
97+ expected : { placeholder : "<media:document> (2 files)" , expectedMediaCount : 2 } ,
13398 } ) ,
134- withLabel ( "counts one inline image in html attachments " , {
135- attachments : createHtmlImageAttachments ( [ TEST_URL_HTML_A ] , " <p>hi</p>" ) ,
136- expected : formatImagePlaceholder ( 1 ) ,
99+ withLabel ( "counts one inline image" , {
100+ attachments : [ createHtmlAttachment ( ' <p>hi</p><img src="https://x.test/one.png" />' ) ] ,
101+ expected : { placeholder : "<media:image>" , expectedMediaCount : 1 } ,
137102 } ) ,
138- withLabel ( "counts many inline images in html attachments" , {
139- attachments : createHtmlImageAttachments ( [ TEST_URL_HTML_A , TEST_URL_HTML_B ] ) ,
140- expected : formatImagePlaceholder ( 2 ) ,
103+ withLabel ( "counts multiple inline images" , {
104+ attachments : [
105+ createHtmlAttachment (
106+ '<img src="https://x.test/one.png" /><img src="https://x.test/two.png" />' ,
107+ ) ,
108+ ] ,
109+ expected : { placeholder : "<media:image> (2 images)" , expectedMediaCount : 2 } ,
141110 } ) ,
142111] ;
143112
113+ const expectMSTeamsMediaPayload = (
114+ payload : MSTeamsMediaPayload ,
115+ expected : { firstPath : string ; paths : string [ ] ; types : string [ ] } ,
116+ ) => {
117+ expect ( payload . MediaPath ) . toBe ( expected . firstPath ) ;
118+ expect ( payload . MediaUrl ) . toBe ( expected . firstPath ) ;
119+ expect ( payload . MediaPaths ) . toEqual ( expected . paths ) ;
120+ expect ( payload . MediaUrls ) . toEqual ( expected . paths ) ;
121+ expect ( payload . MediaTypes ) . toEqual ( expected . types ) ;
122+ } ;
123+
144124const GRAPH_MESSAGE_URL_CASES = [
145125 withLabel ( "builds a channel top-level message URL" , {
146126 params : createChannelGraphMessageUrlParams ( {
@@ -170,25 +150,22 @@ describe("msteams attachment helpers", () => {
170150 setMSTeamsRuntime ( runtimeStub ) ;
171151 } ) ;
172152
173- describe ( "buildMSTeamsAttachmentPlaceholder " , ( ) => {
174- it . each ( ATTACHMENT_PLACEHOLDER_CASES ) ( "$label" , ( { attachments, expected } ) => {
175- expect ( buildMSTeamsAttachmentPlaceholder ( attachments ) ) . toBe ( expected ) ;
153+ describe ( "resolveMSTeamsInboundAttachmentPresentation " , ( ) => {
154+ it . each ( ATTACHMENT_PRESENTATION_CASES ) ( "$label" , ( { attachments, expected } ) => {
155+ expect ( resolveMSTeamsInboundAttachmentPresentation ( attachments ) ) . toEqual ( expected ) ;
176156 } ) ;
177157
178- it ( "respects inline image limits when counting placeholder images " , ( ) => {
158+ it ( "respects inline image limits when choosing the placeholder " , ( ) => {
179159 const attachments = [
180- {
181- contentType : "text/html" ,
182- content : `<img src="data:image/png;base64,${ "A" . repeat ( 16 ) } " />` ,
183- } ,
160+ createHtmlAttachment ( `<img src="data:image/png;base64,${ "A" . repeat ( 16 ) } " />` ) ,
184161 ] ;
185162
186163 expect (
187- buildMSTeamsAttachmentPlaceholder ( attachments , {
164+ resolveMSTeamsInboundAttachmentPresentation ( attachments , {
188165 maxInlineBytes : 4 ,
189166 maxInlineTotalBytes : 4 ,
190167 } ) ,
191- ) . toBe ( "<media:document>" ) ;
168+ ) . toEqual ( { placeholder : "<media:document>" , expectedMediaCount : 1 } ) ;
192169 } ) ;
193170
194171 it ( "counts advertised files without URLs and ignores mention-only HTML" , ( ) => {
0 commit comments