Working test

Add tests for thumbnail:* events.

Show build output

Try adding a non image file?

fixes

Add -b flags to local acceptance tests

fix hanging thumbnail test

Add a corrupt image

revoke

Require passing integration tests

extended debugging?

Try more browser versions

it helps to pick a browser that's available

sort stuff in .travis.yml and add whitespace for easier navigation

[REVERT BEFORE MERGE] only run acceptance tests on this pr

make sure lerna publishes stuff to local

do git tag version during integration test

update lerna

fix install / bootstrap execution order

?

--no-ci

dont do npm ls because it errors with lerna

set a git branch name

blehbleh

ughhhhhhhhhhhh

onerror?

no onerror i guess

onerror 2

Revert "onerror 2"

This reverts commit 64d88551fa1cd337b27e25d16a604dd781a15b43.

onerror 3

more debug data

disable browsers that work

fix syntax for older browsers

thumbnails suite

check different edge versions

abc

use addeventlistener for error, which is different from onerror

no clue

skip thumb test in edge or whatever

Re enable other browsers.

re enable tasks

fix edge skip

this one was intentionally disabled

Remove debug leftovers

edge → supportschoosefile

:ready → :all-generated
This commit is contained in:
Renée Kooi 2018-07-16 14:56:01 +02:00
parent a68bcc1459
commit a67a558eec
No known key found for this signature in database
GPG key ID: 8CDD5F0BC448F040
14 changed files with 1455 additions and 394 deletions

View file

@ -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=

View file

@ -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

View file

@ -26,5 +26,5 @@ done
# Speeecial tests that need custom builds.
pushd "${__root}/test/endtoend/create-react-app"
npm install
npm run build > /dev/null
npm run build
popd

1541
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -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"
},

View file

@ -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,21 +38,20 @@ module.exports = class ThumbnailGenerator extends Plugin {
*/
createThumbnail (file, targetWidth) {
const originalUrl = URL.createObjectURL(file.data)
const revoke = () => URL.revokeObjectURL(originalUrl)
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
reject(new Error('Could not create thumbnail'))
}
})
image.addEventListener('error', (event) => {
URL.revokeObjectURL(originalUrl)
reject(event.error || new Error('Could not create thumbnail'))
})
})
onload.then(revoke, revoke)
return onload
.then(image => {
const targetHeight = this.getProportionalHeight(image, targetWidth)
@ -155,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) {
@ -176,7 +176,8 @@ module.exports = class ThumbnailGenerator extends Plugin {
.then(() => this.processQueue())
} else {
this.queueProcessing = false
this.uppy.emit('thumbnail:ready')
this.uppy.log('[ThumbnailGenerator] Emptied thumbnail queue')
this.uppy.emit('thumbnail:all-generated')
}
}
@ -185,11 +186,13 @@ module.exports = class ThumbnailGenerator extends Plugin {
return this.createThumbnail(file, this.opts.thumbnailWidth)
.then(preview => {
this.setPreviewURL(file.id, preview)
this.uppy.emit('thumbnail:generated', file, 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.emit('thumbnail:error', file, err)
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()

View file

@ -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 }
},

View file

@ -1,3 +1,4 @@
/* eslint-disable */
require('es6-promise/auto')
require('whatwg-fetch')
const Uppy = require('@uppy/core')
@ -13,10 +14,26 @@ const uppyThumbnails = Uppy({
uppyThumbnails.use(ThumbnailGenerator, {})
uppyThumbnails.use(FileInput, { target: '#uppyThumbnails', pretty: false })
uppyThumbnails.on('thumbnail:generated', (file) => {
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)
})
window.ready = new Promise((resolve) => uppyThumbnails.on('thumbnail:ready', resolve))

View file

@ -1,4 +1,4 @@
/* global browser, expect, $ */
/* global browser, expect, $, $$ */
const path = require('path')
const fs = require('fs')
const { selectFakeFile, supportsChooseFile } = require('../utils')
@ -8,21 +8,39 @@ 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/kodim23.png'),
path.join(__dirname, '../../resources/invalid.png')
]
const notImages = [
{ type: 'text/javascript', file: __filename }
]
describe.only('ThumbnailGenerator', () => {
describe('ThumbnailGenerator', () => {
beforeEach(() => {
browser.url(testURL)
})
it('should generate thumbnails for images', () => {
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(
@ -33,8 +51,40 @@ describe.only('ThumbnailGenerator', () => {
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.pause(20 * 1000)
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)
}
})
})

View file

@ -2,11 +2,13 @@
const path = require('path')
const { spawn } = require('child_process')
// 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,${b64}`],
['data:image/svg+xml;base64,' + b64],
{ type: type || 'image/svg+xml' }
)
window[uppyID].addFile({

View file

@ -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).

View file

@ -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/invalid.png Normal file

Binary file not shown.

View file

@ -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 websites examples section is also our playground, please read the [Local Previews](#Local-Previews) section to get up and running.
## Tests