Skip to content

Cloud testing leftovers: note dates follow renames, folder files, Cloud UI tests, several folder vaults - #42

Merged
adibhanna merged 5 commits into
mainfrom
fix/cloud-testing-leftovers
Oct 5, 2026
Merged

adibhanna merged 5 commits into
mainfrom
fix/cloud-testing-leftovers

Conversation

@adibhanna

Copy link
Copy Markdown
Contributor

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.

  1. A renamed or moved note keeps its creation date (eacf146). Renames and moves already carried a note's comments but never its .zennotes/note-metadata date, 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.
  2. A folder lists its files after its notes (f69a58c). The drawer showed only notes and subfolders. It renders core's new Browse files rows, 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).
  3. Cloud UI tests reach the menu and skip without an account (16d7587). The welcome note's bold "More" sat ahead of the menu item, so all six CloudFlowUITests missed their tap. Menu steps now use the polling hittable lookup, the six account tests skip without ZENNOTES_CLOUD_E2E_EMAIL/_PASSWORD (pass them as TEST_RUNNER_…), a new phone test covers More → Settings → Cloud, and SearchCreate's tag test gets the iPad skip its sibling has.
  4. iPhone keeps a list of Files folder vaults (26a51b7). Picking a second folder replaced the first. Folders are now a list (Android's storage key), named by id, with the old single entry migrated as the first folder with its bookmark bytes untouched; the replace question goes. No native change.

Tests: npm test 202 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

  1. export LANG=en_US.UTF-8; npm ci && npx vite build && npx cap sync ios, run on a simulator.
  2. Vaults: with a Files folder vault open, add a second folder from New Vault. Before: "replace the current folder?" and the first one disappears. After: both listed; switch between them.
  3. Sidecars: on desktop, comment on a note; on the phone rename it, then sync. Before: the comment and creation date stay behind. After: both follow the note.
  4. UI tests: 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.

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.
@adibhanna
adibhanna merged commit b421f6a into main Oct 5, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant