Skip to content

Commit

Permalink
Fix photo not displaying on Apple TV with OS 7.2
Browse files Browse the repository at this point in the history
  • Loading branch information
Eugene Nikolskyi committed Jun 2, 2015
1 parent 3016756 commit e40e816
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 23 deletions.
102 changes: 102 additions & 0 deletions ConnectSDKIntegrationTests/AirPlayServiceIntegrationTests.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//
// AirPlayServiceIntegrationTests.m
// ConnectSDK
//
// Created by Eugene Nikolskyi on 2015-02-06.
// Copyright (c) 2015 LG Electronics. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#import "AirPlayService.h"
#import "DiscoveryManager.h"
#import "ZeroConfDiscoveryProvider.h"

#import "OCMArg+ArgumentCaptor.h"
#import "OCMStubRecorder+SpectaAsync.h"

SpecBegin(AirPlayService)

describe(@"ConnectSDK", ^{
__block DiscoveryManager *manager;
__block id delegateStub;

beforeEach(^{
manager = [DiscoveryManager new];
manager.deviceStore = nil;

delegateStub = OCMProtocolMock(@protocol(DiscoveryManagerDelegate));
manager.delegate = delegateStub;

[AirPlayService setAirPlayServiceMode:AirPlayServiceModeMedia];
[manager registerDeviceService:[AirPlayService class]
withDiscovery:[ZeroConfDiscoveryProvider class]];
});

context(@"after AppleTV device is connected", ^{
__block ConnectableDevice *appleTV;

beforeEach(^{
waitUntil(^(DoneCallback done) {
[OCMStub([delegateStub discoveryManager:manager
didFindDevice:[OCMArg captureTo:&appleTV]])
andDoneWaiting:done];

[manager startDiscovery];
});

expect([appleTV serviceWithName:kConnectSDKAirPlayServiceId]).notTo.beNil();
});

it(@"should display photo", ^{
NSURL *url = [[NSBundle bundleForClass:self.class]
URLForResource:@"the-san-francisco-peaks-of-flagstaff-718x544"
withExtension:@"jpg"];
MediaInfo *mediaInfo = [[MediaInfo alloc] initWithURL:url
mimeType:@"image/jpg"];

waitUntil(^(DoneCallback done) {
MediaPlayerSuccessBlock successBlock = ^(MediaLaunchObject *_) {
// the delay is not required here, but allows to visually
// check if the image is indeed displayed
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, .5 * NSEC_PER_SEC),
dispatch_get_main_queue(),
^{
done();
});
};
FailureBlock failureBlock = ^(NSError *error) {
failure([NSString stringWithFormat:@"should not happen: %@",
error]);
done();
};
[[appleTV mediaPlayer] displayImageWithMediaInfo:mediaInfo
success:successBlock
failure:failureBlock];
});
});

afterEach(^{
[appleTV disconnect];
appleTV = nil;
});
});

afterEach(^{
[manager stopDiscovery];
delegateStub = nil;
manager = nil;
});
});

SpecEnd
File renamed without changes.
94 changes: 73 additions & 21 deletions ConnectSDKTests/Services/Helpers/AirPlayServiceHTTPTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,72 @@
#import "AirPlayServiceHTTP_Private.h"

#import "NSInvocation+ObjectGetter.h"
#import "OCMStubRecorder+XCTestExpectation.h"

/// Tests for the @c AirPlayServiceHTTP class.
@interface AirPlayServiceHTTPTests : XCTestCase

@property (strong) id /*AirPlayService **/ serviceMock;
@property (strong) AirPlayServiceHTTP *serviceHTTP;
@property (strong) id /*<ServiceCommandDelegate>*/ serviceCommandDelegateMock;

@end

@implementation AirPlayServiceHTTPTests

#pragma mark - Setup

- (void)setUp {
[super setUp];

self.serviceMock = OCMClassMock([AirPlayService class]);
self.serviceHTTP = [[AirPlayServiceHTTP alloc]
initWithAirPlayService:self.serviceMock];

self.serviceCommandDelegateMock = OCMStrictProtocolMock(@protocol(ServiceCommandDelegate));
self.serviceHTTP.serviceCommandDelegate = self.serviceCommandDelegateMock;
}

- (void)tearDown {
self.serviceCommandDelegateMock = nil;
self.serviceHTTP = nil;
self.serviceMock = nil;

[super tearDown];
}

#pragma mark - Request Tests

