Skip to content

Commit 58bee40

Browse files
committed
feat(currency): map directive args to a currency enum
1 parent b8806d0 commit 58bee40

File tree

3 files changed

+214
-2
lines changed

3 files changed

+214
-2
lines changed

src/directives/currency.ts

+21-1
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,35 @@
11
import { fetchDirective } from '@src/utils'
22
import { MapperKind, mapSchema } from '@graphql-tools/utils'
33
import { GraphQLError, GraphQLSchema, defaultFieldResolver } from 'graphql'
4+
import { CurrencyCode } from '@src/types'
45
import * as cheerio from 'cheerio'
56

67
type CurrencyDirectiveArgs = {
78
from: string
89
to: string
910
}
1011

12+
const generateGraphQLEnum = (origin: Record<string, string>) => {
13+
const formattedCodes = Object.keys(origin).map((code) => {
14+
return `${code} \n`
15+
}).join('')
16+
const result = `enum CurrencyCode {\n${formattedCodes} }`
17+
return result
18+
}
19+
20+
const validateCodes = (...codes: string[]) => {
21+
const validCodes = Object.keys(CurrencyCode)
22+
const invalidCodes = codes.filter(code => !validCodes.includes(code))
23+
if (invalidCodes.length > 0) {
24+
throw new GraphQLError(`Currency codes: ${invalidCodes} are not valid!`)
25+
}
26+
}
27+
1128
const currencyDirective = (directiveName: string = 'currency') => {
1229
return {
13-
currencyDirectiveTypeDefs: `directive @${directiveName}(from: String!, to: String!) on FIELD_DEFINITION`,
30+
currencyDirectiveTypeDefs: `directive @${directiveName} (from: String!, to: String!) on FIELD_DEFINITION
31+
${generateGraphQLEnum(CurrencyCode)}
32+
`,
1433
currencyDirectiveTransformer: (schema: GraphQLSchema) => mapSchema(schema, {
1534
[MapperKind.OBJECT_FIELD]: (fieldConfig) => {
1635
const currencyDirective = fetchDirective<CurrencyDirectiveArgs>(schema, fieldConfig, directiveName)
@@ -20,6 +39,7 @@ const currencyDirective = (directiveName: string = 'currency') => {
2039
return {
2140
...fieldConfig,
2241
resolve: async (source, args, context, info) => {
42+
validateCodes(from, to)
2343
const { fieldName, returnType } = info
2444
const type = returnType.toString()
2545
if (type !== 'String') {

src/types.ts

+160
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
export enum CurrencyCode {
2+
AED = 'AED',
3+
AFN = 'AFN',
4+
ALL = 'ALL',
5+
AMD = 'AMD',
6+
ANG = 'ANG',
7+
AOA = 'AOA',
8+
ARS = 'ARS',
9+
AUD = 'AUD',
10+
AWG = 'AWG',
11+
AZN = 'AZN',
12+
BAM = 'BAM',
13+
BBD = 'BBD',
14+
BDT = 'BDT',
15+
BGN = 'BGN',
16+
BHD = 'BHD',
17+
BIF = 'BIF',
18+
BMD = 'BMD',
19+
BND = 'BND',
20+
BOB = 'BOB',
21+
BRL = 'BRL',
22+
BSD = 'BSD',
23+
BTN = 'BTN',
24+
BWP = 'BWP',
25+
BYN = 'BYN',
26+
BZD = 'BZD',
27+
CAD = 'CAD',
28+
CDF = 'CDF',
29+
CHF = 'CHF',
30+
CLP = 'CLP',
31+
CNY = 'CNY',
32+
COP = 'COP',
33+
CRC = 'CRC',
34+
CUC = 'CUC',
35+
CUP = 'CUP',
36+
CVE = 'CVE',
37+
CZK = 'CZK',
38+
DJF = 'DJF',
39+
DKK = 'DKK',
40+
DOP = 'DOP',
41+
DZD = 'DZD',
42+
EGP = 'EGP',
43+
ERN = 'ERN',
44+
ETB = 'ETB',
45+
EUR = 'EUR',
46+
FJD = 'FJD',
47+
FKP = 'FKP',
48+
GBP = 'GBP',
49+
GEL = 'GEL',
50+
GHS = 'GHS',
51+
GIP = 'GIP',
52+
GMD = 'GMD',
53+
GNF = 'GNF',
54+
GTQ = 'GTQ',
55+
GYD = 'GYD',
56+
HKD = 'HKD',
57+
HNL = 'HNL',
58+
HRK = 'HRK',
59+
HTG = 'HTG',
60+
HUF = 'HUF',
61+
IDR = 'IDR',
62+
ILS = 'ILS',
63+
INR = 'INR',
64+
IQD = 'IQD',
65+
IRR = 'IRR',
66+
ISK = 'ISK',
67+
JMD = 'JMD',
68+
JOD = 'JOD',
69+
JPY = 'JPY',
70+
KES = 'KES',
71+
KGS = 'KGS',
72+
KHR = 'KHR',
73+
KMF = 'KMF',
74+
KPW = 'KPW',
75+
KRW = 'KRW',
76+
KWD = 'KWD',
77+
KYD = 'KYD',
78+
KZT = 'KZT',
79+
LAK = 'LAK',
80+
LBP = 'LBP',
81+
LKR = 'LKR',
82+
LRD = 'LRD',
83+
LSL = 'LSL',
84+
LYD = 'LYD',
85+
MAD = 'MAD',
86+
MDL = 'MDL',
87+
MGA = 'MGA',
88+
MKD = 'MKD',
89+
MMK = 'MMK',
90+
MNT = 'MNT',
91+
MOP = 'MOP',
92+
MRU = 'MRU',
93+
MUR = 'MUR',
94+
MVR = 'MVR',
95+
MWK = 'MWK',
96+
MXN = 'MXN',
97+
MYR = 'MYR',
98+
MZN = 'MZN',
99+
NAD = 'NAD',
100+
NGN = 'NGN',
101+
NIO = 'NIO',
102+
NOK = 'NOK',
103+
NPR = 'NPR',
104+
NZD = 'NZD',
105+
OMR = 'OMR',
106+
PAB = 'PAB',
107+
PEN = 'PEN',
108+
PGK = 'PGK',
109+
PHP = 'PHP',
110+
PKR = 'PKR',
111+
PLN = 'PLN',
112+
PYG = 'PYG',
113+
QAR = 'QAR',
114+
RON = 'RON',
115+
RSD = 'RSD',
116+
RUB = 'RUB',
117+
RWF = 'RWF',
118+
SAR = 'SAR',
119+
SBD = 'SBD',
120+
SCR = 'SCR',
121+
SDG = 'SDG',
122+
SEK = 'SEK',
123+
SGD = 'SGD',
124+
SHP = 'SHP',
125+
SLL = 'SLL',
126+
SOS = 'SOS',
127+
SRD = 'SRD',
128+
SSP = 'SSP',
129+
STN = 'STN',
130+
SVC = 'SVC',
131+
SYP = 'SYP',
132+
SZL = 'SZL',
133+
THB = 'THB',
134+
TJS = 'TJS',
135+
TMT = 'TMT',
136+
TND = 'TND',
137+
TOP = 'TOP',
138+
TRY = 'TRY',
139+
TTD = 'TTD',
140+
TWD = 'TWD',
141+
TZS = 'TZS',
142+
UAH = 'UAH',
143+
UGX = 'UGX',
144+
USD = 'USD',
145+
UYU = 'UYU',
146+
UZS = 'UZS',
147+
VES = 'VES',
148+
VND = 'VND',
149+
VUV = 'VUV',
150+
WST = 'WST',
151+
XAF = 'XAF',
152+
XCD = 'XCD',
153+
XOF = 'XOF',
154+
XPF = 'XPF',
155+
YER = 'YER',
156+
ZAR = 'ZAR',
157+
ZMW = 'ZMW',
158+
ZWL = 'ZWL',
159+
}
160+

test/currency.test.ts

+33-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,39 @@ describe('@currency directive', () => {
6363
expect(fetchSpy).toHaveBeenCalled()
6464
expect(fetchSpy).toHaveBeenCalledWith(`https://www.google.com/search?q=${amount}+${from}+to+${to}+&hl=en`)
6565
})
66+
6667
it.todo('will convert from one currency to another and return a integer')
6768
it.todo('will convert from one currency to another and format with a seperator')
68-
it.todo('will throw an error if currency code is not recognized')
69+
70+
it('will throw an error if currency code(s) are not recognized', async () => {
71+
const fetchSpy = jest.spyOn(global, 'fetch')
72+
const from = 'BLAH'
73+
const to = 'HMMMM'
74+
const schema = buildSchema({
75+
typeDefs: [
76+
`type User {
77+
amount: String @currency(from: "${from}", to: "${to}")
78+
}
79+
80+
type Query {
81+
user: User
82+
}
83+
`,
84+
currencyDirectiveTypeDefs
85+
],
86+
resolvers,
87+
transformers: [currencyDirectiveTransformer]
88+
})
89+
90+
testServer = new ApolloServer({ schema })
91+
92+
const response = await testServer.executeOperation<{ user: { amount: string } }>({
93+
query: testQuery
94+
})
95+
96+
assert(response.body.kind === 'single')
97+
expect(response.body.singleResult.errors).toBeDefined();
98+
expect(response.body.singleResult.errors[0].message).toBe(`Currency codes: ${from},${to} are not valid!`);
99+
expect(fetchSpy).not.toHaveBeenCalled()
100+
})
69101
})

0 commit comments

Comments
 (0)