// // WeChatShareServiceTests.swift // suixinkanTests // import UIKit import WechatOpenSDK import XCTest @testable import suixinkan /// 微信分享服务测试。 @MainActor final class WeChatShareServiceTests: XCTestCase { /// 测试 Universal Link 必须是 HTTPS 且以 `/` 结尾。 func testUniversalLinkMustUseHTTPSAndEndWithSlash() { XCTAssertTrue(WeChatConfig.validateUniversalLink(WeChatConfig.universalLink)) XCTAssertFalse(WeChatConfig.validateUniversalLink("https://www.zhifly.cn/suixinkan")) XCTAssertFalse(WeChatConfig.validateUniversalLink("http://www.zhifly.cn/suixinkan/")) } /// 测试分享场景映射到微信 SDK scene 值。 func testShareSceneMapsToWXValues() { XCTAssertEqual(WeChatShareScene.session.wxSceneValue, 0) XCTAssertEqual(WeChatShareScene.timeline.wxSceneValue, 1) XCTAssertEqual(WeChatShareScene.favorite.wxSceneValue, 2) } /// 测试小程序版本映射到微信 SDK 值。 func testMiniProgramTypeMapsToWXValues() { XCTAssertEqual(WeChatMiniProgramType.release.rawValue, 0) XCTAssertEqual(WeChatMiniProgramType.test.rawValue, 1) XCTAssertEqual(WeChatMiniProgramType.preview.rawValue, 2) } /// 测试 Debug 包使用体验版小程序,Release 包保持传入版本。 func testMiniProgramTypeResolvesForCurrentBuild() { #if DEBUG XCTAssertEqual(WeChatMiniProgramType.release.resolvedForCurrentBuild, .preview) XCTAssertEqual(WeChatMiniProgramType.test.resolvedForCurrentBuild, .preview) #else XCTAssertEqual(WeChatMiniProgramType.release.resolvedForCurrentBuild, .release) XCTAssertEqual(WeChatMiniProgramType.test.resolvedForCurrentBuild, .test) #endif } /// 测试微信错误码解析。 func testShareResultFromWXErrorCode() { XCTAssertEqual(WeChatShareResult.fromWXErrorCode(0), .success) XCTAssertEqual(WeChatShareResult.fromWXErrorCode(-2), .cancelled) XCTAssertEqual(WeChatShareResult.fromWXErrorCode(99), .unknown(99)) } /// 测试缩略图压缩到微信限制内。 func testThumbImageProcessorKeepsDataUnderLimit() throws { let renderer = UIGraphicsImageRenderer(size: CGSize(width: 640, height: 640)) let image = renderer.image { context in UIColor.systemBlue.setFill() context.fill(CGRect(x: 0, y: 0, width: 640, height: 640)) UIColor.white.setFill() context.fill(CGRect(x: 80, y: 80, width: 480, height: 480)) } let thumbData = try XCTUnwrap(WeChatThumbImageProcessor.makeThumbData(from: image)) XCTAssertLessThanOrEqual(thumbData.count, WeChatThumbImageProcessor.maxThumbBytes) } /// 测试小程序高清预览图压缩到微信限制内。 func testMiniProgramHDImageProcessorKeepsDataUnderLimit() throws { let renderer = UIGraphicsImageRenderer(size: CGSize(width: 1200, height: 800)) let image = renderer.image { context in UIColor.systemGreen.setFill() context.fill(CGRect(x: 0, y: 0, width: 1200, height: 800)) UIColor.white.setFill() context.fill(CGRect(x: 160, y: 120, width: 880, height: 560)) UIColor.systemBlue.setFill() context.fill(CGRect(x: 260, y: 220, width: 680, height: 360)) } let imageData = try XCTUnwrap(WeChatThumbImageProcessor.makeMiniProgramHDImageData(from: image)) XCTAssertLessThanOrEqual(imageData.count, WeChatThumbImageProcessor.maxMiniProgramHDImageBytes) XCTAssertNil(WeChatThumbImageProcessor.makeMiniProgramHDImageData(from: image, maxBytes: 0)) } /// 测试空标题和空链接会直接返回参数错误。 func testShareWebPageRejectsInvalidPayloadBeforeSending() { var results: [WeChatShareResult] = [] WeChatShareService.shareWebPage( WeChatWebPageSharePayload(title: " ", description: "desc", url: "https://example.com"), scene: .session ) { result in results.append(result) } WeChatShareService.shareWebPage( WeChatWebPageSharePayload(title: "title", description: "desc", url: " "), scene: .session ) { result in results.append(result) } XCTAssertEqual(results, [ .invalidPayload("分享标题不能为空"), .invalidPayload("分享链接不能为空"), ]) } /// 测试小程序分享请求字段填充。 func testMakeMiniProgramRequestFillsWXObject() throws { let renderer = UIGraphicsImageRenderer(size: CGSize(width: 600, height: 400)) let image = renderer.image { context in UIColor.systemOrange.setFill() context.fill(CGRect(x: 0, y: 0, width: 600, height: 400)) } let payload = WeChatMiniProgramSharePayload( title: " 举报详情 ", description: "查看处理进度", webpageURL: " https://www.zhifly.cn/report/40 ", userName: " gh_xxxxxxxx ", path: " /pages/report/detail?id=40 ", miniProgramType: .preview, withShareTicket: true, disableForward: true ) let request = try XCTUnwrap(try WeChatShareService.makeMiniProgramRequest(payload, scene: .session, previewImage: image).get()) let message = try XCTUnwrap(request.message) let miniProgramObject = try XCTUnwrap(message.mediaObject as? WXMiniProgramObject) XCTAssertFalse(request.bText) XCTAssertEqual(request.scene, WeChatShareScene.session.wxSceneValue) XCTAssertEqual(message.title, "举报详情") XCTAssertEqual(message.description, "查看处理进度") XCTAssertEqual(miniProgramObject.webpageUrl, "https://www.zhifly.cn/report/40") XCTAssertEqual(miniProgramObject.userName, "gh_xxxxxxxx") XCTAssertEqual(miniProgramObject.path, "/pages/report/detail?id=40") XCTAssertEqual(miniProgramObject.miniProgramType.rawValue, UInt(WeChatMiniProgramType.preview.resolvedForCurrentBuild.rawValue)) XCTAssertEqual(miniProgramObject.withShareTicket, true) XCTAssertEqual(miniProgramObject.disableForward, true) XCTAssertLessThanOrEqual(miniProgramObject.hdImageData?.count ?? 0, WeChatThumbImageProcessor.maxMiniProgramHDImageBytes) } /// 测试小程序分享参数校验。 func testMakeMiniProgramRequestRejectsInvalidPayload() { let valid = WeChatMiniProgramSharePayload( title: "举报详情", description: "查看处理进度", webpageURL: "https://www.zhifly.cn/report/40", userName: "gh_xxxxxxxx" ) let longURL = "https://www.zhifly.cn/" + String(repeating: "a", count: 1025) XCTAssertEqual( WeChatShareService.makeMiniProgramRequest(valid, scene: .timeline).failure, .invalidPayload("小程序仅支持分享到微信好友") ) XCTAssertEqual( WeChatShareService.makeMiniProgramRequest( WeChatMiniProgramSharePayload(title: " ", description: "", webpageURL: valid.webpageURL, userName: valid.userName), scene: .session ).failure, .invalidPayload("分享标题不能为空") ) XCTAssertEqual( WeChatShareService.makeMiniProgramRequest( WeChatMiniProgramSharePayload(title: valid.title, description: "", webpageURL: " ", userName: valid.userName), scene: .session ).failure, .invalidPayload("小程序兼容网页链接不能为空") ) XCTAssertEqual( WeChatShareService.makeMiniProgramRequest( WeChatMiniProgramSharePayload(title: valid.title, description: "", webpageURL: longURL, userName: valid.userName), scene: .session ).failure, .invalidPayload("小程序兼容网页链接不能超过1024字节") ) XCTAssertEqual( WeChatShareService.makeMiniProgramRequest( WeChatMiniProgramSharePayload(title: valid.title, description: "", webpageURL: valid.webpageURL, userName: " "), scene: .session ).failure, .invalidPayload("小程序原始 ID 不能为空") ) } } private extension Result where Success == SendMessageToWXReq, Failure == WeChatShareResult { var failure: WeChatShareResult? { guard case .failure(let result) = self else { return nil } return result } }