Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
format
  • Loading branch information
tarrinneal committed Apr 24, 2023
commit c6861f4da1f883a1bb7f2b3bd581760b63c3ac58
Original file line number Diff line number Diff line change
Expand Up @@ -422,14 +422,14 @@ - (int64_t)duration {
- (void)seekTo:(int)location completionHandler:(void (^)(BOOL))completionHandler {
CMTime locationCMT = CMTimeMake(location, 1000);
CMTimeValue duration = _player.currentItem.asset.duration.value;
// Without adding tolerance when seeking to duration,
// seekToTime will never complete, and this call will hang.
// see issue https://github.com/flutter/flutter/issues/124475.
CMTime tolerance = location == duration ? CMTimeMake(1, 1000) : kCMTimeZero;
[_player seekToTime:locationCMT
toleranceBefore:tolerance
toleranceAfter:tolerance
completionHandler:completionHandler];
// Without adding tolerance when seeking to duration,
// seekToTime will never complete, and this call will hang.
// see issue https://github.com/flutter/flutter/issues/124475.
CMTime tolerance = location == duration ? CMTimeMake(1, 1000) : kCMTimeZero;
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you write a unit test (XCTest) for this behavior?

Copy link
Collaborator

@stuartmorgan-g stuartmorgan-g Apr 25, 2023

Choose a reason for hiding this comment

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

I have no idea what I didn't think of that when @tarrinneal and I were talking about testing for this 🤦🏻

It looks like we don't currently have a way to mock out the underlying AVPlayer, which significantly reduces testability. I would suggest wrapping the current call to [AVPlayer playerWithPlayerItem:] in a factory object, and do DI of that factory. So you'd make a test-only header that declared:

  • A protocol for the AVPlayer instance factory (which it looks like would just be a single method)
  • A new init that takes an instance of the factory protocol.

The, similar to the other DI you did recently, you'd have a private implementation of that protocol that's the default version, just wrapping [AVPlayer playerWithPlayerItem:], but tests could replace it with something vending mock AVPlayer instances where you could validate the tolerance parameter.

Copy link
Contributor

Choose a reason for hiding this comment

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

Can also try stubbing the constructor directly if it's easier:

id mockPlayer = OCMClassMock([AVPlayer class]);
OCMStub([AVPlayer playerWithPlayerItem:OCMOCM_ANY]).andReturn(mockPlayer);

Copy link
Collaborator

@stuartmorgan-g stuartmorgan-g Apr 26, 2023

Choose a reason for hiding this comment

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

Please don't. OCMock class mocking is giant foot-gun; it's incredibly easy to accidentally leak mocking across tests.

Copy link
Contributor

Choose a reason for hiding this comment

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

gotcha. i did that a few times for camera plugin iirc. i should clean that up sometime.

[_player seekToTime:locationCMT
toleranceBefore:tolerance
toleranceAfter:tolerance
completionHandler:completionHandler];
}

- (void)setIsLooping:(BOOL)isLooping {
Expand Down