diff --git a/ConnectSDKIntegrationTests/AirPlayServiceIntegrationTests.m b/ConnectSDKIntegrationTests/AirPlayServiceIntegrationTests.m new file mode 100644 index 0000000..b1958b5 --- /dev/null +++ b/ConnectSDKIntegrationTests/AirPlayServiceIntegrationTests.m @@ -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 diff --git a/ConnectSDKIntegrationTests/Info.plist b/ConnectSDKIntegrationTests/SupportingFiles/Info.plist similarity index 100% rename from ConnectSDKIntegrationTests/Info.plist rename to ConnectSDKIntegrationTests/SupportingFiles/Info.plist diff --git a/ConnectSDKTests/Services/Helpers/AirPlayServiceHTTPTests.m b/ConnectSDKTests/Services/Helpers/AirPlayServiceHTTPTests.m index d58ed9b..4f59139 100644 --- a/ConnectSDKTests/Services/Helpers/AirPlayServiceHTTPTests.m +++ b/ConnectSDKTests/Services/Helpers/AirPlayServiceHTTPTests.m @@ -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 /**/ 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 @@ -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 diff --git a/ConnectSDKTests/Info.plist b/ConnectSDKTests/SupportingFiles/Info.plist similarity index 100% rename from ConnectSDKTests/Info.plist rename to ConnectSDKTests/SupportingFiles/Info.plist diff --git a/ConnectSDKTests/SupportingFiles/the-san-francisco-peaks-of-flagstaff-718x544.jpg b/ConnectSDKTests/SupportingFiles/the-san-francisco-peaks-of-flagstaff-718x544.jpg new file mode 100644 index 0000000..2594896 Binary files /dev/null and b/ConnectSDKTests/SupportingFiles/the-san-francisco-peaks-of-flagstaff-718x544.jpg differ diff --git a/Services/Helpers/AirPlayServiceHTTP.m b/Services/Helpers/AirPlayServiceHTTP.m index dd19026..fc8015c 100644 --- a/Services/Helpers/AirPlayServiceHTTP.m +++ b/Services/Helpers/AirPlayServiceHTTP.m @@ -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;