Add sad path test for ObjectMapper & Add test for betaSearch

pull/16/head
Hammy 3 years ago
parent c5502d8414
commit 0c510e4713

@ -16,13 +16,13 @@ import java.util.List;
* *
*/ */
class APIMapper { class APIMapper {
private final ObjectMapper objectMapper; private ObjectMapper objectMapper;
APIMapper() { APIMapper() {
objectMapper = new ObjectMapper(); objectMapper = new ObjectMapper();
} }
/** /*\
* Convert any object passed and return as a {@link String} * Convert any object passed and return as a {@link String}
* *
* @param obj {@link Object} to write as {@link String} * @param obj {@link Object} to write as {@link String}
@ -153,4 +153,8 @@ class APIMapper {
throw new APIMapperException(exceptionMessage, throwable); throw new APIMapperException(exceptionMessage, throwable);
} }
void setObjectMapper(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
} }

@ -39,7 +39,7 @@ public class APIWrapper {
private static final String host = "https://mywaifulist.moe/api/v1/"; private static final String host = "https://mywaifulist.moe/api/v1/";
private String apiKey; private String apiKey;
private final APIMapper apiMapper; private APIMapper apiMapper;
private final HttpClient httpClient; private final HttpClient httpClient;
private final Executor executor = Executors.newFixedThreadPool(10); private final Executor executor = Executors.newFixedThreadPool(10);
@ -413,7 +413,7 @@ public class APIWrapper {
this.apiKey = apiKey; this.apiKey = apiKey;
} }
String getApiKey() { void setApiMapper(APIMapper apiMapper) {
return apiKey; this.apiMapper = apiMapper;
} }
} }

@ -1,5 +1,9 @@
package me.goudham; package me.goudham;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import me.goudham.domain.pagination.PaginationData; import me.goudham.domain.pagination.PaginationData;
import me.goudham.domain.waifu.FilteredWaifu; import me.goudham.domain.waifu.FilteredWaifu;
import me.goudham.domain.waifu.Waifu; import me.goudham.domain.waifu.Waifu;
@ -11,6 +15,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSession;
import java.io.BufferedReader; import java.io.BufferedReader;
@ -29,143 +34,211 @@ import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static me.goudham.APIUtils.listOf;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
class MyWaifuClientTest { class MyWaifuClientTest {
@Mock @Mock
private HttpClient httpClient; private HttpClient httpClient;
private final String apiKey = "ValidAPIKey"; @Spy
private ObjectMapper objectMapper;
private MyWaifuClient sut;
private final String apiKey = "ValidAPIKey";
@BeforeEach
void setUp() { private MyWaifuClient sut;
MockitoAnnotations.openMocks(this);
@BeforeEach
sut = MyWaifuClient.createDefault(apiKey); void setUp() {
APIWrapper apiWrapper = new APIWrapper(apiKey, httpClient); MockitoAnnotations.openMocks(this);
sut.setAPIWrapper(apiWrapper);
} sut = MyWaifuClient.createDefault(apiKey);
APIWrapper apiWrapper = new APIWrapper(apiKey, httpClient);
@Test APIMapper apiMapper = new APIMapper();
void successfullyGetWaifu() throws IOException, InterruptedException, APIMapperException, APIResponseException {
HttpRequest expectedHttpRequest = buildHttpGetRequest(apiKey, "waifu/1"); apiMapper.setObjectMapper(objectMapper);
int expectedStatusCode = 200; apiWrapper.setApiMapper(apiMapper);
String expectedBody = getJsonAsString("getWaifu.json"); sut.setAPIWrapper(apiWrapper);
Waifu expectedWaifu = TestEntity.getExpectedWaifu(); }
HttpResponse<String> expectedHttpResponse = buildHttpResponse(expectedStatusCode, expectedBody);
@Test
doReturn(expectedHttpResponse).when(httpClient).send(expectedHttpRequest, HttpResponse.BodyHandlers.ofString()); void successfullyGetWaifu() throws IOException, InterruptedException, APIMapperException, APIResponseException {
HttpRequest expectedHttpRequest = buildHttpGetRequest(apiKey, "waifu/1");
Response<Waifu> actualWaifuResponse = sut.getWaifu(1); int expectedStatusCode = 200;
String expectedBody = getJsonAsString("getWaifu.json");
assertThat(actualWaifuResponse.getStatusCode(), is(expectedStatusCode)); Waifu expectedWaifu = TestEntity.getExpectedWaifu();
assertThat(actualWaifuResponse.getBody(), is(expectedBody)); HttpResponse<String> expectedHttpResponse = buildHttpResponse(expectedStatusCode, expectedBody);
assertThat(actualWaifuResponse.getModel(), is(expectedWaifu));
verify(httpClient, times(1)).send(expectedHttpRequest, HttpResponse.BodyHandlers.ofString()); doReturn(expectedHttpResponse).when(httpClient).send(expectedHttpRequest, HttpResponse.BodyHandlers.ofString());
verifyNoMoreInteractions(httpClient);
} Response<Waifu> actualWaifuResponse = sut.getWaifu(1);
@Test assertThat(actualWaifuResponse.getStatusCode(), is(expectedStatusCode));
void successfullyGetBestWaifus() throws IOException, InterruptedException, APIMapperException, APIResponseException { assertThat(actualWaifuResponse.getBody(), is(expectedBody));
HttpRequest expectedHttpRequest = buildHttpGetRequest(apiKey, "airing/best"); assertThat(actualWaifuResponse.getModel(), is(expectedWaifu));
int expectedStatusCode = 200; verify(httpClient, times(1)).send(expectedHttpRequest, HttpResponse.BodyHandlers.ofString());
String expectedBody = getJsonAsString("getBestWaifus.json"); verifyNoMoreInteractions(httpClient);
List<FilteredWaifu> expectedBestWaifus = TestEntity.getBestWaifus(); }
HttpResponse<String> expectedHttpResponse = buildHttpResponse(expectedStatusCode, expectedBody);
@Test
doReturn(expectedHttpResponse).when(httpClient).send(expectedHttpRequest, HttpResponse.BodyHandlers.ofString()); void successfullyGetBestWaifus() throws IOException, InterruptedException, APIMapperException, APIResponseException {
HttpRequest expectedHttpRequest = buildHttpGetRequest(apiKey, "airing/best");
Response<List<FilteredWaifu>> actualBestWaifusResponse = sut.getBestWaifus(); int expectedStatusCode = 200;
String expectedBody = getJsonAsString("getBestWaifus.json");
assertThat(actualBestWaifusResponse.getStatusCode(), is(expectedStatusCode)); List<FilteredWaifu> expectedBestWaifus = TestEntity.getBestWaifus();
assertThat(actualBestWaifusResponse.getBody(), is(expectedBody)); HttpResponse<String> expectedHttpResponse = buildHttpResponse(expectedStatusCode, expectedBody);
assertThat(actualBestWaifusResponse.getModel(), is(expectedBestWaifus));
verify(httpClient, times(1)).send(expectedHttpRequest, HttpResponse.BodyHandlers.ofString()); doReturn(expectedHttpResponse).when(httpClient).send(expectedHttpRequest, HttpResponse.BodyHandlers.ofString());
verifyNoMoreInteractions(httpClient);
} Response<List<FilteredWaifu>> actualBestWaifusResponse = sut.getBestWaifus();
@Test assertThat(actualBestWaifusResponse.getStatusCode(), is(expectedStatusCode));
void successfullyGetWaifuImages() throws IOException, InterruptedException, APIMapperException, APIResponseException { assertThat(actualBestWaifusResponse.getBody(), is(expectedBody));
HttpRequest expectedHttpRequest = buildHttpGetRequest(apiKey, "waifu/1/images?page=1"); assertThat(actualBestWaifusResponse.getModel(), is(expectedBestWaifus));
int expectedStatusCode = 200; verify(httpClient, times(1)).send(expectedHttpRequest, HttpResponse.BodyHandlers.ofString());
String expectedBody = getJsonAsString("getWaifuImages.json"); verifyNoMoreInteractions(httpClient);
PaginationData<WaifuImage> expectedWaifuImages = TestEntity.getWaifuImages(); }
HttpResponse<String> expectedHttpResponse = buildHttpResponse(expectedStatusCode, expectedBody);
@Test
doReturn(expectedHttpResponse).when(httpClient).send(expectedHttpRequest, HttpResponse.BodyHandlers.ofString()); void successfullyGetWaifuImages() throws IOException, InterruptedException, APIMapperException, APIResponseException {
HttpRequest expectedHttpRequest = buildHttpGetRequest(apiKey, "waifu/1/images?page=1");
Response<PaginationData<WaifuImage>> actualWaifuImagesResponse = sut.getWaifuImages(1, 1); int expectedStatusCode = 200;
String expectedBody = getJsonAsString("getWaifuImages.json");
assertThat(actualWaifuImagesResponse.getStatusCode(), is(expectedStatusCode)); PaginationData<WaifuImage> expectedWaifuImages = TestEntity.getWaifuImages();
assertThat(actualWaifuImagesResponse.getBody(), is(expectedBody)); HttpResponse<String> expectedHttpResponse = buildHttpResponse(expectedStatusCode, expectedBody);
assertThat(actualWaifuImagesResponse.getModel(), is(expectedWaifuImages));
verify(httpClient, times(1)).send(expectedHttpRequest, HttpResponse.BodyHandlers.ofString()); doReturn(expectedHttpResponse).when(httpClient).send(expectedHttpRequest, HttpResponse.BodyHandlers.ofString());
verifyNoMoreInteractions(httpClient);
} Response<PaginationData<WaifuImage>> actualWaifuImagesResponse = sut.getWaifuImages(1, 1);
private String getJsonAsString(String filename) { assertThat(actualWaifuImagesResponse.getStatusCode(), is(expectedStatusCode));
InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(filename); assertThat(actualWaifuImagesResponse.getBody(), is(expectedBody));
return new BufferedReader(new InputStreamReader(Objects.requireNonNull(resourceAsStream), StandardCharsets.UTF_8)) assertThat(actualWaifuImagesResponse.getModel(), is(expectedWaifuImages));
.lines() verify(httpClient, times(1)).send(expectedHttpRequest, HttpResponse.BodyHandlers.ofString());
.collect(Collectors.joining("\n")); verifyNoMoreInteractions(httpClient);
} }
private HttpRequest buildHttpGetRequest(String apiKey, String param) { @Test
return HttpRequest.newBuilder() void successfullyPostBetaSearch() throws IOException, InterruptedException, APIMapperException, APIResponseException {
.uri(URI.create("https://mywaifulist.moe/api/v1/" + param)) HttpRequest expectedHttpRequest = buildHttpPostRequest(apiKey, "search/beta");
.timeout(Duration.ofSeconds(20)) int expectedStatusCode = 200;
.headers("Content-Type", "application/json", "apikey", apiKey) String expectedBody = getJsonAsString("betaSearch.json");
.GET() List<FilteredWaifu> expectedBetaSearch = TestEntity.getBetaSearch();
.build(); HttpResponse<String> expectedHttpResponse = buildHttpResponse(expectedStatusCode, expectedBody);
}
doReturn(expectedHttpResponse).when(httpClient).send(expectedHttpRequest, HttpResponse.BodyHandlers.ofString());
private HttpResponse<String> buildHttpResponse(int statusCode, String body) {
return new HttpResponse<>() { Response<List<FilteredWaifu>> actualBetaSearchResponse = sut.betaSearch("Yumeko");
@Override
public int statusCode() { assertThat(actualBetaSearchResponse.getStatusCode(), is(expectedStatusCode));
return statusCode; assertThat(actualBetaSearchResponse.getBody(), is(expectedBody));
} assertThat(actualBetaSearchResponse.getModel(), is(expectedBetaSearch));
verify(httpClient, times(1)).send(expectedHttpRequest, HttpResponse.BodyHandlers.ofString());
@Override verifyNoMoreInteractions(httpClient);
public HttpRequest request() { }
return null;
} @Test
void failToGetBestWaifusWhereDeserializationGoesWrong() throws IOException, InterruptedException {
@Override HttpRequest expectedHttpRequest = buildHttpGetRequest(apiKey, "airing/best");
public Optional<HttpResponse<String>> previousResponse() { int expectedStatusCode = 200;
return Optional.empty(); String expectedBody = getJsonAsString("getBestWaifus.json");
} String expectedData = getData(expectedBody);
HttpResponse<String> expectedHttpResponse = buildHttpResponse(expectedStatusCode, expectedBody);
@Override
public HttpHeaders headers() { JavaType expectedModel = listOf(FilteredWaifu.class);
return null; String customExceptionMessage = "If you are seeing this message, " +
} "this is more than likely a fault in my logic. " +
"Please raise an issue including the printed stacktrace :D";
@Override String exceptionMessage = "Uh Oh Somebody Did a No No!";
public String body() { String expectedExceptionMessage = "\n\n" + customExceptionMessage + "\n\n" + exceptionMessage;
return body;
} doReturn(expectedHttpResponse).when(httpClient).send(expectedHttpRequest, HttpResponse.BodyHandlers.ofString());
doThrow(new JsonProcessingException(exceptionMessage) {}).when(objectMapper).readValue(expectedData, expectedModel);
@Override
public Optional<SSLSession> sslSession() { Throwable actualException = assertThrows(APIMapperException.class, () -> sut.getBestWaifus());
return Optional.empty();
} assertThat(actualException.getMessage(), is(expectedExceptionMessage));
verify(httpClient, times(1)).send(expectedHttpRequest, HttpResponse.BodyHandlers.ofString());
@Override verifyNoMoreInteractions(httpClient);
public URI uri() { }
return null;
} private String getData(String jsonBody) throws JsonProcessingException {
JsonNode parent = objectMapper.readTree(jsonBody);
@Override return parent.get("data").toString();
public HttpClient.Version version() { }
return null;
} private HttpRequest buildHttpPostRequest(String apiKey, String param) {
}; return HttpRequest.newBuilder()
} .uri(URI.create("https://mywaifulist.moe/api/v1/" + param))
.timeout(Duration.ofSeconds(20))
.headers("Content-Type", "application/json", "apikey", apiKey)
.POST(HttpRequest.BodyPublishers.ofString(""))
.build();
}
private String getJsonAsString(String filename) {
InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(filename);
return new BufferedReader(new InputStreamReader(Objects.requireNonNull(resourceAsStream), StandardCharsets.UTF_8))
.lines()
.collect(Collectors.joining("\n"));
}
private HttpRequest buildHttpGetRequest(String apiKey, String param) {
return HttpRequest.newBuilder()
.uri(URI.create("https://mywaifulist.moe/api/v1/" + param))
.timeout(Duration.ofSeconds(20))
.headers("Content-Type", "application/json", "apikey", apiKey)
.GET()
.build();
}
private HttpResponse<String> buildHttpResponse(int statusCode, String body) {
return new HttpResponse<>() {
@Override
public int statusCode() {
return statusCode;
}
@Override
public HttpRequest request() {
return null;
}
@Override
public Optional<HttpResponse<String>> previousResponse() {
return Optional.empty();
}
@Override
public HttpHeaders headers() {
return null;
}
@Override
public String body() {
return body;
}
@Override
public Optional<SSLSession> sslSession() {
return Optional.empty();
}
@Override
public URI uri() {
return null;
}
@Override
public HttpClient.Version version() {
return null;
}
};
}
} }

@ -101,7 +101,8 @@ public class TestEntity {
"rika-furude-when-they-cry", "rika-furude-when-they-cry",
42, 42,
"Waifu", "Waifu",
"https://www.mywaifulist.moe/waifu/rika-furude-when-they-cry" "https://www.mywaifulist.moe/waifu/rika-furude-when-they-cry",
1
) )
); );
@ -125,7 +126,8 @@ public class TestEntity {
"shion-that-time-i-got-reincarnated-as-a-slime", "shion-that-time-i-got-reincarnated-as-a-slime",
70, 70,
"Waifu", "Waifu",
"https://www.mywaifulist.moe/waifu/shion-that-time-i-got-reincarnated-as-a-slime" "https://www.mywaifulist.moe/waifu/shion-that-time-i-got-reincarnated-as-a-slime",
1
) )
); );
@ -149,7 +151,8 @@ public class TestEntity {
"milim-nava-that-time-i-got-reincarnated-as-a-slime", "milim-nava-that-time-i-got-reincarnated-as-a-slime",
85, 85,
"Waifu", "Waifu",
"https://www.mywaifulist.moe/waifu/milim-nava-that-time-i-got-reincarnated-as-a-slime" "https://www.mywaifulist.moe/waifu/milim-nava-that-time-i-got-reincarnated-as-a-slime",
1
) )
); );
@ -173,7 +176,8 @@ public class TestEntity {
"shuna-that-time-i-got-reincarnated-as-a-slime", "shuna-that-time-i-got-reincarnated-as-a-slime",
78, 78,
"Waifu", "Waifu",
"https://www.mywaifulist.moe/waifu/shuna-that-time-i-got-reincarnated-as-a-slime" "https://www.mywaifulist.moe/waifu/shuna-that-time-i-got-reincarnated-as-a-slime",
1
) )
); );
@ -197,7 +201,8 @@ public class TestEntity {
"rimuru-tempest-that-time-i-got-reincarnated-as-a-slime", "rimuru-tempest-that-time-i-got-reincarnated-as-a-slime",
55, 55,
"Husbando", "Husbando",
"https://www.mywaifulist.moe/waifu/rimuru-tempest-that-time-i-got-reincarnated-as-a-slime" "https://www.mywaifulist.moe/waifu/rimuru-tempest-that-time-i-got-reincarnated-as-a-slime",
1
) )
); );
@ -220,7 +225,8 @@ public class TestEntity {
"shizue-izawa-that-time-i-got-reincarnated-as-a-slime", "shizue-izawa-that-time-i-got-reincarnated-as-a-slime",
81, 81,
"Waifu", "Waifu",
"https://www.mywaifulist.moe/waifu/shizue-izawa-that-time-i-got-reincarnated-as-a-slime" "https://www.mywaifulist.moe/waifu/shizue-izawa-that-time-i-got-reincarnated-as-a-slime",
1
) )
); );
@ -241,7 +247,8 @@ public class TestEntity {
"alina-gray", "alina-gray",
1, 1,
"Waifu", "Waifu",
"https://www.mywaifulist.moe/waifu/alina-gray" "https://www.mywaifulist.moe/waifu/alina-gray",
1
) )
); );
@ -261,7 +268,8 @@ public class TestEntity {
"jahy", "jahy",
4, 4,
"Waifu", "Waifu",
"https://www.mywaifulist.moe/waifu/jahy" "https://www.mywaifulist.moe/waifu/jahy",
1
) )
); );
@ -284,7 +292,8 @@ public class TestEntity {
"treyni-that-time-i-got-reincarnated-as-a-slime", "treyni-that-time-i-got-reincarnated-as-a-slime",
16, 16,
"Waifu", "Waifu",
"https://www.mywaifulist.moe/waifu/treyni-that-time-i-got-reincarnated-as-a-slime" "https://www.mywaifulist.moe/waifu/treyni-that-time-i-got-reincarnated-as-a-slime",
1
) )
); );
@ -304,7 +313,8 @@ public class TestEntity {
"satan-2", "satan-2",
0, 0,
"Husbando", "Husbando",
"https://www.mywaifulist.moe/waifu/satan-2" "https://www.mywaifulist.moe/waifu/satan-2",
1
) )
); );
@ -401,6 +411,59 @@ public class TestEntity {
return waifuImagesPaginationData; return waifuImagesPaginationData;
} }
public static List<FilteredWaifu> getBetaSearch() {
List<FilteredWaifu> betaSearchResults = new ArrayList<>();
List<FilteredSeries> appearances = new ArrayList<>();
appearances.add(createFullFilteredSeries(
"Unlike many schools, attending Hyakkaou Private Academy prepares students f...",
"https://thicc.mywaifulist.moe/series/1680/13c030778b8e7e44ddccb8ca999e18d6ea2b3d547eacc1f63bf5849ade858bb0.jpeg",
1680,
"Kakegurui: Compulsive Gambler",
"Kakegurui",
1,
null,
"kakegurui-compulsive-gambler",
"TV",
"https://www.mywaifulist.moe/series/kakegurui-compulsive-gambler"
));
betaSearchResults.add(createFilteredWaifu(
appearances,
"Yumeko Jabami is the main protagonist of Kakegurui. She's a transfer studen...",
"https://thicc.mywaifulist.moe/waifus/6167/7bf292a1552161de90ff7d0c1eab2c890b2aa374903773d38d39c6c6e8d6f3d2_thumb.jpeg",
6167.0,
1889,
"Yumeko Jabami",
"蛇喰夢子",
"Jabami Yumeko",
"Jabami Yumeko",
"yumeko-jabami-kakegurui-compulsive-gambler",
172,
"Waifu",
"https://www.mywaifulist.moe/waifu/yumeko-jabami-kakegurui-compulsive-gambler",
2
)
);
return betaSearchResults;
}
private static FilteredSeries createFullFilteredSeries(String description, String displayPicture, int id, String name, String originalName, int relevance, String romajiName, String slug, String type, String url) {
FilteredSeries filteredSeries = new FilteredSeries();
filteredSeries.setDescription(description);
filteredSeries.setDisplayPicture(displayPicture);
filteredSeries.setId(id);
filteredSeries.setName(name);
filteredSeries.setOriginalName(originalName);
filteredSeries.setRelevance(relevance);
filteredSeries.setRomajiName(romajiName);
filteredSeries.setSlug(slug);
filteredSeries.setType(type);
filteredSeries.setUrl(url);
return filteredSeries;
}
private static WaifuImage createWaifuImage(Integer id, String image, String nsfw, String thumbnail) { private static WaifuImage createWaifuImage(Integer id, String image, String nsfw, String thumbnail) {
WaifuImage waifuImage = new WaifuImage(); WaifuImage waifuImage = new WaifuImage();
waifuImage.setId(id); waifuImage.setId(id);
@ -411,8 +474,8 @@ public class TestEntity {
} }
private static FilteredWaifu createFilteredWaifu(List<FilteredSeries> appearances, String description, String displayPicture, private static FilteredWaifu createFilteredWaifu(List<FilteredSeries> appearances, String description, String displayPicture,
Double id, Integer likes, String name, String originalName, String romaji, Double id, Integer likes, String name, String originalName, String romaji,
String romaji_name, String slug, Integer trash, String type, String url) { String romaji_name, String slug, Integer trash, String type, String url, Integer relevance) {
FilteredWaifu filteredWaifu = new FilteredWaifu(); FilteredWaifu filteredWaifu = new FilteredWaifu();
filteredWaifu.setAppearances(appearances); filteredWaifu.setAppearances(appearances);
filteredWaifu.setDescription(description); filteredWaifu.setDescription(description);
@ -427,7 +490,7 @@ public class TestEntity {
filteredWaifu.setTrash(trash); filteredWaifu.setTrash(trash);
filteredWaifu.setType(type); filteredWaifu.setType(type);
filteredWaifu.setUrl(url); filteredWaifu.setUrl(url);
filteredWaifu.setRelevance(1); filteredWaifu.setRelevance(relevance);
return filteredWaifu; return filteredWaifu;
} }

@ -0,0 +1,34 @@
{
"data": [
{
"appearances": [
{
"description": "Unlike many schools, attending Hyakkaou Private Academy prepares students f...",
"display_picture": "https://thicc.mywaifulist.moe/series/1680/13c030778b8e7e44ddccb8ca999e18d6ea2b3d547eacc1f63bf5849ade858bb0.jpeg",
"id": 1680,
"name": "Kakegurui: Compulsive Gambler",
"original_name": "Kakegurui",
"relevance": 1,
"romaji_name": null,
"slug": "kakegurui-compulsive-gambler",
"type": "TV",
"url": "https://www.mywaifulist.moe/series/kakegurui-compulsive-gambler"
}
],
"description": "Yumeko Jabami is the main protagonist of Kakegurui. She's a transfer studen...",
"display_picture": "https://thicc.mywaifulist.moe/waifus/6167/7bf292a1552161de90ff7d0c1eab2c890b2aa374903773d38d39c6c6e8d6f3d2_thumb.jpeg",
"id": 6167,
"likes": 1889,
"name": "Yumeko Jabami",
"original_name": "蛇喰夢子",
"relevance": 2,
"romaji": "Jabami Yumeko",
"romaji_name": "Jabami Yumeko",
"series": null,
"slug": "yumeko-jabami-kakegurui-compulsive-gambler",
"trash": 172,
"type": "Waifu",
"url": "https://www.mywaifulist.moe/waifu/yumeko-jabami-kakegurui-compulsive-gambler"
}
]
}
Loading…
Cancel
Save