Skip to content

[image_picker] Add native tests for image, metadata, photo-asset, and PHPicker save utilities - #12536

Merged
auto-submit[bot] merged 5 commits into
flutter:mainfrom
victogomez-cs:image_picker_coverage_1_util_tests
Sep 1, 2026
Merged

auto-submit[bot] merged 5 commits into
flutter:mainfrom
victogomez-cs:image_picker_coverage_1_util_tests

Conversation

@victogomez-cs

@victogomez-cs victogomez-cs commented Aug 21, 2026 •

Copy link
Copy Markdown
Contributor

Adds native unit tests for previously untested paths in FLTImagePickerImageUtil, FLTImagePickerMetaDataUtil, FLTImagePickerPhotoAssetUtil, and FLTPHPickerSaveImageToPathOperation before the Objective-C → Swift migration. Production code is unchanged.

This is a tests-only change, so it does not bump the package version or CHANGELOG.

Native RunnerTests go from 72 tests to 88 tests (+16).

New test cases

ImageUtilTests:

  • testScaledGIFImage_UsesClampedDelayWhenUnclampedDelayMissing — GIF scaling uses the clamped delay when unclamped delay is missing

MetaDataUtilTests:

  • testGetImageMIMETypeFromImageDataUnknownReturnsOther — unrecognized image bytes map to the Other MIME type
  • testConvertImageIgnoresQualityForPNG — PNG conversion ignores JPEG quality and stays PNG
  • testConvertImageDefaultsNonJPEGNonPNGToJPEG — GIF and other non-JPEG/PNG data convert to JPEG

PhotoAssetUtilTests:

  • testGetAssetFromImagePickerInfoShouldReturnNilIfNotAvailable — picker info without a PHAsset returns nil
  • testGetAssetFromImagePickerInfoShouldReturnAssetIfPresent — picker info with a PHAsset returns that asset
  • testSaveVideoFromURLReturnsNilWhenSourceIsUnreadable — missing source file returns nil
  • testSaveVideoFromURLCopiesReadableFile — a readable video is copied to a new path
  • testSaveVideoFromURLReturnsNilWhenCopyFails — copy failure returns nil
  • testSaveImageWithOriginalImageDataNilUsesDefaultJPEG — nil original data saves as .jpg
  • testCreateFileReturnsPathWhenWriteFails — create-file still returns a path when the write fails

PickerSaveImageToPathOperationTests:

  • testInitWithNilResultReturnsNil — nil PHPicker result does not create an operation
  • testStartWhenCancelledFinishesWithoutSaving — a cancelled operation finishes without calling the save callback
  • testSaveVideoCopiesFile — a video item is copied to the saved path
  • testSaveVideoFailsWhenLoadReturnsError — a load error is reported as invalid_image
  • testSaveVideoFailsWhenCopyFails — a copy error is reported as flutter_image_picker_copy_video_error

First part of image_picker_ios coverage backfill before the Obj-C → Swift migration for flutter/flutter#119107

Pre-Review Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

Footnotes

  1. Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. ↩ ↩2

@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Aug 21, 2026
@victogomez-cs victogomez-cs changed the title [image_picker_ios] Add native tests for image, metadata, photo-asset, and PHPicker save utilities [image_picker] Add native tests for image, metadata, photo-asset, and PHPicker save utilities Aug 21, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds comprehensive unit tests for image, metadata, photo asset, and path operation utilities in the iOS image picker package. The review feedback highlights opportunities to improve test robustness and hygiene, specifically by cleaning up temporary files and guarding against potential crashes caused by passing nil URLs to file management APIs.

Comment on lines +46 to +49
XCTAssertNotNil(destination);
XCTAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:destination.path]);
[[NSFileManager defaultManager] removeItemAtPath:sourcePath error:nil];
[[NSFileManager defaultManager] removeItemAtURL:destination error:nil];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If saveVideoFromURL: returns nil, destination will be nil. Passing a nil URL to removeItemAtURL:error: throws an NSInvalidArgumentException and will crash the test runner instead of failing the test gracefully. We should guard the cleanup call and the file existence check to ensure they only run if destination is non-nil.

  XCTAssertNotNil(destination);
  if (destination) {
    XCTAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:destination.path]);
  }
  [[NSFileManager defaultManager] removeItemAtPath:sourcePath error:nil];
  if (destination) {
    [[NSFileManager defaultManager] removeItemAtURL:destination error:nil];
  }

@victogomez-cs victogomez-cs Aug 21, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed! Good catch, XCTAssertNotNil doesn’t abort the test, so removeItemAtURL: could be called with nil and throw. Guarded the existence check and cleanup so they only run when destination is non-nil