- (void)testDisplayImageShouldSendPUTPhotoRequest {
id serviceDescriptionMock = OCMClassMock([ServiceDescription class]);
[OCMStub([serviceDescriptionMock commandURL]) andReturn:
[NSURL URLWithString:@"http://10.0.0.1:9099/"]];
[OCMStub([self.serviceMock serviceDescription]) andReturn:serviceDescriptionMock];

XCTestExpectation *commandIsSent = [self expectationWithDescription:
@"Proper request should be sent"];
[OCMExpect([self.serviceCommandDelegateMock sendCommand:
[OCMArg checkWithBlock:^BOOL(ServiceCommand *command) {
return [@"PUT" isEqualToString:command.HTTPMethod];
}]
withPayload:OCMOCK_NOTNIL
toURL:
[OCMArg checkWithBlock:^BOOL(NSURL *url) {
return [@"/photo" isEqualToString:url.path];
}]]) andFulfillExpectation:commandIsSent];

NSURL *url = [[NSBundle bundleForClass:self.class] URLForResource:@"the-san-francisco-peaks-of-flagstaff-718x544"
withExtension:@"jpg"];
MediaInfo *mediaInfo = [[MediaInfo alloc] initWithURL:url
mimeType:@"image/jpg"];
[self.serviceHTTP displayImageWithMediaInfo:mediaInfo
success:nil
failure:nil];

[self waitForExpectationsWithTimeout:kDefaultAsyncTestTimeout handler:nil];
OCMVerifyAll(self.serviceCommandDelegateMock);
}

#pragma mark - getPlayState Tests

/// Tests that @c -getPlayStateWithSuccess:failure: properly infers the Paused
Expand Down Expand Up @@ -94,44 +152,38 @@ - (void)checkGetPlayStateShouldReturnPlayState:(MediaControlPlayState)expectedPl
- (void)checkGetPlayStateShouldReturnPlayState:(MediaControlPlayState)expectedPlayState
forMockResponse:(NSDictionary *)response {
// Arrange
id serviceMock = OCMClassMock([AirPlayService class]);
AirPlayServiceHTTP *serviceHTTP = [[AirPlayServiceHTTP alloc]
initWithAirPlayService:serviceMock];

id serviceCommandDelegateMock = OCMProtocolMock(@protocol(ServiceCommandDelegate));
serviceHTTP.serviceCommandDelegate = serviceCommandDelegateMock;

[OCMExpect([serviceCommandDelegateMock sendCommand:OCMOCK_NOTNIL
withPayload:OCMOCK_ANY
toURL:OCMOCK_ANY]) andDo:^(NSInvocation *invocation) {
ServiceCommand *command = [invocation objectArgumentAtIndex:0];
XCTAssertNotNil(command, @"Couldn't get the command argument");

dispatch_async(dispatch_get_main_queue(), ^{
command.callbackComplete(response);
});
[OCMExpect([self.serviceCommandDelegateMock sendCommand:OCMOCK_NOTNIL
withPayload:OCMOCK_ANY
toURL:OCMOCK_ANY])
andDo:^(NSInvocation *invocation) {
ServiceCommand *command = [invocation objectArgumentAtIndex:0];
XCTAssertNotNil(command, @"Couldn't get the command argument");

dispatch_async(dispatch_get_main_queue(), ^{
command.callbackComplete(response);
});
}];

XCTestExpectation *didReceivePlayState = [self expectationWithDescription:
@"received playState"];

// Act
[serviceHTTP getPlayStateWithSuccess:^(MediaControlPlayState playState) {
[self.serviceHTTP getPlayStateWithSuccess:^(MediaControlPlayState playState) {
XCTAssertEqual(playState, expectedPlayState,
@"playState is incorrect");

[didReceivePlayState fulfill];
}
failure:^(NSError *error) {
XCTFail(@"Failure %@", error);
}];
failure:^(NSError *error) {
XCTFail(@"Failure %@", error);
}];

// Assert
[self waitForExpectationsWithTimeout:kDefaultAsyncTestTimeout
handler:^(NSError *error) {
XCTAssertNil(error);
OCMVerifyAll(serviceCommandDelegateMock);
}];
OCMVerifyAll(self.serviceCommandDelegateMock);
}

@end
File renamed without changes.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions Services/Helpers/AirPlayServiceHTTP.m
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,8 @@ - (void) displayImageWithMediaInfo:(MediaInfo *)mediaInfo success:(MediaPlayerSu
NSString *commandPathComponent = @"photo";
NSURL *commandURL = [self.service.serviceDescription.commandURL URLByAppendingPathComponent:commandPathComponent];

ServiceCommand *command = [ServiceCommand commandWithDelegate:self target:commandURL payload:nil];
command.HTTPMethod = @"POST";
ServiceCommand *command = [ServiceCommand commandWithDelegate:self.serviceCommandDelegate target:commandURL payload:nil];
command.HTTPMethod = @"PUT";
command.callbackComplete = ^(id responseObject) {
LaunchSession *launchSession = [LaunchSession launchSessionForAppId:commandPathComponent];
launchSession.sessionType = LaunchSessionTypeMedia;
Expand Down

0 comments on commit e40e816

Please sign in to comment.