Skip to content

feat(NcUploadPicker): migrate component from @nextcloud/upload - #7882

Merged
susnux merged 12 commits into
mainfrom
feat/nc-uploader
Sep 8, 2026
Merged

susnux merged 12 commits into
mainfrom
feat/nc-uploader

Conversation

@susnux

@susnux susnux commented Nov 18, 2025

Copy link
Copy Markdown
Contributor

☑️ Resolves

🚧 Tasks

🏁 Checklist

  • ⛑️ Tests are included or are not applicable
  • 📘 Component documentation has been extended, updated or is not applicable
  • 2️⃣ Backport to stable8 for maintained Vue 2 version or not applicable

@susnux susnux added enhancement New feature or request 2. developing Work in progress labels Nov 18, 2025
@susnux susnux changed the title feat(NcUploadPicker): migrate component from `@nextcloud/upload) feat(NcUploadPicker): migrate component from @nextcloud/upload Nov 18, 2025
@susnux
susnux force-pushed the feat/nc-file-picker branch from be16ff5 to 5272388 Compare January 21, 2026 12:08
@susnux
susnux force-pushed the feat/nc-file-picker branch from 5272388 to 06b7afe Compare February 6, 2026 16:38
Base automatically changed from feat/nc-file-picker to main February 7, 2026 00:51
@susnux
susnux force-pushed the feat/nc-uploader branch 2 times, most recently from a7bbd96 to d56c385 Compare February 10, 2026 01:18
@susnux
susnux force-pushed the feat/nc-uploader branch from d56c385 to 6b45bf8 Compare June 27, 2026 22:07
@susnux
susnux force-pushed the feat/nc-uploader branch 4 times, most recently from f974181 to 6611edc Compare August 19, 2026 16:33
@ShGKme

ShGKme commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

is something missing?

@susnux

susnux commented Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

is something missing?

tests and ts check fails, featurewise this should be done

@susnux
susnux marked this pull request as ready for review August 21, 2026 16:55
@susnux susnux added 3. to review Waiting for reviews component Component discussion and/or suggestion and removed 2. developing Work in progress labels Aug 21, 2026
@codecov

codecov Bot commented Aug 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.13043% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 53.59%. Comparing base (2e332f1) to head (f87d3ce).
⚠️ Report is 13 commits behind head on main.

Files with missing lines Patch % Lines
src/components/NcUploadPicker/NcUploadPicker.vue 99.13% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #7882      +/-   ##
==========================================
+ Coverage   52.18%   53.59%   +1.41%     
==========================================
  Files         120      124       +4     
  Lines        4350     4515     +165     
  Branches     1297     1341      +44     
==========================================
+ Hits         2270     2420     +150     
- Misses       1765     1775      +10     
- Partials      315      320       +5     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread src/components/NcUploadPicker/NcUploadPicker.vue Outdated

@skjnldsv skjnldsv left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice migration, the story plus mockDav approach reads really well and I think we should standardise on it for the other component tests.

Two things before this can go in.

First, conflicts.spec.ts is failing, on my machine and in CI on both shards. It looks like it was written against a ConflictPicker that does not match what @nextcloud/dialogs actually ships. Details in the inline comments.

Second, the retry behaviour from the old Cypress suite is not covered anywhere after the move. retryCondition in @nextcloud/files (lib/upload/utils/upload.ts) decides that 507 is permanent and 423 should be retried, and that file has no spec at all, so those branches are untested in every repo. I opened a follow-up PR #8922 based on this branch, which you can merge into this one if you want a single PR, or keep as a second step. It adds the missing retry tests and a few of the cleanups below.

Separately, the invalid filename flow (rename, skip, cancel on a forbidden name) has no successor at all. filename-validation.ts in @nextcloud/files unit tests the rules but nothing drives the UI. If we are dropping that on purpose it should be called out as a breaking change, otherwise it needs a new home before @nextcloud/upload v2 removes its Vue components. I can open an issue for it.

Comment thread tests/component/components/NcUploadPicker/conflicts.spec.ts Outdated
Comment thread tests/component/components/NcUploadPicker/conflicts.spec.ts Outdated
await expect(conflict.getByRole('checkbox', { name: /^New version/ })).toBeVisible()
await expect(conflict.getByRole('checkbox', { name: /^Existing version/ })).toBeVisible()
// Nothing is uploaded before the conflict is resolved
expect(dav.received('PUT')).toHaveLength(0)

@skjnldsv skjnldsv Sep 4, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

received() only looks at the requests that have arrived so far, so this can pass because the PUT has not been sent yet rather than because it will never be sent. Same on lines 38, 51 and 62.

Line 51 is the weakest one, the dialog check and the progressbar check are both satisfied by nothing having happened, so the test would still pass if conflict handling silently uploaded a moment later.

Two options, either wait for something that proves the uploader got far enough first (line 62 does this nicely with waitFor('HEAD')), or add a small helper to mockDav that snapshots the count, waits, and asserts it did not grow.

The two tests that already pass are hardened in #8922, using waitFor('HEAD') as the sync point plus an expectNoMore() helper added to mockDav. The four that fail are left to this PR.

Comment on lines +172 to +173
expect(dav.received('PUT')).toHaveLength(1)
expect(dav.received('MOVE')).toHaveLength(0)

@skjnldsv skjnldsv Sep 4, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as in conflicts.spec.ts, these two can pass before the remaining chunk would have been sent. Since the point of the test is that pausing stops further uploads, it is worth making sure nothing arrives after a short wait rather than checking the count once.

Done in #8922 with expectNoMore('PUT').

Comment on lines +11 to +14
/** The upload of a file finished successfully */
const UPLOAD_FINISHED = 4
/** The upload of a file failed */
const UPLOAD_FAILED = 6

@skjnldsv skjnldsv Sep 4, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These duplicate UploadStatus by hand here and in cancel.spec.ts, and will drift silently if the values ever change. I know it cannot be imported directly, @nextcloud/files/upload touches window on import while the test bodies run in Node.

What works is importing it as a type only and using satisfies, so the numbers stay literal but the type checker fails if upstream changes them:

import type { UploadStatus as UpstreamUploadStatus } from '@nextcloud/files/upload'

export const UploadStatus = {
  INITIALIZED: 0,
  SCHEDULED: 1,
  UPLOADING: 2,
  ASSEMBLING: 3,
  FINISHED: 4,
  CANCELLED: 5,
  FAILED: 6,
} as const satisfies typeof UpstreamUploadStatus

I checked, changing one of the values gives Type '99' is not assignable to type '4'.

Done in #8922, the mirror lives in upload-helpers and cancel.spec.ts uses it too.

})

test.describe('NcUploadPicker: uploading', () => {
test.skip(({ browserName }) => browserName === 'webkit', 'WebKit does not support file pickers in Playwright yet')

@skjnldsv skjnldsv Sep 4, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This skip is repeated in five describes with the same reason string, here and on line 177, and in cancel.spec.ts, conflicts.spec.ts and progress.spec.ts. Could go into upload-helpers as a small function that calls test.skip, since test is a module singleton it still applies to the surrounding describe.

Done in #8922 as skipWithoutFilePicker().

* @param name - Name of the file
* @param sizeInMiB - Size of the file in MiB
*/
export function createFile(name: string, sizeInMiB: number): FakeFile {

@skjnldsv skjnldsv Sep 4, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small thing, createFile always uses text/plain. Taking the mime type as an optional third argument would let us exercise the accept prop from a component test rather than only in unit tests.

Done in #8922.

@susnux

susnux commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

Second, the retry behaviour from the old Cypress suite is not covered anywhere after the move

Thats not part of the UI - the retry is part of the library function and thus we do not need to duplicate those tests here.
This is only for the UI and should only check the UI is working properly to the library interface.
The actual upload logic is tested in the library itself.

…load`

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
@susnux
susnux enabled auto-merge September 8, 2026 22:11
@susnux
susnux merged commit 40d4364 into main Sep 8, 2026
25 checks passed
@susnux
susnux deleted the feat/nc-uploader branch September 8, 2026 22:12
@skjnldsv skjnldsv mentioned this pull request Sep 11, 2026
@susnux susnux modified the milestones: 9.10.0, 9.12.0 Sep 13, 2026
@Antreesy

