|
@@ -1,34 +1,65 @@
|
|
jest.mock('fs')
|
|
jest.mock('fs')
|
|
-jest.mock('child_process')
|
|
|
|
jest.mock('os')
|
|
jest.mock('os')
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * Asynchronous mock function that returns a promise witch
|
|
|
|
+ * resolves or rejects based on the arguments given.
|
|
|
|
+ * @param {object} unnamed - Either error or result
|
|
|
|
+ */
|
|
|
|
+function AsyncMock ({ result, error }) {
|
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
|
+ if (error) reject(error)
|
|
|
|
+ resolve(result)
|
|
|
|
+ })
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const mockSpawn = jest.fn()
|
|
|
|
+const mockSend = jest.fn()
|
|
|
|
+
|
|
|
|
+const PythonWorker = require('../../src/pythonWorker')
|
|
|
|
+// Mock constructor for the PythonWorker
|
|
|
|
+jest.mock('../../src/pythonWorker', () => {
|
|
|
|
+ return function (args) {
|
|
|
|
+ this.spawn = mockSpawn
|
|
|
|
+ this.send = mockSend
|
|
|
|
+ }
|
|
|
|
+})
|
|
|
|
+
|
|
const md5 = require('md5')
|
|
const md5 = require('md5')
|
|
const { resolvers, typeDefs, __test__ } = require('../../src/interfaces')
|
|
const { resolvers, typeDefs, __test__ } = require('../../src/interfaces')
|
|
-const child_process = require('child_process')
|
|
|
|
-child_process.addCRPair({
|
|
|
|
- input: 'options',
|
|
|
|
- output: "[{'option1':'value1'},{'option2':'value2'}]"
|
|
|
|
-})
|
|
|
|
|
|
+// const child_process = require('child_process')
|
|
|
|
+// child_process.addCRPair({
|
|
|
|
+// input: '{"type":"options"}\n',
|
|
|
|
+// output: "[{'option1':'value1'},{'option2':'value2'}]"
|
|
|
|
+// })
|
|
|
|
|
|
describe('interfaces module', () => {
|
|
describe('interfaces module', () => {
|
|
it('exports resolvers and typeDefs', () => {
|
|
it('exports resolvers and typeDefs', () => {
|
|
expect(resolvers).toBeDefined()
|
|
expect(resolvers).toBeDefined()
|
|
expect(typeDefs).toBeDefined()
|
|
expect(typeDefs).toBeDefined()
|
|
- })
|
|
|
|
- it('resolves queries and mutations', () => {
|
|
|
|
expect(resolvers).toHaveProperty('Query'),
|
|
expect(resolvers).toHaveProperty('Query'),
|
|
expect(resolvers).toHaveProperty('Mutation')
|
|
expect(resolvers).toHaveProperty('Mutation')
|
|
})
|
|
})
|
|
|
|
|
|
it('finds workers', async () => {
|
|
it('finds workers', async () => {
|
|
|
|
+ // Check that all possible return values of fs.readdir are correctly handled.
|
|
const { findWorkers } = __test__
|
|
const { findWorkers } = __test__
|
|
- await expect(findWorkers('/')).resolves.toEqual([])
|
|
|
|
|
|
+
|
|
|
|
+ // 1. Check use case
|
|
await expect(findWorkers('python_workers')).resolves.toEqual([
|
|
await expect(findWorkers('python_workers')).resolves.toEqual([
|
|
'test1_worker.py',
|
|
'test1_worker.py',
|
|
'test2_worker.py'
|
|
'test2_worker.py'
|
|
])
|
|
])
|
|
|
|
+
|
|
|
|
+ // 2. Check empty directory
|
|
|
|
+ await expect(findWorkers('/')).resolves.toEqual([])
|
|
|
|
+
|
|
|
|
+ // 3. Check argument error
|
|
await expect(findWorkers()).rejects.toThrow(
|
|
await expect(findWorkers()).rejects.toThrow(
|
|
'Directory argument must be a string.'
|
|
'Directory argument must be a string.'
|
|
)
|
|
)
|
|
|
|
+
|
|
|
|
+ // 4. Check non-existing path
|
|
await expect(findWorkers('/DOESNTEXIST')).rejects.toThrow(
|
|
await expect(findWorkers('/DOESNTEXIST')).rejects.toThrow(
|
|
`ENOENT: no such file or directory, scandir '/DOESNTEXIST'`
|
|
`ENOENT: no such file or directory, scandir '/DOESNTEXIST'`
|
|
)
|
|
)
|
|
@@ -37,62 +68,63 @@ describe('interfaces module', () => {
|
|
it('finds options', async () => {
|
|
it('finds options', async () => {
|
|
const { getOptions } = __test__
|
|
const { getOptions } = __test__
|
|
const options = [{ option1: 'value1' }]
|
|
const options = [{ option1: 'value1' }]
|
|
- const send = jest.fn()
|
|
|
|
- const workerProcess = { send }
|
|
|
|
|
|
+ const workerProcess = new PythonWorker()
|
|
|
|
|
|
// 1. Check the use case
|
|
// 1. Check the use case
|
|
- send.mockReturnValueOnce(
|
|
|
|
- new Promise((resolve, reject) => {
|
|
|
|
- resolve({ data: options })
|
|
|
|
- })
|
|
|
|
- )
|
|
|
|
|
|
+ mockSend.mockReturnValueOnce(AsyncMock({ result: { data: options } }))
|
|
await expect(getOptions(workerProcess)).resolves.toEqual(options)
|
|
await expect(getOptions(workerProcess)).resolves.toEqual(options)
|
|
|
|
+ expect(mockSend).toHaveBeenCalledWith({ type: 'options' })
|
|
|
|
|
|
// 2. Check empty option case
|
|
// 2. Check empty option case
|
|
- expect(workerProcess.send).toHaveBeenCalledWith({ type: 'options' })
|
|
|
|
- send.mockReturnValueOnce(
|
|
|
|
- new Promise((resolve, reject) => {
|
|
|
|
- resolve({ data: [] })
|
|
|
|
- })
|
|
|
|
- )
|
|
|
|
|
|
+ mockSend.mockReturnValueOnce(AsyncMock({ result: { data: [] } }))
|
|
await expect(getOptions(workerProcess)).resolves.toEqual([])
|
|
await expect(getOptions(workerProcess)).resolves.toEqual([])
|
|
|
|
+ expect(mockSend).toHaveBeenCalledWith({ type: 'options' })
|
|
|
|
|
|
// 3. Check error case
|
|
// 3. Check error case
|
|
- expect(workerProcess.send).toHaveBeenCalledWith({ type: 'options' })
|
|
|
|
- send.mockReturnValueOnce(
|
|
|
|
- new Promise((resolve, reject) => {
|
|
|
|
- resolve({ error: 'Timeout' })
|
|
|
|
- })
|
|
|
|
- )
|
|
|
|
|
|
+ mockSend.mockReturnValueOnce(AsyncMock({ result: { error: 'Timeout' } }))
|
|
await expect(getOptions(workerProcess)).rejects.toThrow('Timeout')
|
|
await expect(getOptions(workerProcess)).rejects.toThrow('Timeout')
|
|
|
|
|
|
// 4. Throw error if workerProcess doesn't have a "send" property.
|
|
// 4. Throw error if workerProcess doesn't have a "send" property.
|
|
- await expect(getOptions()).rejects.toThrow(
|
|
|
|
|
|
+ expect(getOptions()).rejects.toThrow(
|
|
'workerProcess not configured properly.'
|
|
'workerProcess not configured properly.'
|
|
)
|
|
)
|
|
})
|
|
})
|
|
|
|
|
|
- it('generates interface', async () => {
|
|
|
|
|
|
+ it('creates an interface', async () => {
|
|
const { createInterface } = __test__
|
|
const { createInterface } = __test__
|
|
|
|
+ const testInterfaces = []
|
|
|
|
+ mockSpawn.mockReset()
|
|
|
|
+ mockSend.mockReset()
|
|
|
|
+
|
|
|
|
+ // 1. Check the use case
|
|
|
|
+ mockSpawn.mockReturnValueOnce(AsyncMock({ result: { data: 'ready!' } }))
|
|
|
|
+ mockSend.mockReturnValueOnce(AsyncMock({ result: { data: [] } }))
|
|
|
|
+ await expect(
|
|
|
|
+ createInterface('python_workers', 'test1_worker.py', [])
|
|
|
|
+ ).resolves.toMatchObject({
|
|
|
|
+ id: md5(`test1python_workers/test1_worker.py1980-03-18T03:15:00.000Z`),
|
|
|
|
+ interfaceName: 'test1',
|
|
|
|
+ options: [],
|
|
|
|
+ workerProcess: expect.objectContaining({
|
|
|
|
+ send: expect.anything(),
|
|
|
|
+ spawn: expect.anything()
|
|
|
|
+ })
|
|
|
|
+ // diini: 12
|
|
|
|
+ })
|
|
|
|
+ expect(mockSpawn).toHaveBeenCalled()
|
|
|
|
+ expect(mockSend).toHaveBeenCalledWith({ type: 'options' })
|
|
|
|
+
|
|
|
|
+ // 2. Check argument error case
|
|
await expect(createInterface()).rejects.toThrow(
|
|
await expect(createInterface()).rejects.toThrow(
|
|
'Directory argument must be a string.'
|
|
'Directory argument must be a string.'
|
|
)
|
|
)
|
|
|
|
+
|
|
|
|
+ // 3. Check missing file case
|
|
await expect(
|
|
await expect(
|
|
- createInterface('python_workers', 'testXXX_worker.py')
|
|
|
|
|
|
+ createInterface('python_workers', 'testXXX_worker.py', [])
|
|
).rejects.toThrow(
|
|
).rejects.toThrow(
|
|
`ENOENT: no such file or directory, scandir 'python_workers/testXXX_worker.py'`
|
|
`ENOENT: no such file or directory, scandir 'python_workers/testXXX_worker.py'`
|
|
)
|
|
)
|
|
- await expect(
|
|
|
|
- createInterface('python_workers', 'test1_worker.py')
|
|
|
|
- ).resolves.toMatchObject({
|
|
|
|
- id: md5(`test1python_workers/test1_worker.py1980-03-18T03:15:00.000Z`),
|
|
|
|
- interfaceName: 'test1',
|
|
|
|
- options: [],
|
|
|
|
- workerProcess: {
|
|
|
|
- error: []
|
|
|
|
- },
|
|
|
|
- dini: 12
|
|
|
|
- })
|
|
|
|
})
|
|
})
|
|
|
|
|
|
const { Query, Mutation, Interface, Connection } = resolvers
|
|
const { Query, Mutation, Interface, Connection } = resolvers
|