Cloud testing leftovers: note dates follow renames, folder files, Cloud UI tests, several folder vaults - #42
Merged
Merged
Conversation
A note has two app-owned sidecars: its comments (`.zennotes/comments/<note>.comments.json`) and its creation date (`.zennotes/note-metadata/<note>.metadata.json`, written by desktop). The phone already moved the comments with a note but never the date, so a note renamed or moved here lost its creation date on every device, and Cloud sync carried the orphaned file around. Folder renames left the folder's date tree behind the same way. Found in Cloud device testing (2026-10-02). Renames and moves now carry note, comments and date together, and put all three back if any move fails, as desktop's note-sidecars.ts does: - A date already at the destination with no note beside it belongs to nobody and is discarded rather than inherited (ZenNotes#839). - Leftover comments at the destination are another note's discussion, so the move is refused with desktop's exact wording. - A folder rename onto a name that already has a date tree is refused. - Deleting a note or folder, and emptying the trash, remove the dates too; without that, a deleted folder's dates would block a later rename onto its name. Not changed: symlinked notes (the filesystem plugin cannot see links), and creating a note at a path with a stale date still inherits it.
The drawer built a folder's rows from app-core's Browse listing, which carried only folders, databases and notes, so attachments never appeared on the phone while the desktop's folder view shows them. Core's Browse now returns file rows (ZenNotes/zennotes, Fix(mobile): Browse lists a folder's files); the drawer renders them after the notes, with the extension label the desktop sidebar uses, and opens one through openNote like a database row. "No notes here yet" now also needs no files. The rows are read defensively, so on the pinned core 2.60.4 (no `files`) the drawer is exactly as before; they appear once the app adopts a core with the change.
…count All six CloudFlowUITests failed at "More" and never joined the gate. The lookup took the first element labelled "More", and the welcome note has a bold **More** list item that WebKit puts ahead of the menu, hidden under the menu backdrop (seen at x=51), so the tap missed. The next steps had the same trap with the note's bold Settings and Browse; FavoriteUITests passed only because it opens an empty note first. Menu steps now use the polling `hittable(label:in:failure:)` lookup the move and search tests already use, for More, Settings, Cloud, Browse, New, New note and Publish. The plain lookup stays for status text and rows that become tappable only after scrolling. The six account-backed tests skip before launch when ZENNOTES_CLOUD_E2E_EMAIL or _PASSWORD is missing, naming the variable and the TEST_RUNNER_ prefix that passes it through, and a new phone test walks Open menu, More, Settings, Cloud without an account so the route stays covered. testFirstTapOnCreateLandsWhileATagIsTyped gets the iPad skip its sibling has: it waits for the phone-only ensō menu. Simulator (iOS 26.5): iPhone full suite 7 passed, 7 skipped, 0 failed; iPad CloudFlowUITests and DeepLinkUITests passed or skipped, 0 failed.
Picking a Files folder as a vault replaced the one before it: the app kept a single folder entry, used one fixed root token and listed only that folder, so adding a second folder dropped the first from the vault list (Android keeps a list). Found in Cloud device testing (2026-10-02). The native side was never the limit: the bookmark plugin resolves any bookmark and CloudFiles already keeps a list of roots. Folders are now a list under `zn-mobile:external-vaults` (Android's key), each with a random id and the root token `zn://external-vaults/<id>`; the old token still means the current folder. Ids, not bookmarks, name a folder, because iOS hands out new bookmark bytes on every pick and when one goes stale. On first read after the update the old single entry becomes the list's first folder with its bookmark bytes untouched, and stays as the pointer to the current folder so an older build can still read it. Picking a folder already in the list refreshes that entry instead of adding a row; stale-bookmark refreshes and renames are saved; removing one folder leaves the others alone. The drawer and Settings mark the current vault by token, since two folders can share a name. The replace question (1516b23) and its footnote go, with folder-vault-replace.ts: there is nothing left to replace. Checked on a simulator with real Files picker bookmarks: upgrading over a one-folder install kept that folder (same bookmark SHA-256), a second folder was added without a question, switching opened each through its own bookmark, and removing one left the other through a relaunch.
) A high-severity advisory for braces (stack exhaustion on deeply nested patterns, no fixed release) failed the production npm audit gate on every pull request. It reached production through @excalidraw/excalidraw, which lists sass 1.51.0 as a dependency; that sass pulls in chokidar 3, which pulls in braces. Excalidraw never loads sass at runtime: nothing in its build output imports it. Excalidraw's sass is overridden to 1.103.1, the version the desktop repo already carries. It watches files with a chokidar that has no braces, so braces stays only under build tools. No existing package changes version.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes from the Cloud device testing (2026-10-02) and the release prep (2026-10-05). Not a release: version and core stay as they are. One commit per change.
.zennotes/note-metadatadate, so the date was lost on every device and Cloud carried the orphan around. Note, comments and date now move together and roll back together, as desktop's note-sidecars.ts does: a stale date with no note is discarded ([Bug] Creating new note and changing the titel does not work zennotes#839), leftover comments refuse the move with desktop's wording, and deletes remove dates too. 13 new tests.filesrows, read defensively: on the pinned core 2.60.4 the drawer is unchanged, and the rows appear once the app adopts a core built from ZenNotes/zennotes v2.62.0 (4584590c).hittablelookup, the six account tests skip withoutZENNOTES_CLOUD_E2E_EMAIL/_PASSWORD(pass them asTEST_RUNNER_…), a new phone test covers More → Settings → Cloud, and SearchCreate's tag test gets the iPad skip its sibling has.Tests:
npm test202 passed, typecheck and vite build clean. Simulator (iOS 26.5): iPhone UI suite 7 passed, 7 skipped, 0 failed; iPad CloudFlow and DeepLink 0 failed. Folder vaults checked with real Files picker bookmarks: an upgrade over a one-folder install kept the folder (same bookmark SHA-256), a second folder was added without a question, switching and removing worked through a relaunch.How to test locally
export LANG=en_US.UTF-8; npm ci && npx vite build && npx cap sync ios, run on a simulator.xcodebuild test-without-building -workspace ios/App/App.xcworkspace -scheme AppCloudUITests -destination 'platform=iOS Simulator,id=<sim>' -collect-test-diagnostics never. Before: six Cloud failures at "More". After: they skip with the variable named.