Skip to content

Commit

Permalink
Merge pull request #42 from LearningProcesss/36-exception-thrown-when…
Browse files Browse the repository at this point in the history
…-accessing-a-game-without-versions

fix: handle empty xml tag
  • Loading branch information
LearningProcesss authored Jan 23, 2023
2 parents 6378aeb + 5b46155 commit 842e0ea
Show file tree
Hide file tree
Showing 13 changed files with 164 additions and 25 deletions.
5 changes: 5 additions & 0 deletions rest.http
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

GET https://www.boardgamegeek.com/xmlapi2/thing?id=174430&comments=1&marketplace=1&pagesize=10&ratingcomments=1&stats=1&videos=1&type=boardgame&versions=1


###

GET https://www.boardgamegeek.com/xmlapi2/thing?id=21659&versions=1

### family with all options

GET https://www.boardgamegeek.com/xmlapi2/family?id=8374&type=boardgamefamily
Expand Down
2 changes: 1 addition & 1 deletion src/dto/concrete/BggForumDto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export class BggForumDto implements IBggDto {
@JsonAlias({ values: ["threads"] })
@JsonDeserialize({
//eslint-disable-next-line @typescript-eslint/no-explicit-any
using: (items: any[]) => items[0].thread
using: (items: any[]) => items[0]?.thread
})
threads!: BggForumThreadDto[];

Expand Down
6 changes: 3 additions & 3 deletions src/dto/concrete/BggThingDto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export class BggThingDto implements IBggDto {
@JsonManagedReference()
@JsonDeserialize({
//eslint-disable-next-line @typescript-eslint/no-explicit-any
using: (items: any[]) => items[0].listing
using: (items: any[]) => items[0]?.listing
})
marketplacelistings!: BggThingMarketlistingsDto[];

Expand All @@ -137,7 +137,7 @@ export class BggThingDto implements IBggDto {
@JsonManagedReference()
@JsonDeserialize({
//eslint-disable-next-line @typescript-eslint/no-explicit-any
using: (items: any[]) => items[0].item
using: (items: any[]) => items[0]?.item
})
versions: BggThingVersionDto[];
versions!: BggThingVersionDto[];
}
2 changes: 1 addition & 1 deletion src/dto/concrete/BggThreadDto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class BggThreadDto implements IBggDto {
@JsonAlias({ values: ["articles"] })
@JsonDeserialize({
//eslint-disable-next-line @typescript-eslint/no-explicit-any
using: (items: any[]) => items[0].article
using: (items: any[]) => items[0]?.article
})
articles?: BggArticleDto[];
}
2 changes: 1 addition & 1 deletion src/dto/concrete/paginated/BggStatisticsRatingDto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export class BggStatisticsRatingDto {
@JsonClassType({ type: () => [Array, [BggStatisticsRatingRanksDto]] })
@JsonDeserialize({
//eslint-disable-next-line @typescript-eslint/no-explicit-any
using: (items: any[]) => items[0].rank
using: (items: any[]) => items[0]?.rank
})
ranks!: BggStatisticsRatingRanksDto[];
}
2 changes: 1 addition & 1 deletion src/dto/concrete/subdto/BggPlaySubDtos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export class BggPlaysPlayDto {
@JsonManagedReference()
@JsonDeserialize({
//eslint-disable-next-line @typescript-eslint/no-explicit-any
using: (items: any[]) => items[0].player
using: (items: any[]) => items[0]?.player
})
players!: BggPlaysPlayPlayerDto[];
}
2 changes: 1 addition & 1 deletion src/dto/concrete/subdto/BggPlaysPlayItemDto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export class BggPlaysPlayItemDto {
@JsonClassType({ type: () => [Array, [BggPlaysPlayItemSubtypes]] })
@JsonDeserialize({
//eslint-disable-next-line @typescript-eslint/no-explicit-any
using: (items: any[]) => items[0].subtype
using: (items: any[]) => items[0]?.subtype
})
@JsonManagedReference()
subtypes!: BggPlaysPlayItemSubtypes[];
Expand Down
103 changes: 103 additions & 0 deletions test/unit/__fixtures__/response_thing_no_versions.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?xml version="1.0" encoding="utf-8"?>
<items termsofuse="https://boardgamegeek.com/xmlapi/termsofuse">
<item type="boardgameexpansion" id="21659">
<thumbnail>https://cf.geekdo-images.com/89tpRJBBv1L9wMPBL3jpqQ__thumb/img/q8A_0RkeRt7wu_puxFPMdRbktng=/fit-in/200x150/filters:strip_icc()/pic109518.jpg</thumbnail>
<image>https://cf.geekdo-images.com/89tpRJBBv1L9wMPBL3jpqQ__original/img/uVUBNzXKSS2JCao5MLaBSyYOVYg=/0x0/filters:format(jpeg)/pic109518.jpg</image>
<name type="primary" sortindex="1" value="Beyond Boardwalk and Park Place (fan expansion for Monopoly)" />
<description>Beyond Boardwalk and Park Place is an unauthorized variant of Monopoly. Published in the form of a trade paperback, it is designed to address what its authors describe as three problems with the game:&amp;#10;&amp;#10; It takes too long.&amp;#10; There's too much luck.&amp;#10; There's too much dead time.&amp;#10;&amp;#10;&amp;#10;They go about this by making eleven changes to the rules of the game. The boldest of these are that the price to purchase a property landed on is doubled, and that a property may not be mortgaged but can instead be sold back to the bank for its &amp;quot;mortgage value.&amp;quot; The game is changed immensely - it is no longer advisable (or even possible) for a player to buy outright every property landed on, and properties frequently go up for public or private auction.&amp;#10;&amp;#10;In effect, this variant forces the players to make more difficult decisions, reducing the game's luck factor in favor of more emphasis on bidding and negotiation.&amp;#10;&amp;#10;Expands:&amp;#10;&amp;#10; Monopoly&amp;#10;&amp;#10;&amp;#10;</description>
<yearpublished value="1986" />
<minplayers value="2" />
<maxplayers value="8" />
<poll name="suggested_numplayers" title="User Suggested Number of Players" totalvotes="1">
<results numplayers="1">
<result value="Best" numvotes="0" />
<result value="Recommended" numvotes="0" />
<result value="Not Recommended" numvotes="0" />
</results>
<results numplayers="2">
<result value="Best" numvotes="0" />
<result value="Recommended" numvotes="1" />
<result value="Not Recommended" numvotes="0" />
</results>
<results numplayers="3">
<result value="Best" numvotes="0" />
<result value="Recommended" numvotes="1" />
<result value="Not Recommended" numvotes="0" />
</results>
<results numplayers="4">
<result value="Best" numvotes="0" />
<result value="Recommended" numvotes="1" />
<result value="Not Recommended" numvotes="0" />
</results>
<results numplayers="5">
<result value="Best" numvotes="0" />
<result value="Recommended" numvotes="0" />
<result value="Not Recommended" numvotes="0" />
</results>
<results numplayers="6">
<result value="Best" numvotes="0" />
<result value="Recommended" numvotes="0" />
<result value="Not Recommended" numvotes="0" />
</results>
<results numplayers="7">
<result value="Best" numvotes="0" />
<result value="Recommended" numvotes="0" />
<result value="Not Recommended" numvotes="0" />
</results>
<results numplayers="8">
<result value="Best" numvotes="0" />
<result value="Recommended" numvotes="0" />
<result value="Not Recommended" numvotes="0" />
</results>
<results numplayers="8+">
<result value="Best" numvotes="0" />
<result value="Recommended" numvotes="0" />
<result value="Not Recommended" numvotes="0" />
</results>
</poll>
<playingtime value="90" />
<minplaytime value="90" />
<maxplaytime value="90" />
<minage value="8" />
<poll name="suggested_playerage" title="User Suggested Player Age" totalvotes="0">
<results>
<result value="2" numvotes="0" />
<result value="3" numvotes="0" />
<result value="4" numvotes="0" />
<result value="5" numvotes="0" />
<result value="6" numvotes="0" />
<result value="8" numvotes="0" />
<result value="10" numvotes="0" />
<result value="12" numvotes="0" />
<result value="14" numvotes="0" />
<result value="16" numvotes="0" />
<result value="18" numvotes="0" />
<result value="21 and up" numvotes="0" />
</results>
</poll>
<poll name="language_dependence" title="Language Dependence" totalvotes="1">
<results>
<result level="1" value="No necessary in-game text" numvotes="0" />
<result level="2" value="Some necessary text - easily memorized or small crib sheet" numvotes="0" />
<result level="3" value="Moderate in-game text - needs crib sheet or paste ups" numvotes="1" />
<result level="4" value="Extensive use of text - massive conversion needed to be playable" numvotes="0" />
<result level="5" value="Unplayable in another language" numvotes="0" />
</results>
</poll>
<link type="boardgamecategory" id="1021" value="Economic" />
<link type="boardgamecategory" id="1042" value="Expansion for Base-game" />
<link type="boardgamecategory" id="2687" value="Fan Expansion" />
<link type="boardgamecategory" id="1026" value="Negotiation" />
<link type="boardgamemechanic" id="2012" value="Auction/Bidding" />
<link type="boardgamemechanic" id="2072" value="Dice Rolling" />
<link type="boardgamemechanic" id="2035" value="Roll / Spin and Move" />
<link type="boardgamemechanic" id="2004" value="Set Collection" />
<link type="boardgamemechanic" id="2008" value="Trading" />
<link type="boardgamefamily" id="100" value="Series: Monopoly-Like" />
<link type="boardgameexpansion" id="1406" value="Monopoly" inbound="true"/>
<link type="boardgamedesigner" id="6536" value="Noel Gunther" />
<link type="boardgamedesigner" id="6537" value="Richard Hutton" />
<link type="boardgamepublisher" id="5008" value="Bantam Books" />
<versions></versions>
</item>
</items>
31 changes: 18 additions & 13 deletions test/unit/client/IBggThingClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,23 @@ describe('IBggThingClient', () => {

bggThingDtoParserMock.prototype.jsonToDto.mockResolvedValue([]);

test('should call dependency one times each', async () => {
textFetcherMock.prototype.doFetch.mockImplementation((query) => {
return new Promise((resolve) => {
resolve(TextResponseByEndpoint[query]);
});
})
// test('should call dependency one times each', async () => {
// textFetcherMock.prototype.doFetch.mockImplementation((query) => {
// return new Promise((resolve) => {
// resolve(TextResponseByEndpoint[query]);
// });
// })

xmlResponseParserMock.prototype.parseResponse.mockResolvedValue({})
// xmlResponseParserMock.prototype.parseResponse.mockResolvedValue({})

bggThingDtoParserMock.prototype.jsonToDto.mockResolvedValue([])
// bggThingDtoParserMock.prototype.jsonToDto.mockResolvedValue([])

const data = await thingClient.query({ id: 174430 });
// const data = await thingClient.query({ id: 174430 });

expect(textFetcherMock.prototype.doFetch).toHaveBeenCalledTimes(1);
expect(xmlResponseParserMock.prototype.parseResponse).toHaveBeenCalledTimes(1);
expect(bggThingDtoParserMock.prototype.jsonToDto).toHaveBeenCalledTimes(1);
});
// expect(textFetcherMock.prototype.doFetch).toHaveBeenCalledTimes(1);
// expect(xmlResponseParserMock.prototype.parseResponse).toHaveBeenCalledTimes(1);
// expect(bggThingDtoParserMock.prototype.jsonToDto).toHaveBeenCalledTimes(1);
// });
test('should report progress one time with main progressHandler', async () => {
let count = 0;

Expand Down Expand Up @@ -109,6 +109,11 @@ describe('IBggThingClient', () => {
data: expect.any(Array)
});
});
// test('should not throw error', async () => {
// const dtoList = await thingClient.query({ id: 21659, versions: 1 });

// expect(dtoList?.length).toBe(1);
// });
// test('should invoke paginator when request ids is long', async () => {
// const thingClient: IBggThingClient = new BggThingClient(new GenericQueryBuilder<IThingRequest>(),
// textFetcherMock.prototype,
Expand Down
17 changes: 16 additions & 1 deletion test/unit/dtoparser/BggDtoParser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,21 @@ describe('BggDtoParsers', () => {

const validationResult = ValidatorTraverse(dto, reflectionProperties, reflectionPropertiesExcludable)

expect(validationResult).not.toStrictEqual([])
});
it('should parse json with empty property tag', async () => {
const xmlResponse: string = TextResponseByEndpoint['https://www.boardgamegeek.com/xmlapi2/thing?id=21659&versions=1'];

const jsonData = await xmlToJsonParser.parseResponse(xmlResponse);

const dtoParser: BggThingDtoParser = new BggThingDtoParser();

const dtoList: BggThingDto[] = await dtoParser.jsonToDto(jsonData);

const dto: BggThingDto = dtoList[0];

const validationResult = ValidatorTraverse(dto, reflectionProperties, reflectionPropertiesExcludable)

expect(validationResult).not.toStrictEqual([])
});
});
Expand Down Expand Up @@ -171,7 +186,7 @@ describe('BggDtoParsers', () => {
const dtoList = await dtoParser.jsonToDto(jsonData);

const dto: BggPlayDto = dtoList[0]

const validationResult = ValidatorTraverse(dto, reflectionProperties, reflectionPropertiesExcludable)

expect(validationResult).toStrictEqual([])
Expand Down
12 changes: 11 additions & 1 deletion test/unit/parser/BggParsers.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { parse } from "fast-xml-parser";
import { XmlResponseParser } from "../../../src/responseparser";
import { TextResponseByEndpoint, WriteXmlParseByEndpoint } from "../utils";

Expand All @@ -9,7 +10,7 @@ describe('XmlResponseParser', () => {
const parser: XmlResponseParser = new XmlResponseParser();

const parsed = await parser.parseResponse(xmlResponse);

expect(parsed).not.toBeNaN();
});
it('should parse family xml to json when xml response is correctly formatted', async () => {
Expand Down Expand Up @@ -50,6 +51,15 @@ describe('XmlResponseParser', () => {

const parsed = await parser.parseResponse(xmlResponse);

expect(parsed).not.toBeNaN();
});
it('test', async () => {
const xmlResponse: string = TextResponseByEndpoint['https://www.boardgamegeek.com/xmlapi2/thing?id=21659&versions=1'];

const parser: XmlResponseParser = new XmlResponseParser();

const parsed = await parser.parseResponse(xmlResponse);

expect(parsed).not.toBeNaN();
});
});
3 changes: 2 additions & 1 deletion test/unit/utils/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ export const TextResponseByEndpoint: Record<string, string> =
"https://www.boardgamegeek.com/xmlapi2/thing?id=35424,35421,234669,328182,322903&type=boardgame&versions=1&comments=1&ratingcomments=1&marketplace=1&stats=1&videos=1&page=1": fs.readFileSync(path.join(__dirname, '..', '__fixtures__/response_thing_multipleids.xml'), 'utf-8'),
"https://www.boardgamegeek.com/xmlapi2/family?id=8374": fs.readFileSync(path.join(__dirname, '..', '__fixtures__/response_family_8374.xml'), 'utf-8'),
'https://www.boardgamegeek.com/xmlapi2/search?query=gloom': fs.readFileSync(path.join(__dirname, '..', '__fixtures__/response_search_gloom.xml'), 'utf-8'),
'https://www.boardgamegeek.com/xmlapi2/hot?type=boardgame': fs.readFileSync(path.join(__dirname, '..', '__fixtures__/response_hotitems_boardgame.xml'), 'utf-8')
'https://www.boardgamegeek.com/xmlapi2/hot?type=boardgame': fs.readFileSync(path.join(__dirname, '..', '__fixtures__/response_hotitems_boardgame.xml'), 'utf-8'),
'https://www.boardgamegeek.com/xmlapi2/thing?id=21659&versions=1': fs.readFileSync(path.join(__dirname, '..', '__fixtures__/response_thing_no_versions.xml'), 'utf-8')
}

export const WriteXmlParseByEndpoint = (outputName: string, contentData: string, overwrite: boolean = false) => {
Expand Down
Loading

0 comments on commit 842e0ea

Please sign in to comment.