From 2631f8e0af341aeaa1225c58f20ccf2f4ae8bac1 Mon Sep 17 00:00:00 2001 From: queicherius Date: Sun, 28 Jan 2024 18:04:40 +0000 Subject: [PATCH] Fix caching id for /v2/characters --- src/endpoint.js | 11 +-- src/endpoints/characters.js | 1 + tests/endpoint.spec.js | 123 +++++++++++++++++++++++++++++ tests/endpoints/characters.spec.js | 1 + 4 files changed, 131 insertions(+), 5 deletions(-) diff --git a/src/endpoint.js b/src/endpoint.js index 27cfbf30..a587838c 100644 --- a/src/endpoint.js +++ b/src/endpoint.js @@ -19,6 +19,7 @@ module.exports = class AbstractEndpoint { this.isPaginated = false this.maxPageSize = 200 this.isBulk = false + this.bulkId = 'id' this.supportsBulkAll = true this.isLocalized = false this.isAuthenticated = false @@ -202,7 +203,7 @@ module.exports = class AbstractEndpoint { this.debugMessage(`many(${this.url}) resolving partially from cache (${cached.length} ids)`) const missingIds = getMissingIds(ids, cached) return this._many(missingIds, cached.length > 0).then(content => { - const cacheContent = content.map(value => [this._cacheHash(value.id), value]) + const cacheContent = content.map(value => [this._cacheHash(value[this.bulkId]), value]) this._cacheSetMany(cacheContent) // Merge the new content with the cached content and guarantee element order @@ -215,7 +216,7 @@ module.exports = class AbstractEndpoint { const getMissingIds = (ids, cached) => { const cachedIds = {} cached.map(x => { - cachedIds[x.id] = 1 + cachedIds[x[this.bulkId]] = 1 }) return ids.filter(x => cachedIds[x] !== 1) @@ -288,7 +289,7 @@ module.exports = class AbstractEndpoint { let cacheContent = [[hash, content]] if (this.isBulk) { - cacheContent = cacheContent.concat(content.map(value => [this._cacheHash(value.id), value])) + cacheContent = cacheContent.concat(content.map(value => [this._cacheHash(value[this.bulkId]), value])) } this._cacheSetMany(cacheContent) @@ -335,7 +336,7 @@ module.exports = class AbstractEndpoint { let cacheContent = [[hash, content]] if (this.isBulk) { - cacheContent = cacheContent.concat(content.map(value => [this._cacheHash(value.id), value])) + cacheContent = cacheContent.concat(content.map(value => [this._cacheHash(value[this.bulkId]), value])) } this._cacheSetMany(cacheContent) @@ -521,7 +522,7 @@ module.exports = class AbstractEndpoint { }) // Sort by the indexes - entries.sort((a, b) => indexMap[a.id] - indexMap[b.id]) + entries.sort((a, b) => indexMap[a[this.bulkId]] - indexMap[b[this.bulkId]]) return entries } diff --git a/src/endpoints/characters.js b/src/endpoints/characters.js index 8d9d2411..5672798f 100644 --- a/src/endpoints/characters.js +++ b/src/endpoints/characters.js @@ -7,6 +7,7 @@ module.exports = class CharactersEndpoint extends AbstractEndpoint { this.url = '/v2/characters' this.isPaginated = true this.isBulk = true + this.bulkId = 'name' this.supportsBulkAll = false this.isAuthenticated = true this.cacheTime = 5 * 60 diff --git a/tests/endpoint.spec.js b/tests/endpoint.spec.js index 372e6087..d49bad8d 100644 --- a/tests/endpoint.spec.js +++ b/tests/endpoint.spec.js @@ -312,6 +312,34 @@ describe('abstract endpoint', () => { expect(bulkEntriesInCache).toEqual(content) }) + it('caching with custom bulk id', async () => { + let content = [ + { name: 1, profession: 'foo' }, + { name: 2, profession: 'bar' }, + { name: 3, profession: 'fooo' } + ] + endpoint.isBulk = true + endpoint.bulkId = 'name' + endpoint.url = '/v2/test' + endpoint.cacheTime = 60 + fetchMock.addResponse(content) + + let entry = await endpoint.many([1, 2, 3]) + await wait(50) + let entryShouldCache = await endpoint.many([2, 3, 2]) + let bulkEntriesInCache = await endpoint._cacheGetMany([ + 'hash[https://api.guildwars2.com/v2/test:schema]:1', + 'hash[https://api.guildwars2.com/v2/test:schema]:2', + 'hash[https://api.guildwars2.com/v2/test:schema]:3' + ]) + + expect(fetchMock.lastUrl()).toEqual('https://api.guildwars2.com/v2/test?v=schema&ids=1,2,3') + expect(fetchMock.urls().length).toEqual(1) + expect(entry).toEqual(content) + expect(entryShouldCache).toEqual(content.slice(1)) + expect(bulkEntriesInCache).toEqual(content) + }) + it('partial caching', async () => { let content = [ { id: 1, name: 'foo' }, @@ -345,6 +373,40 @@ describe('abstract endpoint', () => { expect(bulkEntriesInCache).toEqual(content) }) + it('partial caching with custom bulk id', async () => { + let content = [ + { name: 1, profession: 'foo' }, + { name: 2, profession: 'bar' }, + { name: 3, profession: 'fooo' }, + { name: 4, profession: 'xd' } + ] + endpoint.isBulk = true + endpoint.bulkId = 'name' + endpoint.url = '/v2/test' + endpoint.cacheTime = 60 + fetchMock.addResponse(content.slice(1, 3)) + fetchMock.addResponse(content.slice(0, 1).concat(content.slice(3, 4))) + + let entry = await endpoint.many([2, 3]) + await wait(50) + let entryShouldCache = await endpoint.many([1, 2, 3, 4]) + await wait(50) + let bulkEntriesInCache = await endpoint._cacheGetMany([ + 'hash[https://api.guildwars2.com/v2/test:schema]:1', + 'hash[https://api.guildwars2.com/v2/test:schema]:2', + 'hash[https://api.guildwars2.com/v2/test:schema]:3', + 'hash[https://api.guildwars2.com/v2/test:schema]:4' + ]) + + expect(fetchMock.urls()).toEqual([ + 'https://api.guildwars2.com/v2/test?v=schema&ids=2,3', + 'https://api.guildwars2.com/v2/test?v=schema&ids=1,4' + ]) + expect(entry).toEqual(content.slice(1, 3)) + expect(entryShouldCache).toEqual(content) + expect(bulkEntriesInCache).toEqual(content) + }) + it('cant mutate cache data', async () => { endpoint.isBulk = true endpoint.url = '/v2/test' @@ -513,6 +575,37 @@ describe('abstract endpoint', () => { expect(bulkEntriesInCache).toEqual(content) }) + it('caching for bulk endpoints with custom bulk id', async () => { + let content = [ + { name: 1, profession: 'foo' }, + { name: 2, profession: 'bar' }, + { name: 3, profession: 'fooo' } + ] + endpoint.isPaginated = true + endpoint.isBulk = true + endpoint.bulkId = 'name' + endpoint.url = '/v2/test' + endpoint.cacheTime = 60 + fetchMock.addResponse(content) + + let entry = await endpoint.page(0, 3) + await wait(50) + let entryShouldCache = await endpoint.page(0, 3) + let entryInCache = await endpoint._cacheGetSingle('hash[https://api.guildwars2.com/v2/test:schema]:page-0/3') + let bulkEntriesInCache = await endpoint._cacheGetMany([ + 'hash[https://api.guildwars2.com/v2/test:schema]:1', + 'hash[https://api.guildwars2.com/v2/test:schema]:2', + 'hash[https://api.guildwars2.com/v2/test:schema]:3' + ]) + + expect(fetchMock.lastUrl()).toEqual('https://api.guildwars2.com/v2/test?v=schema&page=0&page_size=3') + expect(fetchMock.urls().length).toEqual(1) + expect(entry).toEqual(content) + expect(entryShouldCache).toEqual(content) + expect(entryInCache).toEqual(content) + expect(bulkEntriesInCache).toEqual(content) + }) + it('cant mutate cache data', async () => { endpoint.isPaginated = true endpoint.url = '/v2/test' @@ -714,6 +807,36 @@ describe('abstract endpoint', () => { expect(cacheEntries).toEqual(content) }) + it('caching for bulk endpoints with custom bulk id', async () => { + let content = [ + { name: 1, profession: 'foo' }, + { name: 2, profession: 'bar' }, + { name: 3, profession: 'fooo' } + ] + endpoint.isBulk = true + endpoint.bulkId = 'name' + endpoint.url = '/v2/test' + endpoint.cacheTime = 60 + fetchMock.addResponse(content) + + let entry = await endpoint.all() + await wait(50) + let entryShouldCache = await endpoint.all() + let entryInCache = await endpoint._cacheGetSingle('hash[https://api.guildwars2.com/v2/test:schema]:all') + let cacheEntries = await endpoint._cacheGetMany([ + 'hash[https://api.guildwars2.com/v2/test:schema]:1', + 'hash[https://api.guildwars2.com/v2/test:schema]:2', + 'hash[https://api.guildwars2.com/v2/test:schema]:3' + ]) + + expect(fetchMock.lastUrl()).toEqual('https://api.guildwars2.com/v2/test?v=schema&ids=all') + expect(fetchMock.urls().length).toEqual(1) + expect(entry).toEqual(content) + expect(entryShouldCache).toEqual(content) + expect(entryInCache).toEqual(content) + expect(cacheEntries).toEqual(content) + }) + it('cant mutate cache data', async () => { endpoint.isPaginated = true endpoint.url = '/v2/test' diff --git a/tests/endpoints/characters.spec.js b/tests/endpoints/characters.spec.js index e306cf98..9e496e9f 100644 --- a/tests/endpoints/characters.spec.js +++ b/tests/endpoints/characters.spec.js @@ -12,6 +12,7 @@ describe('endpoints > characters', () => { it('test /v2/characters', async () => { expect(endpoint.isPaginated).toEqual(true) expect(endpoint.isBulk).toEqual(true) + expect(endpoint.bulkId).toEqual('name') expect(endpoint.supportsBulkAll).toEqual(false) expect(endpoint.isLocalized).toEqual(false) expect(endpoint.isAuthenticated).toEqual(true)