Update dependencies / Add tests
This commit is contained in:
+9
-8
@@ -12,7 +12,7 @@
|
||||
],
|
||||
"scripts": {
|
||||
"dev": "ts-node src/index.ts",
|
||||
"test": "jest --config jestconfig.json",
|
||||
"test": "jest",
|
||||
"build": "rm -rf pkg/ && pika build",
|
||||
"format": "prettier --write \"src/**/*.ts\" --write \"test/**/*.ts\"",
|
||||
"lint": "tslint -p tsconfig.json && yarn spell",
|
||||
@@ -69,23 +69,24 @@
|
||||
"@pika/pack": "^0.5.0",
|
||||
"@pika/plugin-build-node": "^0.9.2",
|
||||
"@pika/plugin-ts-standard-pkg": "^0.9.2",
|
||||
"@size-limit/preset-small-lib": "^4.3.1",
|
||||
"@size-limit/preset-small-lib": "^4.4.2",
|
||||
"@types/jest": "^25.1.4",
|
||||
"@types/node": "^13.9.1",
|
||||
"@types/node": "^13.9.8",
|
||||
"flowgen": "^1.10.0",
|
||||
"jest": "^25.1.0",
|
||||
"jest": "^25.2.4",
|
||||
"nock": "^12.0.3",
|
||||
"pika-plugin-package.json": "^1.0.2",
|
||||
"pika-plugin-typedefs-to-flow": "^0.0.2",
|
||||
"prettier": "^1.19.1",
|
||||
"size-limit": "^4.3.1",
|
||||
"ts-jest": "^25.2.1",
|
||||
"ts-node": "^8.6.2",
|
||||
"size-limit": "^4.4.2",
|
||||
"ts-jest": "^25.3.0",
|
||||
"ts-node": "^8.8.1",
|
||||
"tslint": "^6.1.0",
|
||||
"tslint-config-prettier": "^1.18.0",
|
||||
"tslint-config-security": "^1.16.0",
|
||||
"tslint-config-standard-plus": "^2.3.0",
|
||||
"typescript": "^3.8.3",
|
||||
"yaspeller": "^6.0.3"
|
||||
"yaspeller": "^6.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.9.0"
|
||||
|
||||
@@ -69,6 +69,7 @@ export const toTuples = (source: Source, recursive = false): TupleSource[] => {
|
||||
|
||||
// if we get there inside of recursion -> this is bad
|
||||
if (recursive) {
|
||||
// by tests looks like this is impossible case -> should remove it?
|
||||
throw new Error('Bad source, possible recursive iterables?')
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import nock from 'nock'
|
||||
import FormData from 'form-data'
|
||||
import { client } from '../../src/client/node'
|
||||
|
||||
// Helper function to get response JOSN body
|
||||
async function toJSON(response: any) {
|
||||
const chunks: any[] = []
|
||||
const text = await new Promise<string>((resolve, reject) => {
|
||||
response.on('data', (chunk: any) => chunks.push(chunk))
|
||||
response.on('error', reject)
|
||||
response.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')))
|
||||
})
|
||||
return JSON.parse(text)
|
||||
}
|
||||
|
||||
test('`client` should return functional client', () => {
|
||||
const clnt = client()
|
||||
expect(typeof clnt.get).toBe('function')
|
||||
expect(typeof clnt.post).toBe('function')
|
||||
})
|
||||
|
||||
test('Should do GET request', async () => {
|
||||
nock('https://127.0.0.1:3000')
|
||||
.get('/ping')
|
||||
.reply(200, { status: 'OK' })
|
||||
|
||||
const clnt = client()
|
||||
const response = await clnt.get!('https://127.0.0.1:3000/ping')
|
||||
expect(await toJSON(response)).toEqual({ status: 'OK' })
|
||||
})
|
||||
|
||||
test('Should throw on bad GET request', async () => {
|
||||
nock('https://127.0.0.1:3000')
|
||||
.get('/ping')
|
||||
.reply(500)
|
||||
|
||||
const clnt = client()
|
||||
let error: any
|
||||
try {
|
||||
await clnt.get!('https://127.0.0.1:3000/ping')
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
expect(error).toEqual(new Error('500 null'))
|
||||
})
|
||||
|
||||
test('Should do POST request', async () => {
|
||||
nock('https://127.0.0.1:3000')
|
||||
.post('/convert/html')
|
||||
.reply(200, { status: 'OK' })
|
||||
|
||||
const clnt = client()
|
||||
const response = await clnt.post('https://127.0.0.1:3000/convert/html', new FormData())
|
||||
expect(await toJSON(response)).toEqual({ status: 'OK' })
|
||||
})
|
||||
|
||||
test('Should throw on bad POST request', async () => {
|
||||
nock('https://127.0.0.1:3000')
|
||||
.post('/convert/html')
|
||||
.reply(500, { status: 'ERROR' })
|
||||
|
||||
const clnt = client()
|
||||
let error: any
|
||||
try {
|
||||
await clnt.post('https://127.0.0.1:3000/convert/html', new FormData())
|
||||
} catch (e) {
|
||||
error = e
|
||||
}
|
||||
expect(error).toEqual(new Error('500 null (undefined)')) // hm???
|
||||
})
|
||||
|
||||
test('Should handle http', async () => {
|
||||
nock('http://127.0.0.1:3000')
|
||||
.get('/ping')
|
||||
.reply(200, { status: 'OK' })
|
||||
|
||||
const clnt = client()
|
||||
const response = await clnt.get!('http://127.0.0.1:3000/ping')
|
||||
expect(await toJSON(response)).toEqual({ status: 'OK' })
|
||||
})
|
||||
@@ -0,0 +1,74 @@
|
||||
import { RequestType } from '../src'
|
||||
import { gotenberg } from '../src/gotenberg'
|
||||
|
||||
test('Test `gotenberg` function without client', () => {
|
||||
const fn = gotenberg('http://120.0.0.1:3000')
|
||||
expect(typeof fn).toBe('function')
|
||||
expect(fn('test')).toMatchObject({
|
||||
type: RequestType.Undefined,
|
||||
url: 'http://120.0.0.1:3000',
|
||||
source: 'test',
|
||||
fields: {},
|
||||
})
|
||||
})
|
||||
|
||||
test('Test `gotenberg` function with custom client', () => {
|
||||
const client = {
|
||||
get() {}, // tslint:disable-line: no-empty
|
||||
post() {}, // tslint:disable-line: no-empty
|
||||
}
|
||||
const fn = gotenberg('http://120.0.0.1:3000', client)
|
||||
expect(typeof fn).toBe('function')
|
||||
expect(fn('test')).toEqual({
|
||||
type: RequestType.Undefined,
|
||||
client,
|
||||
url: 'http://120.0.0.1:3000',
|
||||
source: 'test',
|
||||
fields: {},
|
||||
})
|
||||
})
|
||||
|
||||
test('Test `gotenberg` function with custom functional client', () => {
|
||||
const mock = jest.fn()
|
||||
const clientImpl = {
|
||||
get() {}, // tslint:disable-line: no-empty
|
||||
post() {}, // tslint:disable-line: no-empty
|
||||
}
|
||||
const client = function(arg: any) {
|
||||
mock(arg)
|
||||
return clientImpl
|
||||
}
|
||||
const fn = gotenberg('http://120.0.0.1:3000', client, { base: 'test' })
|
||||
expect(typeof fn).toBe('function')
|
||||
expect(fn('test')).toEqual({
|
||||
type: RequestType.Undefined,
|
||||
client: clientImpl,
|
||||
url: 'http://120.0.0.1:3000',
|
||||
source: 'test',
|
||||
fields: {},
|
||||
})
|
||||
expect(mock.mock.calls.length).toBe(1)
|
||||
expect(mock.mock.calls[0][0]).toEqual({ base: 'test' })
|
||||
})
|
||||
|
||||
test('Test `gotenberg` function with custom class client', () => {
|
||||
const mock = jest.fn()
|
||||
class Client {
|
||||
constructor(arg: any) {
|
||||
mock(arg)
|
||||
}
|
||||
get() {} // tslint:disable-line: no-empty
|
||||
post() {} // tslint:disable-line: no-empty
|
||||
}
|
||||
const fn = gotenberg('http://120.0.0.1:3000', Client, { base: 'test' })
|
||||
expect(typeof fn).toBe('function')
|
||||
expect(fn('test')).toEqual({
|
||||
type: RequestType.Undefined,
|
||||
client: expect.any(Client),
|
||||
url: 'http://120.0.0.1:3000',
|
||||
source: 'test',
|
||||
fields: {},
|
||||
})
|
||||
expect(mock.mock.calls.length).toBe(1)
|
||||
expect(mock.mock.calls[0][0]).toEqual({ base: 'test' })
|
||||
})
|
||||
@@ -0,0 +1,71 @@
|
||||
import { Readable } from 'stream'
|
||||
import { basename } from 'path'
|
||||
import { createReadStream, ReadStream } from 'fs'
|
||||
import {
|
||||
DEFAULT_FILENAME,
|
||||
fromFile,
|
||||
toStream,
|
||||
toStreams,
|
||||
toTuples,
|
||||
} from '../../src/internal/source-converters'
|
||||
|
||||
// tslint:disable no-any
|
||||
|
||||
test('Test `toTuples` function', () => {
|
||||
expect(() => toTuples(undefined as any)).toThrow()
|
||||
expect(toTuples(new URL('http://1'))).toEqual([])
|
||||
expect(toTuples('file://test.html')).toEqual([[DEFAULT_FILENAME, 'file://test.html']])
|
||||
expect(toTuples('file://test.doc')).toEqual([['test.doc', 'file://test.doc']])
|
||||
expect(toTuples('test')).toEqual([[DEFAULT_FILENAME, 'test']])
|
||||
|
||||
const buffer = Buffer.from('test')
|
||||
expect(toTuples(buffer)).toEqual([[DEFAULT_FILENAME, buffer]])
|
||||
|
||||
const stream = new Readable()
|
||||
expect(toTuples(stream)).toEqual([[DEFAULT_FILENAME, stream]])
|
||||
|
||||
const file = createReadStream(__filename)
|
||||
expect(toTuples(file)).toEqual([[basename(__filename), file]])
|
||||
|
||||
expect(toTuples(['index.html', 'test'])).toEqual([['index.html', 'test']])
|
||||
expect(toTuples({ 'index.html': 'test' })).toEqual([['index.html', 'test']])
|
||||
|
||||
const map = new Map<string, any>()
|
||||
map.set('index.html', 'test')
|
||||
expect(toTuples(map)).toEqual([['index.html', 'test']])
|
||||
|
||||
const set = new Set<any>()
|
||||
set.add(new Set<any>())
|
||||
expect(() => toTuples(set)).toThrow('Bad source, don\'t know what to do with "[object Set]"')
|
||||
})
|
||||
|
||||
test('Test `fromFile` function', () => {
|
||||
expect(fromFile('file:' + __filename) instanceof ReadStream).toBe(true)
|
||||
expect(fromFile('file://' + __filename) instanceof ReadStream).toBe(true)
|
||||
})
|
||||
|
||||
test('Test `toStream` function', async () => {
|
||||
const stream0 = new Readable()
|
||||
expect(toStream(stream0)).toEqual(stream0)
|
||||
expect(toStream('file:' + __filename) instanceof ReadStream).toBe(true)
|
||||
expect(toStream('test') instanceof Readable).toBe(true)
|
||||
|
||||
const chunks: any[] = []
|
||||
const stream = toStream('test')
|
||||
const result = await new Promise((resolve, reject) => {
|
||||
stream.on('data', chunk => chunks.push(chunk))
|
||||
stream.on('error', reject)
|
||||
stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')))
|
||||
})
|
||||
expect(result).toEqual('test')
|
||||
})
|
||||
|
||||
test('Test `toStreams` function', () => {
|
||||
expect(toStreams()).toEqual([])
|
||||
|
||||
const result1 = toStreams(Buffer.from('test'))
|
||||
expect(result1 instanceof Array).toBe(true)
|
||||
expect(result1[0] instanceof Array).toBe(true)
|
||||
expect(result1[0][0]).toEqual(DEFAULT_FILENAME)
|
||||
expect(result1[0][1] instanceof Readable).toBe(true)
|
||||
})
|
||||
@@ -0,0 +1,120 @@
|
||||
import FormData from 'form-data'
|
||||
import { createReadStream } from 'fs'
|
||||
import { HtmlRequest, MarkdownRequest, OfficeRequest, PingRequest, RequestType } from '../src'
|
||||
import { please } from '../src/please'
|
||||
|
||||
test('Should make client POST call with request', async () => {
|
||||
const get = jest.fn()
|
||||
const post = jest.fn()
|
||||
const request: HtmlRequest = {
|
||||
type: RequestType.Html,
|
||||
client: { get, post },
|
||||
url: 'http://120.0.0.1:3000/convert/html',
|
||||
source: 'test',
|
||||
fields: {},
|
||||
}
|
||||
|
||||
await please(request)
|
||||
|
||||
expect(post.mock.calls.length).toBe(1)
|
||||
expect(post.mock.calls[0][0]).toEqual('http://120.0.0.1:3000/convert/html')
|
||||
expect(post.mock.calls[0][1]).toEqual(expect.any(FormData))
|
||||
})
|
||||
|
||||
test('Should make client GET call with ping request', async () => {
|
||||
const get = jest.fn()
|
||||
const post = jest.fn()
|
||||
const request: PingRequest = {
|
||||
type: RequestType.Ping,
|
||||
client: {
|
||||
get: async url => {
|
||||
get(url)
|
||||
return createReadStream(__filename)
|
||||
},
|
||||
post,
|
||||
},
|
||||
url: 'http://120.0.0.1:3000/ping',
|
||||
fields: {},
|
||||
}
|
||||
|
||||
await please(request)
|
||||
|
||||
expect(get.mock.calls.length).toBe(1)
|
||||
expect(get.mock.calls[0][0]).toEqual('http://120.0.0.1:3000/ping')
|
||||
})
|
||||
|
||||
test('Should throw on ping request if there is no get method', () => {
|
||||
const post = jest.fn()
|
||||
const request: PingRequest = {
|
||||
type: RequestType.Ping,
|
||||
client: { post },
|
||||
url: 'http://120.0.0.1:3000/ping',
|
||||
fields: {},
|
||||
}
|
||||
|
||||
expect(() => please(request)).toThrow(`Gotenberg client doesn't implements "get" method`)
|
||||
})
|
||||
|
||||
test('Should make client POST call with request', async () => {
|
||||
const get = jest.fn()
|
||||
const post = jest.fn()
|
||||
|
||||
const fields = Object.create({ test: 'test' }) // this is to test 'hasOwnProperty'
|
||||
fields.landscape = true
|
||||
fields.resultFilename = 'index.pdf'
|
||||
fields.waitDelay = undefined
|
||||
|
||||
const request: HtmlRequest = {
|
||||
type: RequestType.Html,
|
||||
client: { get, post },
|
||||
url: 'http://120.0.0.1:3000/convert/html',
|
||||
source: 'test',
|
||||
fields,
|
||||
headers: { 'Gotenberg-Remoteurl-Test': 'Foo' },
|
||||
}
|
||||
|
||||
await please(request)
|
||||
|
||||
expect(post.mock.calls.length).toBe(1)
|
||||
expect(post.mock.calls[0][0]).toEqual('http://120.0.0.1:3000/convert/html')
|
||||
expect(post.mock.calls[0][1]).toEqual(expect.any(FormData))
|
||||
expect(post.mock.calls[0][2]).toEqual({ 'Gotenberg-Remoteurl-Test': 'Foo' })
|
||||
})
|
||||
|
||||
test('Should throw on duplicates', () => {
|
||||
const request: HtmlRequest = {
|
||||
type: RequestType.Html,
|
||||
source: [
|
||||
['index.html', 'test'],
|
||||
['index.html', 'test'],
|
||||
],
|
||||
} as any
|
||||
|
||||
expect(() => please(request)).toThrow(`There are duplicates in file names: index.html`)
|
||||
})
|
||||
|
||||
test('Should throw on wrong source filenames', () => {
|
||||
const request1: HtmlRequest = {
|
||||
type: RequestType.Html,
|
||||
source: { 'test.doc': 'test' },
|
||||
} as any
|
||||
|
||||
expect(() => please(request1)).toThrow(`File "index.html" is required for HTML conversion`)
|
||||
|
||||
const request2: MarkdownRequest = {
|
||||
type: RequestType.Markdown,
|
||||
source: { 'test.doc': 'test' },
|
||||
} as any
|
||||
|
||||
expect(() => please(request2)).toThrow(`File "index.html" is required for Markdown conversion`)
|
||||
|
||||
const request3: OfficeRequest = {
|
||||
type: RequestType.Office,
|
||||
source: { 'index.html': 'test' },
|
||||
} as any
|
||||
|
||||
expect(() => please(request3)).toThrow(
|
||||
`Default filename "index.html" is not allowed for Office conversion, ` +
|
||||
`looks like you didn't set filename for document`
|
||||
)
|
||||
})
|
||||
Reference in New Issue
Block a user