diff --git a/src/api/http-error.test.ts b/src/api/http-error.test.ts index 190dd6c..b693de9 100644 --- a/src/api/http-error.test.ts +++ b/src/api/http-error.test.ts @@ -1,8 +1,58 @@ import { HttpError } from '~/api/http-error' import { useMockedUrlFetchApp } from '~/api/test-helper' -test('HttpError', () => { - const res = useMockedUrlFetchApp(403, '{"message": "Forbidden"}')() - const error = new HttpError('https://example.com', res) - expect(error instanceof HttpError).toBeTruthy() +describe('HttpError', () => { + test('#isInvalidTestingRequest', () => { + const res = useMockedUrlFetchApp(400, '{"message":"Testing apikey is not allowed"}')() + const error = new HttpError('https://example.com', res) + expect(error.isInvalidTestingRequest()).toBeTruthy() + }) + + test('#isInvalidTokenRequest (true)', () => { + const res = useMockedUrlFetchApp(403, '{"message":"Forbidden"}')() + const error = new HttpError('https://example.com', res) + expect(error.isInvalidTokenRequest()).toBeTruthy() + }) + + test('#isInvalidTokenRequest (false)', () => { + const res = useMockedUrlFetchApp(403, '{"message":"Some message"}')() + const error = new HttpError('https://example.com', res) + expect(error.isInvalidTokenRequest()).toBeFalsy() + }) + + test('#isMonthlyLimitExceeded (true)', () => { + const res = useMockedUrlFetchApp(403, '{"message":"Some message"}')() + const error = new HttpError('https://example.com', res) + expect(error.isMonthlyLimitExceeded()).toBeTruthy() + }) + + test('#isMonthlyLimitExceeded (false)', () => { + const res = useMockedUrlFetchApp(403, '{"message":"Forbidden"}')() + const error = new HttpError('https://example.com', res) + expect(error.isMonthlyLimitExceeded()).toBeFalsy() + }) + + test('#isApiQuotaExceeded', () => { + const res = useMockedUrlFetchApp(404, '{"message":"Not found"}')() + const error = new HttpError('https://example.com', res) + expect(error.isResourceNotFound()).toBeTruthy() + }) + + test('#isApiQuotaExceeded', () => { + const res = useMockedUrlFetchApp(429, '{"message":"Rate Limitted"}')() + const error = new HttpError('https://example.com', res) + expect(error.isApiQuotaExceeded()).toBeTruthy() + }) + + test('#is4xxError', () => { + const res = useMockedUrlFetchApp(403, '{"message":"Forbidden"}')() + const error = new HttpError('https://example.com', res) + expect(error.is4xxError()).toBeTruthy() + }) + + test('#is5xxError', () => { + const res = useMockedUrlFetchApp(500, '{"message":"Internal server error"}')() + const error = new HttpError('https://example.com', res) + expect(error.is5xxError()).toBeTruthy() + }) }) diff --git a/src/api/http-error.ts b/src/api/http-error.ts index 96c4c7c..ec2661f 100644 --- a/src/api/http-error.ts +++ b/src/api/http-error.ts @@ -12,19 +12,19 @@ export class HttpError implements Error { public isInvalidTestingRequest(): boolean { const content = this.response.getContentText() return ( - content === '{"message":"Testing Apikey is only allowed to ticker ending with \\"01\\""}' || - content === '{"message":"Testing apikey is not allowed"}' || - content === '{"message":"Trial request only supports ticker ending \'01\'"}' + this.response.getResponseCode() === 400 && + (content === '{"message":"Testing Apikey is only allowed to ticker ending with \\"01\\""}' || + content === '{"message":"Testing apikey is not allowed"}' || + content === '{"message":"Trial request only supports ticker ending \'01\'"}') ) } public isInvalidTokenRequest(): boolean { - const content = this.response.getContentText() - return content === '{"message":"Forbidden"}' + return this.response.getResponseCode() === 403 && this.response.getContentText() === '{"message":"Forbidden"}' } public isMonthlyLimitExceeded(): boolean { - return !this.isInvalidTokenRequest() && this.response.getResponseCode() === 403 + return this.response.getResponseCode() === 403 && !this.isInvalidTokenRequest() } public isResourceNotFound(): boolean { @@ -35,10 +35,14 @@ export class HttpError implements Error { return this.response.getResponseCode() === 429 } - public isBadRequest(): boolean { + public is4xxError(): boolean { return Math.floor(this.response.getResponseCode() / 100) === 4 } + public is5xxError(): boolean { + return Math.floor(this.response.getResponseCode() / 100) === 5 + } + public toString(): string { return this.message } diff --git a/src/api/v3/client.test.ts b/src/api/v3/client.test.ts index d1398b2..20ab39f 100644 --- a/src/api/v3/client.test.ts +++ b/src/api/v3/client.test.ts @@ -15,16 +15,6 @@ import { YearQuarterParam } from '~/fiscal-periods/year-quarter-param' import { YearQuarterRange } from '~/fiscal-periods/year-quarter-range' describe('BuffettCodeApiClientV3', () => { - test('HttpError#isInvalidTestingRequest', () => { - const res1 = useMockedUrlFetchApp(200, '{"message":"Testing apikey is not allowed"}')() - const error1 = new HttpError('https://example.com', res1) - expect(error1.isInvalidTestingRequest()).toBeTruthy() - - const res2 = useMockedUrlFetchApp(403, '{"message": "Forbidden"}')() - const error2 = new HttpError('https://example.com', res2) - expect(error2.isInvalidTestingRequest()).toBeFalsy() - }) - test('request', () => { const mockFetch = useMockedUrlFetchApp(200, '{"message": "this is a message"}') @@ -45,7 +35,7 @@ describe('BuffettCodeApiClientV3', () => { }) test('request when testing apikey error', () => { - useMockedUrlFetchApp(200, '{"message":"Testing Apikey is only allowed to ticker ending with \\"01\\""}') + useMockedUrlFetchApp(400, '{"message":"Testing Apikey is only allowed to ticker ending with \\"01\\""}') const request = BuffettCodeApiClientV3['request'] expect(() => request('http://example.com')).toThrow(HttpError) diff --git a/src/api/v3/client.ts b/src/api/v3/client.ts index 2cee063..c4450c0 100644 --- a/src/api/v3/client.ts +++ b/src/api/v3/client.ts @@ -19,13 +19,13 @@ export class BuffettCodeApiClientV3 { const fullOptions = { ...defaultOptions, ...options } const res = UrlFetchApp.fetch(url, fullOptions) - const code = res.getResponseCode() - const content = res.getContentText() const error = new HttpError(url, res) - if (Math.floor(code / 100) === 4 || Math.floor(code / 100) === 5 || error.isInvalidTestingRequest()) { + if (error.is4xxError() || error.is5xxError()) { throw error } + const content = res.getContentText() + const code = res.getResponseCode() let json try { json = JSON.parse(content) diff --git a/src/services/error-handler.ts b/src/services/error-handler.ts index 952b9d4..c1d5d68 100644 --- a/src/services/error-handler.ts +++ b/src/services/error-handler.ts @@ -37,7 +37,7 @@ export class ErrorHandler { throw new Error('<<データが見つかりません。tickerや期間に間違いがないかご確認ください>>') } else if (e.isApiQuotaExceeded()) { throw new Error('<>') - } else if (e.isBadRequest()) { + } else if (e.is4xxError()) { throw new Error(`<<無効なリクエストです (${e.name}: ${e.message})>>`) } else { console.error('システムエラー', e.name, e.message)