@forgehive/record-tape 0.0.1
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/LICENSE +21 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +176 -0
- package/dist/index.js.map +1 -0
- package/dist/tests/compile-cache.test.d.ts +2 -0
- package/dist/tests/compile-cache.test.d.ts.map +1 -0
- package/dist/tests/compile-cache.test.js +34 -0
- package/dist/tests/compile-cache.test.js.map +1 -0
- package/dist/tests/index.test.d.ts +2 -0
- package/dist/tests/index.test.d.ts.map +1 -0
- package/dist/tests/index.test.js +99 -0
- package/dist/tests/index.test.js.map +1 -0
- package/dist/tests/load.test.d.ts +2 -0
- package/dist/tests/load.test.d.ts.map +1 -0
- package/dist/tests/load.test.js +89 -0
- package/dist/tests/load.test.js.map +1 -0
- package/dist/tests/log-format.test.d.ts +2 -0
- package/dist/tests/log-format.test.d.ts.map +1 -0
- package/dist/tests/log-format.test.js +36 -0
- package/dist/tests/log-format.test.js.map +1 -0
- package/dist/tests/mode.test.d.ts +2 -0
- package/dist/tests/mode.test.d.ts.map +1 -0
- package/dist/tests/mode.test.js +75 -0
- package/dist/tests/mode.test.js.map +1 -0
- package/dist/tests/save.test.d.ts +2 -0
- package/dist/tests/save.test.d.ts.map +1 -0
- package/dist/tests/save.test.js +95 -0
- package/dist/tests/save.test.js.map +1 -0
- package/dist/tests/task-listener.test.d.ts +2 -0
- package/dist/tests/task-listener.test.d.ts.map +1 -0
- package/dist/tests/task-listener.test.js +122 -0
- package/dist/tests/task-listener.test.js.map +1 -0
- package/jest.config.js +6 -0
- package/package.json +23 -0
- package/src/index.ts +218 -0
- package/src/tests/compile-cache.test.ts +41 -0
- package/src/tests/fixtures/load.log +2 -0
- package/src/tests/fixtures/single-cache.log +2 -0
- package/src/tests/index.test.ts +88 -0
- package/src/tests/load.test.ts +108 -0
- package/src/tests/log-format.test.ts +48 -0
- package/src/tests/mode.test.ts +93 -0
- package/src/tests/save.test.ts +127 -0
- package/src/tests/task-listener.test.ts +170 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as path from 'path'
|
|
2
|
+
import { RecordTape } from '../index'
|
|
3
|
+
|
|
4
|
+
const emptyPath = path.resolve('any')
|
|
5
|
+
const tapePath = path.resolve(__dirname, './fixtures/load')
|
|
6
|
+
|
|
7
|
+
describe('Base tests', () => {
|
|
8
|
+
it('Load sync with no file should return a empty tape', () => {
|
|
9
|
+
const tape = new RecordTape({ path: emptyPath })
|
|
10
|
+
tape.loadSync()
|
|
11
|
+
|
|
12
|
+
const data = tape.getLog()
|
|
13
|
+
expect(data.length).toBe(0)
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('Load sync with fixture tape should return a tape with one element', () => {
|
|
17
|
+
const tape = new RecordTape({ path: tapePath })
|
|
18
|
+
tape.loadSync()
|
|
19
|
+
|
|
20
|
+
const data = tape.getLog()
|
|
21
|
+
expect(data.length).toBe(2)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('Load with no file should return a empty tape', async () => {
|
|
25
|
+
const tape = new RecordTape({ path: emptyPath })
|
|
26
|
+
await tape.load()
|
|
27
|
+
|
|
28
|
+
const data = tape.getLog()
|
|
29
|
+
expect(data.length).toBe(0)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('Load with fixture tape should return a tape with one element', async () => {
|
|
33
|
+
type InputType = boolean[]
|
|
34
|
+
type OutputType = boolean
|
|
35
|
+
|
|
36
|
+
const tape = new RecordTape<InputType, OutputType>({ path: tapePath })
|
|
37
|
+
await tape.load()
|
|
38
|
+
|
|
39
|
+
const data = tape.getLog()
|
|
40
|
+
expect(data.length).toBe(2)
|
|
41
|
+
|
|
42
|
+
const successRecord = data[0]
|
|
43
|
+
expect(successRecord.type).toBe('success')
|
|
44
|
+
expect(successRecord.input).toEqual([true])
|
|
45
|
+
expect(successRecord.output).toBe(true)
|
|
46
|
+
expect(successRecord.error).toBeUndefined()
|
|
47
|
+
|
|
48
|
+
const errorRecord = data[1]
|
|
49
|
+
expect(errorRecord.type).toBe('error')
|
|
50
|
+
expect(errorRecord.input).toEqual([true])
|
|
51
|
+
expect(errorRecord.output).toBeUndefined()
|
|
52
|
+
expect(errorRecord.error).toBe('invalid data')
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it('Should create a new tape with generic types', () => {
|
|
56
|
+
type InputType = [{ name: string }]
|
|
57
|
+
type OutputType = {
|
|
58
|
+
age: number
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const tape = new RecordTape<InputType, OutputType>({ path: emptyPath })
|
|
62
|
+
tape.addLogItem('test', { input: [{name: 'test'}], output: { age: 1 } })
|
|
63
|
+
tape.addLogItem('test', { input: [{name: 'test'}], error: new Error('test') })
|
|
64
|
+
|
|
65
|
+
const data = tape.getLog()
|
|
66
|
+
expect(data.length).toBe(2)
|
|
67
|
+
|
|
68
|
+
const input = data[0].input
|
|
69
|
+
const output = data[0].output
|
|
70
|
+
const type = data[0].type
|
|
71
|
+
const error = data[0].error
|
|
72
|
+
|
|
73
|
+
expect(input).toEqual([{name: 'test'}])
|
|
74
|
+
expect(output).toEqual({ age: 1 })
|
|
75
|
+
expect(error).toBeUndefined()
|
|
76
|
+
expect(type).toBe('success')
|
|
77
|
+
|
|
78
|
+
const input2 = data[1].input
|
|
79
|
+
const output2 = data[1].output
|
|
80
|
+
const type2 = data[1].type
|
|
81
|
+
const error2 = data[1].error
|
|
82
|
+
|
|
83
|
+
expect(input2).toEqual([{name: 'test'}])
|
|
84
|
+
expect(output2).toBeUndefined()
|
|
85
|
+
expect(error2).toEqual(new Error('test'))
|
|
86
|
+
expect(type2).toBe('error')
|
|
87
|
+
})
|
|
88
|
+
})
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import path from 'path'
|
|
2
|
+
import fs from 'fs'
|
|
3
|
+
import { RecordTape } from '../index'
|
|
4
|
+
|
|
5
|
+
const baseTapeData = [
|
|
6
|
+
{
|
|
7
|
+
name: 'name',
|
|
8
|
+
type: 'success',
|
|
9
|
+
input: [true],
|
|
10
|
+
output: true,
|
|
11
|
+
boundaries: {}
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
name: 'name',
|
|
15
|
+
type: 'error',
|
|
16
|
+
input: [true],
|
|
17
|
+
error: 'invalid data',
|
|
18
|
+
boundaries: {}
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
describe('Load async', () => {
|
|
23
|
+
it('Load async from file', async () => {
|
|
24
|
+
type InputType = boolean[]
|
|
25
|
+
type OutputType = boolean
|
|
26
|
+
|
|
27
|
+
const tape = new RecordTape<InputType, OutputType>({
|
|
28
|
+
path: path.resolve(__dirname, './fixtures/load')
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
await tape.load()
|
|
32
|
+
const log = tape.getLog()
|
|
33
|
+
|
|
34
|
+
expect(log).toEqual(baseTapeData)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('Load async from file on a directory that doesnt exist', async () => {
|
|
38
|
+
const tape = new RecordTape({
|
|
39
|
+
path: path.resolve(__dirname, './nowhere/nop')
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
await expect(tape.load()).rejects.toThrow('Logs folder doesn\'t exists')
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('Load async from file that doesnt exist', async () => {
|
|
46
|
+
const tapeFilePath = path.resolve(__dirname, './fixtures/nop')
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
await fs.promises.unlink(tapeFilePath + '.log')
|
|
50
|
+
} catch (_e) {
|
|
51
|
+
// eslint-disable-next-line no-console
|
|
52
|
+
// console.warn('Didnt found a file to unlink')
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const tape = new RecordTape({
|
|
56
|
+
path: path.resolve(__dirname, './fixtures/nop')
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
await tape.load()
|
|
60
|
+
const log = tape.getLog()
|
|
61
|
+
|
|
62
|
+
expect(log).toEqual([])
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
describe('Load sync', () => {
|
|
67
|
+
it('load sync from file', () => {
|
|
68
|
+
type InputType = boolean[]
|
|
69
|
+
type OutputType = boolean
|
|
70
|
+
|
|
71
|
+
const tape = new RecordTape<InputType, OutputType>({
|
|
72
|
+
path: path.resolve(__dirname, './fixtures/load')
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
tape.loadSync()
|
|
76
|
+
const log = tape.getLog()
|
|
77
|
+
|
|
78
|
+
expect(log).toEqual(baseTapeData)
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
it('Load sync from file on a directory that doesnt exist', () => {
|
|
82
|
+
const tape = new RecordTape({
|
|
83
|
+
path: path.resolve(__dirname, './somewhere/nop')
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
expect(() => tape.loadSync()).toThrow('Logs folder doesn\'t exists')
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
it('Load sync from file that doesnt exist', () => {
|
|
90
|
+
const tapeFilePath = path.resolve(__dirname, './fixtures/nop')
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
fs.unlinkSync(tapeFilePath + '.log')
|
|
94
|
+
} catch (_e) {
|
|
95
|
+
// eslint-disable-next-line no-console
|
|
96
|
+
// console.warn('Didnt found a file to unlink')
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const tape = new RecordTape({
|
|
100
|
+
path: path.resolve(__dirname, './fixtures/nop')
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
tape.loadSync()
|
|
104
|
+
const log = tape.getLog()
|
|
105
|
+
|
|
106
|
+
expect(log).toEqual([])
|
|
107
|
+
})
|
|
108
|
+
})
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { RecordTape } from '../index'
|
|
2
|
+
|
|
3
|
+
const baseTapeData = [
|
|
4
|
+
{
|
|
5
|
+
name: 'name',
|
|
6
|
+
type: 'success',
|
|
7
|
+
input: [true],
|
|
8
|
+
output: true,
|
|
9
|
+
boundaries: {}
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
name: 'name',
|
|
13
|
+
type: 'error',
|
|
14
|
+
input: [true],
|
|
15
|
+
error: 'invalid data',
|
|
16
|
+
boundaries: {}
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
const logFileData = '{"name":"name","type":"success","input":[true],"output":true,"boundaries":{}}\n{"name":"name","type":"error","input":[true],"error":"invalid data","boundaries":{}}\n'
|
|
21
|
+
|
|
22
|
+
describe('Log format', () => {
|
|
23
|
+
it('Should ensure format', () => {
|
|
24
|
+
type InputType = boolean[]
|
|
25
|
+
type OutputType = boolean
|
|
26
|
+
|
|
27
|
+
const tape = new RecordTape<InputType, OutputType>({})
|
|
28
|
+
|
|
29
|
+
tape.addLogItem('name', { input: [true], output: true, boundaries: {} })
|
|
30
|
+
tape.addLogItem('name', { input: [true], error: 'invalid data', boundaries: {} })
|
|
31
|
+
|
|
32
|
+
expect(tape.getLog()).toEqual(baseTapeData)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('Should serialize to one line per item', () => {
|
|
36
|
+
type InputType = boolean[]
|
|
37
|
+
type OutputType = boolean
|
|
38
|
+
|
|
39
|
+
const tape = new RecordTape<InputType, OutputType>({})
|
|
40
|
+
|
|
41
|
+
tape.addLogItem('name', { input: [true], output: true, boundaries: {} })
|
|
42
|
+
tape.addLogItem('name', { input: [true], error: 'invalid data', boundaries: {} })
|
|
43
|
+
|
|
44
|
+
const logFile = tape.stringify()
|
|
45
|
+
|
|
46
|
+
expect(logFile).toBe(logFileData)
|
|
47
|
+
})
|
|
48
|
+
})
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { RecordTape } from '../index'
|
|
2
|
+
|
|
3
|
+
describe('Mode behavior', () => {
|
|
4
|
+
it('Should start in record mode by default', () => {
|
|
5
|
+
const tape = new RecordTape()
|
|
6
|
+
expect(tape.getMode()).toBe('record')
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
it('Should not add log items in replay mode', () => {
|
|
10
|
+
type InputType = { value: number }
|
|
11
|
+
type OutputType = { result: number }
|
|
12
|
+
|
|
13
|
+
const tape = new RecordTape<InputType, OutputType>()
|
|
14
|
+
tape.setMode('replay')
|
|
15
|
+
|
|
16
|
+
tape.addLogItem('test', {
|
|
17
|
+
input: { value: 1 },
|
|
18
|
+
output: { result: 2 }
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
expect(tape.getLog()).toEqual([])
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('Should add log items in record mode', () => {
|
|
25
|
+
type InputType = { value: number }
|
|
26
|
+
type OutputType = { result: number }
|
|
27
|
+
|
|
28
|
+
const tape = new RecordTape<InputType, OutputType>()
|
|
29
|
+
tape.setMode('record')
|
|
30
|
+
|
|
31
|
+
tape.addLogItem('test', {
|
|
32
|
+
input: { value: 1 },
|
|
33
|
+
output: { result: 2 }
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
expect(tape.getLog()).toEqual([
|
|
37
|
+
{
|
|
38
|
+
name: 'test',
|
|
39
|
+
type: 'success',
|
|
40
|
+
input: { value: 1 },
|
|
41
|
+
output: { result: 2 },
|
|
42
|
+
boundaries: {}
|
|
43
|
+
}
|
|
44
|
+
])
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('Should switch between modes', () => {
|
|
48
|
+
type InputType = { value: number }
|
|
49
|
+
type OutputType = { result: number }
|
|
50
|
+
|
|
51
|
+
const tape = new RecordTape<InputType, OutputType>()
|
|
52
|
+
|
|
53
|
+
// Start in record mode
|
|
54
|
+
expect(tape.getMode()).toBe('record')
|
|
55
|
+
tape.addLogItem('test1', {
|
|
56
|
+
input: { value: 1 },
|
|
57
|
+
output: { result: 2 }
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
// Switch to replay mode
|
|
61
|
+
tape.setMode('replay')
|
|
62
|
+
expect(tape.getMode()).toBe('replay')
|
|
63
|
+
tape.addLogItem('test2', {
|
|
64
|
+
input: { value: 3 },
|
|
65
|
+
output: { result: 4 }
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
// Switch back to record mode
|
|
69
|
+
tape.setMode('record')
|
|
70
|
+
expect(tape.getMode()).toBe('record')
|
|
71
|
+
tape.addLogItem('test3', {
|
|
72
|
+
input: { value: 5 },
|
|
73
|
+
output: { result: 6 }
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
expect(tape.getLog()).toEqual([
|
|
77
|
+
{
|
|
78
|
+
name: 'test1',
|
|
79
|
+
type: 'success',
|
|
80
|
+
input: { value: 1 },
|
|
81
|
+
output: { result: 2 },
|
|
82
|
+
boundaries: {}
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
name: 'test3',
|
|
86
|
+
type: 'success',
|
|
87
|
+
input: { value: 5 },
|
|
88
|
+
output: { result: 6 },
|
|
89
|
+
boundaries: {}
|
|
90
|
+
}
|
|
91
|
+
])
|
|
92
|
+
})
|
|
93
|
+
})
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import { RecordTape } from '../index'
|
|
4
|
+
|
|
5
|
+
const logFileData = '{"name":"name","type":"success","input":[true],"output":true,"boundaries":{}}\n{"name":"name","type":"error","input":[true],"error":"invalid data","boundaries":{}}\n'
|
|
6
|
+
|
|
7
|
+
describe('Save to file async', () => {
|
|
8
|
+
it('Save async to existing file(should add new logs)', async () => {
|
|
9
|
+
type InputType = boolean[]
|
|
10
|
+
type OutputType = boolean
|
|
11
|
+
|
|
12
|
+
const tapeFilePath = path.resolve(__dirname, './fixtures/save')
|
|
13
|
+
try {
|
|
14
|
+
await fs.promises.writeFile(tapeFilePath + '.log', logFileData)
|
|
15
|
+
} catch (_e) {
|
|
16
|
+
// eslint-disable-next-line no-console
|
|
17
|
+
// console.warn('Didnt found a file to unlink')
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const tape = new RecordTape<InputType, OutputType>({ path: tapeFilePath })
|
|
21
|
+
await tape.load()
|
|
22
|
+
tape.addLogItem('name', { input: [true], output: true, boundaries: {} })
|
|
23
|
+
tape.addLogItem('name', { input: [true], error: 'invalid data', boundaries: {} })
|
|
24
|
+
await tape.save()
|
|
25
|
+
|
|
26
|
+
const content = await fs.promises.readFile(tapeFilePath + '.log', 'utf8')
|
|
27
|
+
|
|
28
|
+
expect(tape.getLog().length).toBe(4)
|
|
29
|
+
expect(tape.stringify()).toBe(logFileData + logFileData)
|
|
30
|
+
expect(content).toBe(logFileData + logFileData)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('Save async to a path of invalid folder', async () => {
|
|
34
|
+
type InputType = boolean[]
|
|
35
|
+
type OutputType = boolean
|
|
36
|
+
|
|
37
|
+
const tapeFilePath = path.resolve(__dirname, './nowhere/nop')
|
|
38
|
+
|
|
39
|
+
const tape = new RecordTape<InputType, OutputType>({ path: tapeFilePath })
|
|
40
|
+
tape.addLogItem('name', { input: [true], output: true, boundaries: {} })
|
|
41
|
+
tape.addLogItem('name', { input: [true], error: 'invalid data', boundaries: {} })
|
|
42
|
+
|
|
43
|
+
await expect(tape.save()).rejects.toThrow('Folder doesn\'t exists')
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('Save async to a log file that doesnt exist', async () => {
|
|
47
|
+
type InputType = boolean[]
|
|
48
|
+
type OutputType = boolean
|
|
49
|
+
|
|
50
|
+
const tapeFilePath = path.resolve(__dirname, './fixtures/nop')
|
|
51
|
+
try {
|
|
52
|
+
await fs.promises.unlink(tapeFilePath + '.log')
|
|
53
|
+
} catch (_e) {
|
|
54
|
+
// eslint-disable-next-line no-console
|
|
55
|
+
// console.warn('Didnt found a file to unlink')
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const tape = new RecordTape<InputType, OutputType>({ path: tapeFilePath })
|
|
59
|
+
tape.addLogItem('name', { input: [true], output: true, boundaries: {} })
|
|
60
|
+
tape.addLogItem('name', { input: [true], error: 'invalid data', boundaries: {} })
|
|
61
|
+
await tape.save()
|
|
62
|
+
|
|
63
|
+
const content = await fs.promises.readFile(tapeFilePath + '.log', 'utf8')
|
|
64
|
+
|
|
65
|
+
expect(content).toBe(logFileData)
|
|
66
|
+
})
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
describe('Save to file sync', () => {
|
|
70
|
+
it('Save sync', () => {
|
|
71
|
+
type InputType = boolean[]
|
|
72
|
+
type OutputType = boolean
|
|
73
|
+
|
|
74
|
+
const tapeFilePath = path.resolve(__dirname, './fixtures/save')
|
|
75
|
+
try {
|
|
76
|
+
fs.unlinkSync(tapeFilePath + '.log')
|
|
77
|
+
} catch (_e) {
|
|
78
|
+
// eslint-disable-next-line no-console
|
|
79
|
+
// console.warn('didnt found a file to unlink')
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const tape = new RecordTape<InputType, OutputType>({ path: tapeFilePath })
|
|
83
|
+
tape.addLogItem('name', { input: [true], output: true, boundaries: {} })
|
|
84
|
+
tape.addLogItem('name', { input: [true], error: 'invalid data', boundaries: {} })
|
|
85
|
+
tape.saveSync()
|
|
86
|
+
|
|
87
|
+
const content = fs.readFileSync(tapeFilePath + '.log', 'utf8')
|
|
88
|
+
|
|
89
|
+
expect(content).toBe(logFileData)
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
it('Save sync to a path of invalid folder', () => {
|
|
93
|
+
type InputType = boolean[]
|
|
94
|
+
type OutputType = boolean
|
|
95
|
+
|
|
96
|
+
const tapeFilePath = path.resolve(__dirname, './nowhere/nop')
|
|
97
|
+
|
|
98
|
+
const tape = new RecordTape<InputType, OutputType>({ path: tapeFilePath })
|
|
99
|
+
tape.addLogItem('name', { input: [true], output: true, boundaries: {} })
|
|
100
|
+
tape.addLogItem('name', { input: [true], error: 'invalid data', boundaries: {} })
|
|
101
|
+
|
|
102
|
+
expect(() => tape.saveSync()).toThrow('Folder doesn\'t exists')
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
it('Save sync to a log file that doesnt exist', () => {
|
|
106
|
+
type InputType = boolean[]
|
|
107
|
+
type OutputType = boolean
|
|
108
|
+
|
|
109
|
+
const tapeFilePath = path.resolve(__dirname, './fixtures/nop')
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
fs.unlinkSync(tapeFilePath + '.log')
|
|
113
|
+
} catch (_e) {
|
|
114
|
+
// eslint-disable-next-line no-console
|
|
115
|
+
// console.warn('Didnt found a file to unlink')
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const tape = new RecordTape<InputType, OutputType>({ path: tapeFilePath })
|
|
119
|
+
tape.addLogItem('name', { input: [true], output: true, boundaries: {} })
|
|
120
|
+
tape.addLogItem('name', { input: [true], error: 'invalid data', boundaries: {} })
|
|
121
|
+
tape.saveSync()
|
|
122
|
+
|
|
123
|
+
const content = fs.readFileSync(tapeFilePath + '.log', 'utf8')
|
|
124
|
+
|
|
125
|
+
expect(content).toBe(logFileData)
|
|
126
|
+
})
|
|
127
|
+
})
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { Task, createTask, Schema } from '@forgehive/task'
|
|
2
|
+
import { RecordTape, LogItem } from '../index'
|
|
3
|
+
|
|
4
|
+
describe('Task listener', () => {
|
|
5
|
+
it('Should listen to task events', async () => {
|
|
6
|
+
type InputType = Record<string, unknown>
|
|
7
|
+
type OutputType = { value: number, foo: boolean }
|
|
8
|
+
|
|
9
|
+
const tape = new RecordTape<InputType, OutputType>({})
|
|
10
|
+
const task = new Task(
|
|
11
|
+
async (_input: InputType): Promise<OutputType> => {
|
|
12
|
+
return { value: 1, foo: true }
|
|
13
|
+
}
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
task.addListener<InputType, OutputType>((record) => {
|
|
17
|
+
const logItem: LogItem<InputType, OutputType> = record.error
|
|
18
|
+
? { input: record.input, error: record.error, boundaries: record.boundaries }
|
|
19
|
+
: { input: record.input, output: record.output as OutputType, boundaries: record.boundaries }
|
|
20
|
+
|
|
21
|
+
tape.addLogItem('test', logItem)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
await task.run({})
|
|
25
|
+
|
|
26
|
+
expect(tape.getLog()).toEqual([
|
|
27
|
+
{ name: 'test', type: 'success', input: {}, output: { value: 1, foo: true }, boundaries: {} }
|
|
28
|
+
])
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('Should has errors and sucess items', async () => {
|
|
32
|
+
const task = new Task(
|
|
33
|
+
async (input: { value: number }): Promise<{ result: number }> => {
|
|
34
|
+
if (input.value < 10 || input.value > 20) {
|
|
35
|
+
throw new Error('Value is not between 10 and 20')
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return { result: input.value * 2 }
|
|
39
|
+
}
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
const tape = new RecordTape<{ value: number }, { result: number }>({})
|
|
43
|
+
|
|
44
|
+
task.addListener<{ value: number }, { result: number }>((record) => {
|
|
45
|
+
const logItem: LogItem<{ value: number }, { result: number }> = record.error
|
|
46
|
+
? { input: record.input, error: record.error, boundaries: record.boundaries }
|
|
47
|
+
: { input: record.input, output: record.output as { result: number }, boundaries: record.boundaries }
|
|
48
|
+
|
|
49
|
+
tape.addLogItem('test', logItem)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
await task.run({ value: 5 })
|
|
54
|
+
} catch (_error) {
|
|
55
|
+
// this is expected
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
await task.run({ value: 15 })
|
|
59
|
+
|
|
60
|
+
const log = tape.getLog()
|
|
61
|
+
|
|
62
|
+
expect(log).toEqual([
|
|
63
|
+
{ name: 'test', type: 'error', input: { value: 5 }, error: 'Value is not between 10 and 20', boundaries: {} },
|
|
64
|
+
{ name: 'test', type: 'success', input: { value: 15 }, output: { result: 30 }, boundaries: {} }
|
|
65
|
+
])
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('Should get types from task', async () => {
|
|
69
|
+
// Create a schema for the task
|
|
70
|
+
const schema = new Schema({
|
|
71
|
+
value: Schema.number()
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
// Define the boundaries
|
|
75
|
+
const boundaries = {
|
|
76
|
+
multiply: async (value: number): Promise<number> => {
|
|
77
|
+
return value * 2
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Create the task using createTask
|
|
82
|
+
const task = createTask(
|
|
83
|
+
schema,
|
|
84
|
+
boundaries,
|
|
85
|
+
async (input, { multiply }) => {
|
|
86
|
+
const result = await multiply(input.value)
|
|
87
|
+
return { result }
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
type InputType = typeof schema
|
|
92
|
+
type OutputType = Awaited<ReturnType<typeof task.run>>
|
|
93
|
+
|
|
94
|
+
const tape = new RecordTape<InputType, OutputType>({})
|
|
95
|
+
|
|
96
|
+
task.addListener<InputType, OutputType>((record) => {
|
|
97
|
+
const logItem: LogItem<InputType, OutputType> = record.error
|
|
98
|
+
? { input: record.input, error: record.error, boundaries: record.boundaries }
|
|
99
|
+
: { input: record.input, output: record.output as OutputType, boundaries: record.boundaries }
|
|
100
|
+
|
|
101
|
+
tape.addLogItem('test', logItem)
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
await task.run({ value: 5 })
|
|
105
|
+
|
|
106
|
+
expect(tape.getLog()).toEqual([
|
|
107
|
+
{
|
|
108
|
+
name: 'test',
|
|
109
|
+
type: 'success',
|
|
110
|
+
input: { value: 5 },
|
|
111
|
+
output: { result: 10 },
|
|
112
|
+
boundaries: {
|
|
113
|
+
multiply: [{ input: [5], output: 10 }]
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
])
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
it('Should listen to task events with boundaries', async () => {
|
|
120
|
+
type InputType = { value: number }
|
|
121
|
+
type OutputType = { result: number }
|
|
122
|
+
|
|
123
|
+
const tape = new RecordTape<InputType, OutputType>({})
|
|
124
|
+
|
|
125
|
+
// Create a schema for the task
|
|
126
|
+
const schema = new Schema({
|
|
127
|
+
value: Schema.number()
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
// Define the boundaries
|
|
131
|
+
const boundaries = {
|
|
132
|
+
multiply: async (value: number): Promise<number> => {
|
|
133
|
+
return value * 2
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Create the task using createTask
|
|
138
|
+
const task = createTask(
|
|
139
|
+
schema,
|
|
140
|
+
boundaries,
|
|
141
|
+
async (input, { multiply }) => {
|
|
142
|
+
const result = await multiply(input.value)
|
|
143
|
+
return { result }
|
|
144
|
+
}
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
task.addListener<InputType, OutputType>((record) => {
|
|
148
|
+
const logItem: LogItem<InputType, OutputType> = record.error
|
|
149
|
+
? { input: record.input, error: record.error, boundaries: record.boundaries }
|
|
150
|
+
: { input: record.input, output: record.output as OutputType, boundaries: record.boundaries }
|
|
151
|
+
|
|
152
|
+
tape.addLogItem('test', logItem)
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
await task.run({ value: 5 })
|
|
156
|
+
|
|
157
|
+
expect(tape.getLog()).toEqual([
|
|
158
|
+
{
|
|
159
|
+
name: 'test',
|
|
160
|
+
type: 'success',
|
|
161
|
+
input: { value: 5 },
|
|
162
|
+
output: { result: 10 },
|
|
163
|
+
boundaries: {
|
|
164
|
+
multiply: [{ input: [5], output: 10 }]
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
])
|
|
168
|
+
})
|
|
169
|
+
})
|
|
170
|
+
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "./dist",
|
|
5
|
+
"rootDir": "./src",
|
|
6
|
+
"composite": false,
|
|
7
|
+
"incremental": false,
|
|
8
|
+
"declaration": true,
|
|
9
|
+
"declarationMap": true,
|
|
10
|
+
"sourceMap": true
|
|
11
|
+
},
|
|
12
|
+
"include": [
|
|
13
|
+
"src/**/*"
|
|
14
|
+
],
|
|
15
|
+
"exclude": [
|
|
16
|
+
"node_modules",
|
|
17
|
+
"dist"
|
|
18
|
+
]
|
|
19
|
+
}
|