mirror of
https://github.com/transloadit/uppy.git
synced 2026-07-28 20:40:06 +00:00
Merge pull request #970 from transloadit/feature/thumbnail-test
Add thumbnail generation integration test
This commit is contained in:
commit
fc3dfcbcca
18 changed files with 1545 additions and 385 deletions
37
.travis.yml
37
.travis.yml
|
|
@ -1,6 +1,28 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- 8.11.4
|
||||
|
||||
before_install:
|
||||
- nvm install-latest-npm
|
||||
|
||||
install:
|
||||
- npm install
|
||||
- npm run bootstrap -- --no-ci
|
||||
|
||||
script:
|
||||
- npm run build
|
||||
- npm run test
|
||||
- 'if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then npm run test:acceptance; fi'
|
||||
- npm run uploadcdn
|
||||
|
||||
cache:
|
||||
apt: true
|
||||
directories:
|
||||
- ~/.npm
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
|
|
@ -12,19 +34,7 @@ addons:
|
|||
secure: nAMJ/d1fm9urTYsQ+1uqj6Jjf71J8rzwYBSZbTDAeUEZzAdvGc0a9H3PYWM4pnUDPo5s1c9MMetXi2XNdUbXgMKHbEnePZ2mJamqFtXMmpG8pgFmMqj+btMd7Yybt070tRsn4Vy0uBSi2H/en7F3j+grABJV+SAXqWkSB7CU1fZaN/u0DpoGBNj1ZNwkYCIhpLueYJTPRWBOodMAarXuFv5+7KFOKuZM3tF/JjsMNSSaDgTkz13BZnbX6vNPxGJJNJcyJGSaXrVW8hh1Zmvnk/XdiLy+vt7Wz1wz3A9ebiFDuydo5AAkxrLFsCJ5nGEqLg3bkr6NaTRpbM84ZT3i1FQMTdKP6OHHqwAeBscB6BkyhZhzvsFtl2YRBNK9mA3OtOYvBmTkFkNqvrPQlfu7cFtyG5+AUfSCiTTgS/vWIwoqSVAXaOEqN8Fp54ecUdkzCTttl3gXteZzNLRYvyQcFpoJb6E+dS8qAW0OFOteiwKVuPCh3nGUzBP13bRo1i9UAX7ZCTlpjinkxE8ryzbToo6ZcVQMBAkKhaw/x8GzOtfm5rgYMeQzGEoBJNfr7qqfs7JMxAIEMYjrTL9PXVOp/R8F3FdsqbV70jSyfsxMSMkwSWFRmVslG8+Djy8P3LnckGy1FEbMHnH8GZHZg+hbBzN8Be1/1fV0oRRAr939WRc=
|
||||
access_key:
|
||||
secure: OY3oWwiJghfty9wSPVvlhirvFGxPHDdIRuVkzAv6j7C/hj2BWYAP/UHrwdQ9XiYisHi/B5mGeyRVlrAf0MNGrG84rTDUbTWZbmktfuxl7A+Y6c0czk+s4SdhOiANG5b3tFl5wKq8h7uhrWH5/jWoKQ2Fz1VDCqxTvvZQbo41jSBhi7TBia626hxEePzdaiuw6HhGFZtfaoVs/FX30ylz8WDNrBjwCynjxsT52BaQrVvgEhuyzlOpI69YkZBPOq4fc3KiZ2YR43gLTx8K+sYCE9yJxdg1xT/UAawEhmedU83nyBZVo4rr7+03AixIxtI28MUCfBMlcsGwBxcKEKY/IWcp9UkPCq6+zALQoncV478tP21eYvlmxSFhYCrv+WEQlN+BcNjr4OJlmmFDbCVaF7r9qLeQPImU0+9iJU3OjrW7lpfLxORpGDEr2Nx6awKkIJCxNyK9weefeNo6Fz3V1kkyZ/7yWFeniJnRUCbahrB2XgzxIE+W307s1Qs4fm6JK7hVLTtG4fBzjChmAyGIzu744ws9WqmjvkC9D7OfnuXqanv/VcBFqPiudInerv7NL8FketUC+fxe/7XJfcxdaDGBjk8Kq7zXDohGRGymUXEoMDNJsKkMMlaKzdf7tgqdhsRJoH9NCVqrDXuG5al0UtrDP5RS7qfoxUunJmNFhlg=
|
||||
cache:
|
||||
apt: true
|
||||
directories:
|
||||
- ~/.npm
|
||||
before_install:
|
||||
- nvm install-latest-npm
|
||||
services:
|
||||
- docker
|
||||
script:
|
||||
- npm run build
|
||||
- npm run test
|
||||
- '{ if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then npm run test:acceptance; fi } || true'
|
||||
- npm run uploadcdn
|
||||
|
||||
env:
|
||||
global:
|
||||
- CXX=g++-4.8
|
||||
|
|
@ -50,6 +60,7 @@ env:
|
|||
- secure: V6qVB6vHAuSt1YPgzYpknLglnxbYJM5bsjAjQi78zZQSqrrWCMBgp5Q+Sq7Ad8nycgnPl8W8VpMnUIBqZcK4ciCW+vJBtZ7fBJLIEGMEk8+c8az8JePFcBRiaEicZPvZFuIHPteaAy6jK1GRVpjSjJi3NYEMpcDUs2aTM2bIpX0ks2WjUqTXiK8EvIaK2LTOgSBvyGUOiHwwTkom+PyD50t7jP98g+9Pn7GPwtWaUo1K8UpLArwR2fZ/nm0F2DU6ohz7o2t4LATFXuZhbOCj7O9vh+CmBf+/0C7giT3K23LbckDSK8CNTCDC2bsv8zDo5ZZtgdOvdatOD+VlsbAMkmUzzDgQ3410arZ8g1LVQw8eJwu1H+etcAinYf4r+Tr7s3dTBliMX70/IpjZrkHR9uXEi4LelBNYn6TKdLTW3lfVWkiFs/HPu4SoAmu1+sxSvwxVDDLeexQmb2fwp0r2tDKZ3eRfpQXLPACBaORnGW6ki9qXo8PBdaElxPbpzEWzAfT3F6zRjebpow+cdFBQrAga7/LrOrXerZxH2ekRWKgXzuhw7ERwVFrVN4/NlmDJXo+rm4na7n7CxY/QpZcdpthksDO9KYCqmn5dqMqFGislRvRe7PqIti8gC4pSdeUhDKsIh9OEgVNjCczvnA8rMRQ5aNmFx6wspmrBvO7qRLM=
|
||||
- secure: rVsiFPA9TvH/d2wkP8+1i5QGUuYw0q2BUAUdxyxO9hQcG/nRiHXtQfLbTRZHKwvqf0vyV6J1pJqLlVN4JO/bPhAvk55KAQJWl8UqyaeZiEN9KMcTr3fJuNFlBj4ciYiZ3BWwakblsiaGCjKMRdjki58a9f8XL2rcM8R6ccndjkTMYnBKaopSsAgouI8D5n74wQz6lODUayGOlbwlGLfGtPYplUfSLK4wghC+jgWsNjJySqJhfgYS0JCZc10Qw+FI2BoU4SZ4+P0L0YPIC9zV/cUW4qDT11N/oUgwfjZbPWfM9A/xn/d7sgDH+SpeoGdYler/lvxojj6L2mD/wAh8/lg1E6nL2aKgExE3z+fd2XV8L0osB/sulB7/Exrezg/mVejAx2IkWVHi4VEJmcTV+3WeEvTFOM3fID8dOVf+GUv+hcHdZMxS/hfj3keKCYG1P5ameMJO8FehRqhetNYnr6FTyrK+S+xitaZ/nXrTbHItPS0pZ4XA6CFs5uzMBPeDnk5/D7paPyrE/k2HAc1WmA6g37OyzYIMEV1laBz8IG0qMqg6JJmr09P/Iwrim5Ex2fAssT9Yr1WuOE2gWoF0A3XuVXQHVf4tJT6x/WDKChmbX588a47AvBgkFyoXLRilUYlET2tWnEpVxUovsbJXqvHwTXWMLO9riRjjeInbpvA=
|
||||
- secure: eq5hOqRBN2R7YO2dYdn5OjZc/zLLYYDZcCpCu/K/8fU4HYWTqxrBntjv8T0sZ5qdlAs3IniEfXxemz9V3zwvxR+vh2bGuYr2Xo7RRa2TIDuw+KUPZogrVxhXHPKfyJqstxy+dee2+pWhGkAP7caiu49eyqlboBMkzgpO/xcdehEWYRY5jPgvnlH+QRZ3GADKs1JEeltHDiZ6rYA7nj5Tyx9UoLgv4Av9UXdC29we7dLFTkVfCHE//7wfZW9+/IbxthA4qMjQOFaBrmagN5yweDg87iPTqNMth7FjzOavdUgQ2TW6d10VDEhLIZh36gLGreViKMDCEWKMQ8f/mv05Ao8+DXyXgxIn56II8lhUp5ukQ27ZWixfEKFx2lynJWRZE0pWwf8ec1+bXLQiBOE181Cl4nUT/TbFWzvV6yA+cMiQKe4y59bC4nhkK3IYgpR5kfCFOT+1tFknQ4hNJNacWwUmaDFMxYJaXEtRUn5jJa7eGRYSCrmnymbnzZ6w3Q3nQGNvNxpbBIXX/pzs0VDVTxSlgN4gA+n2jeCyjgVVrMQ/HoAS4uwm1cx89AttW+TANppg1PqWhhrJYuVEZSnvV8PM6R7rbvlS5tluezQj41YklgjsSopH7//+dbGGDNbrTTLic4J9PJR3yEtlAMdOCi53iT0R0Dt5X2WBv2QT5Eg=
|
||||
|
||||
notifications:
|
||||
slack:
|
||||
secure: L3iQQE8sZ0ik1Z26gPoNMiIam9EOEwYhraHCY60Jk/wmfH6SW/727yKXpgcb/yayx37rUZplvoO7H8e05ISxTJKSepEeqbBUIBQs48S8hr+FHk0VPtpP4HGxqaITRLm+mI1coPRvfISxzrB8d240oup6muhC9Ws4/LXi6v8miyIOs2zoYmGxd56TrUeON3UYlKt6dMava0V4bugARzrafN/tfyI9ccqbHzQLBspQvBI61DzZ5I2vnWpkjfWgIHz9Fl4VzXHqMXwjuTUEu8ibA12b3dHZiJEAoqeb9Oj9QcLPbstPLhlNTZZaOrfiFtwLctI2rFh37slDpAfk5idv3ycxcoG5rbCxgyg5i6dpQqrqHxnyglgHg2/nZ+YA5okeS7nJJNtU/4S6AFRWOUUWMVVY0VBEV+8w+uurl0PDy80RUY3uyK64qAgQ8U0M81/Ys1oyWyn78TqHcbby7V2Ws5I9Yakrq8D+mdfsWYCio8F6LXHSwJ0mt2FanJtdDvpPk9sAwsXZN0n8xhELt5TiRp3bzVIQ0IPUgF54dTG9/zWRvC1P4TFaFU/2fg73ZEUC5aWJoFMnLSZjbZvp5gwpCVd0MjSBk80nF9dHYcavIgJ0wMGI3BMb8Nn6+T11Gw/ycr7OGU4NMkj7i8vSFgKF74piWZyiNW8orkMN6XZgM+o=
|
||||
|
|
|
|||
|
|
@ -39,15 +39,22 @@ npm run build
|
|||
# https://github.com/facebook/create-react-app/pull/4626
|
||||
(cd && npm-auth-to-token -u user -p password -e user@example.com -r "$VERDACCIO_REGISTRY")
|
||||
|
||||
git checkout -b endtoend-test-build
|
||||
# HACK this thing changes all the time for some reason on CI
|
||||
# so I'll just ignore it…
|
||||
git checkout -- package-lock.json
|
||||
|
||||
# Simulate a publish of everything, to the local registry,
|
||||
# without changing things in git
|
||||
# Use --cd-version to skip version prompts
|
||||
lerna publish --yes \
|
||||
lerna version prerelease --yes \
|
||||
--exact \
|
||||
--force-publish \
|
||||
--registry="$VERDACCIO_REGISTRY" \
|
||||
--npm-client=npm \
|
||||
--no-git-tag-version --no-push \
|
||||
--canary
|
||||
--no-push
|
||||
lerna publish from-git --yes \
|
||||
--registry="$VERDACCIO_REGISTRY" \
|
||||
--no-verify-access \
|
||||
--npm-client=npm
|
||||
|
||||
# revert version changes
|
||||
git checkout -- packages/*/package.json packages/@uppy/*/package.json
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ __file="${__dir}/$(basename "${BASH_SOURCE[0]}")"
|
|||
__base="$(basename ${__file} .sh)"
|
||||
__root="$(cd "$(dirname "${__dir}")" && pwd)"
|
||||
|
||||
tests="tus-drag-drop tus-dashboard i18n-drag-drop xhr-limit providers"
|
||||
# Tests using a simple build setup.
|
||||
tests="tus-drag-drop tus-dashboard i18n-drag-drop xhr-limit providers thumbnails"
|
||||
|
||||
for t in $tests; do
|
||||
mkdir -p "${__root}/test/endtoend/$t/dist"
|
||||
|
|
@ -22,4 +23,8 @@ for t in $tests; do
|
|||
-t babelify
|
||||
done
|
||||
|
||||
(cd "${__root}/test/endtoend/create-react-app" && npm install && npm run build > /dev/null)
|
||||
# Speeecial tests that need custom builds.
|
||||
pushd "${__root}/test/endtoend/create-react-app"
|
||||
npm install
|
||||
npm run build
|
||||
popd
|
||||
|
|
|
|||
1541
package-lock.json
generated
1541
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -49,7 +49,7 @@
|
|||
"isomorphic-fetch": "2.2.1",
|
||||
"jest": "^23.5.0",
|
||||
"json3": "^3.3.2",
|
||||
"lerna": "^3.0.6",
|
||||
"lerna": "^3.4.0",
|
||||
"lint-staged": "^6.1.1",
|
||||
"minify-stream": "^1.2.0",
|
||||
"mkdirp": "0.5.1",
|
||||
|
|
@ -126,7 +126,7 @@
|
|||
"web:update:frontpage:code:sample": "cd website && ./node_modules/.bin/hexo generate && cp -f public/frontpage-code-sample.html ./themes/uppy/layout/partials/frontpage-code-sample.html",
|
||||
"web": "npm-run-all web:clean web:build",
|
||||
"uploadcdn": "bin/upload-to-cdn.sh",
|
||||
"prepare": "lerna bootstrap --hoist",
|
||||
"bootstrap": "lerna bootstrap --hoist",
|
||||
"contributors": "githubcontrib --owner transloadit --repo uppy --cols 6 $([ \"${GITHUB_TOKEN:-}\" == \"\" ] && echo \"\" || echo \"--authToken ${GITHUB_TOKEN}\") --showlogin true --sortOrder desc",
|
||||
"contributors:save": "replace-x -m '<!--contributors-->[\\s\\S]+<!--/contributors-->' \"<!--contributors-->\n## Contributors\n\n$(npm run --silent contributors)\n<!--/contributors-->\" README.md"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -20,7 +20,10 @@ module.exports = class ThumbnailGenerator extends Plugin {
|
|||
thumbnailWidth: 200
|
||||
}
|
||||
|
||||
this.opts = Object.assign({}, defaultOptions, opts)
|
||||
this.opts = {
|
||||
...defaultOptions,
|
||||
...opts
|
||||
}
|
||||
|
||||
this.addToQueue = this.addToQueue.bind(this)
|
||||
this.onRestored = this.onRestored.bind(this)
|
||||
|
|
@ -35,18 +38,18 @@ module.exports = class ThumbnailGenerator extends Plugin {
|
|||
*/
|
||||
createThumbnail (file, targetWidth) {
|
||||
const originalUrl = URL.createObjectURL(file.data)
|
||||
|
||||
const onload = new Promise((resolve, reject) => {
|
||||
const image = new Image()
|
||||
image.src = originalUrl
|
||||
image.onload = () => {
|
||||
image.addEventListener('load', () => {
|
||||
URL.revokeObjectURL(originalUrl)
|
||||
resolve(image)
|
||||
}
|
||||
image.onerror = () => {
|
||||
// The onerror event is totally useless unfortunately, as far as I know
|
||||
})
|
||||
image.addEventListener('error', (event) => {
|
||||
URL.revokeObjectURL(originalUrl)
|
||||
reject(new Error('Could not create thumbnail'))
|
||||
}
|
||||
reject(event.error || new Error('Could not create thumbnail'))
|
||||
})
|
||||
})
|
||||
|
||||
return onload
|
||||
|
|
@ -154,9 +157,7 @@ module.exports = class ThumbnailGenerator extends Plugin {
|
|||
* Set the preview URL for a file.
|
||||
*/
|
||||
setPreviewURL (fileID, preview) {
|
||||
this.uppy.setFileState(fileID, {
|
||||
preview: preview
|
||||
})
|
||||
this.uppy.setFileState(fileID, { preview })
|
||||
}
|
||||
|
||||
addToQueue (item) {
|
||||
|
|
@ -175,6 +176,8 @@ module.exports = class ThumbnailGenerator extends Plugin {
|
|||
.then(() => this.processQueue())
|
||||
} else {
|
||||
this.queueProcessing = false
|
||||
this.uppy.log('[ThumbnailGenerator] Emptied thumbnail queue')
|
||||
this.uppy.emit('thumbnail:all-generated')
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -183,9 +186,13 @@ module.exports = class ThumbnailGenerator extends Plugin {
|
|||
return this.createThumbnail(file, this.opts.thumbnailWidth)
|
||||
.then(preview => {
|
||||
this.setPreviewURL(file.id, preview)
|
||||
this.uppy.log(`[ThumbnailGenerator] Generated thumbnail for ${file.id}`)
|
||||
this.uppy.emit('thumbnail:generated', this.uppy.getFile(file.id), preview)
|
||||
})
|
||||
.catch(err => {
|
||||
console.warn(err.stack || err.message)
|
||||
this.uppy.log(`[ThumbnailGenerator] Failed thumbnail for ${file.id}`)
|
||||
this.uppy.log(err, 'warning')
|
||||
this.uppy.emit('thumbnail:error', this.uppy.getFile(file.id), err)
|
||||
})
|
||||
}
|
||||
return Promise.resolve()
|
||||
|
|
|
|||
|
|
@ -4,25 +4,34 @@ const emitter = require('namespace-emitter')
|
|||
|
||||
const delay = duration => new Promise(resolve => setTimeout(resolve, duration))
|
||||
|
||||
function MockCore () {
|
||||
const core = emitter()
|
||||
const files = {}
|
||||
core.mockFile = (id, f) => { files[id] = f }
|
||||
core.getFile = (id) => files[id]
|
||||
core.log = () => null
|
||||
return core
|
||||
}
|
||||
|
||||
describe('uploader/ThumbnailGeneratorPlugin', () => {
|
||||
it('should initialise successfully', () => {
|
||||
const plugin = new ThumbnailGeneratorPlugin(null, {})
|
||||
const plugin = new ThumbnailGeneratorPlugin(new MockCore(), {})
|
||||
expect(plugin instanceof Plugin).toEqual(true)
|
||||
})
|
||||
|
||||
it('should accept the thumbnailWidth option and override the default', () => {
|
||||
const plugin1 = new ThumbnailGeneratorPlugin(null) // eslint-disable-line no-new
|
||||
const plugin1 = new ThumbnailGeneratorPlugin(new MockCore()) // eslint-disable-line no-new
|
||||
expect(plugin1.opts.thumbnailWidth).toEqual(200)
|
||||
|
||||
const plugin2 = new ThumbnailGeneratorPlugin(null, { thumbnailWidth: 100 }) // eslint-disable-line no-new
|
||||
const plugin2 = new ThumbnailGeneratorPlugin(new MockCore(), { thumbnailWidth: 100 }) // eslint-disable-line no-new
|
||||
expect(plugin2.opts.thumbnailWidth).toEqual(100)
|
||||
})
|
||||
|
||||
describe('install', () => {
|
||||
it('should subscribe to uppy file-added event', () => {
|
||||
const core = {
|
||||
const core = Object.assign(new MockCore(), {
|
||||
on: jest.fn()
|
||||
}
|
||||
})
|
||||
|
||||
const plugin = new ThumbnailGeneratorPlugin(core)
|
||||
plugin.addToQueue = jest.fn()
|
||||
|
|
@ -35,10 +44,10 @@ describe('uploader/ThumbnailGeneratorPlugin', () => {
|
|||
|
||||
describe('uninstall', () => {
|
||||
it('should unsubscribe from uppy file-added event', () => {
|
||||
const core = {
|
||||
const core = Object.assign(new MockCore(), {
|
||||
on: jest.fn(),
|
||||
off: jest.fn()
|
||||
}
|
||||
})
|
||||
|
||||
const plugin = new ThumbnailGeneratorPlugin(core)
|
||||
plugin.addToQueue = jest.fn()
|
||||
|
|
@ -55,7 +64,7 @@ describe('uploader/ThumbnailGeneratorPlugin', () => {
|
|||
|
||||
describe('queue', () => {
|
||||
it('should add a new file to the queue and start processing the queue when queueProcessing is false', () => {
|
||||
const core = {}
|
||||
const core = new MockCore()
|
||||
const plugin = new ThumbnailGeneratorPlugin(core)
|
||||
plugin.processQueue = jest.fn()
|
||||
|
||||
|
|
@ -73,7 +82,7 @@ describe('uploader/ThumbnailGeneratorPlugin', () => {
|
|||
})
|
||||
|
||||
it('should process items in the queue one by one', () => {
|
||||
const core = {}
|
||||
const core = new MockCore()
|
||||
const plugin = new ThumbnailGeneratorPlugin(core)
|
||||
|
||||
plugin.requestThumbnail = jest.fn(() => delay(100))
|
||||
|
|
@ -106,9 +115,47 @@ describe('uploader/ThumbnailGeneratorPlugin', () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe('events', () => {
|
||||
const core = new MockCore()
|
||||
const plugin = new ThumbnailGeneratorPlugin(core)
|
||||
plugin.createThumbnail = jest.fn((file) => delay(100).then(() => `blob:${file.id}.png`))
|
||||
plugin.setPreviewURL = jest.fn()
|
||||
|
||||
function add (file) {
|
||||
core.mockFile(file.id, file)
|
||||
plugin.addToQueue(file)
|
||||
}
|
||||
|
||||
it('should emit thumbnail:generated when a thumbnail was generated', () => new Promise((resolve, reject) => {
|
||||
const expected = ['bar', 'bar2', 'bar3']
|
||||
core.on('thumbnail:generated', (file, preview) => {
|
||||
try {
|
||||
expect(file.id).toBe(expected.shift())
|
||||
expect(preview).toBe(`blob:${file.id}.png`)
|
||||
} catch (err) {
|
||||
return reject(err)
|
||||
}
|
||||
if (expected.length === 0) resolve()
|
||||
})
|
||||
add({ id: 'bar', type: 'image/png' })
|
||||
add({ id: 'bar2', type: 'image/png' })
|
||||
add({ id: 'bar3', type: 'image/png' })
|
||||
}))
|
||||
|
||||
it('should emit thumbnail:all-generated when all thumbnails were generated', () => {
|
||||
return new Promise((resolve) => {
|
||||
core.on('thumbnail:all-generated', resolve)
|
||||
add({ id: 'bar4', type: 'image/png' })
|
||||
add({ id: 'bar5', type: 'image/png' })
|
||||
}).then(() => {
|
||||
expect(plugin.queue).toHaveLength(0)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('requestThumbnail', () => {
|
||||
it('should call createThumbnail if it is a supported filetype', () => {
|
||||
const core = {}
|
||||
const core = new MockCore()
|
||||
const plugin = new ThumbnailGeneratorPlugin(core)
|
||||
|
||||
plugin.createThumbnail = jest
|
||||
|
|
@ -127,7 +174,7 @@ describe('uploader/ThumbnailGeneratorPlugin', () => {
|
|||
})
|
||||
|
||||
it('should not call createThumbnail if it is not a supported filetype', () => {
|
||||
const core = {}
|
||||
const core = new MockCore()
|
||||
const plugin = new ThumbnailGeneratorPlugin(core)
|
||||
|
||||
plugin.createThumbnail = jest
|
||||
|
|
@ -142,7 +189,7 @@ describe('uploader/ThumbnailGeneratorPlugin', () => {
|
|||
})
|
||||
|
||||
it('should not call createThumbnail if the file is remote', () => {
|
||||
const core = {}
|
||||
const core = new MockCore()
|
||||
const plugin = new ThumbnailGeneratorPlugin(core)
|
||||
|
||||
plugin.createThumbnail = jest
|
||||
|
|
@ -157,7 +204,7 @@ describe('uploader/ThumbnailGeneratorPlugin', () => {
|
|||
})
|
||||
|
||||
it('should call setPreviewURL with the thumbnail image', () => {
|
||||
const core = {}
|
||||
const core = new MockCore()
|
||||
const plugin = new ThumbnailGeneratorPlugin(core)
|
||||
|
||||
plugin.createThumbnail = jest
|
||||
|
|
@ -199,7 +246,7 @@ describe('uploader/ThumbnailGeneratorPlugin', () => {
|
|||
|
||||
describe('getProportionalHeight', () => {
|
||||
it('should calculate the resized height based on the specified width of the image whilst keeping aspect ratio', () => {
|
||||
const core = {}
|
||||
const core = new MockCore()
|
||||
const plugin = new ThumbnailGeneratorPlugin(core)
|
||||
expect(
|
||||
plugin.getProportionalHeight({ width: 200, height: 100 }, 50)
|
||||
|
|
@ -215,7 +262,7 @@ describe('uploader/ThumbnailGeneratorPlugin', () => {
|
|||
|
||||
describe('canvasToBlob', () => {
|
||||
it('should use canvas.toBlob if available', () => {
|
||||
const core = {}
|
||||
const core = new MockCore()
|
||||
const plugin = new ThumbnailGeneratorPlugin(core)
|
||||
const canvas = {
|
||||
toBlob: jest.fn()
|
||||
|
|
@ -242,7 +289,7 @@ describe('uploader/ThumbnailGeneratorPlugin', () => {
|
|||
})
|
||||
|
||||
xit('should scale down the image by the specified number of steps', () => {
|
||||
const core = {}
|
||||
const core = new MockCore()
|
||||
const plugin = new ThumbnailGeneratorPlugin(core)
|
||||
const image = {
|
||||
width: 1000,
|
||||
|
|
@ -299,7 +346,7 @@ describe('uploader/ThumbnailGeneratorPlugin', () => {
|
|||
|
||||
describe('resizeImage', () => {
|
||||
it('should return a canvas with the resized image on it', () => {
|
||||
const core = {}
|
||||
const core = new MockCore()
|
||||
const plugin = new ThumbnailGeneratorPlugin(core)
|
||||
const image = {
|
||||
width: 1000,
|
||||
|
|
@ -324,7 +371,7 @@ describe('uploader/ThumbnailGeneratorPlugin', () => {
|
|||
})
|
||||
|
||||
it('should upsize if original image is smaller than target size', () => {
|
||||
const core = {}
|
||||
const core = new MockCore()
|
||||
const plugin = new ThumbnailGeneratorPlugin(core)
|
||||
const image = {
|
||||
width: 100,
|
||||
|
|
@ -356,7 +403,7 @@ describe('uploader/ThumbnailGeneratorPlugin', () => {
|
|||
b: { preview: 'blob:def' },
|
||||
c: { preview: 'blob:xyz', isRestored: true }
|
||||
}
|
||||
const core = Object.assign(emitter(), {
|
||||
const core = Object.assign(new MockCore(), {
|
||||
getState () {
|
||||
return { files }
|
||||
},
|
||||
|
|
@ -380,7 +427,7 @@ describe('uploader/ThumbnailGeneratorPlugin', () => {
|
|||
const files = {
|
||||
a: { preview: 'http://abc', isRestored: true }
|
||||
}
|
||||
const core = Object.assign(emitter(), {
|
||||
const core = Object.assign(new MockCore(), {
|
||||
getState () {
|
||||
return { files }
|
||||
},
|
||||
|
|
|
|||
25
test/endtoend/thumbnails/index.html
Normal file
25
test/endtoend/thumbnails/index.html
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Uppy test page</title>
|
||||
</head>
|
||||
<body>
|
||||
<style>
|
||||
main {
|
||||
max-width: 700px;
|
||||
margin: auto;
|
||||
}
|
||||
</style>
|
||||
<main>
|
||||
<h2>Thumbnails</h2>
|
||||
<div>
|
||||
<div id="uppyThumbnails"></div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<link href="uppy.min.css" rel="stylesheet">
|
||||
<script src="bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
39
test/endtoend/thumbnails/main.js
Normal file
39
test/endtoend/thumbnails/main.js
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/* eslint-disable */
|
||||
require('es6-promise/auto')
|
||||
require('whatwg-fetch')
|
||||
const Uppy = require('@uppy/core')
|
||||
const ThumbnailGenerator = require('@uppy/thumbnail-generator')
|
||||
const FileInput = require('@uppy/file-input')
|
||||
|
||||
const uppyThumbnails = Uppy({
|
||||
id: 'uppyThumbnails',
|
||||
autoProceed: false,
|
||||
debug: true
|
||||
})
|
||||
|
||||
uppyThumbnails.use(ThumbnailGenerator, {})
|
||||
uppyThumbnails.use(FileInput, { target: '#uppyThumbnails', pretty: false })
|
||||
|
||||
uppyThumbnails.on('file-added', (file) => {
|
||||
const el = document.createElement('p')
|
||||
el.className = 'file-name'
|
||||
el.textContent = file.name
|
||||
document.body.appendChild(el)
|
||||
})
|
||||
|
||||
// Dump errors to the screen so saucelabs shows them in screenshots.
|
||||
uppyThumbnails.on('thumbnail:error', (file, err) => {
|
||||
const el = document.createElement('pre')
|
||||
el.style = 'font: 14pt monospace; background: red; color: white'
|
||||
el.textContent = `Error: ${err.stack}`
|
||||
document.body.appendChild(el)
|
||||
})
|
||||
|
||||
uppyThumbnails.on('thumbnail:generated', (file, preview) => {
|
||||
const img = new Image()
|
||||
img.src = file.preview
|
||||
img.className = 'file-preview'
|
||||
img.style.display = 'block'
|
||||
|
||||
document.body.appendChild(img)
|
||||
})
|
||||
90
test/endtoend/thumbnails/test.js
Normal file
90
test/endtoend/thumbnails/test.js
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
/* global browser, expect, $, $$ */
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const { selectFakeFile, supportsChooseFile } = require('../utils')
|
||||
|
||||
const testURL = 'http://localhost:4567/thumbnails'
|
||||
|
||||
const images = [
|
||||
path.join(__dirname, '../../resources/image.jpg'),
|
||||
path.join(__dirname, '../../resources/baboon.png'),
|
||||
path.join(__dirname, '../../resources/kodim23.png'),
|
||||
path.join(__dirname, '../../resources/invalid.png')
|
||||
]
|
||||
const notImages = [
|
||||
{ type: 'text/javascript', file: __filename }
|
||||
]
|
||||
|
||||
describe('ThumbnailGenerator', () => {
|
||||
beforeEach(() => {
|
||||
browser.url(testURL)
|
||||
})
|
||||
|
||||
it('should generate thumbnails for images', function () {
|
||||
// FIXME why isn't the selectFakeFile alternative below working?
|
||||
if (!supportsChooseFile()) {
|
||||
return this.skip()
|
||||
}
|
||||
|
||||
$('#uppyThumbnails .uppy-FileInput-input').waitForExist()
|
||||
|
||||
browser.execute(/* must be valid ES5 for IE */ function () {
|
||||
window.thumbnailsReady = new Promise(function (resolve) {
|
||||
window.uppyThumbnails.on('thumbnail:all-generated', resolve)
|
||||
})
|
||||
})
|
||||
|
||||
if (supportsChooseFile()) {
|
||||
for (const img of images) {
|
||||
browser.chooseFile('#uppyThumbnails .uppy-FileInput-input', img)
|
||||
}
|
||||
for (const { file } of notImages) {
|
||||
browser.chooseFile('#uppyThumbnails .uppy-FileInput-input', file)
|
||||
}
|
||||
} else {
|
||||
for (const img of images) {
|
||||
browser.execute(
|
||||
selectFakeFile,
|
||||
'uppyThumbnails',
|
||||
path.basename(img), // name
|
||||
`image/${path.extname(img).slice(1)}`, // type
|
||||
fs.readFileSync(img, 'base64') // b64
|
||||
)
|
||||
}
|
||||
for (const { type, file } of notImages) {
|
||||
browser.execute(
|
||||
selectFakeFile,
|
||||
'uppyThumbnails',
|
||||
path.basename(file), // name
|
||||
type, // type
|
||||
fs.readFileSync(file, 'base64') // b64
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
browser.executeAsync(/* must be valid ES5 for IE */ function (done) {
|
||||
window.thumbnailsReady.then(done)
|
||||
})
|
||||
|
||||
// const names = $$('p.file-name')
|
||||
const previews = $$('img.file-preview')
|
||||
|
||||
// Names should all be listed before previews--indicates that previews were generated asynchronously.
|
||||
/* Nevermind this, chooseFile() doesn't accept multiple files so they are added one by one and the thumbnails
|
||||
* have finished generating by the time we add the next.
|
||||
const nys = names.map((el) => el.getLocation('y'))
|
||||
const pys = previews.map((el) => el.getLocation('y'))
|
||||
for (const ny of nys) {
|
||||
for (const py of pys) {
|
||||
expect(ny).to.be.below(py, 'names should be listed before previews')
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
expect(previews).to.have.lengthOf(3) // ex. the invalid image
|
||||
for (const p of previews) {
|
||||
expect(p.getAttribute('src')).to.match(/^blob:/)
|
||||
expect(p.getElementSize('width')).to.equal(200)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
@ -2,14 +2,18 @@
|
|||
const path = require('path')
|
||||
const { spawn } = require('child_process')
|
||||
|
||||
function selectFakeFile (uppyID) {
|
||||
// This function must be valid ES5, because it is run in the browser
|
||||
// and IE10/IE11 do not support new syntax features
|
||||
function selectFakeFile (uppyID, name, type, b64) {
|
||||
if (!b64) b64 = 'PHN2ZyB2aWV3Qm94PSIwIDAgMTIwIDEyMCI+CiAgPGNpcmNsZSBjeD0iNjAiIGN5PSI2MCIgcj0iNTAiLz4KPC9zdmc+Cg=='
|
||||
|
||||
var blob = new Blob(
|
||||
['data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTIwIDEyMCI+CiAgPGNpcmNsZSBjeD0iNjAiIGN5PSI2MCIgcj0iNTAiLz4KPC9zdmc+Cg=='],
|
||||
{ type: 'image/svg+xml' }
|
||||
['data:image/svg+xml;base64,' + b64],
|
||||
{ type: type || 'image/svg+xml' }
|
||||
)
|
||||
window[uppyID].addFile({
|
||||
source: 'test',
|
||||
name: 'test-file',
|
||||
name: name || 'test-file',
|
||||
type: blob.type,
|
||||
data: blob
|
||||
})
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ exports.config = {
|
|||
{ mount: '/tus-drag-drop', path: './test/endtoend/tus-drag-drop/dist' },
|
||||
{ mount: '/xhr-limit', path: './test/endtoend/xhr-limit/dist' },
|
||||
{ mount: '/providers', path: './test/endtoend/providers/dist' },
|
||||
{ mount: '/thumbnails', path: './test/endtoend/thumbnails/dist' },
|
||||
{ mount: '/create-react-app', path: './test/endtoend/create-react-app/build' }
|
||||
],
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,24 @@
|
|||
const base = require('./wdio.base.conf')
|
||||
const { CompanionService } = require('./utils')
|
||||
|
||||
// Use "npm run test:acceptance:local -- -b chrome" to test in chrome
|
||||
// "npm run test:acceptance:local -- -b firefox -b chrome" to test in FF and chrome
|
||||
let prevIsDashB = false
|
||||
const capabilities = []
|
||||
process.argv.forEach((arg) => {
|
||||
if (prevIsDashB) {
|
||||
capabilities.push({ browserName: arg })
|
||||
}
|
||||
prevIsDashB = arg === '-b'
|
||||
})
|
||||
|
||||
// default to testing in firefox
|
||||
if (capabilities.length === 0) {
|
||||
capabilities.push({ browserName: 'firefox' })
|
||||
}
|
||||
|
||||
exports.config = Object.assign(base.config, {
|
||||
capabilities: [
|
||||
{ browserName: 'firefox' }
|
||||
// { browserName: 'MicrosoftEdge', version: '14.14393', platform: 'Windows 10' },
|
||||
// { browserName: 'safari', version: '11.0', platform: 'macOS 10.12' }
|
||||
],
|
||||
capabilities,
|
||||
|
||||
// If you only want to run your tests until a specific amount of tests have failed use
|
||||
// bail (default is 0 - don't bail, run all tests).
|
||||
|
|
|
|||
|
|
@ -2,18 +2,24 @@ const base = require('./wdio.base.conf')
|
|||
const { CompanionService } = require('./utils')
|
||||
|
||||
function createCapability (capability) {
|
||||
return Object.assign({
|
||||
return {
|
||||
'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER,
|
||||
build: process.env.TRAVIS_BUILD_NUMBER
|
||||
}, capability)
|
||||
build: process.env.TRAVIS_BUILD_NUMBER,
|
||||
extendedDebugging: true,
|
||||
...capability
|
||||
}
|
||||
}
|
||||
|
||||
exports.config = Object.assign(base.config, {
|
||||
capabilities: [
|
||||
{ browserName: 'firefox', version: '38.0', platform: 'Linux' },
|
||||
{ browserName: 'firefox', version: '61.0', platform: 'Windows 10' },
|
||||
{ browserName: 'internet explorer', version: '10.0', platform: 'Windows 7' },
|
||||
{ browserName: 'internet explorer', version: '11.0', platform: 'Windows 7' },
|
||||
{ browserName: 'chrome', version: '50.0', platform: 'Windows 7' },
|
||||
{ browserName: 'MicrosoftEdge', version: '14.14393', platform: 'Windows 10' },
|
||||
{ browserName: 'chrome', version: '69.0', platform: 'Windows 10' },
|
||||
{ browserName: 'MicrosoftEdge', version: '14', platform: 'Windows 10' },
|
||||
{ browserName: 'MicrosoftEdge', version: '17', platform: 'Windows 10' },
|
||||
// { browserName: 'safari', version: '11.0', platform: 'macOS 10.12' },
|
||||
{ browserName: 'safari', version: '10.0', platformName: 'iOS', platformVersion: '10.0', deviceOrientation: 'portrait', deviceName: 'iPhone 6 Simulator', appiumVersion: '1.7.1' },
|
||||
{ browserName: 'chrome', platformName: 'Android', platformVersion: '6.0', deviceOrientation: 'portrait', deviceName: 'Android Emulator', appiumVersion: '1.7.1' }
|
||||
|
|
|
|||
BIN
test/resources/baboon.png
Normal file
BIN
test/resources/baboon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 636 KiB |
BIN
test/resources/invalid.png
Normal file
BIN
test/resources/invalid.png
Normal file
Binary file not shown.
BIN
test/resources/kodim23.png
Normal file
BIN
test/resources/kodim23.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 544 KiB |
|
|
@ -14,8 +14,11 @@ After you have successfully forked the repo, clone and install the project:
|
|||
git clone git@github.com:YOUR_USERNAME/uppy.git
|
||||
cd uppy
|
||||
npm install
|
||||
npm run bootstrap
|
||||
```
|
||||
|
||||
We use lerna to manage the many plugin packages Uppy has. You should always do `npm run bootstrap` after an `npm install` to make sure lerna has installed the dependencies of each package and that the `package-lock.json` in the repository root is up to date.
|
||||
|
||||
Our website’s examples section is also our playground, please read the [Local Previews](#Local-Previews) section to get up and running.
|
||||
|
||||
## Tests
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue