Write tests for fileUpload

This commit is contained in:
Robert Schäfer 2019-05-21 00:39:26 +02:00
parent 4dbf1b2a2c
commit d624a3f232
4 changed files with 90 additions and 21 deletions

View File

View File

@ -0,0 +1,27 @@
import { createWriteStream } from 'fs'
import path from 'path'
import slug from 'slug'
const storeUpload = ({ createReadStream, fileLocation}) =>
new Promise((resolve, reject) =>
createReadStream()
.pipe(createWriteStream(`public${fileLocation}`))
.on("finish", resolve)
.on("error", reject)
);
export default async function fileUpload(params, { file, url}, uploadCallback = storeUpload) {
const upload = params[file]
if (upload) {
const { createReadStream, filename } = await upload;
const { name } = path.parse(filename)
const fileLocation = `/uploads/${Date.now()}-${slug(name)}`
await uploadCallback({ createReadStream, fileLocation });
delete params[file]
params[url] = fileLocation
}
return params
}

View File

@ -0,0 +1,56 @@
import fileUpload from '.'
describe('fileUpload', () => {
let params
let uploadCallback
beforeEach(() => {
params = {
uploadAttribute: {
filename: 'avatar.jpg',
mimetype: 'image/jpeg',
encoding: '7bit',
createReadStream: jest.fn()
}
}
uploadCallback = jest.fn()
})
it('calls uploadCallback', async () => {
await fileUpload(params, { file: 'uploadAttribute', url: 'attribute'}, uploadCallback)
expect(uploadCallback).toHaveBeenCalled()
})
describe('file name', () => {
it('saves the upload url in params[url]', async () => {
await fileUpload(params, { file: 'uploadAttribute', url: 'attribute'}, uploadCallback)
expect(params.attribute).toMatch(/^\/uploads\/\d+-avatar$/)
})
it('uses the name without file ending', async () => {
params.uploadAttribute.filename = 'somePng.png'
await fileUpload(params, { file: 'uploadAttribute', url: 'attribute'}, uploadCallback)
expect(params.attribute).toMatch(/^\/uploads\/\d+-somePng/)
})
it('creates a url safe name', async () => {
params.uploadAttribute.filename = '/path/to/awkward?/ file-location/?foo- bar-avatar.jpg?foo- bar'
await fileUpload(params, { file: 'uploadAttribute', url: 'attribute'}, uploadCallback)
expect(params.attribute).toMatch(/^\/uploads\/\d+-foo-bar-avatar$/)
})
describe('in case of duplicates', () => {
it('creates unique names to avoid overwriting existing files', async () => {
const { attribute: first } = await fileUpload({
...params
}, { file: 'uploadAttribute', url: 'attribute'}, uploadCallback)
await new Promise(resolve => setTimeout(resolve, 1000));
const { attribute: second } = await fileUpload({
...params
}, { file: 'uploadAttribute', url: 'attribute'}, uploadCallback)
expect(first).not.toEqual(second)
})
})
})
})

View File

@ -1,29 +1,15 @@
import { neo4jgraphql } from 'neo4j-graphql-js'
import { createWriteStream } from 'fs'
const storeUpload = ({ stream, fileLocation}) =>
new Promise((resolve, reject) =>
stream
.pipe(createWriteStream(`public${fileLocation}`))
.on("finish", () => resolve())
.on("error", reject)
);
import fileUpload from './fileUpload'
export default {
Mutation: {
UpdateUser: async (object, params, context, resolveInfo) => {
const { avatarUpload } = params
if (avatarUpload) {
const { stream, filename } = await avatarUpload ;
const fileLocation = `/uploads/${filename}`
await storeUpload({ stream, fileLocation });
delete params.avatarUpload
params.avatar = fileLocation
}
params = await fileUpload(params, { file: 'avatarUpload', url: 'avatar'})
return await neo4jgraphql(object, params, context, resolveInfo, false)
},
CreateUser: async (object, params, context, resolveInfo) => {
params = await fileUpload(params, { file: 'avatarUpload', url: 'avatar'})
return await neo4jgraphql(object, params, context, resolveInfo, false)
}
},
}
};