Skip to content

Commit

Permalink
[FEATURE] Now play command endpoint does not require body (#70)
Browse files Browse the repository at this point in the history
Implementation of #69

Now play command does not require body, if body missing, then we assume that user want to resume the playback
  • Loading branch information
justJavaProgrammer authored Aug 2, 2024
1 parent 59f8d48 commit a3eba97
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 33 deletions.
2 changes: 1 addition & 1 deletion sonata-connect-run.test.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/bin/bash

docker-compose -f docker-compose.test.yml up --abort-on-container-exit
docker compose -f docker-compose.test.yml up --abort-on-container-exit
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ public Mono<CurrentPlayerState> playOrResume(@NotNull final User user,
}

@NotNull
private Mono<CurrentPlayerState> executeCommand(@NotNull final PlayCommandContext context,
private Mono<CurrentPlayerState> executeCommand(@NotNull final PlayCommandContext playback,
@NotNull final CurrentPlayerState state) {

if ( context.getContextUri() == null ) {
if ( playback.shouldBeResumed() ) {
return resumePlayback(state);
}

return playableItemLoader.loadPlayableItem(context.getContextUri())
return playableItemLoader.loadPlayableItem(playback.getContextUri())
.switchIfEmpty(Mono.defer(() -> Mono.error(PlayableItemNotFoundException.defaultException())))
.flatMap(item -> play(state, item));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import java.lang.reflect.Parameter;
import java.util.List;
import java.util.function.Function;

/**
* Resolves a {@link PlayCommandContext} from the given {@link ServerWebExchange}
Expand All @@ -41,25 +42,27 @@ public Mono<Object> resolveArgument(@NotNull final MethodParameter parameter,

final Parameter bodyTypeParameter = resolveBodyTypeParameter();

return readBody(MethodParameter.forParameter(bodyTypeParameter), parameter, true, bindingContext, exchange)
return readBody(MethodParameter.forParameter(bodyTypeParameter), parameter, false, bindingContext, exchange)
.cast(PlayResumePlaybackRequest.class)
.map(PlayResumePlaybackRequest::getContextUri)
.flatMap(PlayCommandContextResolver::tryParseContextUri);
.flatMap(PlayCommandContextResolver::tryParseCommandRequest)
.defaultIfEmpty(PlayCommandContext.resumePlayback())
// we need this because java can't recognize type correctly :(
.map(Function.identity());
}

@NotNull
private static Mono<PlayCommandContext> tryParseContextUri(final String contextUriStr) {
private static Mono<PlayCommandContext> tryParseCommandRequest(final PlayResumePlaybackRequest playResumePlaybackRequest) {
final String contextUriStr = playResumePlaybackRequest.getContextUri();

if ( ContextUri.isValid(contextUriStr) ) {
return Mono.just(
PlayCommandContext.from(
ContextUri.fromString(contextUriStr)
));
return Mono.just(PlayCommandContext.from(
ContextUri.fromString(contextUriStr)
));
}

return Mono.defer(
() -> Mono.error(
new ReasonCodeAwareMalformedContextUriException("Context uri is malformed", contextUriStr)
));
return Mono.defer(() -> Mono.error(
new ReasonCodeAwareMalformedContextUriException("Context uri is malformed", contextUriStr)
));
}

@NotNull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public PlayableItemLoader testablePlayableItemLoader() {
void shouldReturn204Status() {
connectDevice();

WebTestClient.ResponseSpec responseSpec = sendResumeEndpointRequest(
WebTestClient.ResponseSpec responseSpec = sendPlayOrResumeCommandRequest(
PlayResumePlaybackRequest.of(EXISTING_TRACK_CONTEXT_URI)
);

Expand All @@ -97,7 +97,7 @@ void shouldReturn204Status() {
void shouldChangePlayerCurrentPlayableItemToProvided() {
connectDevice();

final WebTestClient.ResponseSpec ignored = sendResumeEndpointRequest(
final WebTestClient.ResponseSpec ignored = sendPlayOrResumeCommandRequest(
PlayResumePlaybackRequest.of(EXISTING_TRACK_CONTEXT_URI)
);

Expand All @@ -111,7 +111,7 @@ void shouldChangePlayerCurrentPlayableItemToProvided() {
void shouldSetTrueToPlayingField() {
connectDevice();

final WebTestClient.ResponseSpec ignored = sendResumeEndpointRequest(
final WebTestClient.ResponseSpec ignored = sendPlayOrResumeCommandRequest(
PlayResumePlaybackRequest.of(EXISTING_TRACK_CONTEXT_URI)
);

Expand All @@ -123,10 +123,9 @@ void shouldSetTrueToPlayingField() {

@Test
void shouldUpdateCurrentlyPlayingType() {
Hooks.onOperatorDebug();
connectDevice();

final WebTestClient.ResponseSpec ignored = sendResumeEndpointRequest(
final WebTestClient.ResponseSpec ignored = sendPlayOrResumeCommandRequest(
PlayResumePlaybackRequest.of(EXISTING_TRACK_CONTEXT_URI)
);

Expand All @@ -136,13 +135,31 @@ void shouldUpdateCurrentlyPlayingType() {
.currentlyPlayingType().track();
}

@Test
void shouldResumePlaybackIfBodyWasNotSetAndPlayerHasPlayableItem() {
connectDevice();

final WebTestClient.ResponseSpec ignored = sendPlayOrResumeCommandRequest(
PlayResumePlaybackRequest.of(EXISTING_TRACK_CONTEXT_URI)
);

pausePlayback();


sendResumeCurrentPlaybackRequest();

final PlayerStateDto updatedState = getCurrentState();

PlayerStateDtoAssert.forState(updatedState).shouldPlay();
}

@Test
void shouldReturn400BadRequestIfContextUriMalformed() {
connectDevice();

final String invalidContextUri = "sonata:somethinginvalid:mikuuuu";

final WebTestClient.ResponseSpec responseSpec = sendResumeEndpointRequest(PlayResumePlaybackRequest.of(invalidContextUri));
final WebTestClient.ResponseSpec responseSpec = sendPlayOrResumeCommandRequest(PlayResumePlaybackRequest.of(invalidContextUri));

responseSpec.expectStatus().isBadRequest();
}
Expand All @@ -153,7 +170,7 @@ void shouldReturnExceptionMessage() {

final String invalidContextUri = "sonata:somethinginvalid:mikuuuu";

final WebTestClient.ResponseSpec responseSpec = sendResumeEndpointRequest(PlayResumePlaybackRequest.of(invalidContextUri));
final WebTestClient.ResponseSpec responseSpec = sendPlayOrResumeCommandRequest(PlayResumePlaybackRequest.of(invalidContextUri));

final ReasonCodeAwareExceptionMessage body = responseSpec.expectBody(ReasonCodeAwareExceptionMessage.class)
.returnResult().getResponseBody();
Expand All @@ -168,7 +185,7 @@ void shouldReturnExceptionReasonCode() {

final String invalidContextUri = "sonata:somethinginvalid:mikuuuu";

final WebTestClient.ResponseSpec responseSpec = sendResumeEndpointRequest(PlayResumePlaybackRequest.of(invalidContextUri));
final WebTestClient.ResponseSpec responseSpec = sendPlayOrResumeCommandRequest(PlayResumePlaybackRequest.of(invalidContextUri));

final ReasonCodeAwareExceptionMessage body = responseSpec.expectBody(ReasonCodeAwareExceptionMessage.class).returnResult().getResponseBody();

Expand All @@ -180,7 +197,7 @@ void shouldReturnExceptionReasonCode() {
void shouldDoNothingIfPlayerWasJustCreated() {
final PlayerStateDto beforeRequest = getCurrentState();

final WebTestClient.ResponseSpec ignored = sendResumeCurrentPlaybackEndpointRequest();
final WebTestClient.ResponseSpec ignored = sendResumeCurrentPlaybackRequest();

final PlayerStateDto afterRequest = getCurrentState();

Expand All @@ -190,7 +207,7 @@ void shouldDoNothingIfPlayerWasJustCreated() {

@Test
void shouldReturn400StatusForEmptyState() {
WebTestClient.ResponseSpec responseSpec = sendResumeCurrentPlaybackEndpointRequest();
WebTestClient.ResponseSpec responseSpec = sendResumeCurrentPlaybackRequest();

responseSpec.expectStatus().isBadRequest();
}
Expand All @@ -202,7 +219,7 @@ class EmptyDeviceListTest {
@Test
void shouldReturnBadRequest() {

final WebTestClient.ResponseSpec responseSpec = sendResumeEndpointRequest(
final WebTestClient.ResponseSpec responseSpec = sendPlayOrResumeCommandRequest(
PlayResumePlaybackRequest.of(EXISTING_TRACK_CONTEXT_URI)
);

Expand All @@ -211,7 +228,7 @@ void shouldReturnBadRequest() {

@Test
void shouldReturnExceptionMessageInBody() {
final WebTestClient.ResponseSpec responseSpec = sendResumeEndpointRequest(
final WebTestClient.ResponseSpec responseSpec = sendPlayOrResumeCommandRequest(
PlayResumePlaybackRequest.of(EXISTING_TRACK_CONTEXT_URI)
);

Expand All @@ -225,7 +242,7 @@ void shouldReturnExceptionMessageInBody() {
@Test
void shouldReturnExceptionReasonInBody() {

final WebTestClient.ResponseSpec responseSpec = sendResumeEndpointRequest(
final WebTestClient.ResponseSpec responseSpec = sendPlayOrResumeCommandRequest(
PlayResumePlaybackRequest.of(EXISTING_TRACK_CONTEXT_URI)
);

Expand All @@ -234,21 +251,25 @@ void shouldReturnExceptionReasonInBody() {
ReasonCodeAwareExceptionMessageAssert.forMessage(body)
.reasonCode().isEqualTo("no_active_device");
}
}

}
private void connectDevice() {
final ConnectDeviceRequest connectDeviceRequest = ConnectDeviceRequestFaker.create().get();

testOperations.connectDevice(VALID_ACCESS_TOKEN, connectDeviceRequest);
}

private void pausePlayback() {
testOperations.pause(VALID_ACCESS_TOKEN);
}

@NotNull
private WebTestClient.ResponseSpec sendResumeCurrentPlaybackEndpointRequest() {
return sendResumeEndpointRequest(null);
private WebTestClient.ResponseSpec sendResumeCurrentPlaybackRequest() {
return sendPlayOrResumeCommandRequest(null);
}

@NotNull
private WebTestClient.ResponseSpec sendResumeEndpointRequest(@Nullable PlayResumePlaybackRequest body) {
private WebTestClient.ResponseSpec sendPlayOrResumeCommandRequest(@Nullable PlayResumePlaybackRequest body) {

final WebTestClient.RequestBodySpec builder = webTestClient.put()
.uri("/player/play")
Expand Down
2 changes: 2 additions & 0 deletions src/test/java/testing/shared/SonataTestHttpOperations.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public interface SonataTestHttpOperations {

void playOrResumePlayback(String authorizationHeaderValue, PlayResumePlaybackRequest body);

void pause(String validAccessToken);

void changeShuffle(String authorizationHeaderValue, boolean shuffleMode);

void switchDevices(String authorizationHeaderValue, DeviceSwitchRequest body);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ public void playOrResumePlayback(String authorizationHeaderValue, PlayResumePlay
.exchange();
}

@Override
public void pause(String authorizationHeaderValue) {
webTestClient.put()
.uri("/player/pause")
.header(HttpHeaders.AUTHORIZATION, authorizationHeaderValue)
.exchange()
.expectStatus().isNoContent();
}

@Override
public void changeShuffle(String authorizationHeaderValue, boolean shuffleMode) {
webTestClient.put()
Expand Down

0 comments on commit a3eba97

Please sign in to comment.