Copy link
Copy Markdown
Contributor

I'm hitting error from manual install, assume it originates from this PR?

>> npm i @nextcloud/vue@9.12.0
npm error code ERESOLVE
npm error ERESOLVE could not resolve
npm error
npm error While resolving: @nextcloud/vue@9.12.0
npm error Found: @nextcloud/files@4.0.0
npm error node_modules/@nextcloud/files
npm error   @nextcloud/files@"^4.0.0" from @nextcloud/dialogs@7.5.0
npm error   node_modules/@nextcloud/dialogs
npm error     @nextcloud/dialogs@"^7.5.0" from the root project
npm error     peerOptional @nextcloud/dialogs@"^7.4.0" from @nextcloud/vue@9.12.0
npm error   optional @nextcloud/files@"^3.12.2 || ^4.0.0" from @nextcloud/sharing@0.4.0
npm error   node_modules/@nextcloud/sharing
npm error     @nextcloud/sharing@"^0.4.0" from @nextcloud/dialogs@7.5.0
npm error     node_modules/@nextcloud/dialogs
npm error       @nextcloud/dialogs@"^7.5.0" from the root project
npm error       1 more (@nextcloud/vue)
npm error     @nextcloud/sharing@"^0.4.0" from the root project
npm error     1 more (@nextcloud/vue)
npm error   1 more (the root project)
npm error
npm error Could not resolve dependency:
npm error peerOptional @nextcloud/files@"^4.1.0-beta.2" from @nextcloud/vue@9.12.0
npm error node_modules/@nextcloud/vue
npm error   @nextcloud/vue@"9.12.0" from the root project
npm error   @nextcloud/vue@"^9.9.0" from @nextcloud/dialogs@7.5.0
npm error   node_modules/@nextcloud/dialogs
npm error     @nextcloud/dialogs@"^7.5.0" from the root project
npm error     1 more (@nextcloud/vue)
npm error
npm error Conflicting peer dependency: @nextcloud/files@4.1.0-beta.2
npm error node_modules/@nextcloud/files
npm error   peerOptional @nextcloud/files@"^4.1.0-beta.2" from @nextcloud/vue@9.12.0
npm error   node_modules/@nextcloud/vue
npm error     @nextcloud/vue@"9.12.0" from the root project
npm error     @nextcloud/vue@"^9.9.0" from @nextcloud/dialogs@7.5.0
npm error     node_modules/@nextcloud/dialogs
npm error       @nextcloud/dialogs@"^7.5.0" from the root project
npm error       1 more (@nextcloud/vue)

@susnux

susnux commented Sep 17, 2026

Copy link
Copy Markdown
Contributor Author

@Antreesy should be fixed with #8972

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3. to review Waiting for reviews component Component discussion and/or suggestion enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[RFC] export of vue components

5 participants