diff --git a/.github/workflows/analyse.yml b/.github/workflows/analyse.yml index 2482bad0..1d7943eb 100644 --- a/.github/workflows/analyse.yml +++ b/.github/workflows/analyse.yml @@ -12,6 +12,11 @@ on: schedule: - cron: '0 13 * * 1' +permissions: + security-events: write + actions: read + contents: read + jobs: code-ql: name: CodeQL @@ -25,16 +30,16 @@ jobs: distribution: 'temurin' java-version: 17 - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v2 with: languages: java - name: Autobuild - uses: github/codeql-action/autobuild@v1 + uses: github/codeql-action/autobuild@v2 env: GITHUB_USER: RakSrinaNa GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v2 qodana: name: Qodana diff --git a/miner/src/main/java/fr/raksrinana/channelpointsminer/miner/MinerApplication.java b/miner/src/main/java/fr/raksrinana/channelpointsminer/miner/MinerApplication.java index b08a9a1b..6fb37c28 100644 --- a/miner/src/main/java/fr/raksrinana/channelpointsminer/miner/MinerApplication.java +++ b/miner/src/main/java/fr/raksrinana/channelpointsminer/miner/MinerApplication.java @@ -77,7 +77,7 @@ private static void preSetup(){ Unirest.config() .enableCookieManagement(true) .setObjectMapper(new JacksonObjectMapper(JacksonUtils.getMapper())) - .setDefaultHeader(USER_AGENT, "Mozilla/5.0 (X11; Linux x86_64; rv:85.0) Gecko/20100101 Firefox/85.0") + .setDefaultHeader(USER_AGENT, "Mozilla/5.0 (X11; Linux x86_64; rv:104.0) Gecko/20100101 Firefox/104.0") .interceptor(new UnirestLogger()); } } diff --git a/miner/src/main/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApi.java b/miner/src/main/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApi.java index f6c35164..f1cb6be6 100644 --- a/miner/src/main/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApi.java +++ b/miner/src/main/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApi.java @@ -3,6 +3,7 @@ import fr.raksrinana.channelpointsminer.miner.api.gql.data.GQLError; import fr.raksrinana.channelpointsminer.miner.api.gql.data.GQLResponse; import fr.raksrinana.channelpointsminer.miner.api.gql.data.IGQLOperation; +import fr.raksrinana.channelpointsminer.miner.api.gql.data.IntegrityResponse; import fr.raksrinana.channelpointsminer.miner.api.gql.data.channelfollows.ChannelFollowsData; import fr.raksrinana.channelpointsminer.miner.api.gql.data.channelfollows.ChannelFollowsOperation; import fr.raksrinana.channelpointsminer.miner.api.gql.data.channelpointscontext.ChannelPointsContextData; @@ -32,37 +33,54 @@ import fr.raksrinana.channelpointsminer.miner.api.gql.data.videoplayerstreaminfooverlaychannel.VideoPlayerStreamInfoOverlayChannelData; import fr.raksrinana.channelpointsminer.miner.api.gql.data.videoplayerstreaminfooverlaychannel.VideoPlayerStreamInfoOverlayChannelOperation; import fr.raksrinana.channelpointsminer.miner.api.passport.TwitchLogin; +import fr.raksrinana.channelpointsminer.miner.api.passport.exceptions.IntegrityError; import fr.raksrinana.channelpointsminer.miner.api.passport.exceptions.InvalidCredentials; +import fr.raksrinana.channelpointsminer.miner.factory.TimeFactory; import kong.unirest.core.Unirest; -import lombok.RequiredArgsConstructor; import lombok.extern.log4j.Log4j2; +import org.apache.commons.lang3.RandomStringUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.Set; import static kong.unirest.core.HeaderNames.AUTHORIZATION; @Log4j2 -@RequiredArgsConstructor public class GQLApi{ - private static final String ENDPOINT = "https://gql.twitch.tv/gql"; + public static final String CLIENT_ID = "kimne78kx3ncx6brgo4mv6wki5h1ko"; + private static final String ENDPOINT = "https://gql.twitch.tv"; + private static final String CLIENT_INTEGRITY_HEADER = "Client-Integrity"; + private static final String CLIENT_ID_HEADER = "Client-ID"; private static final String ORDER_DESC = "DESC"; private static final Set EXPECTED_ERROR_MESSAGES = Set.of("service timeout", "service error", "server error", "service unavailable"); + private static final String DEVICE_ID_HEADER = "Device-ID"; + private static final int DEVICE_ID_LENGTH = 26; private final TwitchLogin twitchLogin; + private final String deviceId; + private IntegrityResponse integrityResponse; + + public GQLApi(TwitchLogin twitchLogin){ + this.twitchLogin = twitchLogin; + this.deviceId = RandomStringUtils.randomAlphanumeric(DEVICE_ID_LENGTH); + } @NotNull public Optional> reportMenuItem(@NotNull String username){ - return postRequest(new ReportMenuItemOperation(username)); + return postGqlRequest(new ReportMenuItemOperation(username)); } @NotNull - private Optional> postRequest(@NotNull IGQLOperation operation){ - var response = Unirest.post(ENDPOINT) + private Optional> postGqlRequest(@NotNull IGQLOperation operation){ + var response = Unirest.post(ENDPOINT + "/gql") .header(AUTHORIZATION, "OAuth " + twitchLogin.getAccessToken()) + .header(CLIENT_INTEGRITY_HEADER, getClientIntegrity()) + .header(CLIENT_ID_HEADER, CLIENT_ID) + .header(DEVICE_ID_HEADER, deviceId) .body(operation) .asObject(operation.getResponseType()); @@ -89,6 +107,31 @@ private Optional> postRequest(@NotNull IGQLOperation opera return Optional.ofNullable(response.getBody()); } + @NotNull + private String getClientIntegrity(){ + if(Objects.nonNull(integrityResponse) && integrityResponse.getExpiration().isAfter(TimeFactory.now())){ + return integrityResponse.getToken(); + } + + log.info("Querying new integrity token"); + var response = Unirest.post(ENDPOINT + "/integrity") + .header(AUTHORIZATION, "OAuth " + twitchLogin.getAccessToken()) + .asObject(IntegrityResponse.class); + + if(!response.isSuccess()){ + throw new RuntimeException(new IntegrityError(response.getStatus(), "Http code is not a success")); + } + + var body = response.getBody(); + if(Objects.isNull(body.getToken())){ + throw new RuntimeException(new IntegrityError(response.getStatus(), body.getMessage())); + } + + log.info("New integrity token will expire at {}", body.getExpiration()); + integrityResponse = body; + return body.getToken(); + } + private boolean isErrorExpected(@NotNull Collection errors){ return errors.stream().allMatch(this::isErrorExpected); } @@ -99,47 +142,47 @@ private boolean isErrorExpected(@NotNull GQLError error){ @NotNull public Optional> channelPointsContext(@NotNull String username){ - return postRequest(new ChannelPointsContextOperation(username)); + return postGqlRequest(new ChannelPointsContextOperation(username)); } @NotNull public Optional> videoPlayerStreamInfoOverlayChannel(@NotNull String username){ - return postRequest(new VideoPlayerStreamInfoOverlayChannelOperation(username)); + return postGqlRequest(new VideoPlayerStreamInfoOverlayChannelOperation(username)); } @NotNull public Optional> dropsHighlightServiceAvailableDrops(@NotNull String channelId){ - return postRequest(new DropsHighlightServiceAvailableDropsOperation(channelId)); + return postGqlRequest(new DropsHighlightServiceAvailableDropsOperation(channelId)); } @NotNull public Optional> claimCommunityPoints(@NotNull String channelId, @NotNull String claimId){ - return postRequest(new ClaimCommunityPointsOperation(channelId, claimId)); + return postGqlRequest(new ClaimCommunityPointsOperation(channelId, claimId)); } @NotNull public Optional> claimCommunityMoment(@NotNull String momentId){ - return postRequest(new CommunityMomentCalloutClaimOperation(momentId)); + return postGqlRequest(new CommunityMomentCalloutClaimOperation(momentId)); } @NotNull public Optional> joinRaid(@NotNull String raidId){ - return postRequest(new JoinRaidOperation(raidId)); + return postGqlRequest(new JoinRaidOperation(raidId)); } @NotNull public Optional> inventory(){ - return postRequest(new InventoryOperation()); + return postGqlRequest(new InventoryOperation()); } @NotNull public Optional> dropsPageClaimDropRewards(@NotNull String dropInstanceId){ - return postRequest(new DropsPageClaimDropRewardsOperation(dropInstanceId)); + return postGqlRequest(new DropsPageClaimDropRewardsOperation(dropInstanceId)); } @NotNull public Optional> makePrediction(@NotNull String eventId, @NotNull String outcomeId, int amount, @NotNull String transactionId){ - return postRequest(new MakePredictionOperation(eventId, outcomeId, amount, transactionId)); + return postGqlRequest(new MakePredictionOperation(eventId, outcomeId, amount, transactionId)); } @NotNull @@ -174,11 +217,11 @@ public List allChannelFollows(){ @NotNull public Optional> channelFollows(int limit, @NotNull String order, @Nullable String cursor){ - return postRequest(new ChannelFollowsOperation(limit, order, cursor)); + return postGqlRequest(new ChannelFollowsOperation(limit, order, cursor)); } @NotNull public Optional> chatRoomBanStatus(@NotNull String channelId, @NotNull String targetUserId){ - return postRequest(new ChatRoomBanStatusOperation(channelId, targetUserId)); + return postGqlRequest(new ChatRoomBanStatusOperation(channelId, targetUserId)); } } diff --git a/miner/src/main/java/fr/raksrinana/channelpointsminer/miner/api/gql/data/IntegrityResponse.java b/miner/src/main/java/fr/raksrinana/channelpointsminer/miner/api/gql/data/IntegrityResponse.java new file mode 100644 index 00000000..1b02b882 --- /dev/null +++ b/miner/src/main/java/fr/raksrinana/channelpointsminer/miner/api/gql/data/IntegrityResponse.java @@ -0,0 +1,34 @@ +package fr.raksrinana.channelpointsminer.miner.api.gql.data; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import fr.raksrinana.channelpointsminer.miner.util.json.MillisecondsTimestampDeserializer; +import fr.raksrinana.channelpointsminer.miner.util.json.UnknownDeserializer; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.ToString; +import java.time.Instant; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Builder +@ToString +@EqualsAndHashCode +public class IntegrityResponse{ + @JsonProperty("expiration") + @JsonDeserialize(using = MillisecondsTimestampDeserializer.class) + private Instant expiration; + @JsonProperty("request_id") + private String requestId; + @JsonProperty("token") + private String token; + @JsonProperty("error") + @JsonDeserialize(using = UnknownDeserializer.class) + private Object error; + @JsonProperty("message") + private String message; +} diff --git a/miner/src/main/java/fr/raksrinana/channelpointsminer/miner/api/passport/exceptions/IntegrityError.java b/miner/src/main/java/fr/raksrinana/channelpointsminer/miner/api/passport/exceptions/IntegrityError.java new file mode 100644 index 00000000..5de1d207 --- /dev/null +++ b/miner/src/main/java/fr/raksrinana/channelpointsminer/miner/api/passport/exceptions/IntegrityError.java @@ -0,0 +1,12 @@ +package fr.raksrinana.channelpointsminer.miner.api.passport.exceptions; + +import org.jetbrains.annotations.Nullable; + +/** + * Error while getting integrity token. + */ +public class IntegrityError extends Exception{ + public IntegrityError(int statusCode, @Nullable String description){ + super("Failed to get integrity token. Status code is " + statusCode + " : " + description); + } +} diff --git a/miner/src/main/java/fr/raksrinana/channelpointsminer/miner/util/json/MillisecondsTimestampDeserializer.java b/miner/src/main/java/fr/raksrinana/channelpointsminer/miner/util/json/MillisecondsTimestampDeserializer.java new file mode 100644 index 00000000..e4ce1852 --- /dev/null +++ b/miner/src/main/java/fr/raksrinana/channelpointsminer/miner/util/json/MillisecondsTimestampDeserializer.java @@ -0,0 +1,26 @@ +package fr.raksrinana.channelpointsminer.miner.util.json; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import java.io.IOException; +import java.time.Instant; + +public class MillisecondsTimestampDeserializer extends StdDeserializer{ + protected MillisecondsTimestampDeserializer(){ + this(null); + } + + protected MillisecondsTimestampDeserializer(Class vc){ + super(vc); + } + + @Override + public Instant deserialize(JsonParser p, DeserializationContext ctxt) throws IOException{ + var value = p.getValueAsLong(-1); + if(value < 0){ + return null; + } + return Instant.ofEpochMilli(value); + } +} diff --git a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/discord/DiscordApiTest.java b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/discord/DiscordApiTest.java index 2cd5697a..cfa69060 100644 --- a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/discord/DiscordApiTest.java +++ b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/discord/DiscordApiTest.java @@ -2,9 +2,9 @@ import fr.raksrinana.channelpointsminer.miner.api.discord.data.Webhook; import fr.raksrinana.channelpointsminer.miner.tests.TestUtils; +import fr.raksrinana.channelpointsminer.miner.tests.UnirestMock; import fr.raksrinana.channelpointsminer.miner.tests.UnirestMockExtension; import kong.unirest.core.HttpMethod; -import kong.unirest.core.MockClient; import org.mockito.junit.jupiter.MockitoExtension; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -30,7 +30,7 @@ void setUp() throws MalformedURLException{ } @Test - void nominal(MockClient unirest){ + void nominal(UnirestMock unirest){ var webhook = Webhook.builder() .username("UsernameWillBeOverriden") .content("Test message") @@ -48,7 +48,7 @@ void nominal(MockClient unirest){ } @Test - void nominalRetryAfter(MockClient unirest){ + void nominalRetryAfter(UnirestMock unirest){ var webhook = Webhook.builder() .content("Test message") .build(); @@ -65,7 +65,7 @@ void nominalRetryAfter(MockClient unirest){ } @Test - void error(MockClient unirest){ + void error(UnirestMock unirest){ var webhook = Webhook.builder() .content("Test message") .build(); diff --git a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/AbstractGQLTest.java b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/AbstractGQLTest.java new file mode 100644 index 00000000..f79f9db7 --- /dev/null +++ b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/AbstractGQLTest.java @@ -0,0 +1,72 @@ +package fr.raksrinana.channelpointsminer.miner.api.gql; + +import fr.raksrinana.channelpointsminer.miner.tests.TestUtils; +import fr.raksrinana.channelpointsminer.miner.tests.UnirestMock; +import static kong.unirest.core.HttpMethod.POST; + +public abstract class AbstractGQLTest{ + protected static final String ACCESS_TOKEN = "access-token"; + private static final String INTEGRITY_TOKEN = "integrity-token"; + + protected void expectValidRequestOkWithIntegrityOk(UnirestMock unirest, String responseBody){ + expectBodyRequestOkWithIntegrityOk(unirest, getValidRequest(), responseBody); + } + + protected void expectBodyRequestOkWithIntegrityOk(UnirestMock unirest, String requestBody, String responseBody){ + setupIntegrityOk(unirest); + expectBodyRequestOk(unirest, requestBody, responseBody); + } + + protected abstract String getValidRequest(); + + protected void setupIntegrityOk(UnirestMock unirest){ + unirest.expect(POST, "https://gql.twitch.tv/integrity") + .header("Authorization", "OAuth " + ACCESS_TOKEN) + .thenReturn(TestUtils.getAllResourceContent("api/gql/integrity_ok.json")) + .withStatus(200); + } + + protected void expectBodyRequestOk(UnirestMock unirest, String requestBody, String responseBody){ + expectRequest(unirest, requestBody, 200, responseBody); + } + + private void expectRequest(UnirestMock unirest, String requestBody, int responseStatus, String responseBody){ + unirest.expect(POST, "https://gql.twitch.tv/gql") + .header("Authorization", "OAuth " + ACCESS_TOKEN) + .header("Client-Integrity", INTEGRITY_TOKEN) + .header("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko") + .body(requestBody) + .thenReturn(responseBody == null ? null : TestUtils.getAllResourceContent(responseBody)) + .withStatus(responseStatus); + } + + protected void expectValidRequestOk(UnirestMock unirest, String responseBody){ + expectBodyRequestOk(unirest, getValidRequest(), responseBody); + } + + protected void expectValidRequestWithIntegrityOk(UnirestMock unirest, int responseStatus, String responseBody){ + setupIntegrityOk(unirest); + expectRequest(unirest, getValidRequest(), responseStatus, responseBody); + } + + protected void setupIntegrityWillNeedRefresh(UnirestMock unirest){ + unirest.expect(POST, "https://gql.twitch.tv/integrity") + .header("Authorization", "OAuth " + ACCESS_TOKEN) + .thenReturn(TestUtils.getAllResourceContent("api/gql/integrity_needRefresh.json")) + .withStatus(200); + } + + protected void setupIntegrityNoToken(UnirestMock unirest){ + unirest.expect(POST, "https://gql.twitch.tv/integrity") + .header("Authorization", "OAuth " + ACCESS_TOKEN) + .thenReturn(TestUtils.getAllResourceContent("api/gql/integrity_noToken.json")) + .withStatus(200); + } + + protected void setupIntegrityStatus(UnirestMock unirest, int status){ + unirest.expect(POST, "https://gql.twitch.tv/integrity") + .header("Authorization", "OAuth " + ACCESS_TOKEN) + .thenReturn() + .withStatus(status); + } +} diff --git a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/CommonGQLTest.java b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/CommonGQLTest.java new file mode 100644 index 00000000..ec9c5366 --- /dev/null +++ b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/CommonGQLTest.java @@ -0,0 +1,116 @@ +package fr.raksrinana.channelpointsminer.miner.api.gql; + +import fr.raksrinana.channelpointsminer.miner.api.passport.TwitchLogin; +import fr.raksrinana.channelpointsminer.miner.api.passport.exceptions.IntegrityError; +import fr.raksrinana.channelpointsminer.miner.tests.UnirestMock; +import fr.raksrinana.channelpointsminer.miner.tests.UnirestMockExtension; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +@ExtendWith(UnirestMockExtension.class) +public class CommonGQLTest extends AbstractGQLTest{ + private static final String RAID_ID = "raid-id"; + + @InjectMocks + private GQLApi tested; + + @Mock + private TwitchLogin twitchLogin; + + @BeforeEach + void setUp(){ + when(twitchLogin.getAccessToken()).thenReturn(ACCESS_TOKEN); + } + + @Test + void invalidCredentials(UnirestMock unirest){ + expectValidRequestWithIntegrityOk(unirest, 401, "api/gql/invalidAuth.json"); + + assertThrows(RuntimeException.class, () -> tested.joinRaid(RAID_ID)); + + unirest.verifyAll(); + } + + @Test + void invalidRequest(UnirestMock unirest){ + expectValidRequestOkWithIntegrityOk(unirest, "api/gql/invalidRequest.json"); + + assertThat(tested.joinRaid(RAID_ID)).isEmpty(); + + unirest.verifyAll(); + } + + @Test + void invalidResponse(UnirestMock unirest){ + expectValidRequestWithIntegrityOk(unirest, 500, null); + + assertThat(tested.joinRaid(RAID_ID)).isEmpty(); + + unirest.verifyAll(); + } + + @Test + void integrityIsNotQueriedTwice(UnirestMock unirest){ + expectValidRequestOkWithIntegrityOk(unirest, "api/gql/joinRaid.json"); + + assertThat(tested.joinRaid(RAID_ID)).isNotEmpty(); + unirest.verifyAll(); + unirest.reset(); + + expectValidRequestOk(unirest, "api/gql/joinRaid.json"); + assertThat(tested.joinRaid(RAID_ID)).isNotEmpty(); + unirest.verifyAll(); + } + + @Test + void integrityIsRefreshed(UnirestMock unirest){ + setupIntegrityWillNeedRefresh(unirest); + expectValidRequestOk(unirest, "api/gql/joinRaid.json"); + + assertThat(tested.joinRaid(RAID_ID)).isNotEmpty(); + unirest.verifyAll(); + unirest.reset(); + + setupIntegrityOk(unirest); + expectValidRequestOk(unirest, "api/gql/joinRaid.json"); + assertThat(tested.joinRaid(RAID_ID)).isNotEmpty(); + unirest.verifyAll(); + } + + @Test + void integrityNotSuccess(UnirestMock unirest){ + setupIntegrityStatus(unirest, 500); + + var thrown = assertThrows(RuntimeException.class, () -> tested.joinRaid(RAID_ID)); + + assertThat(thrown) + .hasCauseInstanceOf(IntegrityError.class) + .hasCause(new IntegrityError(500, "Http code is not a success")); + unirest.verifyAll(); + } + + @Test + void integrityNoToken(UnirestMock unirest){ + setupIntegrityNoToken(unirest); + + var thrown = assertThrows(RuntimeException.class, () -> tested.joinRaid(RAID_ID)); + + assertThat(thrown) + .hasCauseInstanceOf(IntegrityError.class) + .hasCause(new IntegrityError(200, "error-message")); + unirest.verifyAll(); + } + + @Override + protected String getValidRequest(){ + return "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"c6a332a86d1087fbbb1a8623aa01bd1313d2386e7c63be60fdb2d1901f01a4ae\",\"version\":1}},\"operationName\":\"JoinRaid\",\"variables\":{\"input\":{\"raidID\":\"%s\"}}}".formatted(RAID_ID); + } +} diff --git a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiChannelPointsContextTest.java b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiChannelPointsContextTest.java index 82715aa6..c0161846 100644 --- a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiChannelPointsContextTest.java +++ b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiChannelPointsContextTest.java @@ -22,9 +22,8 @@ import fr.raksrinana.channelpointsminer.miner.api.gql.data.types.User; import fr.raksrinana.channelpointsminer.miner.api.gql.data.types.UserSelfConnection; import fr.raksrinana.channelpointsminer.miner.api.passport.TwitchLogin; -import fr.raksrinana.channelpointsminer.miner.tests.TestUtils; +import fr.raksrinana.channelpointsminer.miner.tests.UnirestMock; import fr.raksrinana.channelpointsminer.miner.tests.UnirestMockExtension; -import kong.unirest.core.MockClient; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -42,17 +41,13 @@ import static fr.raksrinana.channelpointsminer.miner.api.gql.data.types.ContentType.CUSTOM_REWARD; import static fr.raksrinana.channelpointsminer.miner.api.gql.data.types.RewardType.SEND_HIGHLIGHTED_MESSAGE; import static java.time.ZoneOffset.UTC; -import static kong.unirest.core.HttpMethod.POST; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @ExtendWith(UnirestMockExtension.class) -class GQLApiChannelPointsContextTest{ - private static final String ACCESS_TOKEN = "access-token"; +class GQLApiChannelPointsContextTest extends AbstractGQLTest{ private static final String USERNAME = "username"; - private static final String VALID_QUERY = "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"9988086babc615a918a1e9a722ff41d98847acac822645209ac7379eecb27152\",\"version\":1}},\"operationName\":\"ChannelPointsContext\",\"variables\":{\"channelLogin\":\"%s\"}}"; @InjectMocks private GQLApi tested; @@ -66,7 +61,7 @@ void setUp(){ } @Test - void nominal(MockClient unirest) throws MalformedURLException{ + void nominal(UnirestMock unirest) throws MalformedURLException{ var communityPointsImage = CommunityPointsImage.builder() .url(new URL("https://image")) .url2X(new URL("https://image2x")) @@ -192,11 +187,7 @@ void nominal(MockClient unirest) throws MalformedURLException{ .build()) .build(); - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(USERNAME)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/channelPointsContext_noClaim.json")) - .withStatus(200); + expectValidRequestOkWithIntegrityOk(unirest, "api/gql/channelPointsContext_noClaim.json"); assertThat(tested.channelPointsContext(USERNAME)).isPresent().get().isEqualTo(expected); @@ -204,7 +195,7 @@ void nominal(MockClient unirest) throws MalformedURLException{ } @Test - void nominalWithClaim(MockClient unirest) throws MalformedURLException{ + void nominalWithClaim(UnirestMock unirest) throws MalformedURLException{ var communityPointsImage = CommunityPointsImage.builder() .url(new URL("https://image")) .url2X(new URL("https://image2x")) @@ -333,53 +324,15 @@ void nominalWithClaim(MockClient unirest) throws MalformedURLException{ .build()) .build(); - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(USERNAME)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/channelPointsContext_withClaim.json")) - .withStatus(200); + expectValidRequestOkWithIntegrityOk(unirest, "api/gql/channelPointsContext_withClaim.json"); assertThat(tested.channelPointsContext(USERNAME)).isPresent().get().isEqualTo(expected); unirest.verifyAll(); } - @Test - void invalidCredentials(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(USERNAME)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/invalidAuth.json")) - .withStatus(401); - - assertThrows(RuntimeException.class, () -> tested.channelPointsContext(USERNAME)); - - unirest.verifyAll(); - } - - @Test - void invalidRequest(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(USERNAME)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/invalidRequest.json")) - .withStatus(200); - - assertThat(tested.channelPointsContext(USERNAME)).isEmpty(); - - unirest.verifyAll(); - } - - @Test - void invalidResponse(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(USERNAME)) - .thenReturn() - .withStatus(500); - - assertThat(tested.channelPointsContext(USERNAME)).isEmpty(); - - unirest.verifyAll(); + @Override + protected String getValidRequest(){ + return "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"9988086babc615a918a1e9a722ff41d98847acac822645209ac7379eecb27152\",\"version\":1}},\"operationName\":\"ChannelPointsContext\",\"variables\":{\"channelLogin\":\"%s\"}}".formatted(USERNAME); } } \ No newline at end of file diff --git a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiChatRoomBanStatusTest.java b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiChatRoomBanStatusTest.java index 8afba40a..539325e7 100644 --- a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiChatRoomBanStatusTest.java +++ b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiChatRoomBanStatusTest.java @@ -5,9 +5,8 @@ import fr.raksrinana.channelpointsminer.miner.api.gql.data.types.ChatRoomBanStatus; import fr.raksrinana.channelpointsminer.miner.api.gql.data.types.User; import fr.raksrinana.channelpointsminer.miner.api.passport.TwitchLogin; -import fr.raksrinana.channelpointsminer.miner.tests.TestUtils; +import fr.raksrinana.channelpointsminer.miner.tests.UnirestMock; import fr.raksrinana.channelpointsminer.miner.tests.UnirestMockExtension; -import kong.unirest.core.MockClient; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -17,18 +16,14 @@ import java.time.ZonedDateTime; import java.util.Map; import static java.time.ZoneOffset.UTC; -import static kong.unirest.core.HttpMethod.POST; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @ExtendWith(UnirestMockExtension.class) -class GQLApiChatRoomBanStatusTest{ - private static final String ACCESS_TOKEN = "access-token"; +class GQLApiChatRoomBanStatusTest extends AbstractGQLTest{ private static final String USERNAME = "username"; private static final String CHANNEL = "channel"; - private static final String VALID_QUERY = "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"319f2a9a3ac7ddecd7925944416c14b818b65676ab69da604460b68938d22bea\",\"version\":1}},\"operationName\":\"ChatRoomBanStatus\",\"variables\":{\"targetUserID\":\"%s\",\"channelID\":\"%s\"}}"; @InjectMocks private GQLApi tested; @@ -42,7 +37,7 @@ void setUp(){ } @Test - void notBanned(MockClient unirest){ + void notBanned(UnirestMock unirest){ var expected = GQLResponse. builder() .extensions(Map.of( "durationMilliseconds", 21, @@ -57,11 +52,7 @@ void notBanned(MockClient unirest){ .build()) .build(); - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(USERNAME, CHANNEL)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/channelRoomBanStatus_notBanned.json")) - .withStatus(200); + expectValidRequestOkWithIntegrityOk(unirest, "api/gql/channelRoomBanStatus_notBanned.json"); assertThat(tested.chatRoomBanStatus(CHANNEL, USERNAME)).isPresent().get().isEqualTo(expected); @@ -69,7 +60,7 @@ void notBanned(MockClient unirest){ } @Test - void banned(MockClient unirest){ + void banned(UnirestMock unirest){ var expected = GQLResponse. builder() .extensions(Map.of( "durationMilliseconds", 21, @@ -94,11 +85,7 @@ void banned(MockClient unirest){ .build()) .build(); - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(USERNAME, CHANNEL)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/channelRoomBanStatus_banned.json")) - .withStatus(200); + expectValidRequestOkWithIntegrityOk(unirest, "api/gql/channelRoomBanStatus_banned.json"); var actual = tested.chatRoomBanStatus(CHANNEL, USERNAME); assertThat(actual).isPresent().get().isEqualTo(expected); @@ -106,42 +93,8 @@ void banned(MockClient unirest){ unirest.verifyAll(); } - @Test - void invalidCredentials(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(USERNAME, CHANNEL)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/invalidAuth.json")) - .withStatus(401); - - assertThrows(RuntimeException.class, () -> tested.chatRoomBanStatus(CHANNEL, USERNAME)); - - unirest.verifyAll(); - } - - @Test - void invalidRequest(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(USERNAME, CHANNEL)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/invalidRequest.json")) - .withStatus(200); - - assertThat(tested.chatRoomBanStatus(CHANNEL, USERNAME)).isEmpty(); - - unirest.verifyAll(); - } - - @Test - void invalidResponse(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(USERNAME, CHANNEL)) - .thenReturn() - .withStatus(500); - - assertThat(tested.chatRoomBanStatus(CHANNEL, USERNAME)).isEmpty(); - - unirest.verifyAll(); + @Override + protected String getValidRequest(){ + return "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"319f2a9a3ac7ddecd7925944416c14b818b65676ab69da604460b68938d22bea\",\"version\":1}},\"operationName\":\"ChatRoomBanStatus\",\"variables\":{\"targetUserID\":\"%s\",\"channelID\":\"%s\"}}".formatted(USERNAME, CHANNEL); } } \ No newline at end of file diff --git a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiClaimCommunityMomentTest.java b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiClaimCommunityMomentTest.java index a0c47062..7b8cf37e 100644 --- a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiClaimCommunityMomentTest.java +++ b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiClaimCommunityMomentTest.java @@ -5,9 +5,8 @@ import fr.raksrinana.channelpointsminer.miner.api.gql.data.types.ClaimCommunityMomentPayload; import fr.raksrinana.channelpointsminer.miner.api.gql.data.types.CommunityMoment; import fr.raksrinana.channelpointsminer.miner.api.passport.TwitchLogin; -import fr.raksrinana.channelpointsminer.miner.tests.TestUtils; +import fr.raksrinana.channelpointsminer.miner.tests.UnirestMock; import fr.raksrinana.channelpointsminer.miner.tests.UnirestMockExtension; -import kong.unirest.core.MockClient; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -15,17 +14,13 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import java.util.Map; -import static kong.unirest.core.HttpMethod.POST; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @ExtendWith(UnirestMockExtension.class) -class GQLApiClaimCommunityMomentTest{ - private static final String ACCESS_TOKEN = "access-token"; +class GQLApiClaimCommunityMomentTest extends AbstractGQLTest{ private static final String MOMENT_ID = "moment-id"; - private static final String VALID_QUERY = "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"e2d67415aead910f7f9ceb45a77b750a1e1d9622c936d832328a0689e054db62\",\"version\":1}},\"operationName\":\"CommunityMomentCallout_Claim\",\"variables\":{\"input\":{\"momentID\":\"%s\"}}}"; @InjectMocks private GQLApi tested; @@ -39,7 +34,7 @@ void setUp(){ } @Test - void nominalClaimed(MockClient unirest){ + void nominalClaimed(UnirestMock unirest){ var expected = GQLResponse. builder() .extensions(Map.of( "durationMilliseconds", 9, @@ -55,53 +50,15 @@ void nominalClaimed(MockClient unirest){ .build()) .build(); - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(MOMENT_ID)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/communityMomentCalloutClaim_success.json")) - .withStatus(200); + expectValidRequestOkWithIntegrityOk(unirest, "api/gql/communityMomentCalloutClaim_success.json"); assertThat(tested.claimCommunityMoment(MOMENT_ID)).isPresent().get().isEqualTo(expected); unirest.verifyAll(); } - @Test - void invalidCredentials(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(MOMENT_ID)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/invalidAuth.json")) - .withStatus(401); - - assertThrows(RuntimeException.class, () -> tested.claimCommunityMoment(MOMENT_ID)); - - unirest.verifyAll(); - } - - @Test - void invalidRequest(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(MOMENT_ID)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/invalidRequest.json")) - .withStatus(200); - - assertThat(tested.claimCommunityMoment(MOMENT_ID)).isEmpty(); - - unirest.verifyAll(); - } - - @Test - void invalidResponse(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(MOMENT_ID)) - .thenReturn() - .withStatus(500); - - assertThat(tested.claimCommunityMoment(MOMENT_ID)).isEmpty(); - - unirest.verifyAll(); + @Override + protected String getValidRequest(){ + return "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"e2d67415aead910f7f9ceb45a77b750a1e1d9622c936d832328a0689e054db62\",\"version\":1}},\"operationName\":\"CommunityMomentCallout_Claim\",\"variables\":{\"input\":{\"momentID\":\"%s\"}}}".formatted(MOMENT_ID); } } \ No newline at end of file diff --git a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiClaimCommunityPointsTest.java b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiClaimCommunityPointsTest.java index 658c82d1..e3b7d7de 100644 --- a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiClaimCommunityPointsTest.java +++ b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiClaimCommunityPointsTest.java @@ -6,9 +6,8 @@ import fr.raksrinana.channelpointsminer.miner.api.gql.data.types.ClaimCommunityPointsPayload; import fr.raksrinana.channelpointsminer.miner.api.gql.data.types.CommunityPointsClaim; import fr.raksrinana.channelpointsminer.miner.api.passport.TwitchLogin; -import fr.raksrinana.channelpointsminer.miner.tests.TestUtils; +import fr.raksrinana.channelpointsminer.miner.tests.UnirestMock; import fr.raksrinana.channelpointsminer.miner.tests.UnirestMockExtension; -import kong.unirest.core.MockClient; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -17,18 +16,14 @@ import org.junit.jupiter.api.extension.ExtendWith; import java.util.Map; import static fr.raksrinana.channelpointsminer.miner.api.gql.data.types.ClaimErrorCode.NOT_FOUND; -import static kong.unirest.core.HttpMethod.POST; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @ExtendWith(UnirestMockExtension.class) -class GQLApiClaimCommunityPointsTest{ - private static final String ACCESS_TOKEN = "access-token"; +class GQLApiClaimCommunityPointsTest extends AbstractGQLTest{ private static final String CHANNEL_ID = "channel-id"; private static final String CLAIM_ID = "claim-id"; - private static final String VALID_QUERY = "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"46aaeebe02c99afdf4fc97c7c0cba964124bf6b0af229395f1f6d1feed05b3d0\",\"version\":1}},\"operationName\":\"ClaimCommunityPoints\",\"variables\":{\"input\":{\"channelID\":\"%s\",\"claimID\":\"%s\"}}}"; @InjectMocks private GQLApi tested; @@ -42,7 +37,7 @@ void setUp(){ } @Test - void nominalClaimed(MockClient unirest){ + void nominalClaimed(UnirestMock unirest){ var expected = GQLResponse. builder() .extensions(Map.of( "durationMilliseconds", 55, @@ -61,11 +56,7 @@ void nominalClaimed(MockClient unirest){ .build()) .build(); - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(CHANNEL_ID, CLAIM_ID)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/claimCommunityPoints_claimed.json")) - .withStatus(200); + expectValidRequestOkWithIntegrityOk(unirest, "api/gql/claimCommunityPoints_claimed.json"); assertThat(tested.claimCommunityPoints(CHANNEL_ID, CLAIM_ID)).isPresent().get().isEqualTo(expected); @@ -73,7 +64,7 @@ void nominalClaimed(MockClient unirest){ } @Test - void nominalNotFound(MockClient unirest){ + void nominalNotFound(UnirestMock unirest){ var expected = GQLResponse. builder() .extensions(Map.of( "durationMilliseconds", 7, @@ -89,53 +80,15 @@ void nominalNotFound(MockClient unirest){ .build()) .build(); - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(CHANNEL_ID, CLAIM_ID)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/claimCommunityPoints_notFound.json")) - .withStatus(200); + expectValidRequestOkWithIntegrityOk(unirest, "api/gql/claimCommunityPoints_notFound.json"); assertThat(tested.claimCommunityPoints(CHANNEL_ID, CLAIM_ID)).isPresent().get().isEqualTo(expected); unirest.verifyAll(); } - @Test - void invalidCredentials(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(CHANNEL_ID, CLAIM_ID)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/invalidAuth.json")) - .withStatus(401); - - assertThrows(RuntimeException.class, () -> tested.claimCommunityPoints(CHANNEL_ID, CLAIM_ID)); - - unirest.verifyAll(); - } - - @Test - void invalidRequest(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(CHANNEL_ID, CLAIM_ID)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/invalidRequest.json")) - .withStatus(200); - - assertThat(tested.claimCommunityPoints(CHANNEL_ID, CLAIM_ID)).isEmpty(); - - unirest.verifyAll(); - } - - @Test - void invalidResponse(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(CHANNEL_ID, CLAIM_ID)) - .thenReturn() - .withStatus(500); - - assertThat(tested.claimCommunityPoints(CHANNEL_ID, CLAIM_ID)).isEmpty(); - - unirest.verifyAll(); + @Override + protected String getValidRequest(){ + return "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"46aaeebe02c99afdf4fc97c7c0cba964124bf6b0af229395f1f6d1feed05b3d0\",\"version\":1}},\"operationName\":\"ClaimCommunityPoints\",\"variables\":{\"input\":{\"channelID\":\"%s\",\"claimID\":\"%s\"}}}".formatted(CHANNEL_ID, CLAIM_ID); } } \ No newline at end of file diff --git a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiDropsHighlightServiceAvailableDropsTest.java b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiDropsHighlightServiceAvailableDropsTest.java index 8c56c614..043a14e1 100644 --- a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiDropsHighlightServiceAvailableDropsTest.java +++ b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiDropsHighlightServiceAvailableDropsTest.java @@ -11,9 +11,8 @@ import fr.raksrinana.channelpointsminer.miner.api.gql.data.types.TimeBasedDrop; import fr.raksrinana.channelpointsminer.miner.api.gql.data.types.User; import fr.raksrinana.channelpointsminer.miner.api.passport.TwitchLogin; -import fr.raksrinana.channelpointsminer.miner.tests.TestUtils; +import fr.raksrinana.channelpointsminer.miner.tests.UnirestMock; import fr.raksrinana.channelpointsminer.miner.tests.UnirestMockExtension; -import kong.unirest.core.MockClient; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -26,17 +25,13 @@ import java.util.List; import java.util.Map; import static java.time.ZoneOffset.UTC; -import static kong.unirest.core.HttpMethod.POST; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @ExtendWith(UnirestMockExtension.class) -class GQLApiDropsHighlightServiceAvailableDropsTest{ - private static final String ACCESS_TOKEN = "access-token"; +class GQLApiDropsHighlightServiceAvailableDropsTest extends AbstractGQLTest{ private static final String STREAMER_ID = "streamer-id"; - private static final String VALID_QUERY = "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"b19ee96a0e79e3f8281c4108bc4c7b3f232266db6f96fd04a339ab393673a075\",\"version\":1}},\"operationName\":\"DropsHighlightService_AvailableDrops\",\"variables\":{\"channelID\":\"%s\"}}"; @InjectMocks private GQLApi tested; @@ -50,7 +45,7 @@ void setUp(){ } @Test - void nominalWithDrops(MockClient unirest) throws MalformedURLException{ + void nominalWithDrops(UnirestMock unirest) throws MalformedURLException{ var game = Game.builder() .id("159357") .name("game-name") @@ -96,11 +91,7 @@ void nominalWithDrops(MockClient unirest) throws MalformedURLException{ .build()) .build(); - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(STREAMER_ID)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/dropsHighlightServiceAvailableDrops_withDrops.json")) - .withStatus(200); + expectValidRequestOkWithIntegrityOk(unirest, "api/gql/dropsHighlightServiceAvailableDrops_withDrops.json"); assertThat(tested.dropsHighlightServiceAvailableDrops(STREAMER_ID)).isPresent().get().isEqualTo(expected); @@ -108,7 +99,7 @@ void nominalWithDrops(MockClient unirest) throws MalformedURLException{ } @Test - void nominalNoDrops(MockClient unirest){ + void nominalNoDrops(UnirestMock unirest){ var expected = GQLResponse. builder() .extensions(Map.of( "durationMilliseconds", 31, @@ -126,53 +117,15 @@ void nominalNoDrops(MockClient unirest){ .build()) .build(); - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(STREAMER_ID)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/dropsHighlightServiceAvailableDrops_noDrops.json")) - .withStatus(200); + expectValidRequestOkWithIntegrityOk(unirest, "api/gql/dropsHighlightServiceAvailableDrops_noDrops.json"); assertThat(tested.dropsHighlightServiceAvailableDrops(STREAMER_ID)).isPresent().get().isEqualTo(expected); unirest.verifyAll(); } - @Test - void invalidCredentials(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(STREAMER_ID)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/invalidAuth.json")) - .withStatus(401); - - assertThrows(RuntimeException.class, () -> tested.dropsHighlightServiceAvailableDrops(STREAMER_ID)); - - unirest.verifyAll(); - } - - @Test - void invalidRequest(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(STREAMER_ID)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/invalidRequest.json")) - .withStatus(200); - - assertThat(tested.dropsHighlightServiceAvailableDrops(STREAMER_ID)).isEmpty(); - - unirest.verifyAll(); - } - - @Test - void invalidResponse(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(STREAMER_ID)) - .thenReturn() - .withStatus(500); - - assertThat(tested.dropsHighlightServiceAvailableDrops(STREAMER_ID)).isEmpty(); - - unirest.verifyAll(); + @Override + protected String getValidRequest(){ + return "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"b19ee96a0e79e3f8281c4108bc4c7b3f232266db6f96fd04a339ab393673a075\",\"version\":1}},\"operationName\":\"DropsHighlightService_AvailableDrops\",\"variables\":{\"channelID\":\"%s\"}}".formatted(STREAMER_ID); } } \ No newline at end of file diff --git a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiDropsPageClaimDropRewardsTest.java b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiDropsPageClaimDropRewardsTest.java index 7eec5767..f1658bcb 100644 --- a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiDropsPageClaimDropRewardsTest.java +++ b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiDropsPageClaimDropRewardsTest.java @@ -4,10 +4,9 @@ import fr.raksrinana.channelpointsminer.miner.api.gql.data.dropspageclaimdroprewards.DropsPageClaimDropRewardsData; import fr.raksrinana.channelpointsminer.miner.api.gql.data.types.ClaimDropRewardsPayload; import fr.raksrinana.channelpointsminer.miner.api.gql.data.types.ClaimDropRewardsStatus; -import fr.raksrinana.channelpointsminer.miner.api.gql.data.types.Game; import fr.raksrinana.channelpointsminer.miner.api.passport.TwitchLogin; +import fr.raksrinana.channelpointsminer.miner.tests.UnirestMock; import fr.raksrinana.channelpointsminer.miner.tests.UnirestMockExtension; -import kong.unirest.core.MockClient; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -15,20 +14,14 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import java.net.MalformedURLException; -import java.net.URL; import java.util.Map; -import static fr.raksrinana.channelpointsminer.miner.tests.TestUtils.getAllResourceContent; -import static kong.unirest.core.HttpMethod.POST; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @ExtendWith(UnirestMockExtension.class) -class GQLApiDropsPageClaimDropRewardsTest{ - private static final String VALID_QUERY = "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"2f884fa187b8fadb2a49db0adc033e636f7b6aaee6e76de1e2bba9a7baf0daf6\",\"version\":1}},\"operationName\":\"DropsPage_ClaimDropRewards\",\"variables\":{\"input\":{\"dropInstanceID\":\"%s\"}}}"; - private static final String ACCESS_TOKEN = "access-token"; - private static final String DROP_ID = ""; +class GQLApiDropsPageClaimDropRewardsTest extends AbstractGQLTest{ + private static final String DROP_ID = "drop-id"; @InjectMocks private GQLApi tested; @@ -42,12 +35,7 @@ void setUp(){ } @Test - void nominal(MockClient unirest) throws MalformedURLException{ - var game = Game.builder() - .id("123") - .name("game-1") - .boxArtUrl(new URL("https://bow-art-1")) - .build(); + void nominal(UnirestMock unirest) throws MalformedURLException{ var expected = GQLResponse. builder() .extensions(Map.of( "durationMilliseconds", 18, @@ -62,53 +50,15 @@ void nominal(MockClient unirest) throws MalformedURLException{ .build()) .build(); - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(DROP_ID)) - .thenReturn(getAllResourceContent("api/gql/dropspageclaimdroprewardsdata_eligibleforall.json")) - .withStatus(200); + expectValidRequestOkWithIntegrityOk(unirest, "api/gql/dropspageclaimdroprewardsdata_eligibleforall.json"); assertThat(tested.dropsPageClaimDropRewards(DROP_ID)).isPresent().get().isEqualTo(expected); unirest.verifyAll(); } - @Test - void invalidCredentials(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(DROP_ID)) - .thenReturn(getAllResourceContent("api/gql/invalidAuth.json")) - .withStatus(401); - - assertThrows(RuntimeException.class, () -> tested.dropsPageClaimDropRewards(DROP_ID)); - - unirest.verifyAll(); - } - - @Test - void invalidRequest(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(DROP_ID)) - .thenReturn(getAllResourceContent("api/gql/invalidRequest.json")) - .withStatus(200); - - assertThat(tested.dropsPageClaimDropRewards(DROP_ID)).isEmpty(); - - unirest.verifyAll(); - } - - @Test - void invalidResponse(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(DROP_ID)) - .thenReturn() - .withStatus(500); - - assertThat(tested.dropsPageClaimDropRewards(DROP_ID)).isEmpty(); - - unirest.verifyAll(); + @Override + protected String getValidRequest(){ + return "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"2f884fa187b8fadb2a49db0adc033e636f7b6aaee6e76de1e2bba9a7baf0daf6\",\"version\":1}},\"operationName\":\"DropsPage_ClaimDropRewards\",\"variables\":{\"input\":{\"dropInstanceID\":\"%s\"}}}".formatted(DROP_ID); } } \ No newline at end of file diff --git a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiInventoryTest.java b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiInventoryTest.java index 1f643477..0ab7b923 100644 --- a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiInventoryTest.java +++ b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiInventoryTest.java @@ -16,8 +16,8 @@ import fr.raksrinana.channelpointsminer.miner.api.gql.data.types.User; import fr.raksrinana.channelpointsminer.miner.api.gql.data.types.UserDropReward; import fr.raksrinana.channelpointsminer.miner.api.passport.TwitchLogin; +import fr.raksrinana.channelpointsminer.miner.tests.UnirestMock; import fr.raksrinana.channelpointsminer.miner.tests.UnirestMockExtension; -import kong.unirest.core.MockClient; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -29,19 +29,13 @@ import java.time.ZonedDateTime; import java.util.List; import java.util.Map; -import static fr.raksrinana.channelpointsminer.miner.tests.TestUtils.getAllResourceContent; import static java.time.ZoneOffset.UTC; -import static kong.unirest.core.HttpMethod.POST; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @ExtendWith(UnirestMockExtension.class) -class GQLApiInventoryTest{ - public static final String VALID_QUERY = "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"e0765ebaa8e8eeb4043cc6dfeab3eac7f682ef5f724b81367e6e55c7aef2be4c\",\"version\":1}},\"operationName\":\"Inventory\",\"variables\":{}}"; - private static final String ACCESS_TOKEN = "access-token"; - +class GQLApiInventoryTest extends AbstractGQLTest{ @InjectMocks private GQLApi tested; @@ -54,7 +48,7 @@ void setUp(){ } @Test - void nominal(MockClient unirest) throws MalformedURLException{ + void nominal(UnirestMock unirest) throws MalformedURLException{ var game = Game.builder() .id("123") .name("game-1") @@ -170,53 +164,15 @@ void nominal(MockClient unirest) throws MalformedURLException{ .build()) .build(); - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY) - .thenReturn(getAllResourceContent("api/gql/inventory.json")) - .withStatus(200); + expectValidRequestOkWithIntegrityOk(unirest, "api/gql/inventory.json"); assertThat(tested.inventory()).isPresent().get().isEqualTo(expected); unirest.verifyAll(); } - @Test - void invalidCredentials(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY) - .thenReturn(getAllResourceContent("api/gql/invalidAuth.json")) - .withStatus(401); - - assertThrows(RuntimeException.class, () -> tested.inventory()); - - unirest.verifyAll(); - } - - @Test - void invalidRequest(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY) - .thenReturn(getAllResourceContent("api/gql/invalidRequest.json")) - .withStatus(200); - - assertThat(tested.inventory()).isEmpty(); - - unirest.verifyAll(); - } - - @Test - void invalidResponse(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY) - .thenReturn() - .withStatus(500); - - assertThat(tested.inventory()).isEmpty(); - - unirest.verifyAll(); + @Override + protected String getValidRequest(){ + return "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"e0765ebaa8e8eeb4043cc6dfeab3eac7f682ef5f724b81367e6e55c7aef2be4c\",\"version\":1}},\"operationName\":\"Inventory\",\"variables\":{}}"; } } \ No newline at end of file diff --git a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiJoinRaidTest.java b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiJoinRaidTest.java index b82c3d07..fc7e7098 100644 --- a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiJoinRaidTest.java +++ b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiJoinRaidTest.java @@ -4,8 +4,8 @@ import fr.raksrinana.channelpointsminer.miner.api.gql.data.joinraid.JoinRaidData; import fr.raksrinana.channelpointsminer.miner.api.gql.data.types.JoinRaidPayload; import fr.raksrinana.channelpointsminer.miner.api.passport.TwitchLogin; +import fr.raksrinana.channelpointsminer.miner.tests.UnirestMock; import fr.raksrinana.channelpointsminer.miner.tests.UnirestMockExtension; -import kong.unirest.core.MockClient; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -13,18 +13,14 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import java.util.Map; -import static fr.raksrinana.channelpointsminer.miner.tests.TestUtils.getAllResourceContent; -import static kong.unirest.core.HttpMethod.POST; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @ExtendWith(UnirestMockExtension.class) -class GQLApiJoinRaidTest{ - public static final String VALID_QUERY = "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"c6a332a86d1087fbbb1a8623aa01bd1313d2386e7c63be60fdb2d1901f01a4ae\",\"version\":1}},\"operationName\":\"JoinRaid\",\"variables\":{\"input\":{\"raidID\":\"%s\"}}}"; - private static final String ACCESS_TOKEN = "access-token"; +class GQLApiJoinRaidTest extends AbstractGQLTest{ private static final String RAID_ID = "raid-id"; + @InjectMocks private GQLApi tested; @@ -37,7 +33,7 @@ void setUp(){ } @Test - void nominalFollowRaid(MockClient unirest){ + void nominalFollowRaid(UnirestMock unirest){ var expected = GQLResponse. builder() .extensions(Map.of( "durationMilliseconds", 4, @@ -51,53 +47,15 @@ void nominalFollowRaid(MockClient unirest){ .build()) .build(); - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(RAID_ID)) - .thenReturn(getAllResourceContent("api/gql/joinRaid.json")) - .withStatus(200); + expectValidRequestOkWithIntegrityOk(unirest, "api/gql/joinRaid.json"); assertThat(tested.joinRaid(RAID_ID)).isPresent().get().isEqualTo(expected); unirest.verifyAll(); } - @Test - void invalidCredentials(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(RAID_ID)) - .thenReturn(getAllResourceContent("api/gql/invalidAuth.json")) - .withStatus(401); - - assertThrows(RuntimeException.class, () -> tested.joinRaid(RAID_ID)); - - unirest.verifyAll(); - } - - @Test - void invalidRequest(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(RAID_ID)) - .thenReturn(getAllResourceContent("api/gql/invalidRequest.json")) - .withStatus(200); - - assertThat(tested.joinRaid(RAID_ID)).isEmpty(); - - unirest.verifyAll(); - } - - @Test - void invalidResponse(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(RAID_ID)) - .thenReturn() - .withStatus(500); - - assertThat(tested.joinRaid(RAID_ID)).isEmpty(); - - unirest.verifyAll(); + @Override + protected String getValidRequest(){ + return "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"c6a332a86d1087fbbb1a8623aa01bd1313d2386e7c63be60fdb2d1901f01a4ae\",\"version\":1}},\"operationName\":\"JoinRaid\",\"variables\":{\"input\":{\"raidID\":\"%s\"}}}".formatted(RAID_ID); } } \ No newline at end of file diff --git a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiMakePredictionTest.java b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiMakePredictionTest.java index 685edb8b..e78eb98b 100644 --- a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiMakePredictionTest.java +++ b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiMakePredictionTest.java @@ -6,8 +6,8 @@ import fr.raksrinana.channelpointsminer.miner.api.gql.data.types.MakePredictionErrorCode; import fr.raksrinana.channelpointsminer.miner.api.gql.data.types.MakePredictionPayload; import fr.raksrinana.channelpointsminer.miner.api.passport.TwitchLogin; +import fr.raksrinana.channelpointsminer.miner.tests.UnirestMock; import fr.raksrinana.channelpointsminer.miner.tests.UnirestMockExtension; -import kong.unirest.core.MockClient; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -15,17 +15,12 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import java.util.Map; -import static fr.raksrinana.channelpointsminer.miner.tests.TestUtils.getAllResourceContent; -import static kong.unirest.core.HttpMethod.POST; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @ExtendWith(UnirestMockExtension.class) -class GQLApiMakePredictionTest{ - public static final String VALID_QUERY = "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"b44682ecc88358817009f20e69d75081b1e58825bb40aa53d5dbadcc17c881d8\",\"version\":1}},\"operationName\":\"MakePrediction\",\"variables\":{\"input\":{\"eventID\":\"%s\",\"outcomeID\":\"%s\",\"points\":%d,\"transactionID\":\"%s\"}}}"; - private static final String ACCESS_TOKEN = "access-token"; +class GQLApiMakePredictionTest extends AbstractGQLTest{ private static final String EVENT_ID = "event-id"; private static final String OUTCOME_ID = "outcome-id"; private static final int POINTS = 20; @@ -43,7 +38,7 @@ void setUp(){ } @Test - void nominalMakePrediction(MockClient unirest){ + void nominalMakePrediction(UnirestMock unirest){ var expected = GQLResponse. builder() .extensions(Map.of( "durationMilliseconds", 127, @@ -55,11 +50,7 @@ void nominalMakePrediction(MockClient unirest){ .build()) .build(); - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(EVENT_ID, OUTCOME_ID, POINTS, TRANSACTION_ID)) - .thenReturn(getAllResourceContent("api/gql/makePrediction_success.json")) - .withStatus(200); + expectValidRequestOkWithIntegrityOk(unirest, "api/gql/makePrediction_success.json"); assertThat(tested.makePrediction(EVENT_ID, OUTCOME_ID, POINTS, TRANSACTION_ID)).isPresent().get().isEqualTo(expected); @@ -67,7 +58,7 @@ void nominalMakePrediction(MockClient unirest){ } @Test - void errorMakePrediction(MockClient unirest){ + void errorMakePrediction(UnirestMock unirest){ var expected = GQLResponse. builder() .extensions(Map.of( "durationMilliseconds", 37, @@ -83,53 +74,15 @@ void errorMakePrediction(MockClient unirest){ .build()) .build(); - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(EVENT_ID, OUTCOME_ID, POINTS, TRANSACTION_ID)) - .thenReturn(getAllResourceContent("api/gql/makePrediction_notEnoughPoints.json")) - .withStatus(200); + expectValidRequestOkWithIntegrityOk(unirest, "api/gql/makePrediction_notEnoughPoints.json"); assertThat(tested.makePrediction(EVENT_ID, OUTCOME_ID, POINTS, TRANSACTION_ID)).isPresent().get().isEqualTo(expected); unirest.verifyAll(); } - @Test - void invalidCredentials(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(EVENT_ID, OUTCOME_ID, POINTS, TRANSACTION_ID)) - .thenReturn(getAllResourceContent("api/gql/invalidAuth.json")) - .withStatus(401); - - assertThrows(RuntimeException.class, () -> tested.makePrediction(EVENT_ID, OUTCOME_ID, POINTS, TRANSACTION_ID)); - - unirest.verifyAll(); - } - - @Test - void invalidRequest(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(EVENT_ID, OUTCOME_ID, POINTS, TRANSACTION_ID)) - .thenReturn(getAllResourceContent("api/gql/invalidRequest.json")) - .withStatus(200); - - assertThat(tested.makePrediction(EVENT_ID, OUTCOME_ID, POINTS, TRANSACTION_ID)).isEmpty(); - - unirest.verifyAll(); - } - - @Test - void invalidResponse(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(EVENT_ID, OUTCOME_ID, POINTS, TRANSACTION_ID)) - .thenReturn() - .withStatus(500); - - assertThat(tested.makePrediction(EVENT_ID, OUTCOME_ID, POINTS, TRANSACTION_ID)).isEmpty(); - - unirest.verifyAll(); + @Override + protected String getValidRequest(){ + return "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"b44682ecc88358817009f20e69d75081b1e58825bb40aa53d5dbadcc17c881d8\",\"version\":1}},\"operationName\":\"MakePrediction\",\"variables\":{\"input\":{\"eventID\":\"%s\",\"outcomeID\":\"%s\",\"points\":%d,\"transactionID\":\"%s\"}}}".formatted(EVENT_ID, OUTCOME_ID, POINTS, TRANSACTION_ID); } } \ No newline at end of file diff --git a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiReportMenuItemTest.java b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiReportMenuItemTest.java index d07660e5..e48d479b 100644 --- a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiReportMenuItemTest.java +++ b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiReportMenuItemTest.java @@ -6,9 +6,8 @@ import fr.raksrinana.channelpointsminer.miner.api.gql.data.types.Stream; import fr.raksrinana.channelpointsminer.miner.api.gql.data.types.User; import fr.raksrinana.channelpointsminer.miner.api.passport.TwitchLogin; -import fr.raksrinana.channelpointsminer.miner.tests.TestUtils; +import fr.raksrinana.channelpointsminer.miner.tests.UnirestMock; import fr.raksrinana.channelpointsminer.miner.tests.UnirestMockExtension; -import kong.unirest.core.MockClient; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -18,17 +17,13 @@ import java.time.ZonedDateTime; import java.util.Map; import static java.time.ZoneOffset.UTC; -import static kong.unirest.core.HttpMethod.POST; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @ExtendWith(UnirestMockExtension.class) -class GQLApiReportMenuItemTest{ - private static final String ACCESS_TOKEN = "access-token"; +class GQLApiReportMenuItemTest extends AbstractGQLTest{ private static final String USERNAME = "username"; - private static final String VALID_QUERY = "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"8f3628981255345ca5e5453dfd844efffb01d6413a9931498836e6268692a30c\",\"version\":1}},\"operationName\":\"ReportMenuItem\",\"variables\":{\"channelLogin\":\"%s\"}}"; @InjectMocks private GQLApi tested; @@ -42,7 +37,7 @@ void setUp(){ } @Test - void nominalOffline(MockClient unirest){ + void nominalOffline(UnirestMock unirest){ var expected = GQLResponse. builder() .extensions(Map.of( "durationMilliseconds", 41, @@ -59,11 +54,7 @@ void nominalOffline(MockClient unirest){ .build()) .build(); - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(USERNAME)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/reportMenuItem_offline.json")) - .withStatus(200); + expectValidRequestOkWithIntegrityOk(unirest, "api/gql/reportMenuItem_offline.json"); assertThat(tested.reportMenuItem(USERNAME)).isPresent().get().isEqualTo(expected); @@ -71,7 +62,7 @@ void nominalOffline(MockClient unirest){ } @Test - void nominalOnline(MockClient unirest){ + void nominalOnline(UnirestMock unirest){ var expected = GQLResponse. builder() .extensions(Map.of( "durationMilliseconds", 41, @@ -92,11 +83,7 @@ void nominalOnline(MockClient unirest){ .build()) .build(); - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(USERNAME)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/reportMenuItem_online.json")) - .withStatus(200); + expectValidRequestOkWithIntegrityOk(unirest, "api/gql/reportMenuItem_online.json"); var result = tested.reportMenuItem(USERNAME); assertThat(result).isPresent().get().isEqualTo(expected); @@ -104,42 +91,8 @@ void nominalOnline(MockClient unirest){ unirest.verifyAll(); } - @Test - void invalidCredentials(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(USERNAME)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/invalidAuth.json")) - .withStatus(401); - - assertThrows(RuntimeException.class, () -> tested.reportMenuItem(USERNAME)); - - unirest.verifyAll(); - } - - @Test - void invalidRequest(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(USERNAME)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/invalidRequest.json")) - .withStatus(200); - - assertThat(tested.reportMenuItem(USERNAME)).isEmpty(); - - unirest.verifyAll(); - } - - @Test - void invalidResponse(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(USERNAME)) - .thenReturn() - .withStatus(500); - - assertThat(tested.reportMenuItem(USERNAME)).isEmpty(); - - unirest.verifyAll(); + @Override + protected String getValidRequest(){ + return "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"8f3628981255345ca5e5453dfd844efffb01d6413a9931498836e6268692a30c\",\"version\":1}},\"operationName\":\"ReportMenuItem\",\"variables\":{\"channelLogin\":\"%s\"}}".formatted(USERNAME); } } \ No newline at end of file diff --git a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiVideoPlayerStreamInfoOverlayChannelTest.java b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiVideoPlayerStreamInfoOverlayChannelTest.java index 149d274c..d3863304 100644 --- a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiVideoPlayerStreamInfoOverlayChannelTest.java +++ b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLApiVideoPlayerStreamInfoOverlayChannelTest.java @@ -8,9 +8,8 @@ import fr.raksrinana.channelpointsminer.miner.api.gql.data.types.User; import fr.raksrinana.channelpointsminer.miner.api.gql.data.videoplayerstreaminfooverlaychannel.VideoPlayerStreamInfoOverlayChannelData; import fr.raksrinana.channelpointsminer.miner.api.passport.TwitchLogin; -import fr.raksrinana.channelpointsminer.miner.tests.TestUtils; +import fr.raksrinana.channelpointsminer.miner.tests.UnirestMock; import fr.raksrinana.channelpointsminer.miner.tests.UnirestMockExtension; -import kong.unirest.core.MockClient; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -21,17 +20,13 @@ import java.net.URL; import java.util.List; import java.util.Map; -import static kong.unirest.core.HttpMethod.POST; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @ExtendWith(UnirestMockExtension.class) -class GQLApiVideoPlayerStreamInfoOverlayChannelTest{ - private static final String ACCESS_TOKEN = "access-token"; +class GQLApiVideoPlayerStreamInfoOverlayChannelTest extends AbstractGQLTest{ private static final String USERNAME = "username"; - private static final String VALID_QUERY = "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"a5f2e34d626a9f4f5c0204f910bab2194948a9502089be558bb6e779a9e1b3d2\",\"version\":1}},\"operationName\":\"VideoPlayerStreamInfoOverlayChannel\",\"variables\":{\"channel\":\"%s\"}}"; @InjectMocks private GQLApi tested; @@ -45,7 +40,7 @@ void setUp(){ } @Test - void nominalOnline(MockClient unirest) throws MalformedURLException{ + void nominalOnline(UnirestMock unirest) throws MalformedURLException{ var expected = GQLResponse. builder() .extensions(Map.of( "durationMilliseconds", 58, @@ -82,11 +77,7 @@ void nominalOnline(MockClient unirest) throws MalformedURLException{ .build()) .build(); - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(USERNAME)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/videoPlayerStreamInfoOverlayChannel_online.json")) - .withStatus(200); + expectValidRequestOkWithIntegrityOk(unirest, "api/gql/videoPlayerStreamInfoOverlayChannel_online.json"); assertThat(tested.videoPlayerStreamInfoOverlayChannel(USERNAME)).isPresent().get().isEqualTo(expected); @@ -94,7 +85,7 @@ void nominalOnline(MockClient unirest) throws MalformedURLException{ } @Test - void nominalOffline(MockClient unirest) throws MalformedURLException{ + void nominalOffline(UnirestMock unirest) throws MalformedURLException{ var expected = GQLResponse. builder() .extensions(Map.of( "durationMilliseconds", 58, @@ -121,53 +112,15 @@ void nominalOffline(MockClient unirest) throws MalformedURLException{ .build()) .build(); - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(USERNAME)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/videoPlayerStreamInfoOverlayChannel_offline.json")) - .withStatus(200); + expectValidRequestOkWithIntegrityOk(unirest, "api/gql/videoPlayerStreamInfoOverlayChannel_offline.json"); assertThat(tested.videoPlayerStreamInfoOverlayChannel(USERNAME)).isPresent().get().isEqualTo(expected); unirest.verifyAll(); } - @Test - void invalidCredentials(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(USERNAME)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/invalidAuth.json")) - .withStatus(401); - - assertThrows(RuntimeException.class, () -> tested.videoPlayerStreamInfoOverlayChannel(USERNAME)); - - unirest.verifyAll(); - } - - @Test - void invalidRequest(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(USERNAME)) - .thenReturn(TestUtils.getAllResourceContent("api/gql/invalidRequest.json")) - .withStatus(200); - - assertThat(tested.videoPlayerStreamInfoOverlayChannel(USERNAME)).isEmpty(); - - unirest.verifyAll(); - } - - @Test - void invalidResponse(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(USERNAME)) - .thenReturn() - .withStatus(500); - - assertThat(tested.videoPlayerStreamInfoOverlayChannel(USERNAME)).isEmpty(); - - unirest.verifyAll(); + @Override + protected String getValidRequest(){ + return "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"a5f2e34d626a9f4f5c0204f910bab2194948a9502089be558bb6e779a9e1b3d2\",\"version\":1}},\"operationName\":\"VideoPlayerStreamInfoOverlayChannel\",\"variables\":{\"channel\":\"%s\"}}".formatted(USERNAME); } } \ No newline at end of file diff --git a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLChannelFollowsTest.java b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLChannelFollowsTest.java index 497a2a16..28856505 100644 --- a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLChannelFollowsTest.java +++ b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/gql/GQLChannelFollowsTest.java @@ -9,8 +9,8 @@ import fr.raksrinana.channelpointsminer.miner.api.gql.data.types.User; import fr.raksrinana.channelpointsminer.miner.api.gql.data.types.UserSelfConnection; import fr.raksrinana.channelpointsminer.miner.api.passport.TwitchLogin; +import fr.raksrinana.channelpointsminer.miner.tests.UnirestMock; import fr.raksrinana.channelpointsminer.miner.tests.UnirestMockExtension; -import kong.unirest.core.MockClient; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; @@ -22,19 +22,16 @@ import java.time.ZonedDateTime; import java.util.List; import java.util.Map; -import static fr.raksrinana.channelpointsminer.miner.tests.TestUtils.getAllResourceContent; import static java.time.ZoneOffset.UTC; -import static kong.unirest.core.HttpMethod.POST; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @ExtendWith(UnirestMockExtension.class) -class GQLChannelFollowsTest{ +class GQLChannelFollowsTest extends AbstractGQLTest{ public static final String VALID_QUERY = "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"4b9cb31b54b9213e5760f2f6e9e935ad09924cac2f78aac51f8a64d85f028ed0\",\"version\":1}},\"operationName\":\"ChannelFollows\",\"variables\":{\"limit\":%d,\"order\":\"%s\"}}"; public static final String VALID_QUERY_WITH_CURSOR = "{\"extensions\":{\"persistedQuery\":{\"sha256Hash\":\"4b9cb31b54b9213e5760f2f6e9e935ad09924cac2f78aac51f8a64d85f028ed0\",\"version\":1}},\"operationName\":\"ChannelFollows\",\"variables\":{\"cursor\":\"%s\",\"limit\":%d,\"order\":\"%s\"}}"; - private static final String ACCESS_TOKEN = "access-token"; private static final int LIMIT = 15; private static final int ALL_LIMIT = 100; private static final String ORDER = "DESC"; @@ -51,7 +48,7 @@ void setUp(){ } @Test - void nominal(MockClient unirest) throws MalformedURLException{ + void nominal(UnirestMock unirest) throws MalformedURLException{ var expected = GQLResponse. builder() .extensions(Map.of( "durationMilliseconds", 102, @@ -85,12 +82,7 @@ void nominal(MockClient unirest) throws MalformedURLException{ .build()) .build()) .build(); - - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(LIMIT, ORDER)) - .thenReturn(getAllResourceContent("api/gql/channelFollows_oneFollow.json")) - .withStatus(200); + expectValidRequestOkWithIntegrityOk(unirest, "api/gql/channelFollows_oneFollow.json"); assertThat(tested.channelFollows(LIMIT, ORDER, null)).isPresent().get().isEqualTo(expected); @@ -98,7 +90,7 @@ void nominal(MockClient unirest) throws MalformedURLException{ } @Test - void nominalWithCursor(MockClient unirest) throws MalformedURLException{ + void nominalWithCursor(UnirestMock unirest) throws MalformedURLException{ var expected = GQLResponse. builder() .extensions(Map.of( "durationMilliseconds", 102, @@ -135,11 +127,7 @@ void nominalWithCursor(MockClient unirest) throws MalformedURLException{ var cursor = "my-cursor"; - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY_WITH_CURSOR.formatted(cursor, LIMIT, ORDER)) - .thenReturn(getAllResourceContent("api/gql/channelFollows_oneFollow.json")) - .withStatus(200); + expectBodyRequestOkWithIntegrityOk(unirest, VALID_QUERY_WITH_CURSOR.formatted(cursor, LIMIT, ORDER), "api/gql/channelFollows_oneFollow.json"); assertThat(tested.channelFollows(LIMIT, ORDER, cursor)).isPresent().get().isEqualTo(expected); @@ -147,18 +135,10 @@ void nominalWithCursor(MockClient unirest) throws MalformedURLException{ } @Test - void getAllFollowsNominal(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(ALL_LIMIT, ORDER)) - .thenReturn(getAllResourceContent("api/gql/channelFollows_severalFollows.json")) - .withStatus(200); - - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY_WITH_CURSOR.formatted("cursor-id-2", ALL_LIMIT, ORDER)) - .thenReturn(getAllResourceContent("api/gql/channelFollows_oneFollow.json")) - .withStatus(200); + void getAllFollowsNominal(UnirestMock unirest){ + setupIntegrityOk(unirest); + expectBodyRequestOk(unirest, VALID_QUERY.formatted(ALL_LIMIT, ORDER), "api/gql/channelFollows_severalFollows.json"); + expectBodyRequestOk(unirest, VALID_QUERY_WITH_CURSOR.formatted("cursor-id-2", ALL_LIMIT, ORDER), "api/gql/channelFollows_oneFollow.json"); assertThat(tested.allChannelFollows()).hasSize(3); @@ -166,12 +146,8 @@ void getAllFollowsNominal(MockClient unirest){ } @Test - void getAllFollowsNominalOnePage(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(ALL_LIMIT, ORDER)) - .thenReturn(getAllResourceContent("api/gql/channelFollows_oneFollow.json")) - .withStatus(200); + void getAllFollowsNominalOnePage(UnirestMock unirest){ + expectBodyRequestOkWithIntegrityOk(unirest, VALID_QUERY.formatted(ALL_LIMIT, ORDER), "api/gql/channelFollows_oneFollow.json"); assertThat(tested.allChannelFollows()).hasSize(1); @@ -179,54 +155,16 @@ void getAllFollowsNominalOnePage(MockClient unirest){ } @Test - void getAllFollowsErrorGettingCursor(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(ALL_LIMIT, ORDER)) - .thenReturn(getAllResourceContent("api/gql/channelFollows_invalidCursor.json")) - .withStatus(200); + void getAllFollowsErrorGettingCursor(UnirestMock unirest){ + expectBodyRequestOkWithIntegrityOk(unirest, VALID_QUERY.formatted(ALL_LIMIT, ORDER), "api/gql/channelFollows_invalidCursor.json"); assertThrows(IllegalStateException.class, () -> tested.allChannelFollows()); unirest.verifyAll(); } - @Test - void invalidCredentials(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(LIMIT, ORDER)) - .thenReturn(getAllResourceContent("api/gql/invalidAuth.json")) - .withStatus(401); - - assertThrows(RuntimeException.class, () -> tested.channelFollows(LIMIT, ORDER, null)); - - unirest.verifyAll(); - } - - @Test - void invalidRequest(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(LIMIT, ORDER)) - .thenReturn(getAllResourceContent("api/gql/invalidRequest.json")) - .withStatus(200); - - assertThat(tested.channelFollows(LIMIT, ORDER, null)).isEmpty(); - - unirest.verifyAll(); - } - - @Test - void invalidResponse(MockClient unirest){ - unirest.expect(POST, "https://gql.twitch.tv/gql") - .header("Authorization", "OAuth " + ACCESS_TOKEN) - .body(VALID_QUERY.formatted(LIMIT, ORDER)) - .thenReturn() - .withStatus(500); - - assertThat(tested.channelFollows(LIMIT, ORDER, null)).isEmpty(); - - unirest.verifyAll(); + @Override + protected String getValidRequest(){ + return VALID_QUERY.formatted(LIMIT, ORDER); } } \ No newline at end of file diff --git a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/passport/PassportApiTest.java b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/passport/PassportApiTest.java index 107a8b74..d2a4c2c8 100644 --- a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/passport/PassportApiTest.java +++ b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/passport/PassportApiTest.java @@ -4,10 +4,10 @@ import fr.raksrinana.channelpointsminer.miner.api.passport.exceptions.CaptchaSolveRequired; import fr.raksrinana.channelpointsminer.miner.api.passport.exceptions.InvalidCredentials; import fr.raksrinana.channelpointsminer.miner.api.passport.exceptions.LoginException; +import fr.raksrinana.channelpointsminer.miner.tests.UnirestMock; import fr.raksrinana.channelpointsminer.miner.tests.UnirestMockExtension; import fr.raksrinana.channelpointsminer.miner.util.CommonUtils; import kong.unirest.core.Cookie; -import kong.unirest.core.MockClient; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.junit.jupiter.api.BeforeEach; @@ -58,7 +58,7 @@ void setUp(){ } @Test - void newAuthWithout2FA(MockClient unirest) throws LoginException, IOException{ + void newAuthWithout2FA(UnirestMock unirest) throws LoginException, IOException{ unirest.expect(POST, "https://passport.twitch.tv/login") .header(CONTENT_TYPE, APPLICATION_JSON.toString()) .header("Client-Id", CLIENT_ID) @@ -85,7 +85,7 @@ void newAuthWithout2FA(MockClient unirest) throws LoginException, IOException{ } @Test - void newAuthWithObscuredEmail(MockClient unirest) throws LoginException, IOException{ + void newAuthWithObscuredEmail(UnirestMock unirest) throws LoginException, IOException{ unirest.expect(POST, "https://passport.twitch.tv/login") .header(CONTENT_TYPE, APPLICATION_JSON.toString()) .header("Client-Id", CLIENT_ID) @@ -112,7 +112,7 @@ void newAuthWithObscuredEmail(MockClient unirest) throws LoginException, IOExcep } @Test - void newAuthWith2FA(MockClient unirest) throws LoginException, IOException{ + void newAuthWith2FA(UnirestMock unirest) throws LoginException, IOException{ try(var commonUtils = Mockito.mockStatic(CommonUtils.class)){ commonUtils.when(() -> CommonUtils.getUserInput(anyString())).thenReturn(TWO_FACTOR); @@ -149,7 +149,7 @@ void newAuthWith2FA(MockClient unirest) throws LoginException, IOException{ 3011, 3012 }) - void newAuthWithMissing2FAOnFirstTry(int errorCode, MockClient unirest) throws LoginException, IOException{ + void newAuthWithMissing2FAOnFirstTry(int errorCode, UnirestMock unirest) throws LoginException, IOException{ try(var commonUtils = Mockito.mockStatic(CommonUtils.class)){ commonUtils.when(() -> CommonUtils.getUserInput(anyString())).thenReturn(TWO_FACTOR); unirest.expect(POST, "https://passport.twitch.tv/login") @@ -190,7 +190,7 @@ void newAuthWithMissing2FAOnFirstTry(int errorCode, MockClient unirest) throws L 3022, 3023 }) - void newAuthWithMissingTwitchGuardOnFirstTry(int errorCode, MockClient unirest) throws LoginException, IOException{ + void newAuthWithMissingTwitchGuardOnFirstTry(int errorCode, UnirestMock unirest) throws LoginException, IOException{ try(var commonUtils = Mockito.mockStatic(CommonUtils.class)){ commonUtils.when(() -> CommonUtils.getUserInput(anyString())).thenReturn(TWO_FACTOR); unirest.expect(POST, "https://passport.twitch.tv/login") @@ -227,7 +227,7 @@ void newAuthWithMissingTwitchGuardOnFirstTry(int errorCode, MockClient unirest) } @Test - void failedAuthWithCaptchaRequired(MockClient unirest){ + void failedAuthWithCaptchaRequired(UnirestMock unirest){ unirest.expect(POST, "https://passport.twitch.tv/login") .header(CONTENT_TYPE, APPLICATION_JSON.toString()) .header("Client-Id", CLIENT_ID) @@ -246,7 +246,7 @@ void failedAuthWithCaptchaRequired(MockClient unirest){ 3001, 3003 }) - void failedAuthWithInvalidCredentials(int errorCode, MockClient unirest){ + void failedAuthWithInvalidCredentials(int errorCode, UnirestMock unirest){ unirest.expect(POST, "https://passport.twitch.tv/login") .header(CONTENT_TYPE, APPLICATION_JSON.toString()) .header("Client-Id", CLIENT_ID) @@ -261,7 +261,7 @@ void failedAuthWithInvalidCredentials(int errorCode, MockClient unirest){ } @Test - void failedAuthWithMissing2FA(MockClient unirest){ + void failedAuthWithMissing2FA(UnirestMock unirest){ try(var commonUtils = Mockito.mockStatic(CommonUtils.class)){ commonUtils.when(() -> CommonUtils.getUserInput(anyString())).thenReturn(TWO_FACTOR); unirest.expect(POST, "https://passport.twitch.tv/login") @@ -286,7 +286,7 @@ void failedAuthWithMissing2FA(MockClient unirest){ } @Test - void failedAuthWithMissingTwitchGuard(MockClient unirest){ + void failedAuthWithMissingTwitchGuard(UnirestMock unirest){ try(var commonUtils = Mockito.mockStatic(CommonUtils.class)){ commonUtils.when(() -> CommonUtils.getUserInput(anyString())).thenReturn(TWO_FACTOR); unirest.expect(POST, "https://passport.twitch.tv/login") @@ -311,7 +311,7 @@ void failedAuthWithMissingTwitchGuard(MockClient unirest){ } @Test - void failedAuthWithUnknownErrorCode(MockClient unirest){ + void failedAuthWithUnknownErrorCode(UnirestMock unirest){ unirest.expect(POST, "https://passport.twitch.tv/login") .header(CONTENT_TYPE, APPLICATION_JSON.toString()) .header("Client-Id", CLIENT_ID) @@ -326,7 +326,7 @@ void failedAuthWithUnknownErrorCode(MockClient unirest){ } @Test - void failedAuthWithNoErrorCode(MockClient unirest){ + void failedAuthWithNoErrorCode(UnirestMock unirest){ unirest.expect(POST, "https://passport.twitch.tv/login") .header(CONTENT_TYPE, APPLICATION_JSON.toString()) .header("Client-Id", CLIENT_ID) @@ -341,7 +341,7 @@ void failedAuthWithNoErrorCode(MockClient unirest){ } @Test - void failedAuthWithServerError(MockClient unirest){ + void failedAuthWithServerError(UnirestMock unirest){ unirest.expect(POST, "https://passport.twitch.tv/login") .header(CONTENT_TYPE, APPLICATION_JSON.toString()) .header("Client-Id", CLIENT_ID) diff --git a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/twitch/TwitchApiTest.java b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/twitch/TwitchApiTest.java index f52f8bd2..6c045503 100644 --- a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/twitch/TwitchApiTest.java +++ b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/api/twitch/TwitchApiTest.java @@ -4,9 +4,9 @@ import fr.raksrinana.channelpointsminer.miner.api.twitch.data.MinuteWatchedEvent; import fr.raksrinana.channelpointsminer.miner.api.twitch.data.MinuteWatchedProperties; import fr.raksrinana.channelpointsminer.miner.api.twitch.data.PlayerEvent; +import fr.raksrinana.channelpointsminer.miner.tests.UnirestMock; import fr.raksrinana.channelpointsminer.miner.tests.UnirestMockExtension; import fr.raksrinana.channelpointsminer.miner.util.json.JacksonUtils; -import kong.unirest.core.MockClient; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.junit.jupiter.api.BeforeEach; @@ -50,7 +50,7 @@ void setUp() throws MalformedURLException{ } @Test - void sendMinutesWatched(MockClient unirest){ + void sendMinutesWatched(UnirestMock unirest){ var json = "[{\"event\":\"minute-watched\",\"properties\":{\"broadcast_id\":\"%s\",\"channel_id\":\"%s\",\"player\":\"%s\",\"user_id\":%d}}]" .formatted(BROADCAST_ID, CHANNEL_ID, PLAYER, USER_ID); var expectedData = new String(Base64.getEncoder().encode(json.getBytes(UTF_8))); @@ -74,7 +74,7 @@ void sendMinutesWatched(MockClient unirest){ } @Test - void sendMinutesWatchedWithGame(MockClient unirest){ + void sendMinutesWatchedWithGame(UnirestMock unirest){ var json = "[{\"event\":\"minute-watched\",\"properties\":{\"broadcast_id\":\"%s\",\"channel_id\":\"%s\",\"game\":\"%s\",\"player\":\"%s\",\"user_id\":%d}}]" .formatted(BROADCAST_ID, CHANNEL_ID, GAME, PLAYER, USER_ID); var expectedData = new String(Base64.getEncoder().encode(json.getBytes(UTF_8))); @@ -99,7 +99,7 @@ void sendMinutesWatchedWithGame(MockClient unirest){ } @Test - void sendMinutesWatchedNotSuccess(MockClient unirest){ + void sendMinutesWatchedNotSuccess(UnirestMock unirest){ var json = "[{\"event\":\"minute-watched\",\"properties\":{\"broadcast_id\":\"%s\",\"channel_id\":\"%s\",\"player\":\"%s\",\"user_id\":%d}}]" .formatted(BROADCAST_ID, CHANNEL_ID, PLAYER, USER_ID); var expectedData = new String(Base64.getEncoder().encode(json.getBytes(UTF_8))); @@ -142,7 +142,7 @@ void sendMinutesWatchedJsonError(){ } @Test - void getSpadeUrl(MockClient unirest){ + void getSpadeUrl(UnirestMock unirest){ unirest.expect(GET, STREAMER_URL) .thenReturn(CONFIG_BODY) .withStatus(200); @@ -156,7 +156,7 @@ void getSpadeUrl(MockClient unirest){ } @Test - void getSpadeUrlInvalidConfigUrlResponse(MockClient unirest){ + void getSpadeUrlInvalidConfigUrlResponse(UnirestMock unirest){ unirest.expect(GET, STREAMER_URL) .thenReturn(CONFIG_BODY) .withStatus(500); @@ -165,7 +165,7 @@ void getSpadeUrlInvalidConfigUrlResponse(MockClient unirest){ } @Test - void getSpadeUrlNoConfigUrl(MockClient unirest){ + void getSpadeUrlNoConfigUrl(UnirestMock unirest){ unirest.expect(GET, STREAMER_URL) .thenReturn("") .withStatus(200); @@ -174,7 +174,7 @@ void getSpadeUrlNoConfigUrl(MockClient unirest){ } @Test - void getSpadeUrlInvalidResponse(MockClient unirest){ + void getSpadeUrlInvalidResponse(UnirestMock unirest){ unirest.expect(GET, STREAMER_URL) .thenReturn(CONFIG_BODY) .withStatus(200); @@ -187,7 +187,7 @@ void getSpadeUrlInvalidResponse(MockClient unirest){ } @Test - void getSpadeUrlInvalidFormat(MockClient unirest){ + void getSpadeUrlInvalidFormat(UnirestMock unirest){ unirest.expect(GET, STREAMER_URL) .thenReturn(CONFIG_BODY) .withStatus(200); @@ -200,7 +200,7 @@ void getSpadeUrlInvalidFormat(MockClient unirest){ } @Test - void getSpadeUrlNoUrl(MockClient unirest){ + void getSpadeUrlNoUrl(UnirestMock unirest){ unirest.expect(GET, STREAMER_URL) .thenReturn(CONFIG_BODY) .withStatus(200); diff --git a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/tests/UnirestMock.java b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/tests/UnirestMock.java new file mode 100644 index 00000000..7b91ae65 --- /dev/null +++ b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/tests/UnirestMock.java @@ -0,0 +1,25 @@ +package fr.raksrinana.channelpointsminer.miner.tests; + +import kong.unirest.core.Expectation; +import kong.unirest.core.HttpMethod; +import kong.unirest.core.MockClient; + +public class UnirestMock{ + private MockClient unirest; + + public UnirestMock(){ + reset(); + } + + public void reset(){ + unirest = MockClient.register(); + } + + public void verifyAll(){ + unirest.verifyAll(); + } + + public Expectation expect(HttpMethod method, String path){ + return unirest.expect(method, path); + } +} diff --git a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/tests/UnirestMockExtension.java b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/tests/UnirestMockExtension.java index 2fd7106d..7a0fd4a2 100644 --- a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/tests/UnirestMockExtension.java +++ b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/tests/UnirestMockExtension.java @@ -22,7 +22,7 @@ @Log4j2 public class UnirestMockExtension implements Extension, BeforeAllCallback, BeforeEachCallback, AfterEachCallback, ParameterResolver{ - private MockClient unirest; + private UnirestMock unirest; @Override public void beforeAll(ExtensionContext context){ @@ -46,7 +46,7 @@ public void onResponse(HttpResponse response, HttpRequestSummary request, Con @Override public void beforeEach(ExtensionContext context){ Unirest.config().clearDefaultHeaders(); - unirest = MockClient.register(); + unirest = new UnirestMock(); } @Override @@ -56,7 +56,7 @@ public void afterEach(ExtensionContext context){ @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException{ - return Objects.equals(parameterContext.getParameter().getType(), MockClient.class); + return Objects.equals(parameterContext.getParameter().getType(), UnirestMock.class); } @Override diff --git a/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/util/json/MillisecondsTimestampDeserializerTest.java b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/util/json/MillisecondsTimestampDeserializerTest.java new file mode 100644 index 00000000..a4873ea4 --- /dev/null +++ b/miner/src/test/java/fr/raksrinana/channelpointsminer/miner/util/json/MillisecondsTimestampDeserializerTest.java @@ -0,0 +1,25 @@ +package fr.raksrinana.channelpointsminer.miner.util.json; + +import com.fasterxml.jackson.databind.JsonDeserializer; +import fr.raksrinana.channelpointsminer.miner.tests.ParallelizableTest; +import org.junit.jupiter.api.Test; +import java.time.Instant; +import static org.assertj.core.api.Assertions.assertThat; + +@ParallelizableTest +class MillisecondsTimestampDeserializerTest extends DeserializerTest{ + @Test + void longValue(){ + assertThat(deserialize("%d".formatted(1633717410096L))).isEqualTo(Instant.parse("2021-10-08T18:23:30.096000Z")); + } + + @Test + void empty(){ + assertThat(deserialize("\"\"")).isNull(); + } + + @Override + protected JsonDeserializer getDeserializer(){ + return new MillisecondsTimestampDeserializer(); + } +} \ No newline at end of file diff --git a/miner/src/test/resources/api/gql/integrity_needRefresh.json b/miner/src/test/resources/api/gql/integrity_needRefresh.json new file mode 100644 index 00000000..a7bf6f3e --- /dev/null +++ b/miner/src/test/resources/api/gql/integrity_needRefresh.json @@ -0,0 +1,5 @@ +{ + "token" : "integrity-token", + "expiration" : 0, + "request_id" : "request-id" +} \ No newline at end of file diff --git a/miner/src/test/resources/api/gql/integrity_noToken.json b/miner/src/test/resources/api/gql/integrity_noToken.json new file mode 100644 index 00000000..f7d536f5 --- /dev/null +++ b/miner/src/test/resources/api/gql/integrity_noToken.json @@ -0,0 +1,4 @@ +{ + "request_id" : "request-id", + "message" : "error-message" +} \ No newline at end of file diff --git a/miner/src/test/resources/api/gql/integrity_ok.json b/miner/src/test/resources/api/gql/integrity_ok.json new file mode 100644 index 00000000..7c02ea0b --- /dev/null +++ b/miner/src/test/resources/api/gql/integrity_ok.json @@ -0,0 +1,5 @@ +{ + "token" : "integrity-token", + "expiration" : 9999999999999, + "request_id" : "request-id" +} \ No newline at end of file