Update dependencies / Add tests
This commit is contained in:
+9
-8
@@ -12,7 +12,7 @@
|
|||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "ts-node src/index.ts",
|
"dev": "ts-node src/index.ts",
|
||||||
"test": "jest --config jestconfig.json",
|
"test": "jest",
|
||||||
"build": "rm -rf pkg/ && pika build",
|
"build": "rm -rf pkg/ && pika build",
|
||||||
"format": "prettier --write \"src/**/*.ts\" --write \"test/**/*.ts\"",
|
"format": "prettier --write \"src/**/*.ts\" --write \"test/**/*.ts\"",
|
||||||
"lint": "tslint -p tsconfig.json && yarn spell",
|
"lint": "tslint -p tsconfig.json && yarn spell",
|
||||||
@@ -69,23 +69,24 @@
|
|||||||
"@pika/pack": "^0.5.0",
|
"@pika/pack": "^0.5.0",
|
||||||
"@pika/plugin-build-node": "^0.9.2",
|
"@pika/plugin-build-node": "^0.9.2",
|
||||||
"@pika/plugin-ts-standard-pkg": "^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/jest": "^25.1.4",
|
||||||
"@types/node": "^13.9.1",
|
"@types/node": "^13.9.8",
|
||||||
"flowgen": "^1.10.0",
|
"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-package.json": "^1.0.2",
|
||||||
"pika-plugin-typedefs-to-flow": "^0.0.2",
|
"pika-plugin-typedefs-to-flow": "^0.0.2",
|
||||||
"prettier": "^1.19.1",
|
"prettier": "^1.19.1",
|
||||||
"size-limit": "^4.3.1",
|
"size-limit": "^4.4.2",
|
||||||
"ts-jest": "^25.2.1",
|
"ts-jest": "^25.3.0",
|
||||||
"ts-node": "^8.6.2",
|
"ts-node": "^8.8.1",
|
||||||
"tslint": "^6.1.0",
|
"tslint": "^6.1.0",
|
||||||
"tslint-config-prettier": "^1.18.0",
|
"tslint-config-prettier": "^1.18.0",
|
||||||
"tslint-config-security": "^1.16.0",
|
"tslint-config-security": "^1.16.0",
|
||||||
"tslint-config-standard-plus": "^2.3.0",
|
"tslint-config-standard-plus": "^2.3.0",
|
||||||
"typescript": "^3.8.3",
|
"typescript": "^3.8.3",
|
||||||
"yaspeller": "^6.0.3"
|
"yaspeller": "^6.1.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.9.0"
|
"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 we get there inside of recursion -> this is bad
|
||||||
if (recursive) {
|
if (recursive) {
|
||||||
|
// by tests looks like this is impossible case -> should remove it?
|
||||||
throw new Error('Bad source, possible recursive iterables?')
|
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