//
// C o p y r i g h t ( c ) 2 0 1 9 O p e n W h i s p e r S y s t e m s . A l l r i g h t s r e s e r v e d .
//
import Foundation
@ testable import SignalServiceKit
import XCTest
class OWSLinkPreviewTest : SSKBaseTestSwift {
override func setUp ( ) {
super . setUp ( )
// P u t s e t u p c o d e h e r e . T h i s m e t h o d i s c a l l e d b e f o r e t h e i n v o c a t i o n o f e a c h t e s t m e t h o d i n t h e c l a s s .
}
override func tearDown ( ) {
// P u t t e a r d o w n c o d e h e r e . T h i s m e t h o d i s c a l l e d a f t e r t h e i n v o c a t i o n o f e a c h t e s t m e t h o d i n t h e c l a s s .
super . tearDown ( )
}
func testBuildValidatedLinkPreview_TitleAndImage ( ) {
let url = " https://www.youtube.com/watch?v=tP-Ipsat90c "
let body = " \( url ) "
let previewBuilder = SSKProtoDataMessagePreview . builder ( url : url )
previewBuilder . setTitle ( " Some Youtube Video " )
let imageAttachmentBuilder = SSKProtoAttachmentPointer . builder ( id : 1 )
imageAttachmentBuilder . setKey ( Randomness . generateRandomBytes ( 32 ) )
imageAttachmentBuilder . setContentType ( OWSMimeTypeImageJpeg )
previewBuilder . setImage ( try ! imageAttachmentBuilder . build ( ) )
let dataBuilder = SSKProtoDataMessage . builder ( )
dataBuilder . addPreview ( try ! previewBuilder . build ( ) )
self . readWrite { ( transaction ) in
XCTAssertNotNil ( try ! OWSLinkPreview . buildValidatedLinkPreview ( dataMessage : try ! dataBuilder . build ( ) ,
body : body ,
transaction : transaction ) )
}
}
func testBuildValidatedLinkPreview_Title ( ) {
let url = " https://www.youtube.com/watch?v=tP-Ipsat90c "
let body = " \( url ) "
let previewBuilder = SSKProtoDataMessagePreview . builder ( url : url )
previewBuilder . setTitle ( " Some Youtube Video " )
let dataBuilder = SSKProtoDataMessage . builder ( )
dataBuilder . addPreview ( try ! previewBuilder . build ( ) )
self . readWrite { ( transaction ) in
XCTAssertNotNil ( try ! OWSLinkPreview . buildValidatedLinkPreview ( dataMessage : try ! dataBuilder . build ( ) ,
body : body ,
transaction : transaction ) )
}
}
func testBuildValidatedLinkPreview_Image ( ) {
let url = " https://www.youtube.com/watch?v=tP-Ipsat90c "
let body = " \( url ) "
let previewBuilder = SSKProtoDataMessagePreview . builder ( url : url )
let imageAttachmentBuilder = SSKProtoAttachmentPointer . builder ( id : 1 )
imageAttachmentBuilder . setKey ( Randomness . generateRandomBytes ( 32 ) )
imageAttachmentBuilder . setContentType ( OWSMimeTypeImageJpeg )
previewBuilder . setImage ( try ! imageAttachmentBuilder . build ( ) )
let dataBuilder = SSKProtoDataMessage . builder ( )
dataBuilder . addPreview ( try ! previewBuilder . build ( ) )
self . readWrite { ( transaction ) in
XCTAssertNotNil ( try ! OWSLinkPreview . buildValidatedLinkPreview ( dataMessage : try ! dataBuilder . build ( ) ,
body : body ,
transaction : transaction ) )
}
}
func testBuildValidatedLinkPreview_NoTitleOrImage ( ) {
let url = " https://www.youtube.com/watch?v=tP-Ipsat90c "
let body = " \( url ) "
let previewBuilder = SSKProtoDataMessagePreview . builder ( url : url )
let dataBuilder = SSKProtoDataMessage . builder ( )
dataBuilder . addPreview ( try ! previewBuilder . build ( ) )
self . readWrite { ( transaction ) in
do {
_ = try OWSLinkPreview . buildValidatedLinkPreview ( dataMessage : try ! dataBuilder . build ( ) ,
body : body ,
transaction : transaction )
XCTFail ( " Missing expected error. " )
} catch {
// D o n o t h i n g .
}
}
}
func testIsValidLinkUrl ( ) {
XCTAssertTrue ( OWSLinkPreview . isValidLinkUrl ( " https://www.youtube.com/watch?v=tP-Ipsat90c " ) )
XCTAssertTrue ( OWSLinkPreview . isValidLinkUrl ( " https://youtube.com/watch?v=tP-Ipsat90c " ) )
// C a s e s h o u l d n ' t m a t t e r .
XCTAssertTrue ( OWSLinkPreview . isValidLinkUrl ( " https://WWW.YOUTUBE.COM/watch?v=tP-Ipsat90c " ) )
// A l l o w a r b i t r a r y s u b d o m a i n s .
XCTAssertTrue ( OWSLinkPreview . isValidMediaUrl ( " https://some.random.subdomain.youtube.com/watch?v=tP-Ipsat90c " ) )
// D o n ' t a l l o w H T T P , o n l y H T T P S
XCTAssertFalse ( OWSLinkPreview . isValidLinkUrl ( " http://youtube.com/watch?v=tP-Ipsat90c " ) )
XCTAssertFalse ( OWSLinkPreview . isValidLinkUrl ( " mailto://youtube.com/watch?v=tP-Ipsat90c " ) )
XCTAssertFalse ( OWSLinkPreview . isValidLinkUrl ( " ftp://youtube.com/watch?v=tP-Ipsat90c " ) )
// D o n ' t a l l o w s i m i l a r d o m a i n s .
XCTAssertFalse ( OWSLinkPreview . isValidLinkUrl ( " https://xyoutube.com/watch?v=tP-Ipsat90c " ) )
XCTAssertFalse ( OWSLinkPreview . isValidLinkUrl ( " https://youtubex.com/watch?v=tP-Ipsat90c " ) )
XCTAssertFalse ( OWSLinkPreview . isValidLinkUrl ( " https://youtube.comx/watch?v=tP-Ipsat90c " ) )
XCTAssertFalse ( OWSLinkPreview . isValidLinkUrl ( " https://www.xyoutube.com/watch?v=tP-Ipsat90c " ) )
XCTAssertFalse ( OWSLinkPreview . isValidLinkUrl ( " https://www.youtubex.com/watch?v=tP-Ipsat90c " ) )
XCTAssertFalse ( OWSLinkPreview . isValidLinkUrl ( " https://www.youtube.comx/watch?v=tP-Ipsat90c " ) )
// D o n ' t a l l o w m e d i a d o m a i n s .
XCTAssertFalse ( OWSLinkPreview . isValidLinkUrl ( " https://i.ytimg.com/vi/tP-Ipsat90c/maxresdefault.jpg " ) )
// A l l o w a l l w h i t e l i s t e d d o m a i n s .
XCTAssertTrue ( OWSLinkPreview . isValidLinkUrl ( " https://www.youtube.com/watch?v=tP-Ipsat90c " ) )
XCTAssertTrue ( OWSLinkPreview . isValidLinkUrl ( " https://youtu.be/tP-Ipsat90c " ) )
XCTAssertTrue ( OWSLinkPreview . isValidLinkUrl ( " https://www.reddit.com/r/androiddev/comments/a7gctz/androidx_release_notes_this_is_the_first_release/ " ) )
XCTAssertTrue ( OWSLinkPreview . isValidLinkUrl ( " https://www.reddit.com/r/WhitePeopleTwitter/comments/a7j3mm/why/ " ) )
XCTAssertTrue ( OWSLinkPreview . isValidLinkUrl ( " https://imgur.com/gallery/KFCL8fm " ) )
XCTAssertTrue ( OWSLinkPreview . isValidLinkUrl ( " https://imgur.com/gallery/FMdwTiV " ) )
XCTAssertTrue ( OWSLinkPreview . isValidLinkUrl ( " https://www.instagram.com/p/BrgpsUjF9Jo/?utm_source=ig_web_button_share_sheet " ) )
XCTAssertTrue ( OWSLinkPreview . isValidLinkUrl ( " https://www.instagram.com/p/BrgpsUjF9Jo/?utm_source=ig_share_sheet&igshid=94c7ihqjfmbm " ) )
XCTAssertTrue ( OWSLinkPreview . isValidLinkUrl ( " https://imgur.com/gallery/igHOwDM " ) )
// S t r i p t r a i l i n g c o m m a s .
XCTAssertTrue ( OWSLinkPreview . isValidLinkUrl ( " https://imgur.com/gallery/igHOwDM, " ) )
// I g n o r e U R L s w i t h a n e m p t y p a t h .
XCTAssertFalse ( OWSLinkPreview . isValidLinkUrl ( " https://imgur.com " ) )
XCTAssertFalse ( OWSLinkPreview . isValidLinkUrl ( " https://imgur.com/ " ) )
XCTAssertTrue ( OWSLinkPreview . isValidLinkUrl ( " https://imgur.com/X " ) )
}
func testIsValidMediaUrl ( ) {
XCTAssertTrue ( OWSLinkPreview . isValidMediaUrl ( " https://www.youtube.com/watch?v=tP-Ipsat90c " ) )
XCTAssertTrue ( OWSLinkPreview . isValidMediaUrl ( " https://youtube.com/watch?v=tP-Ipsat90c " ) )
// A l l o w a r b i t r a r y s u b d o m a i n s .
XCTAssertTrue ( OWSLinkPreview . isValidMediaUrl ( " https://some.random.subdomain.youtube.com/watch?v=tP-Ipsat90c " ) )
// D o n ' t a l l o w H T T P , o n l y H T T P S
XCTAssertFalse ( OWSLinkPreview . isValidMediaUrl ( " http://youtube.com/watch?v=tP-Ipsat90c " ) )
XCTAssertFalse ( OWSLinkPreview . isValidMediaUrl ( " mailto://youtube.com/watch?v=tP-Ipsat90c " ) )
XCTAssertFalse ( OWSLinkPreview . isValidMediaUrl ( " ftp://youtube.com/watch?v=tP-Ipsat90c " ) )
// D o n ' t a l l o w s i m i l a r d o m a i n s .
XCTAssertFalse ( OWSLinkPreview . isValidMediaUrl ( " https://xyoutube.com/watch?v=tP-Ipsat90c " ) )
XCTAssertFalse ( OWSLinkPreview . isValidMediaUrl ( " https://youtubex.com/watch?v=tP-Ipsat90c " ) )
XCTAssertFalse ( OWSLinkPreview . isValidMediaUrl ( " https://youtube.comx/watch?v=tP-Ipsat90c " ) )
XCTAssertFalse ( OWSLinkPreview . isValidMediaUrl ( " https://www.xyoutube.com/watch?v=tP-Ipsat90c " ) )
XCTAssertFalse ( OWSLinkPreview . isValidMediaUrl ( " https://www.youtubex.com/watch?v=tP-Ipsat90c " ) )
XCTAssertFalse ( OWSLinkPreview . isValidMediaUrl ( " https://www.youtube.comx/watch?v=tP-Ipsat90c " ) )
// A l l o w m e d i a d o m a i n s .
XCTAssertTrue ( OWSLinkPreview . isValidMediaUrl ( " https://i.ytimg.com/vi/tP-Ipsat90c/maxresdefault.jpg " ) )
}
func testPreviewUrlForMessageBodyText ( ) {
XCTAssertNil ( OWSLinkPreview . previewUrl ( forMessageBodyText : " " ) )
XCTAssertNil ( OWSLinkPreview . previewUrl ( forMessageBodyText : " alice bob jim " ) )
XCTAssertNil ( OWSLinkPreview . previewUrl ( forMessageBodyText : " alice bob jim http:// " ) )
XCTAssertNil ( OWSLinkPreview . previewUrl ( forMessageBodyText : " alice bob jim http://a.com " ) )
XCTAssertEqual ( OWSLinkPreview . previewUrl ( forMessageBodyText : " https://www.youtube.com/watch?v=tP-Ipsat90c " ) ,
" https://www.youtube.com/watch?v=tP-Ipsat90c " )
XCTAssertEqual ( OWSLinkPreview . previewUrl ( forMessageBodyText : " alice bob https://www.youtube.com/watch?v=tP-Ipsat90c jim " ) ,
" https://www.youtube.com/watch?v=tP-Ipsat90c " )
// I f t h e r e a r e m o r e t h a n o n e , t a k e t h e f i r s t .
XCTAssertEqual ( OWSLinkPreview . previewUrl ( forMessageBodyText : " alice bob https://www.youtube.com/watch?v=tP-Ipsat90c jim https://www.youtube.com/watch?v=other-url carol " ) ,
" https://www.youtube.com/watch?v=tP-Ipsat90c " )
}
func testUtils ( ) {
XCTAssertNil ( OWSLinkPreview . fileExtension ( forImageUrl : " " ) )
XCTAssertNil ( OWSLinkPreview . fileExtension ( forImageUrl : " https://www.some.host/path/imagename " ) )
XCTAssertNil ( OWSLinkPreview . fileExtension ( forImageUrl : " https://www.some.host/path/imagename. " ) )
XCTAssertEqual ( OWSLinkPreview . fileExtension ( forImageUrl : " https://www.some.host/path/imagename.jpg " ) , " jpg " )
XCTAssertEqual ( OWSLinkPreview . fileExtension ( forImageUrl : " https://www.some.host/path/imagename.gif " ) , " gif " )
XCTAssertEqual ( OWSLinkPreview . fileExtension ( forImageUrl : " https://www.some.host/path/imagename.png " ) , " png " )
XCTAssertEqual ( OWSLinkPreview . fileExtension ( forImageUrl : " https://www.some.host/path/imagename.boink " ) , " boink " )
XCTAssertNil ( OWSLinkPreview . mimetype ( forImageFileExtension : " " ) )
XCTAssertNil ( OWSLinkPreview . mimetype ( forImageFileExtension : " boink " ) )
XCTAssertNil ( OWSLinkPreview . mimetype ( forImageFileExtension : " tiff " ) )
XCTAssertNil ( OWSLinkPreview . mimetype ( forImageFileExtension : " gif " ) )
XCTAssertEqual ( OWSLinkPreview . mimetype ( forImageFileExtension : " jpg " ) , OWSMimeTypeImageJpeg )
XCTAssertEqual ( OWSLinkPreview . mimetype ( forImageFileExtension : " png " ) , OWSMimeTypeImagePng )
}
func testLinkDownloadAndParsing ( ) {
let expectation = self . expectation ( description : " link download and parsing " )
OWSLinkPreview . tryToBuildPreviewInfo ( previewUrl : " https://www.youtube.com/watch?v=tP-Ipsat90c " )
. done { ( draft ) in
XCTAssertNotNil ( draft )
XCTAssertEqual ( draft . title , " Randomness is Random - Numberphile " )
XCTAssertNotNil ( draft . imageFilePath )
expectation . fulfill ( )
} . catch { ( error ) in
Logger . error ( " error: \( error ) " )
XCTFail ( " Unexpected error: \( error ) " )
expectation . fulfill ( )
} . retainUntilComplete ( )
self . waitForExpectations ( timeout : 5.0 , handler : nil )
}
func testLinkDataParsing_Empty ( ) {
let linkText = " "
let linkData = linkText . data ( using : . utf8 ) !
let content = try ! OWSLinkPreview . parse ( linkData : linkData )
XCTAssertNotNil ( content )
XCTAssertNil ( content . title )
XCTAssertNil ( content . imageUrl )
}
func testLinkDataParsing ( ) {
let linkText = ( " <meta property= \" og:title \" content= \" Randomness is Random - Numberphile \" > " +
" <meta property= \" og:image \" content= \" https://i.ytimg.com/vi/tP-Ipsat90c/maxresdefault.jpg \" > " )
let linkData = linkText . data ( using : . utf8 ) !
let content = try ! OWSLinkPreview . parse ( linkData : linkData )
XCTAssertNotNil ( content )
XCTAssertEqual ( content . title , " Randomness is Random - Numberphile " )
XCTAssertEqual ( content . imageUrl , " https://i.ytimg.com/vi/tP-Ipsat90c/maxresdefault.jpg " )
}
}