w-trade-solve 1.0.5 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/w-trade-solve.umd.js +4 -4
- package/dist/w-trade-solve.umd.js.map +1 -1
- package/docs/calcFitness.mjs.html +1 -1
- package/docs/calcLevelNumTrade.mjs.html +1 -1
- package/docs/cont.mjs.html +2 -2
- package/docs/estimComps.mjs.html +1 -1
- package/docs/estimFinder.mjs.html +1 -1
- package/docs/estimKeys.mjs.html +145 -77
- package/docs/estimPicks.mjs.html +1 -1
- package/docs/genSid.mjs.html +1 -1
- package/docs/genStrategyFileName.mjs.html +14 -10
- package/docs/genTid.mjs.html +1 -1
- package/docs/global.html +192 -22
- package/docs/index.html +1 -1
- package/docs/ott.mjs.html +1 -1
- package/docs/p2r.mjs.html +1 -1
- package/docs/readStrategies.mjs.html +127 -43
- package/g.mjs +3 -2
- package/package.json +2 -2
- package/src/cont.mjs +1 -1
- package/src/estimKeys.mjs +144 -76
- package/src/genStrategyFileName.mjs +12 -8
- package/src/readStrategies.mjs +126 -42
- package/test/unit-estimKeys.test.mjs +222 -5
- package/test/unit-genStrategyFileName.test.mjs +56 -17
- package/test/unit-readStrategies.test.mjs +189 -53
|
@@ -4,6 +4,7 @@ import path from 'path'
|
|
|
4
4
|
import readStrategies from '../src/readStrategies.mjs'
|
|
5
5
|
import genStrategyFileName from '../src/genStrategyFileName.mjs'
|
|
6
6
|
import genTid from '../src/genTid.mjs'
|
|
7
|
+
import calcLevelNumTrade from '../src/calcLevelNumTrade.mjs'
|
|
7
8
|
import cont from '../src/cont.mjs'
|
|
8
9
|
import { buildFdTmp } from './unit-setup.mjs'
|
|
9
10
|
|
|
@@ -12,12 +13,15 @@ import { buildFdTmp } from './unit-setup.mjs'
|
|
|
12
13
|
// readStrategies(fd, opt): 列舉fd第1層之檔案並解析策略資訊
|
|
13
14
|
// fd非資料夾時回傳[], 資料夾內無檔案時回傳[]
|
|
14
15
|
// 僅列檔案, 資料夾不列入(fsTreeFolder預設levelLimit=1, 故子資料夾內檔案亦不列入)
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
16
|
+
// opt.fromContent決定解析來源, 可選'filename'|'content'|'auto'(預設):
|
|
17
|
+
// 'filename': 主檔名以wsemi replace剔除全部'.json'後依cont.dlmPkgs切段, 依序為tid、levelNumTrade與
|
|
18
|
+
// rEquivalentCumuProfitOrLossFinalNormYear, 三者皆為字串, 缺段者為空字串, 切不出tid者略過
|
|
19
|
+
// 'content': 讀檔內json之tid、tkid、levelNumTrade與summary.rEquivalentCumuProfitOrLossFinalNormYear,
|
|
20
|
+
// levelNumTrade轉為字串, 無tkid欄位時由tid與levelNumTrade組出, 非合法json或無tid者略過
|
|
21
|
+
// 'auto': 檔名符合`^(long|short)_\d+_[0-9a-f]{16}\.json$`者走'content', 其餘走'filename'
|
|
18
22
|
// tid再依cont.dlmSeps切段, 首段為mode, 其餘為ps
|
|
19
23
|
// tkid為`${tid}:${levelNumTrade}`
|
|
20
|
-
// opt.readContent為true時以data
|
|
24
|
+
// opt.readContent為true時以data提供檔案內容
|
|
21
25
|
|
|
22
26
|
|
|
23
27
|
let fdTmp = buildFdTmp('readStrategies')
|
|
@@ -34,14 +38,35 @@ let buildFd = (fd) => {
|
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
|
|
37
|
-
//
|
|
38
|
-
let
|
|
39
|
-
let
|
|
41
|
+
//writeStrategyNew: 以genStrategyFileName之雜湊檔名規則寫出策略檔, 內容含識別欄位(同estimKeys所寫出者)
|
|
42
|
+
let writeStrategyNew = (fdData, keys, numTrade, rEq, extra = {}) => {
|
|
43
|
+
let summary = {
|
|
40
44
|
numTrade,
|
|
41
45
|
rEquivalentCumuProfitOrLossFinalNormYear: rEq,
|
|
42
|
-
}
|
|
46
|
+
}
|
|
47
|
+
let fn = genStrategyFileName('btc', '4hr', 'long', keys, settings, summary)
|
|
48
|
+
let tid = genTid('btc', '4hr', 'long', keys)
|
|
49
|
+
let levelNumTrade = calcLevelNumTrade(numTrade)
|
|
50
|
+
let content = {
|
|
51
|
+
tid,
|
|
52
|
+
tkid: `${tid}:${levelNumTrade}`,
|
|
53
|
+
levelNumTrade,
|
|
54
|
+
mode: 'long',
|
|
55
|
+
summary,
|
|
56
|
+
...extra,
|
|
57
|
+
}
|
|
58
|
+
fs.writeFileSync(path.resolve(fdData, fn), JSON.stringify(content), 'utf8')
|
|
59
|
+
return { fn, tid, levelNumTrade, content }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
//writeStrategyLegacy: 以舊式`${tid} ⊙ ${levelNumTrade} ⊙ ${rEq}.json`檔名規則寫出策略檔
|
|
64
|
+
let writeStrategyLegacy = (fdData, keys, numTrade, rEq, content = {}) => {
|
|
65
|
+
let tid = genTid('btc', '4hr', 'long', keys)
|
|
66
|
+
let levelNumTrade = calcLevelNumTrade(numTrade)
|
|
67
|
+
let fn = `${tid}${cont.dlmPkgs}${levelNumTrade}${cont.dlmPkgs}${rEq}.json`
|
|
43
68
|
fs.writeFileSync(path.resolve(fdData, fn), JSON.stringify(content), 'utf8')
|
|
44
|
-
return fn
|
|
69
|
+
return { fn, tid, levelNumTrade }
|
|
45
70
|
}
|
|
46
71
|
|
|
47
72
|
|
|
@@ -51,17 +76,15 @@ describe('readStrategies', function() {
|
|
|
51
76
|
fs.rmSync(fdTmp, { recursive: true, force: true })
|
|
52
77
|
})
|
|
53
78
|
|
|
54
|
-
describe('
|
|
79
|
+
describe('新格式(雜湊檔名, auto走content)', function() {
|
|
55
80
|
|
|
56
|
-
it('讀出genStrategyFileName所寫之策略檔,
|
|
57
|
-
let fd = buildFd('basic')
|
|
81
|
+
it('讀出genStrategyFileName所寫之策略檔, 各欄位取自檔內json', function() {
|
|
82
|
+
let fd = buildFd('new-basic')
|
|
58
83
|
let keys = ['btc_price_4hr_ma_1day']
|
|
59
|
-
let fn =
|
|
84
|
+
let { fn, tid } = writeStrategyNew(fd, keys, 30, '31.25%')
|
|
60
85
|
|
|
61
86
|
let ss = readStrategies(fd)
|
|
62
87
|
assert.strictEqual(ss.length, 1)
|
|
63
|
-
|
|
64
|
-
let tid = genTid('btc', '4hr', 'long', keys)
|
|
65
88
|
assert.strictEqual(ss[0].name, fn)
|
|
66
89
|
assert.strictEqual(ss[0].tid, tid)
|
|
67
90
|
assert.strictEqual(ss[0].levelNumTrade, '12')
|
|
@@ -69,44 +92,99 @@ describe('readStrategies', function() {
|
|
|
69
92
|
assert.strictEqual(ss[0].rEquivalentCumuProfitOrLossFinalNormYear, '31.25%')
|
|
70
93
|
})
|
|
71
94
|
|
|
72
|
-
it('levelNumTrade
|
|
73
|
-
let fd = buildFd('str')
|
|
74
|
-
|
|
95
|
+
it('levelNumTrade與等效年化盈虧皆轉為與檔名反解一致之字串', function() {
|
|
96
|
+
let fd = buildFd('new-str')
|
|
97
|
+
writeStrategyNew(fd, ['aa'], 30, '31.25%')
|
|
75
98
|
|
|
76
99
|
let ss = readStrategies(fd)
|
|
77
100
|
assert.strictEqual(typeof ss[0].levelNumTrade, 'string')
|
|
78
101
|
assert.strictEqual(typeof ss[0].rEquivalentCumuProfitOrLossFinalNormYear, 'string')
|
|
79
102
|
})
|
|
80
103
|
|
|
81
|
-
it('tid
|
|
82
|
-
let fd = buildFd('modeps')
|
|
104
|
+
it('tid依dlmSeps拆為mode與ps', function() {
|
|
105
|
+
let fd = buildFd('new-modeps')
|
|
83
106
|
//keys經genTid縮寫後為p_ma_1day與i_rsi_4hr
|
|
84
|
-
|
|
107
|
+
writeStrategyNew(fd, ['btc_price_4hr_ma_1day', 'btc_index_rsi_4hr'], 30, '10%')
|
|
85
108
|
|
|
86
109
|
let ss = readStrategies(fd)
|
|
87
110
|
assert.strictEqual(ss[0].mode, 'long')
|
|
88
111
|
assert.deepStrictEqual(ss[0].ps, ['p_ma_1day', 'i_rsi_4hr'])
|
|
89
112
|
})
|
|
90
113
|
|
|
91
|
-
it('
|
|
92
|
-
let fd = buildFd('
|
|
93
|
-
|
|
114
|
+
it('內容無tkid欄位時由tid與levelNumTrade組出', function() {
|
|
115
|
+
let fd = buildFd('new-notkid')
|
|
116
|
+
let keys = ['aa']
|
|
117
|
+
let summary = { numTrade: 30, rEquivalentCumuProfitOrLossFinalNormYear: '10%' }
|
|
118
|
+
let fn = genStrategyFileName('btc', '4hr', 'long', keys, settings, summary)
|
|
119
|
+
let tid = genTid('btc', '4hr', 'long', keys)
|
|
120
|
+
fs.writeFileSync(path.resolve(fd, fn), JSON.stringify({ tid, levelNumTrade: 12, summary }), 'utf8')
|
|
121
|
+
|
|
122
|
+
let ss = readStrategies(fd)
|
|
123
|
+
assert.strictEqual(ss[0].tkid, `${tid}:12`)
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
it('同tid不同級距之策略檔各自為一筆, tkid不同', function() {
|
|
127
|
+
let fd = buildFd('new-levels')
|
|
128
|
+
let keys = ['aa']
|
|
129
|
+
writeStrategyNew(fd, keys, 20, '10%') //級距11
|
|
130
|
+
writeStrategyNew(fd, keys, 30, '20%') //級距12
|
|
131
|
+
|
|
132
|
+
let ss = readStrategies(fd)
|
|
133
|
+
assert.strictEqual(ss.length, 2)
|
|
134
|
+
|
|
135
|
+
let tid = genTid('btc', '4hr', 'long', keys)
|
|
136
|
+
let tkids = ss.map((v) => {
|
|
137
|
+
return v.tkid
|
|
138
|
+
}).sort()
|
|
139
|
+
assert.deepStrictEqual(tkids, [`${tid}:11`, `${tid}:12`].sort())
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
it('雜湊檔名但內容非合法json者略過', function() {
|
|
143
|
+
let fd = buildFd('new-badjson')
|
|
144
|
+
writeStrategyNew(fd, ['aa'], 30, '10%')
|
|
145
|
+
fs.writeFileSync(path.resolve(fd, 'long_12_0123456789abcdef.json'), 'not-a-json', 'utf8')
|
|
146
|
+
|
|
147
|
+
let ss = readStrategies(fd)
|
|
148
|
+
assert.strictEqual(ss.length, 1)
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
it('雜湊檔名但內容無tid欄位者略過', function() {
|
|
152
|
+
let fd = buildFd('new-notid')
|
|
153
|
+
fs.writeFileSync(path.resolve(fd, 'long_12_0123456789abcdef.json'), '{}', 'utf8')
|
|
94
154
|
|
|
95
155
|
let ss = readStrategies(fd)
|
|
96
|
-
assert.deepStrictEqual(ss
|
|
156
|
+
assert.deepStrictEqual(ss, [])
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
describe('舊格式(dlmPkgs檔名, auto走filename)', function() {
|
|
162
|
+
|
|
163
|
+
it('讀出舊式檔名之策略檔, 各欄位可由檔名反解', function() {
|
|
164
|
+
let fd = buildFd('legacy-basic')
|
|
165
|
+
let keys = ['btc_price_4hr_ma_1day']
|
|
166
|
+
let { fn, tid } = writeStrategyLegacy(fd, keys, 30, '31.25%')
|
|
167
|
+
|
|
168
|
+
let ss = readStrategies(fd)
|
|
169
|
+
assert.strictEqual(ss.length, 1)
|
|
170
|
+
assert.strictEqual(ss[0].name, fn)
|
|
171
|
+
assert.strictEqual(ss[0].tid, tid)
|
|
172
|
+
assert.strictEqual(ss[0].levelNumTrade, '12')
|
|
173
|
+
assert.strictEqual(ss[0].tkid, `${tid}:12`)
|
|
174
|
+
assert.strictEqual(ss[0].rEquivalentCumuProfitOrLossFinalNormYear, '31.25%')
|
|
97
175
|
})
|
|
98
176
|
|
|
99
177
|
it('等效年化盈虧為負值時亦可正確反解', function() {
|
|
100
|
-
let fd = buildFd('neg')
|
|
101
|
-
|
|
178
|
+
let fd = buildFd('legacy-neg')
|
|
179
|
+
writeStrategyLegacy(fd, ['aa'], 30, '-71.17%')
|
|
102
180
|
|
|
103
181
|
let ss = readStrategies(fd)
|
|
104
182
|
assert.strictEqual(ss[0].rEquivalentCumuProfitOrLossFinalNormYear, '-71.17%')
|
|
105
183
|
})
|
|
106
184
|
|
|
107
185
|
it('path為絕對路徑, 即使fd以相對路徑給予', function() {
|
|
108
|
-
let fd = buildFd('abs')
|
|
109
|
-
let fn =
|
|
186
|
+
let fd = buildFd('legacy-abs')
|
|
187
|
+
let { fn } = writeStrategyLegacy(fd, ['aa'], 30, '10%')
|
|
110
188
|
|
|
111
189
|
let fdRel = path.relative(process.cwd(), fd)
|
|
112
190
|
let ss = readStrategies(fdRel)
|
|
@@ -114,32 +192,82 @@ describe('readStrategies', function() {
|
|
|
114
192
|
assert.ok(path.isAbsolute(ss[0].path))
|
|
115
193
|
})
|
|
116
194
|
|
|
117
|
-
it('
|
|
118
|
-
let fd = buildFd('
|
|
119
|
-
let keys = ['
|
|
120
|
-
|
|
121
|
-
|
|
195
|
+
it('與舊檔名規則可往返: 由讀回之欄位可重組原檔名', function() {
|
|
196
|
+
let fd = buildFd('legacy-roundtrip')
|
|
197
|
+
let keys = ['btc_price_4hr_ma_1day', 'btc_index_rsi_4hr']
|
|
198
|
+
let { fn } = writeStrategyLegacy(fd, keys, 300, '8.5%')
|
|
199
|
+
|
|
200
|
+
let ss = readStrategies(fd)
|
|
201
|
+
let s = ss[0]
|
|
202
|
+
let fnRebuild = `${s.tid}${cont.dlmPkgs}${s.levelNumTrade}${cont.dlmPkgs}${s.rEquivalentCumuProfitOrLossFinalNormYear}.json`
|
|
203
|
+
assert.strictEqual(fnRebuild, fn)
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
describe('新舊格式混存', function() {
|
|
209
|
+
|
|
210
|
+
it('auto模式下新舊格式皆正確列舉', function() {
|
|
211
|
+
let fd = buildFd('mixed')
|
|
212
|
+
let { tid: tidNew } = writeStrategyNew(fd, ['btc_price_4hr_ma_1day'], 30, '10%')
|
|
213
|
+
let { tid: tidLegacy } = writeStrategyLegacy(fd, ['btc_index_rsi_4hr'], 20, '20%')
|
|
122
214
|
|
|
123
215
|
let ss = readStrategies(fd)
|
|
124
216
|
assert.strictEqual(ss.length, 2)
|
|
125
217
|
|
|
126
|
-
let tid = genTid('btc', '4hr', 'long', keys)
|
|
127
218
|
let tkids = ss.map((v) => {
|
|
128
219
|
return v.tkid
|
|
129
220
|
}).sort()
|
|
130
|
-
assert.deepStrictEqual(tkids, [`${
|
|
131
|
-
assert.strictEqual(ss[0].tid, ss[1].tid)
|
|
221
|
+
assert.deepStrictEqual(tkids, [`${tidNew}:12`, `${tidLegacy}:11`].sort())
|
|
132
222
|
})
|
|
133
223
|
|
|
134
|
-
|
|
135
|
-
let fd = buildFd('roundtrip')
|
|
136
|
-
let keys = ['btc_price_4hr_ma_1day', 'btc_index_rsi_4hr']
|
|
137
|
-
let fn = writeStrategy(fd, keys, 300, '8.5%')
|
|
224
|
+
})
|
|
138
225
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
226
|
+
describe('fromContent選項', function() {
|
|
227
|
+
|
|
228
|
+
it("fromContent為'filename'時雜湊檔名不讀內容, 整個主檔名成為tid", function() {
|
|
229
|
+
let fd = buildFd('fc-filename')
|
|
230
|
+
let { fn } = writeStrategyNew(fd, ['aa'], 30, '10%')
|
|
231
|
+
|
|
232
|
+
let ss = readStrategies(fd, { fromContent: 'filename' })
|
|
233
|
+
assert.strictEqual(ss.length, 1)
|
|
234
|
+
//雜湊檔名內無dlmPkgs, 故主檔名整段為tid, 其餘欄位為空字串
|
|
235
|
+
assert.strictEqual(ss[0].tid, fn.slice(0, -5))
|
|
236
|
+
assert.strictEqual(ss[0].levelNumTrade, '')
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
it("fromContent為'content'時舊式檔名亦讀內容, 內容具tid欄位者以內容為準", function() {
|
|
240
|
+
let fd = buildFd('fc-content')
|
|
241
|
+
let keys = ['btc_price_4hr_ma_1day']
|
|
242
|
+
let tid = genTid('btc', '4hr', 'long', keys)
|
|
243
|
+
writeStrategyLegacy(fd, keys, 30, '10%', {
|
|
244
|
+
tid,
|
|
245
|
+
tkid: `${tid}:12`,
|
|
246
|
+
levelNumTrade: 12,
|
|
247
|
+
summary: { numTrade: 30, rEquivalentCumuProfitOrLossFinalNormYear: '10%' },
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
let ss = readStrategies(fd, { fromContent: 'content' })
|
|
251
|
+
assert.strictEqual(ss.length, 1)
|
|
252
|
+
assert.strictEqual(ss[0].tid, tid)
|
|
253
|
+
assert.strictEqual(ss[0].tkid, `${tid}:12`)
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
it("fromContent為'content'時內容無tid欄位者略過", function() {
|
|
257
|
+
let fd = buildFd('fc-content-skip')
|
|
258
|
+
writeStrategyLegacy(fd, ['aa'], 30, '10%', {}) //舊檔內容無識別欄位
|
|
259
|
+
|
|
260
|
+
let ss = readStrategies(fd, { fromContent: 'content' })
|
|
261
|
+
assert.deepStrictEqual(ss, [])
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
it("fromContent非三值之一時採'auto'", function() {
|
|
265
|
+
let fd = buildFd('fc-fallback')
|
|
266
|
+
let { tid } = writeStrategyNew(fd, ['aa'], 30, '10%')
|
|
267
|
+
|
|
268
|
+
let ss = readStrategies(fd, { fromContent: 'xxx' })
|
|
269
|
+
assert.strictEqual(ss.length, 1)
|
|
270
|
+
assert.strictEqual(ss[0].tid, tid)
|
|
143
271
|
})
|
|
144
272
|
|
|
145
273
|
})
|
|
@@ -179,7 +307,7 @@ describe('readStrategies', function() {
|
|
|
179
307
|
|
|
180
308
|
it('主檔名剔除.json後為空字串者被略過', function() {
|
|
181
309
|
let fd = buildFd('emptyname')
|
|
182
|
-
|
|
310
|
+
writeStrategyNew(fd, ['aa'], 30, '10%')
|
|
183
311
|
fs.writeFileSync(path.resolve(fd, '.json'), '{}', 'utf8')
|
|
184
312
|
|
|
185
313
|
let ss = readStrategies(fd)
|
|
@@ -193,10 +321,10 @@ describe('readStrategies', function() {
|
|
|
193
321
|
|
|
194
322
|
it('僅列第1層, 子資料夾與其內檔案皆不列入', function() {
|
|
195
323
|
let fd = buildFd('nested')
|
|
196
|
-
|
|
324
|
+
writeStrategyNew(fd, ['aa'], 30, '10%')
|
|
197
325
|
let fdSub = path.resolve(fd, 'sub')
|
|
198
326
|
fs.mkdirSync(fdSub, { recursive: true })
|
|
199
|
-
|
|
327
|
+
writeStrategyNew(fdSub, ['bb'], 30, '10%')
|
|
200
328
|
|
|
201
329
|
let ss = readStrategies(fd)
|
|
202
330
|
assert.strictEqual(ss.length, 1)
|
|
@@ -230,22 +358,30 @@ describe('readStrategies', function() {
|
|
|
230
358
|
|
|
231
359
|
it('預設不讀取內容, 無data欄位', function() {
|
|
232
360
|
let fd = buildFd('nodata')
|
|
233
|
-
|
|
361
|
+
writeStrategyNew(fd, ['aa'], 30, '10%', { fitness: 1.5 })
|
|
234
362
|
|
|
235
363
|
let ss = readStrategies(fd)
|
|
236
364
|
assert.strictEqual(ss[0].data, undefined)
|
|
237
365
|
})
|
|
238
366
|
|
|
239
|
-
it('opt.readContent為true時以data提供檔案內容', function() {
|
|
240
|
-
let fd = buildFd('data')
|
|
367
|
+
it('opt.readContent為true時以data提供檔案內容(新格式)', function() {
|
|
368
|
+
let fd = buildFd('data-new')
|
|
369
|
+
let { content } = writeStrategyNew(fd, ['aa'], 30, '10%', { fitness: 1.5 })
|
|
370
|
+
|
|
371
|
+
let ss = readStrategies(fd, { readContent: true })
|
|
372
|
+
assert.deepStrictEqual(ss[0].data, content)
|
|
373
|
+
})
|
|
374
|
+
|
|
375
|
+
it('opt.readContent為true時以data提供檔案內容(舊格式)', function() {
|
|
376
|
+
let fd = buildFd('data-legacy')
|
|
241
377
|
let content = { tid: 'x', fitness: 1.5, summary: { numTrade: 30 } }
|
|
242
|
-
|
|
378
|
+
writeStrategyLegacy(fd, ['aa'], 30, '10%', content)
|
|
243
379
|
|
|
244
380
|
let ss = readStrategies(fd, { readContent: true })
|
|
245
381
|
assert.deepStrictEqual(ss[0].data, content)
|
|
246
382
|
})
|
|
247
383
|
|
|
248
|
-
it('
|
|
384
|
+
it('舊式檔名內容非合法json時data為null', function() {
|
|
249
385
|
let fd = buildFd('badjson')
|
|
250
386
|
fs.writeFileSync(path.resolve(fd, 'bad.json'), 'not-a-json', 'utf8')
|
|
251
387
|
|