├── .browserslistrc
├── .eslintrc.js
├── .gitignore
├── .prettierrc
├── .travis.yml
├── LICENSE
├── README.md
├── babel.config.js
├── jest.config.js
├── package-lock.json
├── package.json
├── postcss.config.js
├── src
├── CancelButton.vue
├── DeleteButton.vue
├── Filename.vue
├── Filesize.vue
├── PauseResumeButton.vue
├── ProgressBar.vue
├── RetryButton.vue
├── Status.vue
└── renderless
│ ├── CancelButton.vue
│ ├── DeleteButton.vue
│ ├── FileProgressBar.vue
│ ├── Filename.vue
│ ├── Filesize.vue
│ ├── PauseResumeButton.vue
│ ├── RetryButton.vue
│ ├── Status.vue
│ └── TotalProgressBar.vue
├── tests
└── unit
│ ├── .eslintrc.js
│ ├── CancelButton.spec.js
│ ├── DeleteButton.spec.js
│ ├── Filename.spec.js
│ ├── Filesize.spec.js
│ ├── PauseResumeButton.spec.js
│ ├── ProgressBar.spec.js
│ ├── RenderlessCancelButton.spec.js
│ ├── RenderlessDeleteButton.spec.js
│ ├── RenderlessFileProgressBar.spec.js
│ ├── RenderlessFilename.spec.js
│ ├── RenderlessFilesize.spec.js
│ ├── RenderlessPauseResumeButton.spec.js
│ ├── RenderlessRetryButton.spec.js
│ ├── RenderlessStatus.spec.js
│ ├── RenderlessTotalProgressBar.spec.js
│ ├── RetryButton.spec.js
│ ├── Status.spec.js
│ └── __snapshots__
│ ├── CancelButton.spec.js.snap
│ ├── DeleteButton.spec.js.snap
│ ├── Filename.spec.js.snap
│ ├── Filesize.spec.js.snap
│ ├── PauseResumeButton.spec.js.snap
│ ├── ProgressBar.spec.js.snap
│ ├── RetryButton.spec.js.snap
│ └── Status.spec.js.snap
└── vue.config.js
/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not ie <= 8
4 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 |
4 | env: {
5 | node: true,
6 | },
7 |
8 | extends: ['plugin:vue/recommended', '@vue/prettier'],
9 |
10 | rules: {
11 | 'no-console': 'off',
12 | 'no-debugger': 'off',
13 | },
14 |
15 | parserOptions: {
16 | parser: 'babel-eslint',
17 | },
18 | }
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 | # local env files
6 | .env.local
7 | .env.*.local
8 |
9 | # Log files
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # Editor directories and files
15 | .idea
16 | .vscode
17 | *.suo
18 | *.ntvs*
19 | *.njsproj
20 | *.sln
21 | *.sw*
22 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "bracketSpacing": true,
3 | "jsxBracketSameLine": true,
4 | "printWidth": 80,
5 | "arrowParens": "avoid",
6 | "semi": false,
7 | "singleQuote": true,
8 | "tabWidth": 2,
9 | "trailingComma": "all",
10 | "useTabs": false,
11 | "overrides": [
12 | {
13 | "files": ".prettierrc",
14 | "options": {
15 | "parser": "json"
16 | }
17 | }
18 | ]
19 | }
20 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 |
3 | cache:
4 | directories:
5 | - $HOME/.npm
6 | - node_modules
7 |
8 | node_js:
9 | - "8"
10 |
11 | install:
12 | - npm install
13 | script:
14 | - npm run test:unit
15 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | [](https://www.npmjs.com/package/vue-fineuploader)
4 | [](LICENSE)
5 | [](https://travis-ci.org/FineUploader/vue-fineuploader)
6 |
7 | Makes using [Fine Uploader](http://fineuploader.com) in a VueJS 2 app simple. Drop-in high-level components for a turn-key UI. Use small focused components to build a more custom UI.
8 |
9 | # ❗️ This is a work in progress refactor ️️❗️
10 |
11 | ### The current working version is on the v2 branch which is [right here](https://github.com/FineUploader/vue-fineuploader/tree/v2).
12 |
13 | I know I never really finished the v2 and that it's full of bugs. This is why I'm restarting from the ground up. I'm not the developer I was 2 years ago when I made this library and I think that I can now offer something way more powerful that its current state.
14 |
15 | ### What will change
16 |
17 | #### 1. The repo is going to be renamed `vue-fine-uploader` to match the naming convention of FineUploader.
18 |
19 | #### 2. Introduction of renderless components to offer full control over the presentation of the different components.
20 |
21 | To avoid forcing everyone to switch to renderless components a set of opiniated components will be created.
22 |
23 | I'm going to try and make them as accessible as possible.
24 |
25 | #### 3. Unit tests.
26 |
27 | It had no unit test until now, which made it fairly complicated to debug an issue and tests PRs.
28 |
29 | #### Improved documentation with CodeSandbox examples.
30 |
31 | I'm going to rewrite the whole documentation and make it user friendlier (is that even a word?) and create CodeSandbox example instead of plain text inside the README.
32 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['@vue/app'],
3 | }
4 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
3 | transform: {
4 | '^.+\\.vue$': 'vue-jest',
5 | '.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$':
6 | 'jest-transform-stub',
7 | '^.+\\.jsx?$': 'babel-jest',
8 | },
9 | moduleNameMapper: {
10 | '^@/(.*)$': '/src/$1',
11 | },
12 | snapshotSerializers: ['jest-serializer-vue'],
13 | testMatch: [
14 | '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)',
15 | ],
16 | testURL: 'http://localhost/',
17 | }
18 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-fine-uploader",
3 | "version": "3.0.0-alpha.0",
4 | "private": true,
5 | "license": "MIT",
6 | "description": "VueJS 2 components for using Fine Uploader in a Vue based project.",
7 | "homepage": "https://github.com/FineUploader/vue-fine-uploader#readme",
8 | "repository": {
9 | "url": "https://github.com/FineUploader/vue-fine-uploader.git",
10 | "type": "git"
11 | },
12 | "bugs": {
13 | "url": "https://github.com/FineUploader/vue-fine-uploader/issues"
14 | },
15 | "author": {
16 | "name": "Dieter Stinglhamber",
17 | "email": "elhebert@hotmail.be",
18 | "url": "https://dieterstinglhamber.me/"
19 | },
20 | "keywords": [
21 | "file",
22 | "blob",
23 | "file-uploader",
24 | "fine-uploader",
25 | "vue",
26 | "upload",
27 | "widget"
28 | ],
29 | "scripts": {
30 | "serve": "vue-cli-service serve",
31 | "build": "vue-cli-service build",
32 | "lint": "vue-cli-service lint",
33 | "test:unit": "vue-cli-service test:unit"
34 | },
35 | "peerDependencies": {
36 | "vue": "^2.5"
37 | },
38 | "dependencies": {
39 | "fine-uploader": "^5.16.2",
40 | "fine-uploader-wrappers": "^1.0.1"
41 | },
42 | "devDependencies": {
43 | "@vue/cli-plugin-babel": "^3.0.1",
44 | "@vue/cli-plugin-eslint": "^3.0.1",
45 | "@vue/cli-plugin-unit-jest": "^3.0.1",
46 | "@vue/cli-service": "^3.0.1",
47 | "@vue/eslint-config-prettier": "^3.0.1",
48 | "@vue/test-utils": "^1.0.0-beta.20",
49 | "babel-core": "7.0.0-bridge.0",
50 | "babel-jest": "^23.0.1",
51 | "vue": "^2.5.17",
52 | "vue-template-compiler": "^2.5.17"
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | autoprefixer: {},
4 | },
5 | }
6 |
--------------------------------------------------------------------------------
/src/CancelButton.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
15 |
16 |
17 |
18 |
42 |
--------------------------------------------------------------------------------
/src/DeleteButton.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
15 |
16 |
17 |
18 |
42 |
--------------------------------------------------------------------------------
/src/Filename.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 | {{ filename }}
7 |
8 |
9 |
10 |
30 |
--------------------------------------------------------------------------------
/src/Filesize.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 | {{ size }} {{ units[unit] }}
10 |
11 |
12 |
13 |
43 |
--------------------------------------------------------------------------------
/src/PauseResumeButton.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
16 |
17 |
18 |
19 |
47 |
--------------------------------------------------------------------------------
/src/ProgressBar.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
16 |
17 |
18 |
19 |
52 |
--------------------------------------------------------------------------------
/src/RetryButton.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
15 |
16 |
17 |
18 |
41 |
--------------------------------------------------------------------------------
/src/Status.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 | {{ statuses[status] }}
7 |
8 |
9 |
10 |
43 |
--------------------------------------------------------------------------------
/src/renderless/CancelButton.vue:
--------------------------------------------------------------------------------
1 |
94 |
--------------------------------------------------------------------------------
/src/renderless/DeleteButton.vue:
--------------------------------------------------------------------------------
1 |
106 |
--------------------------------------------------------------------------------
/src/renderless/FileProgressBar.vue:
--------------------------------------------------------------------------------
1 |
83 |
--------------------------------------------------------------------------------
/src/renderless/Filename.vue:
--------------------------------------------------------------------------------
1 |
48 |
--------------------------------------------------------------------------------
/src/renderless/Filesize.vue:
--------------------------------------------------------------------------------
1 |
79 |
--------------------------------------------------------------------------------
/src/renderless/PauseResumeButton.vue:
--------------------------------------------------------------------------------
1 |
141 |
--------------------------------------------------------------------------------
/src/renderless/RetryButton.vue:
--------------------------------------------------------------------------------
1 |
100 |
--------------------------------------------------------------------------------
/src/renderless/Status.vue:
--------------------------------------------------------------------------------
1 |
49 |
--------------------------------------------------------------------------------
/src/renderless/TotalProgressBar.vue:
--------------------------------------------------------------------------------
1 |
74 |
--------------------------------------------------------------------------------
/tests/unit/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | jest: true,
4 | },
5 | rules: {
6 | 'import/no-extraneous-dependencies': 'off',
7 | },
8 | }
9 |
--------------------------------------------------------------------------------
/tests/unit/CancelButton.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils'
2 | import CancelButton from '@/CancelButton.vue'
3 | import FineUploader from 'fine-uploader-wrappers'
4 | import { status } from 'fine-uploader/lib/core/all'
5 |
6 | describe('CancelButton.vue', () => {
7 | let wrapper
8 | let uploader
9 |
10 | const sampleBlob = new Blob(['hi!'], { type: 'text/plain' })
11 |
12 | beforeEach(done => {
13 | uploader = new FineUploader({ options: { autoUpload: false } })
14 | uploader.on('submitted', done)
15 | uploader.methods.addFiles(sampleBlob)
16 |
17 | wrapper = mount(CancelButton, {
18 | propsData: { id: 0, uploader },
19 | })
20 | })
21 |
22 | it('renders the button for a submitted file', () => {
23 | expect(wrapper).toMatchSnapshot()
24 | expect(wrapper.html()).toBeDefined()
25 | expect(wrapper.attributes().disabled).toBeUndefined()
26 | })
27 |
28 | it('cancels the upload if clicked', done => {
29 | wrapper.trigger('click')
30 |
31 | wrapper.vm.$nextTick(() => {
32 | expect(uploader.methods.getUploads()[0].status).toMatch(status.CANCELED)
33 |
34 | done()
35 | })
36 | })
37 |
38 | it('removes the button by default if the file can no longer be canceled', done => {
39 | uploader.methods.cancel(0)
40 |
41 | wrapper.vm.$nextTick(() => {
42 | expect(wrapper).toMatchSnapshot()
43 | expect(wrapper.isEmpty()).toBe(true)
44 |
45 | done()
46 | })
47 | })
48 |
49 | it('disables the button if requested when the file can no longer be canceled', done => {
50 | wrapper.setProps({ onlyRenderIfCancelable: false })
51 | uploader.methods.cancel(0)
52 |
53 | wrapper.vm.$nextTick(() => {
54 | expect(wrapper).toMatchSnapshot()
55 | expect(wrapper.html()).toBeDefined()
56 | expect(wrapper.attributes().disabled).toBeDefined()
57 |
58 | done()
59 | })
60 | })
61 | })
62 |
--------------------------------------------------------------------------------
/tests/unit/DeleteButton.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils'
2 | import DeleteButton from '@/DeleteButton.vue'
3 | import FineUploader from 'fine-uploader-wrappers'
4 | import { status } from 'fine-uploader/lib/core/all'
5 |
6 | describe('DeleteButton.vue', () => {
7 | let wrapper
8 | let renderless
9 | let uploader
10 |
11 | beforeEach(() => {
12 | uploader = new FineUploader({ options: {} })
13 |
14 | wrapper = mount(DeleteButton, {
15 | propsData: { id: 0, uploader },
16 | })
17 |
18 | renderless = wrapper.vm.$children[0]
19 | })
20 |
21 | it('renders the button for a successfully uploaded file', () => {
22 | renderless.onStatusChange(0, null, status.UPLOAD_SUCCESSFUL)
23 |
24 | expect(wrapper).toMatchSnapshot()
25 | expect(wrapper.html()).toBeDefined()
26 | expect(wrapper.attributes().disabled).toBeUndefined()
27 | })
28 |
29 | it('deletes the file if clicked', () => {
30 | uploader.methods.deleteFile = jest.fn()
31 |
32 | renderless.onStatusChange(0, null, status.UPLOAD_SUCCESSFUL)
33 |
34 | wrapper.trigger('click')
35 | expect(uploader.methods.deleteFile).toHaveBeenCalled()
36 | })
37 |
38 | it('removes the button if the file can no longer be deleted', () => {
39 | renderless.onStatusChange(0, null, status.DELETED)
40 |
41 | expect(wrapper).toMatchSnapshot()
42 | expect(wrapper.isEmpty()).toBe(true)
43 | })
44 |
45 | it('disabled the button while the delete is in progress', () => {
46 | renderless.onStatusChange(0, null, status.DELETING)
47 |
48 | expect(wrapper).toMatchSnapshot()
49 | expect(wrapper.attributes().disabled).toBeDefined()
50 | })
51 |
52 | it('disables the button if requested when the file can no longer be deleted', () => {
53 | wrapper.setProps({ onlyRenderIfDeletable: false })
54 | renderless.onStatusChange(0, null, status.DELETED)
55 |
56 | expect(wrapper).toMatchSnapshot()
57 | expect(wrapper.html()).toBeDefined()
58 | expect(wrapper.attributes().disabled).toBeDefined()
59 | })
60 | })
61 |
--------------------------------------------------------------------------------
/tests/unit/Filename.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils'
2 | import Filename from '@/Filename.vue'
3 | import FineUploader from 'fine-uploader-wrappers'
4 |
5 | describe('Filename.vue', () => {
6 | let uploader
7 | let wrapper
8 |
9 | const sampleBlob = new Blob(['hi!'], { type: 'text/plain' })
10 | const sampleBlobWrapper = { blob: sampleBlob, name: 'test' }
11 |
12 | beforeEach(done => {
13 | uploader = new FineUploader({ options: { autoUpload: false } })
14 | uploader.on('submitted', done)
15 | uploader.methods.addFiles(sampleBlobWrapper)
16 |
17 | wrapper = mount(Filename, {
18 | propsData: { id: 0, uploader },
19 | })
20 | })
21 |
22 | it('renders initial filename', () => {
23 | expect(wrapper).toMatchSnapshot()
24 | expect(wrapper.text()).toBe('test')
25 | })
26 |
27 | it('updates filename on setName', () => {
28 | uploader.methods.setName(0, 'new-name')
29 |
30 | expect(wrapper).toMatchSnapshot()
31 | expect(wrapper.text()).toBe('new-name')
32 | })
33 | })
34 |
--------------------------------------------------------------------------------
/tests/unit/Filesize.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils'
2 | import Filesize from '@/Filesize.vue'
3 | import FineUploader from 'fine-uploader-wrappers'
4 |
5 | describe('Filesize.vue', () => {
6 | const nativeObjectToString = Object.prototype.toString
7 |
8 | beforeEach(() => {
9 | Object.prototype.toString = function() {
10 | if (this && this.type === 'fakeBlob') {
11 | return '[object Blob]'
12 | }
13 |
14 | return nativeObjectToString.apply(this, arguments)
15 | }
16 | })
17 |
18 | afterEach(() => {
19 | Object.prototype.toString = nativeObjectToString
20 | })
21 |
22 | it('renders an empty filesize component if size is not known initially', () => {
23 | const uploader = new FineUploader({ options: { autoUpload: false } })
24 | uploader.methods.addFiles({ type: 'fakeBlob' })
25 |
26 | const wrapper = mount(Filesize, {
27 | propsData: { id: 0, uploader },
28 | })
29 |
30 | expect(wrapper).toMatchSnapshot()
31 | expect(wrapper.text()).toBe('')
32 | })
33 |
34 | it('renders formatted file size for various sized files', () => {
35 | const uploader = new FineUploader({ options: { autoUpload: false } })
36 |
37 | uploader.methods.addFiles([
38 | { size: 1100, type: 'fakeBlob' },
39 | { size: 1100000, type: 'fakeBlob' },
40 | { size: 1100000000, type: 'fakeBlob' },
41 | { size: 1100000000000, type: 'fakeBlob' },
42 | ])
43 |
44 | const expectedSizes = [
45 | { size: '1.10', units: 'KB' },
46 | { size: '1.10', units: 'MB' },
47 | { size: '1.10', units: 'GB' },
48 | { size: '1.10', units: 'TB' },
49 | ]
50 |
51 | expectedSizes.forEach((expectedSize, id) => {
52 | const wrapper = mount(Filesize, {
53 | propsData: { id, uploader },
54 | })
55 |
56 | expect(wrapper).toMatchSnapshot()
57 | expect(wrapper.text()).toBe(`${expectedSize.size} ${expectedSize.units}`)
58 | })
59 | })
60 |
61 | it('renders file size at upload time for scaled blobs', () => {
62 | const uploader = new FineUploader({
63 | options: {
64 | autoUpload: false,
65 | scaling: { sizes: [{ name: 'test', maxSize: 100 }] },
66 | },
67 | })
68 | uploader.methods.addFiles({ type: 'fakeBlob' })
69 |
70 | const wrapper = mount(Filesize, {
71 | propsData: { id: 0, uploader },
72 | })
73 |
74 | expect(wrapper).toMatchSnapshot()
75 | expect(wrapper.text()).toBe('')
76 |
77 | uploader.methods.getSize = jest.fn(() => 1)
78 |
79 | const renderless = wrapper.vm.$children[0]
80 | renderless.onUpload(0)
81 |
82 | expect(uploader.methods.getSize).toHaveBeenCalledWith(0)
83 | expect(wrapper).toMatchSnapshot()
84 | expect(wrapper.text()).toEqual('1 B')
85 | })
86 | })
87 |
--------------------------------------------------------------------------------
/tests/unit/PauseResumeButton.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils'
2 | import PauseResumeButton from '@/PauseResumeButton.vue'
3 | import FineUploader from 'fine-uploader-wrappers'
4 | import { status as STATUSES } from 'fine-uploader/lib/core/all'
5 |
6 | describe('PauseResumeButton.vue', () => {
7 | let wrapper
8 | let renderless
9 | let uploader
10 |
11 | beforeEach(() => {
12 | uploader = new FineUploader({ options: {} })
13 |
14 | wrapper = mount(PauseResumeButton, {
15 | propsData: { id: 0, uploader },
16 | })
17 |
18 | renderless = wrapper.vm.$children[0]
19 | })
20 |
21 | it("doesn't render the button until the first chunk has been uploaded", () => {
22 | expect(wrapper.isEmpty()).toBe(true)
23 | expect(wrapper).toMatchSnapshot()
24 |
25 | renderless.onUploadChunk(0, null, { partIndex: 3 })
26 |
27 | expect(wrapper.html()).toBeDefined()
28 | expect(wrapper).toMatchSnapshot()
29 | })
30 |
31 | it('removes the pause button when the upload is no longer actionable', () => {
32 | renderless.onUploadChunk(0, null, { partIndex: 1 })
33 |
34 | expect(wrapper.html()).toBeDefined()
35 | expect(wrapper).toMatchSnapshot()
36 |
37 | renderless.onStatusChange(0, null, STATUSES.DELETED)
38 |
39 | expect(wrapper).toMatchSnapshot()
40 | expect(wrapper.html()).toBeUndefined()
41 | })
42 |
43 | it('disables the button, if requested, when the upload is no longer actionable', () => {
44 | wrapper.setProps({ onlyRenderIfEnabled: false })
45 |
46 | renderless.onUploadChunk(0, null, { partIndex: 1 })
47 |
48 | expect(wrapper.html()).toBeDefined()
49 | expect(wrapper).toMatchSnapshot()
50 |
51 | renderless.onStatusChange(0, null, STATUSES.DELETED)
52 |
53 | expect(wrapper).toMatchSnapshot()
54 | expect(wrapper.html()).toBeDefined()
55 | expect(wrapper.attributes().disabled).toBeDefined()
56 | })
57 | })
58 |
--------------------------------------------------------------------------------
/tests/unit/ProgressBar.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils'
2 | import ProgressBar from '@/ProgressBar.vue'
3 | import FineUploader from 'fine-uploader-wrappers'
4 |
5 | describe('ProgressBar.vue', () => {
6 | it('hides the progress bar by default', () => {
7 | const uploader = new FineUploader({ options: {} })
8 | let wrapper = mount(ProgressBar, { propsData: { id: 0, uploader } })
9 |
10 | expect(wrapper.attributes().hidden).toBeDefined()
11 | expect(wrapper).toMatchSnapshot()
12 |
13 | wrapper = mount(ProgressBar, { propsData: { uploader } })
14 |
15 | expect(wrapper.attributes().hidden).toBeDefined()
16 | expect(wrapper).toMatchSnapshot()
17 | })
18 |
19 | it('shows the file progress bar before uploading start if specified', () => {
20 | const uploader = new FineUploader({ options: {} })
21 | let wrapper = mount(ProgressBar, {
22 | propsData: { id: 0, uploader, hidesWhenNotUploading: false },
23 | })
24 |
25 | expect(wrapper.attributes().hidden).toBeUndefined()
26 | expect(wrapper).toMatchSnapshot()
27 | })
28 |
29 | it('shows the total progress bar before uploading start if specified', () => {
30 | const uploader = new FineUploader({ options: {} })
31 | let wrapper = mount(ProgressBar, {
32 | propsData: { uploader, hidesWhenNotUploading: false },
33 | })
34 |
35 | expect(wrapper.attributes().hidden).toBeUndefined()
36 | expect(wrapper).toMatchSnapshot()
37 | })
38 |
39 | it('show the file progress if an ID is supplied', () => {
40 | const uploader = new FineUploader({ options: {} })
41 | const wrapper = mount(ProgressBar, { propsData: { id: 3, uploader } })
42 | const renderless = wrapper.vm.$children[0]
43 |
44 | renderless.onProgress(3, 'foo.jpeg', 100, 1000)
45 |
46 | expect(wrapper).toMatchSnapshot()
47 | expect(wrapper.attributes().style).toBe('width: 10%;')
48 | })
49 |
50 | it('show the total progress if no ID is supplied', () => {
51 | const uploader = new FineUploader({ options: {} })
52 | const wrapper = mount(ProgressBar, { propsData: { uploader } })
53 | const renderless = wrapper.vm.$children[0]
54 |
55 | renderless.onProgress(100, 1000)
56 |
57 | expect(wrapper).toMatchSnapshot()
58 | expect(wrapper.attributes().style).toBe('width: 10%;')
59 | })
60 |
61 | it('hides total progress bar after all uploads are complete', () => {
62 | const uploader = new FineUploader({ options: {} })
63 | const wrapper = mount(ProgressBar, { propsData: { uploader } })
64 | const renderless = wrapper.vm.$children[0]
65 |
66 | // uploading
67 | uploader.methods['getInProgress'] = jest.fn(() => 1)
68 | renderless.onStatusChange(
69 | 0,
70 | uploader.qq.status.QUEUED,
71 | uploader.qq.status.UPLOADING,
72 | )
73 |
74 | expect(wrapper).toMatchSnapshot()
75 | expect(wrapper.attributes().hidden).toBeUndefined()
76 |
77 | // done uploading
78 | uploader.methods['getInProgress'] = jest.fn(() => 0)
79 | renderless.onStatusChange(
80 | 0,
81 | uploader.qq.status.UPLOADING,
82 | uploader.qq.status.UPLOAD_SUCCESSFUL,
83 | )
84 |
85 | expect(wrapper).toMatchSnapshot()
86 | expect(wrapper.attributes().hidden).toBeDefined()
87 | })
88 |
89 | it('hides file progress bar after all upload is complete', () => {
90 | const uploader = new FineUploader({ options: {} })
91 | const wrapper = mount(ProgressBar, { propsData: { id: 0, uploader } })
92 | const renderless = wrapper.vm.$children[0]
93 |
94 | // uploading
95 | renderless.onStatusChange(
96 | 0,
97 | uploader.qq.status.QUEUED,
98 | uploader.qq.status.UPLOADING,
99 | )
100 |
101 | expect(wrapper).toMatchSnapshot()
102 | expect(wrapper.attributes().hidden).toBeUndefined()
103 |
104 | // done uploading
105 | renderless.onStatusChange(
106 | 0,
107 | uploader.qq.status.UPLOADING,
108 | uploader.qq.status.UPLOAD_SUCCESSFUL,
109 | )
110 |
111 | expect(wrapper).toMatchSnapshot()
112 | expect(wrapper.attributes().hidden).toBeDefined()
113 | })
114 |
115 | it('shows total progress bar after all uploads are complete if requested', () => {
116 | const uploader = new FineUploader({ options: {} })
117 | const wrapper = mount(ProgressBar, {
118 | propsData: { uploader, hidesWhenNotUploading: false },
119 | })
120 | const renderless = wrapper.vm.$children[0]
121 |
122 | // uploading
123 | uploader.methods['getInProgress'] = jest.fn(() => 1)
124 | renderless.onStatusChange(
125 | 0,
126 | uploader.qq.status.QUEUED,
127 | uploader.qq.status.UPLOADING,
128 | )
129 |
130 | expect(wrapper).toMatchSnapshot()
131 | expect(wrapper.attributes().hidden).toBeUndefined()
132 |
133 | // done uploading
134 | uploader.methods['getInProgress'] = jest.fn(() => 0)
135 | renderless.onStatusChange(
136 | 0,
137 | uploader.qq.status.UPLOADING,
138 | uploader.qq.status.UPLOAD_SUCCESSFUL,
139 | )
140 |
141 | expect(wrapper).toMatchSnapshot()
142 | expect(wrapper.attributes().hidden).toBeUndefined()
143 | })
144 |
145 | it('shows file progress bar after all upload is complete if requested', () => {
146 | const uploader = new FineUploader({ options: {} })
147 | const wrapper = mount(ProgressBar, {
148 | propsData: { id: 0, uploader, hidesWhenNotUploading: false },
149 | })
150 | const renderless = wrapper.vm.$children[0]
151 |
152 | // uploading
153 | renderless.onStatusChange(
154 | 0,
155 | uploader.qq.status.QUEUED,
156 | uploader.qq.status.UPLOADING,
157 | )
158 |
159 | expect(wrapper).toMatchSnapshot()
160 | expect(wrapper.attributes().hidden).toBeUndefined()
161 |
162 | // done uploading
163 | renderless.onStatusChange(
164 | 0,
165 | uploader.qq.status.UPLOADING,
166 | uploader.qq.status.UPLOAD_SUCCESSFUL,
167 | )
168 |
169 | expect(wrapper).toMatchSnapshot()
170 | expect(wrapper.attributes().hidden).toBeUndefined()
171 | })
172 | })
173 |
--------------------------------------------------------------------------------
/tests/unit/RenderlessCancelButton.spec.js:
--------------------------------------------------------------------------------
1 | import { shallowMount } from '@vue/test-utils'
2 | import CancelButton from '@/renderless/CancelButton.vue'
3 | import FineUploader from 'fine-uploader-wrappers'
4 | import { status } from 'fine-uploader/lib/core/all'
5 |
6 | describe('renderless/CancelButton.vue', () => {
7 | let wrapper
8 | let uploader
9 |
10 | const sampleBlob = new Blob(['hi!'], { type: 'text/plain' })
11 |
12 | beforeEach(done => {
13 | uploader = new FineUploader({ options: { autoUpload: false } })
14 | uploader.on('submitted', done)
15 | uploader.methods.addFiles(sampleBlob)
16 |
17 | wrapper = shallowMount(CancelButton, {
18 | propsData: { id: 0, uploader },
19 | scopedSlots: { default: slots => slots },
20 | })
21 | })
22 |
23 | it('makes a file cancelable when added', () => {
24 | expect(wrapper.vm.cancelable).toBe(true)
25 | })
26 |
27 | it('cancels the upload if onClick is triggered', done => {
28 | wrapper.vm.onClick({ preventDefault: jest.fn() })
29 |
30 | wrapper.vm.$nextTick(() => {
31 | expect(uploader.methods.getUploads()[0].status).toMatch(status.CANCELED)
32 | expect(wrapper.vm.cancelable).toBe(false)
33 |
34 | done()
35 | })
36 | })
37 | })
38 |
--------------------------------------------------------------------------------
/tests/unit/RenderlessDeleteButton.spec.js:
--------------------------------------------------------------------------------
1 | import { shallowMount } from '@vue/test-utils'
2 | import DeleteButton from '@/renderless/DeleteButton.vue'
3 | import FineUploader from 'fine-uploader-wrappers'
4 | import { status } from 'fine-uploader/lib/core/all'
5 |
6 | describe('renderless/DeleteButton.vue', () => {
7 | let wrapper
8 | let uploader
9 |
10 | beforeEach(() => {
11 | uploader = new FineUploader({ options: {} })
12 |
13 | wrapper = shallowMount(DeleteButton, {
14 | propsData: { id: 0, uploader },
15 | scopedSlots: { default: slots => slots },
16 | })
17 | })
18 |
19 | it('makes the file deletable on successfully uploaded', () => {
20 | wrapper.vm.onStatusChange(0, null, status.UPLOAD_SUCCESSFUL)
21 |
22 | expect(wrapper.vm.deletable).toBe(true)
23 | })
24 |
25 | it('deletes the file if onClick is trigger', () => {
26 | uploader.methods.deleteFile = jest.fn()
27 |
28 | wrapper.vm.onStatusChange(0, null, status.UPLOAD_SUCCESSFUL)
29 |
30 | wrapper.vm.onClick({ preventDefault: jest.fn() })
31 | expect(uploader.methods.deleteFile).toHaveBeenCalled()
32 | })
33 |
34 | it('makes the files undeletable if the file can no longer be deleted', () => {
35 | wrapper.vm.onStatusChange(0, null, status.DELETED)
36 |
37 | expect(wrapper.vm.deleting).toBe(false)
38 | expect(wrapper.vm.deletable).toBe(false)
39 | })
40 |
41 | it('makes the files undeletable while the delete is in progress', () => {
42 | wrapper.vm.onStatusChange(0, null, status.DELETING)
43 |
44 | expect(wrapper.vm.deleting).toBe(true)
45 | expect(wrapper.vm.deletable).toBe(false)
46 | })
47 | })
48 |
--------------------------------------------------------------------------------
/tests/unit/RenderlessFileProgressBar.spec.js:
--------------------------------------------------------------------------------
1 | import { shallowMount } from '@vue/test-utils'
2 | import ProgressBar from '@/renderless/FileProgressBar.vue'
3 | import FineUploader from 'fine-uploader-wrappers'
4 |
5 | describe('renderless/FileProgressBar.vue', () => {
6 | it('is not uploading the file on initialisation', () => {
7 | const uploader = new FineUploader({ options: {} })
8 | let wrapper = shallowMount(ProgressBar, {
9 | propsData: { id: 0, uploader },
10 | scopedSlots: { default: slots => slots },
11 | })
12 |
13 | expect(wrapper.vm.uploading).toBe(false)
14 | })
15 |
16 | it('keeps track of the file progress during the upload', () => {
17 | const uploader = new FineUploader({ options: {} })
18 | let wrapper = shallowMount(ProgressBar, {
19 | propsData: { id: 3, uploader },
20 | scopedSlots: { default: slots => slots },
21 | })
22 |
23 | wrapper.vm.onProgress(3, 'foo.jpeg', 100, 1000)
24 |
25 | expect(wrapper.vm.bytesUploaded).toBe(100)
26 | expect(wrapper.vm.totalSize).toBe(1000)
27 | })
28 |
29 | it('is no longer uploading when upload is finished', () => {
30 | const uploader = new FineUploader({ options: {} })
31 | const wrapper = shallowMount(ProgressBar, {
32 | propsData: { id: 0, uploader },
33 | scopedSlots: { default: slots => slots },
34 | })
35 | // uploading
36 | wrapper.vm.onStatusChange(
37 | 0,
38 | uploader.qq.status.QUEUED,
39 | uploader.qq.status.UPLOADING,
40 | )
41 |
42 | expect(wrapper.vm.uploading).toBe(true)
43 |
44 | // done uploading
45 | wrapper.vm.onStatusChange(
46 | 0,
47 | uploader.qq.status.UPLOADING,
48 | uploader.qq.status.UPLOAD_SUCCESSFUL,
49 | )
50 |
51 | expect(wrapper.vm.uploading).toBe(false)
52 | })
53 | })
54 |
--------------------------------------------------------------------------------
/tests/unit/RenderlessFilename.spec.js:
--------------------------------------------------------------------------------
1 | import { shallowMount } from '@vue/test-utils'
2 | import Filename from '@/renderless/Filename.vue'
3 | import FineUploader from 'fine-uploader-wrappers'
4 |
5 | describe('renderless/Filename.vue', () => {
6 | let uploader
7 | let wrapper
8 |
9 | const sampleBlob = new Blob(['hi!'], { type: 'text/plain' })
10 | const sampleBlobWrapper = { blob: sampleBlob, name: 'test' }
11 |
12 | beforeEach(done => {
13 | uploader = new FineUploader({ options: { autoUpload: false } })
14 | uploader.on('submitted', done)
15 | uploader.methods.addFiles(sampleBlobWrapper)
16 |
17 | wrapper = shallowMount(Filename, {
18 | propsData: { id: 0, uploader },
19 | scopedSlots: { default: object => object },
20 | })
21 | })
22 |
23 | it('set initial filename', () => {
24 | expect(wrapper.vm.filename).toBe('test')
25 | })
26 |
27 | it('update filename on setName', () => {
28 | uploader.methods.setName(0, 'new-name')
29 |
30 | expect(wrapper.vm.filename).toBe('new-name')
31 | })
32 | })
33 |
--------------------------------------------------------------------------------
/tests/unit/RenderlessFilesize.spec.js:
--------------------------------------------------------------------------------
1 | import { shallowMount } from '@vue/test-utils'
2 | import Filesize from '@/renderless/Filesize.vue'
3 | import FineUploader from 'fine-uploader-wrappers'
4 |
5 | describe('renderless/Filesize.vue', () => {
6 | const sampleBlob = new Blob(['hi!'], { type: 'text/plain' })
7 | const sampleBlobWrapper = { blob: sampleBlob, name: 'test' }
8 | const nativeObjectToString = Object.prototype.toString
9 |
10 | beforeEach(() => {
11 | Object.prototype.toString = function() {
12 | if (this && this.type === 'fakeBlob') {
13 | return '[object Blob]'
14 | }
15 |
16 | return nativeObjectToString.apply(this, arguments)
17 | }
18 | })
19 |
20 | afterEach(() => {
21 | Object.prototype.toString = nativeObjectToString
22 | })
23 |
24 | it('renders file size for tiny file using default units/text', () => {
25 | const uploader = new FineUploader({ options: { autoUpload: false } })
26 | uploader.methods.addFiles(sampleBlobWrapper)
27 |
28 | const wrapper = shallowMount(Filesize, {
29 | propsData: { id: 0, uploader },
30 | scopedSlots: { default: object => object },
31 | })
32 |
33 | expect(wrapper.vm.size).toBe(sampleBlob.size)
34 | })
35 |
36 | it('renders formatted file size for various sized files', () => {
37 | const uploader = new FineUploader({ options: { autoUpload: false } })
38 |
39 | uploader.methods.addFiles([
40 | { size: 1100, type: 'fakeBlob' },
41 | { size: 1100000, type: 'fakeBlob' },
42 | { size: 1100000000, type: 'fakeBlob' },
43 | { size: 1100000000000, type: 'fakeBlob' },
44 | ])
45 |
46 | const expectedSizes = [
47 | { size: '1.10', units: 'kilobyte' },
48 | { size: '1.10', units: 'megabyte' },
49 | { size: '1.10', units: 'gigabyte' },
50 | { size: '1.10', units: 'terabyte' },
51 | ]
52 |
53 | expectedSizes.forEach((expectedSize, id) => {
54 | const wrapper = shallowMount(Filesize, {
55 | propsData: { id, uploader },
56 | scopedSlots: { default: object => object },
57 | })
58 |
59 | expect(wrapper.vm.formatted).toEqual({
60 | size: expectedSize.size,
61 | unit: expectedSize.units,
62 | })
63 | })
64 | })
65 |
66 | it('renders file size at upload time for scaled blobs', () => {
67 | const uploader = new FineUploader({
68 | options: {
69 | autoUpload: false,
70 | scaling: { sizes: [{ name: 'test', maxSize: 100 }] },
71 | },
72 | })
73 | uploader.methods.addFiles({ type: 'fakeBlob' })
74 |
75 | const wrapper = shallowMount(Filesize, {
76 | propsData: { id: 0, uploader },
77 | scopedSlots: { default: object => object },
78 | })
79 |
80 | expect(wrapper.vm.size).toBe(-1)
81 |
82 | uploader.methods.getSize = jest.fn(() => 1)
83 | wrapper.vm.onUpload(0)
84 |
85 | expect(uploader.methods.getSize).toHaveBeenCalledWith(0)
86 | expect(wrapper.vm.formatted).toEqual({ size: 1, unit: 'byte' })
87 | })
88 | })
89 |
--------------------------------------------------------------------------------
/tests/unit/RenderlessPauseResumeButton.spec.js:
--------------------------------------------------------------------------------
1 | import { shallowMount } from '@vue/test-utils'
2 | import PauseResumeButton from '@/renderless/PauseResumeButton.vue'
3 | import FineUploader from 'fine-uploader-wrappers'
4 | import { status } from 'fine-uploader/lib/core/all'
5 |
6 | describe('renderless/PauseResumeButton.vue', () => {
7 | let wrapper
8 | let uploader
9 |
10 | beforeEach(() => {
11 | uploader = new FineUploader({ options: {} })
12 |
13 | wrapper = shallowMount(PauseResumeButton, {
14 | propsData: { id: 0, uploader },
15 | scopedSlots: { default: object => object },
16 | })
17 | })
18 |
19 | it('pausable is false until the first chunk has been uploaded', () => {
20 | expect(wrapper.vm.pausable).toBe(false)
21 |
22 | wrapper.vm.onUploadChunk(0, null, { partIndex: 3 })
23 |
24 | expect(wrapper.vm.pausable).toBe(true)
25 | })
26 |
27 | it('pausable is false when the upload is no longer actionable', () => {
28 | wrapper.vm.onUploadChunk(0, null, { partIndex: 1 })
29 |
30 | expect(wrapper.vm.pausable).toBe(true)
31 |
32 | wrapper.vm.onStatusChange(0, null, status.DELETED)
33 |
34 | expect(wrapper.vm.pausable).toBe(false)
35 | })
36 |
37 | it('allows a paused upload to be resumed and then paused again', () => {
38 | wrapper.vm.onUploadChunk(0, null, { partIndex: 7 })
39 | wrapper.vm.onStatusChange(0, null, status.PAUSED)
40 |
41 | expect(wrapper.vm.pausable).toBe(false)
42 | expect(wrapper.vm.resumable).toBe(true)
43 |
44 | uploader.methods.continueUpload = jest.fn()
45 | wrapper.vm.onClick({ preventDefault: jest.fn() })
46 | expect(uploader.methods.continueUpload).toHaveBeenCalledWith(0)
47 |
48 | wrapper.vm.onStatusChange(0, null, status.UPLOADING)
49 |
50 | expect(wrapper.vm.pausable).toBe(true)
51 | expect(wrapper.vm.resumable).toBe(false)
52 |
53 | uploader.methods.pauseUpload = jest.fn()
54 | wrapper.vm.onClick({ preventDefault: jest.fn() })
55 | expect(uploader.methods.pauseUpload).toHaveBeenCalledWith(0)
56 |
57 | wrapper.vm.onStatusChange(0, null, status.PAUSED)
58 |
59 | expect(wrapper.vm.pausable).toBe(false)
60 | expect(wrapper.vm.resumable).toBe(true)
61 | })
62 |
63 | it('allows a resumed file to be paused immediately', () => {
64 | wrapper.vm.onResume(0)
65 |
66 | expect(wrapper.vm.pausable).toBe(true)
67 | expect(wrapper.vm.resumable).toBe(false)
68 | })
69 | })
70 |
--------------------------------------------------------------------------------
/tests/unit/RenderlessRetryButton.spec.js:
--------------------------------------------------------------------------------
1 | import { shallowMount } from '@vue/test-utils'
2 | import RetryButton from '@/renderless/RetryButton.vue'
3 | import FineUploader from 'fine-uploader-wrappers'
4 |
5 | describe('renderless/RetryButton.vue', () => {
6 | let wrapper
7 | let uploader
8 |
9 | beforeEach(() => {
10 | uploader = new FineUploader({ options: {} })
11 |
12 | wrapper = shallowMount(RetryButton, {
13 | propsData: { id: 0, uploader },
14 | scopedSlots: { default: slots => slots },
15 | })
16 | })
17 |
18 | it('is not retryable if upload has not failed', () => {
19 | wrapper.vm.onComplete(0, 'foo.bar', { success: true })
20 |
21 | expect(wrapper.vm.retryable).toBe(false)
22 | })
23 |
24 | it('is retryable if upload has failed', () => {
25 | wrapper.vm.onComplete(0, 'foo.bar', { success: false })
26 |
27 | expect(wrapper.vm.retryable).toBe(true)
28 | })
29 |
30 | it('retries upload if onClick is triggered', () => {
31 | wrapper.vm.onComplete(0, 'foo.bar', { success: false })
32 | uploader.methods.retry = jest.fn()
33 | wrapper.vm.onClick()
34 |
35 | expect(uploader.methods.retry).toHaveBeenCalledWith(0)
36 | })
37 |
38 | it('is not retryable if upload has failed and retries are forbidden (default response property)', () => {
39 | wrapper.vm.onComplete(0, 'foo.bar', { success: false, preventRetry: true })
40 |
41 | expect(wrapper.vm.retryable).toBe(false)
42 | })
43 |
44 | it('is not retryable if upload has failed and retries are forbidden (custom response property)', () => {
45 | const uploader = new FineUploader({
46 | options: { retry: { preventRetryResponseProperty: 'dontDareRetry' } },
47 | })
48 | wrapper.setProps({ uploader })
49 | wrapper.vm.onComplete(0, 'foo.bar', { success: false, dontDareRetry: true })
50 |
51 | expect(wrapper.vm.retryable).toBe(false)
52 | })
53 | })
54 |
--------------------------------------------------------------------------------
/tests/unit/RenderlessStatus.spec.js:
--------------------------------------------------------------------------------
1 | import { shallowMount } from '@vue/test-utils'
2 | import Status from '@/renderless/Status.vue'
3 | import FineUploader from 'fine-uploader-wrappers'
4 | import { status as STATUSES } from 'fine-uploader/lib/core/all'
5 |
6 | describe('renderless/Status.vue', () => {
7 | let wrapper
8 | let uploader
9 |
10 | beforeEach(() => {
11 | uploader = new FineUploader({ options: {} })
12 |
13 | wrapper = shallowMount(Status, {
14 | propsData: { id: 0, uploader },
15 | scopedSlots: { default: slots => slots },
16 | })
17 | })
18 |
19 | it('saves the files new status on status change', () => {
20 | wrapper.vm.onStatusChange(0, STATUSES.UPLOAD_SUCCESSFUL, STATUSES.DELETING)
21 |
22 | expect(wrapper.vm.status).toBe(STATUSES.DELETING)
23 | })
24 |
25 | it('set the status to null for an untracked file', () => {
26 | wrapper.vm.onStatusChange(1, STATUSES.UPLOAD_SUCCESSFUL, STATUSES.DELETING)
27 |
28 | expect(wrapper.vm.status).toBeNull()
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/tests/unit/RenderlessTotalProgressBar.spec.js:
--------------------------------------------------------------------------------
1 | import { shallowMount } from '@vue/test-utils'
2 | import ProgressBar from '@/renderless/TotalProgressBar.vue'
3 | import FineUploader from 'fine-uploader-wrappers'
4 |
5 | describe('renderless/FileProgressBar.vue', () => {
6 | it('is not uploading any file on initialisation', () => {
7 | const uploader = new FineUploader({ options: {} })
8 | let wrapper = shallowMount(ProgressBar, {
9 | propsData: { uploader },
10 | scopedSlots: { default: slots => slots },
11 | })
12 |
13 | expect(wrapper.vm.uploading).toBe(false)
14 | })
15 |
16 | it('keeps track of the files progress during the upload', () => {
17 | const uploader = new FineUploader({ options: {} })
18 | let wrapper = shallowMount(ProgressBar, {
19 | propsData: { uploader },
20 | scopedSlots: { default: slots => slots },
21 | })
22 |
23 | wrapper.vm.onProgress(100, 1000)
24 |
25 | expect(wrapper.vm.bytesUploaded).toBe(100)
26 | expect(wrapper.vm.totalSize).toBe(1000)
27 | })
28 |
29 | it('is no longer uploading when upload is finished', () => {
30 | const uploader = new FineUploader({ options: {} })
31 | const wrapper = shallowMount(ProgressBar, {
32 | propsData: { uploader },
33 | scopedSlots: { default: slots => slots },
34 | })
35 | // uploading
36 | uploader.methods['getInProgress'] = jest.fn(() => 1)
37 | wrapper.vm.onStatusChange(
38 | 0,
39 | uploader.qq.status.QUEUED,
40 | uploader.qq.status.UPLOADING,
41 | )
42 |
43 | expect(wrapper.vm.uploading).toBe(true)
44 |
45 | // done uploading
46 | uploader.methods['getInProgress'] = jest.fn(() => 0)
47 | wrapper.vm.onStatusChange(
48 | 0,
49 | uploader.qq.status.UPLOADING,
50 | uploader.qq.status.UPLOAD_SUCCESSFUL,
51 | )
52 |
53 | expect(wrapper.vm.uploading).toBe(false)
54 | })
55 | })
56 |
--------------------------------------------------------------------------------
/tests/unit/RetryButton.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils'
2 | import RetryButton from '@/RetryButton.vue'
3 | import FineUploader from 'fine-uploader-wrappers'
4 |
5 | describe('RetryButton.vue', () => {
6 | let wrapper
7 | let renderless
8 | let uploader
9 |
10 | beforeEach(() => {
11 | uploader = new FineUploader({ options: {} })
12 |
13 | wrapper = mount(RetryButton, {
14 | propsData: { id: 0, uploader },
15 | })
16 | renderless = wrapper.vm.$children[0]
17 | })
18 |
19 | it('does not display retry button by default if upload has not failed', () => {
20 | renderless.onComplete(0, 'foo.bar', { success: true })
21 |
22 | expect(wrapper).toMatchSnapshot()
23 | expect(wrapper.isEmpty()).toBe(true)
24 | })
25 |
26 | it('disables retry button if upload has not failed', () => {
27 | wrapper.setProps({ onlyRenderIfRetryable: false })
28 | renderless.onComplete(0, 'foo.bar', { success: true })
29 |
30 | expect(wrapper).toMatchSnapshot()
31 | expect(wrapper.attributes().disabled).toBeDefined()
32 | })
33 |
34 | it('displays retry button if upload has failed', () => {
35 | wrapper = mount(RetryButton, {
36 | propsData: { id: 0, uploader },
37 | })
38 | renderless = wrapper.vm.$children[0]
39 |
40 | renderless.onComplete(0, 'foo.bar', { success: false })
41 |
42 | expect(wrapper).toMatchSnapshot()
43 | expect(wrapper.attributes().disabled).toBeUndefined()
44 | })
45 |
46 | it('retries upload if button has been clicked', () => {
47 | renderless.onComplete(0, 'foo.bar', { success: false })
48 | uploader.methods.retry = jest.fn()
49 | wrapper.trigger('click')
50 |
51 | expect(wrapper).toMatchSnapshot()
52 | expect(uploader.methods.retry).toHaveBeenCalledWith(0)
53 | })
54 |
55 | it('does not display retry button by default if upload has failed and retries are forbidden (default response property)', () => {
56 | renderless.onComplete(0, 'foo.bar', { success: false, preventRetry: true })
57 |
58 | expect(wrapper).toMatchSnapshot()
59 | expect(wrapper.isEmpty()).toBe(true)
60 | })
61 |
62 | it('does not display retry button by default if upload has failed and retries are forbidden (custom response property)', () => {
63 | const uploader = new FineUploader({
64 | options: { retry: { preventRetryResponseProperty: 'dontDareRetry' } },
65 | })
66 | wrapper.setProps({ uploader })
67 | renderless.onComplete(0, 'foo.bar', { success: false, dontDareRetry: true })
68 |
69 | expect(wrapper).toMatchSnapshot()
70 | expect(wrapper.isEmpty()).toBe(true)
71 | })
72 |
73 | it('disables retry button if upload has failed and retries are forbidden', () => {
74 | wrapper.setProps({ onlyRenderIfRetryable: false })
75 | renderless.onComplete(0, 'foo.bar', { success: false, preventRetry: true })
76 |
77 | expect(wrapper).toMatchSnapshot()
78 | expect(wrapper.attributes().disabled).toBeDefined()
79 | })
80 | })
81 |
--------------------------------------------------------------------------------
/tests/unit/Status.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from '@vue/test-utils'
2 | import Status from '@/Status.vue'
3 | import FineUploader from 'fine-uploader-wrappers'
4 | import { status as STATUSES } from 'fine-uploader/lib/core/all'
5 |
6 | describe('Status.vue', () => {
7 | let wrapper
8 | let uploader
9 | let renderless
10 |
11 | beforeEach(() => {
12 | uploader = new FineUploader({ options: {} })
13 |
14 | wrapper = mount(Status, {
15 | propsData: { id: 0, uploader },
16 | })
17 | renderless = wrapper.vm.$children[0]
18 | })
19 |
20 | it('render nothing for a different file', () => {
21 | renderless.onStatusChange(1, STATUSES.UPLOAD_SUCCESSFUL, STATUSES.DELETING)
22 |
23 | expect(wrapper).toMatchSnapshot()
24 | expect(wrapper.text()).toBe('')
25 | })
26 |
27 | it('render nothing for an untracked status value', () => {
28 | renderless.onStatusChange(0, STATUSES.DELETING, STATUSES.DELETE_FAILED)
29 |
30 | expect(wrapper).toMatchSnapshot()
31 | expect(wrapper.text()).toBe('')
32 | })
33 |
34 | it('renders the status for the tracked file', () => {
35 | renderless.onStatusChange(0, STATUSES.UPLOAD_SUCCESSFUL, STATUSES.DELETING)
36 |
37 | expect(wrapper).toMatchSnapshot()
38 | expect(wrapper.text()).toBe('Deleting...')
39 | })
40 | })
41 |
--------------------------------------------------------------------------------
/tests/unit/__snapshots__/CancelButton.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`CancelButton.vue disables the button if requested when the file can no longer be canceled 1`] = `
4 |
7 | `;
8 |
9 | exports[`CancelButton.vue removes the button by default if the file can no longer be canceled 1`] = ``;
10 |
11 | exports[`CancelButton.vue renders the button for a submitted file 1`] = `
12 |
15 | `;
16 |
--------------------------------------------------------------------------------
/tests/unit/__snapshots__/DeleteButton.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`DeleteButton.vue disabled the button while the delete is in progress 1`] = `
4 |
7 | `;
8 |
9 | exports[`DeleteButton.vue disables the button if requested when the file can no longer be deleted 1`] = `
10 |
13 | `;
14 |
15 | exports[`DeleteButton.vue removes the button if the file can no longer be deleted 1`] = ``;
16 |
17 | exports[`DeleteButton.vue renders the button for a successfully uploaded file 1`] = `
18 |
21 | `;
22 |
--------------------------------------------------------------------------------
/tests/unit/__snapshots__/Filename.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`Filename.vue renders initial filename 1`] = `test`;
4 |
5 | exports[`Filename.vue updates filename on setName 1`] = `new-name`;
6 |
--------------------------------------------------------------------------------
/tests/unit/__snapshots__/Filesize.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`Filesize.vue renders an empty filesize component if size is not known initially 1`] = ``;
4 |
5 | exports[`Filesize.vue renders file size at upload time for scaled blobs 1`] = ``;
6 |
7 | exports[`Filesize.vue renders file size at upload time for scaled blobs 2`] = `1 B`;
8 |
9 | exports[`Filesize.vue renders formatted file size for various sized files 1`] = `1.10 KB`;
10 |
11 | exports[`Filesize.vue renders formatted file size for various sized files 2`] = `1.10 MB`;
12 |
13 | exports[`Filesize.vue renders formatted file size for various sized files 3`] = `1.10 GB`;
14 |
15 | exports[`Filesize.vue renders formatted file size for various sized files 4`] = `1.10 TB`;
16 |
--------------------------------------------------------------------------------
/tests/unit/__snapshots__/PauseResumeButton.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`PauseResumeButton.vue disables the button, if requested, when the upload is no longer actionable 1`] = ``;
4 |
5 | exports[`PauseResumeButton.vue disables the button, if requested, when the upload is no longer actionable 2`] = ``;
6 |
7 | exports[`PauseResumeButton.vue doesn't render the button until the first chunk has been uploaded 1`] = ``;
8 |
9 | exports[`PauseResumeButton.vue doesn't render the button until the first chunk has been uploaded 2`] = ``;
10 |
11 | exports[`PauseResumeButton.vue removes the pause button when the upload is no longer actionable 1`] = ``;
12 |
13 | exports[`PauseResumeButton.vue removes the pause button when the upload is no longer actionable 2`] = ``;
14 |
--------------------------------------------------------------------------------
/tests/unit/__snapshots__/ProgressBar.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`ProgressBar.vue hides file progress bar after all upload is complete 1`] = ``;
4 |
5 | exports[`ProgressBar.vue hides file progress bar after all upload is complete 2`] = ``;
6 |
7 | exports[`ProgressBar.vue hides the progress bar by default 1`] = ``;
8 |
9 | exports[`ProgressBar.vue hides the progress bar by default 2`] = ``;
10 |
11 | exports[`ProgressBar.vue hides total progress bar after all uploads are complete 1`] = ``;
12 |
13 | exports[`ProgressBar.vue hides total progress bar after all uploads are complete 2`] = ``;
14 |
15 | exports[`ProgressBar.vue show the file progress if an ID is supplied 1`] = ``;
16 |
17 | exports[`ProgressBar.vue show the total progress if no ID is supplied 1`] = ``;
18 |
19 | exports[`ProgressBar.vue shows file progress bar after all upload is complete if requested 1`] = ``;
20 |
21 | exports[`ProgressBar.vue shows file progress bar after all upload is complete if requested 2`] = ``;
22 |
23 | exports[`ProgressBar.vue shows the file progress bar before uploading start if specified 1`] = ``;
24 |
25 | exports[`ProgressBar.vue shows the total progress bar before uploading start if specified 1`] = ``;
26 |
27 | exports[`ProgressBar.vue shows total progress bar after all uploads are complete if requested 1`] = ``;
28 |
29 | exports[`ProgressBar.vue shows total progress bar after all uploads are complete if requested 2`] = ``;
30 |
--------------------------------------------------------------------------------
/tests/unit/__snapshots__/RetryButton.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`RetryButton.vue disables retry button if upload has failed and retries are forbidden 1`] = `
4 |
7 | `;
8 |
9 | exports[`RetryButton.vue disables retry button if upload has not failed 1`] = `
10 |
13 | `;
14 |
15 | exports[`RetryButton.vue displays retry button if upload has failed 1`] = `
16 |
19 | `;
20 |
21 | exports[`RetryButton.vue does not display retry button by default if upload has failed and retries are forbidden (custom response property) 1`] = ``;
22 |
23 | exports[`RetryButton.vue does not display retry button by default if upload has failed and retries are forbidden (default response property) 1`] = ``;
24 |
25 | exports[`RetryButton.vue does not display retry button by default if upload has not failed 1`] = ``;
26 |
27 | exports[`RetryButton.vue retries upload if button has been clicked 1`] = `
28 |
31 | `;
32 |
--------------------------------------------------------------------------------
/tests/unit/__snapshots__/Status.spec.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`Status.vue render nothing for a different file 1`] = ``;
4 |
5 | exports[`Status.vue render nothing for an untracked status value 1`] = ``;
6 |
7 | exports[`Status.vue renders the status for the tracked file 1`] = `Deleting...`;
8 |
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {}
2 |
--------------------------------------------------------------------------------