diff --git a/CHANGELOG.md b/CHANGELOG.md index 945e66b3..e6940da5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. Adheres to [Semantic Versioning](http://semver.org/). --- +## 4.0.6 + +##### Features + * Update GeoPackage library to 8.0.3 + +##### Bug Fixes + * PNG photo attachments converted to JPEG get a `.jpeg` file extension to match media type + ## 4.0.5 ##### Features diff --git a/MAGE.xcodeproj/project.pbxproj b/MAGE.xcodeproj/project.pbxproj index 959b8c2c..f8dc1fdc 100644 --- a/MAGE.xcodeproj/project.pbxproj +++ b/MAGE.xcodeproj/project.pbxproj @@ -92,6 +92,7 @@ 4C546FEC195A27F4000CF230 /* LocationAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C546FEB195A27F4000CF230 /* LocationAnnotation.m */; }; 4CF141B21992A5D900C4B70E /* DeviceUUID.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CF141B11992A5D900C4B70E /* DeviceUUID.m */; }; 7BE337090E1E1E71380E1A61 /* libPods-MAGETests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E35CAAC522CDD65F899A0C68 /* libPods-MAGETests.a */; }; + 7D0F874B2AA795CD009664E5 /* test_image_attachment.png in Resources */ = {isa = PBXBuildFile; fileRef = 7D0F874A2AA795CD009664E5 /* test_image_attachment.png */; }; 8474FD9726FB8B220041891A /* EmailBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 8474FD9626FB8B220041891A /* EmailBuilder.m */; }; 8474FD9A26FB8B890041891A /* LinkGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 8474FD9926FB8B890041891A /* LinkGenerator.m */; }; 8474FD9D26FB8C410041891A /* ContactInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 8474FD9C26FB8C410041891A /* ContactInfo.m */; }; @@ -748,6 +749,7 @@ 4CF141B01992A5D900C4B70E /* DeviceUUID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DeviceUUID.h; sourceTree = ""; }; 4CF141B11992A5D900C4B70E /* DeviceUUID.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DeviceUUID.m; sourceTree = ""; }; 4FF82DA2D695899B2556C0D1 /* Pods-MAGE-MAGETests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MAGE-MAGETests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-MAGE-MAGETests/Pods-MAGE-MAGETests.debug.xcconfig"; sourceTree = ""; }; + 7D0F874A2AA795CD009664E5 /* test_image_attachment.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = test_image_attachment.png; sourceTree = ""; }; 8474FD9526FB8B220041891A /* EmailBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EmailBuilder.h; sourceTree = ""; }; 8474FD9626FB8B220041891A /* EmailBuilder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EmailBuilder.m; sourceTree = ""; }; 8474FD9826FB8B890041891A /* LinkGenerator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LinkGenerator.h; sourceTree = ""; }; @@ -2141,6 +2143,7 @@ F7614DA820068FF300676366 /* responses */ = { isa = PBXGroup; children = ( + 7D0F874A2AA795CD009664E5 /* test_image_attachment.png */, F7CE22FF254368B000D710DE /* allTheThings.json */, F70039452006CB0700E6E660 /* apiFail.json */, F7614DA92006902000676366 /* apiSuccess.json */, @@ -2996,6 +2999,7 @@ F7F7532B2565862F00EF51FF /* testmovie.MOV in Resources */, F71446F524A3FAF5005A5EC1 /* feedContent.json in Resources */, F7154A982608D2A0002C8617 /* apiSuccess6NoDisclaimer.json in Resources */, + 7D0F874B2AA795CD009664E5 /* test_image_attachment.png in Resources */, F70D19E32742CE0D006E12F8 /* plantsAnimalsBuildingsIcons.zip in Resources */, F795ED1424BD061C0028FBFC /* observations.json in Resources */, F7098F262492C36700313703 /* test_marker.png in Resources */, @@ -3837,21 +3841,23 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = MAGE/MAGE.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; DEVELOPMENT_TEAM = ZL8G5D9G2H; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = ZL8G5D9G2H; ENABLE_BITCODE = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Mage/MAGE-Prefix.pch"; INFOPLIST_FILE = "Mage/MAGE-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 4.0.5; + MARKETING_VERSION = 4.0.6; OTHER_LDFLAGS = "$(inherited)"; OTHER_SWIFT_FLAGS = "$(inherited) -D COCOAPODS -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/AFNetworking/AFNetworking.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/DateTools/DateTools.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/HexColors/HexColors.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/MDFInternationalization/MDFInternationalization.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/MDFTextAccessibility/MDFTextAccessibility.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/MagicalRecord/MagicalRecord.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/MaterialComponents/MaterialComponents.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/MotionAnimator/MotionAnimator.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/MotionInterchange/MotionInterchange.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/PureLayout/PureLayout.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/SSZipArchive/SSZipArchive.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/UIImage_Categories/UIImage-Categories.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/geopackage_ios/geopackage-ios.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/libPhoneNumber_iOS/libPhoneNumber-iOS.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/ogc_api_features_json_ios/ogc-api-features-json-ios.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/sf_geojson_ios/sf-geojson-ios.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/sf_ios/sf-ios.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/sf_proj_ios/sf-proj-ios.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/sf_wkb_ios/sf-wkb-ios.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/sf_wkt_ios/sf-wkt-ios.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/tiff_ios/tiff-ios.modulemap\" -Xcc -fmodule-map-file=\"${PODS_ROOT}/Headers/Public/zxcvbn_ios/zxcvbn-ios.modulemap\""; PRODUCT_BUNDLE_IDENTIFIER = mil.nga.mage; PRODUCT_NAME = MAGE; PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = "MAGE Development"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "MAGE Development"; SWIFT_OBJC_BRIDGING_HEADER = "Mage/MAGE-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -3871,20 +3877,22 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = MAGE/MAGE.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; DEVELOPMENT_TEAM = ZL8G5D9G2H; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = ZL8G5D9G2H; ENABLE_BITCODE = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "Mage/MAGE-Prefix.pch"; INFOPLIST_FILE = "Mage/MAGE-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 14.0; - MARKETING_VERSION = 4.0.5; + MARKETING_VERSION = 4.0.6; OTHER_LDFLAGS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = mil.nga.mage; PRODUCT_NAME = MAGE; PROVISIONING_PROFILE = ""; PROVISIONING_PROFILE_SPECIFIER = "MAGE Development"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "MAGE Development"; SWIFT_OBJC_BRIDGING_HEADER = "Mage/MAGE-Bridging-Header.h"; SWIFT_VERSION = 5.0; WRAPPER_EXTENSION = app; diff --git a/Mage/AttachmentCreationCoordinator.swift b/Mage/AttachmentCreationCoordinator.swift index e83a061d..e109b383 100644 --- a/Mage/AttachmentCreationCoordinator.swift +++ b/Mage/AttachmentCreationCoordinator.swift @@ -193,50 +193,49 @@ extension AttachmentCreationCoordinator: AttachmentCreationDelegate { extension AttachmentCreationCoordinator: PHPickerViewControllerDelegate { - func handlePhoto(phasset: PHAsset?, utType: UTType?) { + func handlePhoto(photo: PHAsset?, utType: UTType?) { DispatchQueue.global(qos: .userInitiated).async { [self] in - if let phasset = phasset { - let dateFormatter = DateFormatter(); - dateFormatter.dateFormat = "yyyyMMdd_HHmmss"; - - let fileType = utType?.preferredFilenameExtension ?? "jpeg" - let mimeType = utType?.preferredMIMEType ?? "image/jpeg" - - guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { - return; + guard let photo else { + galleryPermissionDenied() + return + } + let dateFormatter = DateFormatter(); + dateFormatter.dateFormat = "yyyyMMdd_HHmmss"; + guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { + return + } + let attachmentsDirectory = documentsDirectory.appendingPathComponent("attachments") + let manager = PHImageManager.default() + let requestOptions = PHImageRequestOptions() + requestOptions.isSynchronous = true + requestOptions.deliveryMode = .fastFormat + requestOptions.isNetworkAccessAllowed = true + + manager.requestImageDataAndOrientation(for: photo, options: requestOptions) { (data, fileName, orientation, info) in + guard let data else { + return } - let attachmentsDirectory = documentsDirectory.appendingPathComponent("attachments") - let fileToWriteTo = attachmentsDirectory.appendingPathComponent("MAGE_\(dateFormatter.string(from: Date())).\(fileType)"); - - let manager = PHImageManager.default() - let requestOptions = PHImageRequestOptions() - requestOptions.isSynchronous = true - requestOptions.deliveryMode = .fastFormat - requestOptions.isNetworkAccessAllowed = true - - manager.requestImageDataAndOrientation(for: phasset, options: requestOptions) { (data, fileName, orientation, info) in - if let data = data, - let cImage = CIImage(data: data) { - do { - try FileManager.default.createDirectory(at: fileToWriteTo.deletingLastPathComponent(), withIntermediateDirectories: true, attributes: [.protectionKey : FileProtectionType.complete]); - - guard let finalData = cImage.qualityScaled() else { return } - - do { - try finalData.write(to: fileToWriteTo, options: .completeFileProtection) - self.addAttachmentForSaving(location: fileToWriteTo, contentType: mimeType) - } catch { - print("Unable to write image to file \(fileToWriteTo): \(error)") - } - - } catch { - print("Error creating directory path \(fileToWriteTo.deletingLastPathComponent()): \(error)") - } - - } + let scaledImagePath = attachmentsDirectory.appendingPathComponent("MAGE_\(dateFormatter.string(from: Date())).jpeg") + do { + try FileManager.default.createDirectory(at: attachmentsDirectory, withIntermediateDirectories: true, attributes: [.protectionKey : FileProtectionType.complete]) + } + catch { + print("error creating directory \(attachmentsDirectory) to save scaled attachment file \(fileName ?? "")", error) + return + } + guard let baseImage = CIImage(data: data) else { + return + } + guard let scaledImageData = baseImage.qualityScaled() else { + return + } + do { + try scaledImageData.write(to: scaledImagePath, options: .completeFileProtection) + self.addAttachmentForSaving(location: scaledImagePath, contentType: "image/jpeg") + } + catch { + print("error saving scaled attachment image \(scaledImagePath) from base image \(fileName ?? "")", error) } - } else { - galleryPermissionDenied() } } } @@ -358,7 +357,7 @@ extension AttachmentCreationCoordinator: PHPickerViewControllerDelegate { let options = PHFetchOptions() options.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.image.rawValue) let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [assetIdentifier], options: nil) - handlePhoto(phasset: fetchResult.firstObject, utType: utType) + handlePhoto(photo: fetchResult.firstObject, utType: utType) picker.dismiss(animated: true, completion: nil) return } @@ -372,7 +371,7 @@ extension AttachmentCreationCoordinator: PHPickerViewControllerDelegate { return } } - MDCSnackbarManager.default.show(MDCSnackbarMessage(text: "Could not handle asset of types: \(itemProvider.registeredTypeIdentifiers)")) + MDCSnackbarManager.default.show(MDCSnackbarMessage(text: "Could not handle asset types: \(itemProvider.registeredTypeIdentifiers)")) } } } @@ -424,7 +423,6 @@ extension AttachmentCreationCoordinator: UIImagePickerControllerDelegate { do { try FileManager.default.createDirectory(at: fileToWriteTo.deletingLastPathComponent(), withIntermediateDirectories: true, attributes: [.protectionKey : FileProtectionType.complete]); -// let finalImage = chosenImage.qualityScaled(); guard let imageData = chosenImage.qualityScaled() else { return }; var metadata: [AnyHashable : Any] = info[.mediaMetadata] as? [AnyHashable : Any] ?? [:]; diff --git a/Mage/Extensions/MageImage.swift b/Mage/Extensions/MageImage.swift index bef1dda3..50ad67f6 100644 --- a/Mage/Extensions/MageImage.swift +++ b/Mage/Extensions/MageImage.swift @@ -40,7 +40,7 @@ extension CIImage { func jpegData() -> Data? { if let colorSpace = CGColorSpace(name: CGColorSpace.sRGB) { - let context = CIContext() + let context = CIContext() return context.jpegRepresentation(of: self, colorSpace: colorSpace, options: [kCGImageDestinationLossyCompressionQuality as CIImageRepresentationOption : 1.0]) } return nil diff --git a/Mage/SettingsDataSource.m b/Mage/SettingsDataSource.m index b88448a9..3b717c30 100644 --- a/Mage/SettingsDataSource.m +++ b/Mage/SettingsDataSource.m @@ -48,15 +48,19 @@ - (instancetype) initWithScheme: (id) containerScheme { User *user = [User fetchCurrentUserWithContext:[NSManagedObjectContext MR_defaultContext]]; NSArray *recentEventIds = [user.recentEventIds filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF != %@", self.event.remoteId]]; - NSFetchRequest *recentRequest = [Event MR_requestAllInContext:[NSManagedObjectContext MR_defaultContext]]; - [recentRequest setPredicate:[NSPredicate predicateWithFormat:@"(remoteId IN %@)", recentEventIds]]; - [recentRequest setIncludesSubentities:NO]; - NSSortDescriptor* sortBy = [NSSortDescriptor sortDescriptorWithKey:@"recentSortOrder" ascending:YES]; - [recentRequest setSortDescriptors:[NSArray arrayWithObject:sortBy]]; - - NSError *error = nil; - self.recentEvents = [[NSManagedObjectContext MR_defaultContext] executeFetchRequest:recentRequest error:&error]; - if (error != nil) { + if (recentEventIds != nil) { + NSFetchRequest *recentRequest = [Event MR_requestAllInContext:[NSManagedObjectContext MR_defaultContext]]; + [recentRequest setPredicate:[NSPredicate predicateWithFormat:@"(remoteId IN %@)", recentEventIds]]; + [recentRequest setIncludesSubentities:NO]; + NSSortDescriptor* sortBy = [NSSortDescriptor sortDescriptorWithKey:@"recentSortOrder" ascending:YES]; + [recentRequest setSortDescriptors:[NSArray arrayWithObject:sortBy]]; + + NSError *error = nil; + self.recentEvents = [[NSManagedObjectContext MR_defaultContext] executeFetchRequest:recentRequest error:&error]; + if (error != nil) { + self.recentEvents = [[NSArray alloc] init]; + } + } else { self.recentEvents = [[NSArray alloc] init]; } diff --git a/MageTests/Observation/Attachment/AttachmentCreationCoordinatorTests.swift b/MageTests/Observation/Attachment/AttachmentCreationCoordinatorTests.swift index 66f840fa..e01017d5 100644 --- a/MageTests/Observation/Attachment/AttachmentCreationCoordinatorTests.swift +++ b/MageTests/Observation/Attachment/AttachmentCreationCoordinatorTests.swift @@ -12,16 +12,20 @@ import Nimble //import Nimble_Snapshots import OHHTTPStubs import UniformTypeIdentifiers +import Photos +import PhotosUI @testable import MAGE class MockAttachmentCreationCoordinatorDelegate: AttachmentCreationCoordinatorDelegate { - var attachmentCreatedCalled = false; - var createdAttachment: Attachment?; - var attachmentCreationCancelledCalled = false; + + let attachmentCreatedCalled = XCTestExpectation(description: "attachmentCreated called") + let attachmentCreationCancelledCalled = XCTestExpectation(description: "attachmentCreationCancelled called") + var createdAttachment: Attachment? + func attachmentCreated(attachment: Attachment) { - createdAttachment = attachment; - attachmentCreatedCalled = true; + createdAttachment = attachment + attachmentCreatedCalled.fulfill() } func attachmentCreated(fieldValue: [String : AnyHashable]) { @@ -29,7 +33,7 @@ class MockAttachmentCreationCoordinatorDelegate: AttachmentCreationCoordinatorDe } func attachmentCreationCancelled() { - attachmentCreationCancelledCalled = true; + attachmentCreationCancelledCalled.fulfill() } } @@ -37,7 +41,8 @@ class AttachmentCreationCoordinatorTests: KIFSpec { override func spec() { - xdescribe("AttachmentCreationCoordinatorTests") { + describe("AttachmentCreationCoordinatorTests") { + var attachmentCreationCoordinator: AttachmentCreationCoordinator! var view: UIView! var controller: UIViewController! @@ -78,7 +83,7 @@ class AttachmentCreationCoordinatorTests: KIFSpec { HTTPStubs.removeAllStubs(); } - it("present gallery") { + xit("presents the gallery") { let observation: Observation = Observation.mr_createEntity()!; let delegate = MockAttachmentCreationCoordinatorDelegate(); @@ -97,7 +102,7 @@ class AttachmentCreationCoordinatorTests: KIFSpec { attachmentCreationCoordinator.imagePickerController(mockPicker, didFinishPickingMediaWithInfo: info) - expect(delegate.attachmentCreatedCalled).to(beTrue()); + self.wait(for: [ delegate.attachmentCreatedCalled ], timeout: 0.0) expect(delegate.createdAttachment).toNot(beNil()); let createdAttachment: Attachment = delegate.createdAttachment!; @@ -109,10 +114,44 @@ class AttachmentCreationCoordinatorTests: KIFSpec { expect(createdAttachment.remotePath).to(beNil()); expect(createdAttachment.url).to(beNil()); expect(createdAttachment.contentType).to(equal("image/jpeg")); + } + it("converts png to jpeg and marks the attachment as a jpeg") { + + let pngUrl = Bundle(for: AttachmentFieldViewTests.self).url(forResource: "test_image_attachment", withExtension: "png")! + var assetId: String? = nil + try PHPhotoLibrary.shared().performChangesAndWait { + let addPngToLibrary = PHAssetCreationRequest.creationRequestForAssetFromImage(atFileURL: pngUrl) + let placeholder = addPngToLibrary?.placeholderForCreatedAsset + assetId = placeholder?.localIdentifier + } + let selectedAsset = PHAsset.fetchAssets(withLocalIdentifiers: [ assetId! ], options: nil).firstObject! + let observation: Observation = Observation.mr_createEntity()! + let delegate = MockAttachmentCreationCoordinatorDelegate() + let attachmentCreationCoordinator = AttachmentCreationCoordinator(rootViewController: controller, observation: observation, delegate: delegate) + + // there is no way to call the delegate method picker(picker:didFinishPicking:) because + // the sdk provides no accessible constructor for the PHPickerResult struct. thanks, apple + attachmentCreationCoordinator.handlePhoto(photo: selectedAsset, utType: UTType.png) + self.wait(for: [ delegate.attachmentCreatedCalled ], timeout: 5.0) + + let createdAttachment: Attachment = delegate.createdAttachment! + expect(createdAttachment).toNot(beNil()) + let createdJpegData = FileManager.default.contents(atPath: createdAttachment.localPath!) + let jpegFirstBytes = Data([ 0xff, 0xd8, 0xff ]) + expect(createdJpegData).notTo(beNil()) + expect(createdJpegData?[0..<3]).to(equal(jpegFirstBytes)) + expect(createdAttachment.lastModified).toNot(beNil()); + expect(createdAttachment.dirty).to(beTrue()); + expect(createdAttachment.observation).to(equal(observation)); + expect(createdAttachment.remoteId).to(beNil()); + expect(createdAttachment.remotePath).to(beNil()); + expect(createdAttachment.url).to(beNil()); + expect(createdAttachment.contentType).to(equal("image/jpeg")); + expect(createdAttachment.name).to(endWith(".jpeg")) } - it("choose a movie") { + xit("choose a movie") { let observation: Observation = Observation.mr_createEntity()!; let delegate = MockAttachmentCreationCoordinatorDelegate(); @@ -131,8 +170,8 @@ class AttachmentCreationCoordinatorTests: KIFSpec { mockPicker.sourceType = .camera; attachmentCreationCoordinator.imagePickerController(mockPicker, didFinishPickingMediaWithInfo: info) - - expect(delegate.attachmentCreatedCalled).toEventually(beTrue(), timeout: DispatchTimeInterval.seconds(10), pollInterval: DispatchTimeInterval.seconds(1), description: "Movie failed to export"); + + self.wait(for: [ delegate.attachmentCreatedCalled ], timeout: 10.0) expect(delegate.createdAttachment).toEventuallyNot(beNil()); let createdAttachment: Attachment = delegate.createdAttachment!; @@ -146,7 +185,7 @@ class AttachmentCreationCoordinatorTests: KIFSpec { expect(createdAttachment.contentType).to(equal("video/mp4")); } - it("create a recording") { + xit("create a recording") { let observation: Observation = Observation.mr_createEntity()!; let delegate = MockAttachmentCreationCoordinatorDelegate(); @@ -162,7 +201,7 @@ class AttachmentCreationCoordinatorTests: KIFSpec { attachmentCreationCoordinator.recordingAvailable(recording: recording); - expect(delegate.attachmentCreatedCalled).toEventually(beTrue()); + self.wait(for: [ delegate.attachmentCreatedCalled ]); expect(delegate.createdAttachment).toNot(beNil()); let createdAttachment: Attachment = delegate.createdAttachment!; diff --git a/MageTests/Observation/Fields/AttachmentFieldViewTests.swift b/MageTests/Observation/Fields/AttachmentFieldViewTests.swift index b1a5dc9a..6d4fcbf3 100644 --- a/MageTests/Observation/Fields/AttachmentFieldViewTests.swift +++ b/MageTests/Observation/Fields/AttachmentFieldViewTests.swift @@ -765,8 +765,8 @@ class AttachmentFieldViewTests: KIFSpec { tester().waitForAnimationsToFinish(withTimeout: 0.01); expect(attachmentLoaded).toEventually(beTrue(), timeout: DispatchTimeInterval.seconds(5), pollInterval: DispatchTimeInterval.seconds(1), description: "Loading Attachment"); - // expect(view).to(haveValidSnapshot(usesDrawRect: true)); + tester().waitForView(withAccessibilityLabel: "attachment \(attachment.name ?? "") loaded") } it("should call the attachment selection delegate on tap") { diff --git a/responses/test_image_attachment.png b/responses/test_image_attachment.png new file mode 100644 index 00000000..5d4f2ad3 Binary files /dev/null and b/responses/test_image_attachment.png differ diff --git a/sdk/AttachmentPushService.m b/sdk/AttachmentPushService.m index 8da7713f..4b34d8e4 100644 --- a/sdk/AttachmentPushService.m +++ b/sdk/AttachmentPushService.m @@ -271,7 +271,7 @@ - (void) attachmentUploadCompleteWithTask:(NSURLSessionTask *) task withError:(N NSDate *date = [NSDate dateFromIso8601String:dateString]; [attachment setLastModified:date]; } - + if (attachment.url) { __weak __typeof__(self) weakSelf = self;