Comment on lines +84 to +85
XCTAssertEqualObjects([NSURL fileURLWithPath:savedPath].pathExtension, @"jpg");
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The temporary file created at savedPath is not cleaned up after the test completes, which leaks files in the temporary directory. We should remove the file at savedPath at the end of the test.

  XCTAssertEqualObjects([NSURL fileURLWithPath:savedPath].pathExtension, @"jpg");
  if (savedPath) {
    [[NSFileManager defaultManager] removeItemAtPath:savedPath error:nil];
  }
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed and fixed. The test now removes savedPath after the assertion.

Comment on lines +301 to +305
savedPathBlock:^(NSString *savedPath, FlutterError *error) {
XCTAssertNil(error);
XCTAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:savedPath]);
[pathExpectation fulfill];
}];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The temporary file created at savedPath by the operation is not cleaned up, leaking files in the temporary directory. We should delete the file at savedPath inside the completion block.

Suggested change
savedPathBlock:^(NSString *savedPath, FlutterError *error) {
XCTAssertNil(error);
XCTAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:savedPath]);
[pathExpectation fulfill];
}];
savedPathBlock:^(NSString *savedPath, FlutterError *error) {
XCTAssertNil(error);
XCTAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:savedPath]);
if (savedPath) {
[[NSFileManager defaultManager] removeItemAtPath:savedPath error:nil];
}
[pathExpectation fulfill];
}];

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed and fixed. The copied file is now deleted after the operation finishes (in addition to the source .mov).

victogomez-cs and others added 2 commits August 21, 2026 12:50
…onTests to ensure temporary files are removed after assertions. This prevents potential file clutter during test execution.

@danielleon-cmd danielleon-cmd left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked each new test against the corresponding implementation (FLTImagePickerImageUtil, FLTImagePickerMetaDataUtil, FLTImagePickerPhotoAssetUtil, FLTPHPickerSaveImageToPathOperation) and built + ran the full RunnerTests target covering these files on a simulator: all 55 tests pass, including the 16 added here. Assertions match actual behavior in each case, and the tests clean up their temp files. Test-only change, so no CHANGELOG/version bump needed.

@jmagman jmagman added the triage-ios Should be looked at in iOS triage label Aug 27, 2026
@LouiseHsu
LouiseHsu self-requested a review August 27, 2026 21:55

@LouiseHsu LouiseHsu left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm!

@jmagman jmagman added the autosubmit Merge PR when tree becomes green via auto submit App label Sep 1, 2026
@auto-submit
auto-submit Bot merged commit e71317b into flutter:main Sep 1, 2026
13 of 14 checks passed
@victogomez-cs
victogomez-cs deleted the image_picker_coverage_1_util_tests branch September 1, 2026 21:42
pull Bot pushed a commit to Mu-L/flutter that referenced this pull request Sep 2, 2026
…r#192191)

flutter/packages@7a7912f...18fe786

2026-09-02 [email protected]
[path_parsing] Fix deprecation lints (flutter/packages#12704)
2026-09-02 [email protected] [material_ui] Use super parameters in
more places (flutter/packages#12460)
2026-09-02 [email protected] [material_ui] Add
a README and placeholders for migrating gen_defaults templates
(flutter/packages#12714)
2026-09-01 [email protected] [image_picker] Add native tests
for image, metadata, photo-asset, and PHPicker save utilities
(flutter/packages#12536)
2026-09-01 [email protected] [material_ui] Port routes_transition_test
to material_ui (flutter/packages#12634)
2026-09-01 [email protected] Roll Flutter from
c8c5e3b to 0cbd1a4 (23 revisions) (flutter/packages#12712)
2026-09-01 [email protected]
[material_ui] Remove !chrome in text_field_test.dart
(flutter/packages#12548)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages-flutter-autoroll
Please CC [email protected] on the revert to ensure that a
human
is aware of the problem.

To file a bug in Flutter:
https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
victorsanni pushed a commit to victorsanni/packages that referenced this pull request Sep 9, 2026
… PHPicker save utilities (flutter#12536)

Adds native unit tests for previously untested paths in `FLTImagePickerImageUtil`, `FLTImagePickerMetaDataUtil`, `FLTImagePickerPhotoAssetUtil`, and `FLTPHPickerSaveImageToPathOperation` before the Objective-C → Swift migration. Production code is unchanged.

This is a tests-only change, so it does not bump the package version or CHANGELOG.

Native `RunnerTests` go from 72 tests to 88 tests (+16).

### New test cases

**`ImageUtilTests`:**
- `testScaledGIFImage_UsesClampedDelayWhenUnclampedDelayMissing` — GIF scaling uses the clamped delay when unclamped delay is missing

**`MetaDataUtilTests`:**
- `testGetImageMIMETypeFromImageDataUnknownReturnsOther` — unrecognized image bytes map to the Other MIME type
- `testConvertImageIgnoresQualityForPNG` — PNG conversion ignores JPEG quality and stays PNG
- `testConvertImageDefaultsNonJPEGNonPNGToJPEG` — GIF and other non-JPEG/PNG data convert to JPEG

**`PhotoAssetUtilTests`:**
- `testGetAssetFromImagePickerInfoShouldReturnNilIfNotAvailable` — picker info without a PHAsset returns `nil`
- `testGetAssetFromImagePickerInfoShouldReturnAssetIfPresent` — picker info with a PHAsset returns that asset
- `testSaveVideoFromURLReturnsNilWhenSourceIsUnreadable` — missing source file returns `nil`
- `testSaveVideoFromURLCopiesReadableFile` — a readable video is copied to a new path
- `testSaveVideoFromURLReturnsNilWhenCopyFails` — copy failure returns `nil`
- `testSaveImageWithOriginalImageDataNilUsesDefaultJPEG` — `nil` original data saves as `.jpg`
- `testCreateFileReturnsPathWhenWriteFails` — create-file still returns a path when the write fails

**`PickerSaveImageToPathOperationTests`:**
- `testInitWithNilResultReturnsNil` — `nil` PHPicker result does not create an operation
- `testStartWhenCancelledFinishesWithoutSaving` — a cancelled operation finishes without calling the save callback
- `testSaveVideoCopiesFile` — a video item is copied to the saved path
- `testSaveVideoFailsWhenLoadReturnsError` — a load error is reported as `invalid_image`
- `testSaveVideoFailsWhenCopyFails` — a copy error is reported as `flutter_image_picker_copy_video_error`

First part of `image_picker_ios` coverage backfill before the Obj-C → Swift migration for flutter/flutter#119107

## Pre-Review Checklist

**Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

[^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling.
victorsanni pushed a commit to victorsanni/packages that referenced this pull request Sep 9, 2026
… PHPicker save utilities (flutter#12536)

Adds native unit tests for previously untested paths in `FLTImagePickerImageUtil`, `FLTImagePickerMetaDataUtil`, `FLTImagePickerPhotoAssetUtil`, and `FLTPHPickerSaveImageToPathOperation` before the Objective-C → Swift migration. Production code is unchanged.

This is a tests-only change, so it does not bump the package version or CHANGELOG.

Native `RunnerTests` go from 72 tests to 88 tests (+16).

### New test cases

**`ImageUtilTests`:**
- `testScaledGIFImage_UsesClampedDelayWhenUnclampedDelayMissing` — GIF scaling uses the clamped delay when unclamped delay is missing

**`MetaDataUtilTests`:**
- `testGetImageMIMETypeFromImageDataUnknownReturnsOther` — unrecognized image bytes map to the Other MIME type
- `testConvertImageIgnoresQualityForPNG` — PNG conversion ignores JPEG quality and stays PNG
- `testConvertImageDefaultsNonJPEGNonPNGToJPEG` — GIF and other non-JPEG/PNG data convert to JPEG

**`PhotoAssetUtilTests`:**
- `testGetAssetFromImagePickerInfoShouldReturnNilIfNotAvailable` — picker info without a PHAsset returns `nil`
- `testGetAssetFromImagePickerInfoShouldReturnAssetIfPresent` — picker info with a PHAsset returns that asset
- `testSaveVideoFromURLReturnsNilWhenSourceIsUnreadable` — missing source file returns `nil`
- `testSaveVideoFromURLCopiesReadableFile` — a readable video is copied to a new path
- `testSaveVideoFromURLReturnsNilWhenCopyFails` — copy failure returns `nil`
- `testSaveImageWithOriginalImageDataNilUsesDefaultJPEG` — `nil` original data saves as `.jpg`
- `testCreateFileReturnsPathWhenWriteFails` — create-file still returns a path when the write fails

**`PickerSaveImageToPathOperationTests`:**
- `testInitWithNilResultReturnsNil` — `nil` PHPicker result does not create an operation
- `testStartWhenCancelledFinishesWithoutSaving` — a cancelled operation finishes without calling the save callback
- `testSaveVideoCopiesFile` — a video item is copied to the saved path
- `testSaveVideoFailsWhenLoadReturnsError` — a load error is reported as `invalid_image`
- `testSaveVideoFailsWhenCopyFails` — a copy error is reported as `flutter_image_picker_copy_video_error`

First part of `image_picker_ios` coverage backfill before the Obj-C → Swift migration for flutter/flutter#119107

## Pre-Review Checklist

**Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

[^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

autosubmit Merge PR when tree becomes green via auto submit App CICD Run CI/CD p: image_picker platform-ios triage-ios Should be looked at in iOS triage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants