Daniel Bohry vor 1 Woche
Ursprung
Commit
190ff09042

+ 0 - 149
TESTING_WORKFLOW.md

@@ -1,149 +0,0 @@
-# 🧪 How to Test Your GitHub Workflow
-
-Your unified workflow is ready! Here are **3 safe ways** to test it before going live:
-
-## ✅ **All Tests Pass Locally!**
-
-```bash
-# Run the local validation script:
-./test-workflow.sh
-```
-
-**Results:**
-- ✅ Repository structure is correct
-- ✅ All required configuration files present
-- ✅ Workflow files are properly configured
-- ✅ Desktop app version: 1.1.0
-- ✅ 11 frontend files ready for desktop app
-- ✅ Node.js, npm, and Docker all available
-
----
-
-## 🧪 **Option 1: SAFE DRY RUN (Recommended First Test)**
-
-### What it does:
-- ✅ **Tests workflow logic** without deploying anything
-- ✅ **Validates all steps** on all platforms (Linux, Windows, macOS)
-- ✅ **No Docker push** - completely safe
-- ✅ **No GitHub releases** created
-
-### How to run:
-1. **Push your code** to GitHub (if not already pushed)
-2. **Go to GitHub** → Your repository → **Actions**
-3. **Click "Test Workflow (Dry Run)"** on the left
-4. **Click "Run workflow"** button
-5. **Choose test level**:
-   - `basic` - Fast validation (5 minutes)
-   - `full` - Complete validation (15 minutes)
-6. **Click "Run workflow"**
-
-### Expected output:
-```
-✅ Java Build Test: PASSED
-✅ Docker Build Test: PASSED
-✅ Release Creation Test: PASSED
-✅ Linux Desktop Test: PASSED
-✅ Windows Desktop Test: PASSED
-✅ macOS Desktop Test: PASSED
-
-🚀 Your unified workflow is ready!
-```
-
----
-
-## 🧪 **Option 2: MANUAL TRIGGER (Real Workflow)**
-
-### What it does:
-- ⚠️ **WILL actually deploy** Docker image
-- ⚠️ **WILL create GitHub release** with desktop apps
-- ⚠️ **WILL update** https://notes.lhamacorp.com
-
-### How to run:
-1. **Go to GitHub** → Your repository → **Actions**
-2. **Click "Release"** on the left
-3. **Click "Run workflow"** button
-4. **Click "Run workflow"**
-
-### Use when:
-- Dry run test passed ✅
-- You're ready to deploy
-- You want to test the full flow manually
-
----
-
-## 🚀 **Option 3: AUTOMATIC TRIGGER (Production)**
-
-### What it does:
-- ⚠️ **WILL deploy everything** automatically
-- ⚠️ **WILL update production** on every push to main
-
-### How it works:
-```bash
-# Any change triggers deployment:
-echo "// Test change" >> src/main/resources/static/css/style.css
-git add .
-git commit -m "Test workflow"
-git push origin main
-
-# → GitHub Actions automatically:
-# 1. Builds and tests Java app
-# 2. Deploys Docker to production
-# 3. Creates GitHub release
-# 4. Builds desktop apps for all platforms
-```
-
-### Use when:
-- Manual trigger test passed ✅
-- You're confident in the workflow
-- Ready for automatic deployments
-
----
-
-## 📊 **Test Results Dashboard**
-
-After running tests, you can monitor progress at:
-- **GitHub** → **Actions** tab
-- **Real-time logs** for each job
-- **Build artifacts** and results
-
-### Typical timing:
-- **Dry run**: ~5-15 minutes
-- **Manual trigger**: ~10-20 minutes
-- **Automatic**: ~10-20 minutes
-
----
-
-## 🔧 **Troubleshooting**
-
-### If workflow fails:
-1. **Check the logs** in GitHub Actions
-2. **Common issues**:
-   - Missing secrets (DOCKERHUB_USERNAME, DOCKERHUB_TOKEN)
-   - ~~GitHub token permissions~~ ✅ **FIXED**: Added explicit permissions
-   - Node.js version conflicts
-
-### If desktop builds fail:
-1. **Check npm install** step in logs
-2. **Verify electron-builder** configuration
-3. **Try local build** first: `npm run build-linux`
-
----
-
-## 🎯 **Recommended Testing Order**
-
-1. **✅ Local validation** - `./test-workflow.sh`
-2. **🧪 Dry run test** - GitHub Actions test workflow
-3. **🧪 Manual trigger** - Real workflow when ready
-4. **🚀 Automatic** - Push to main for production
-
----
-
-## 💡 **Pro Tips**
-
-- **Start with dry run** to catch issues early
-- **Test on a branch** first if you want extra safety
-- **Check GitHub releases** page after successful runs
-- **Desktop apps take longest** - be patient (~10-15 mins)
-- **Each platform builds in parallel** for speed
-
-Your workflow is **production-ready**! 🎉

+ 0 - 121
UNIFIED_WORKFLOW.md

@@ -1,121 +0,0 @@
-# 🚀 Unified Release Workflow
-
-Your GitHub Actions workflow now handles **both Docker deployment AND desktop app releases** in a single, streamlined process!
-
-## 📋 Workflow Overview
-
-**Trigger**: Push to `main` branch → **One unified workflow does everything**
-
-```mermaid
-graph TD
-    A[Push to main] --> B[Build and Test Java App]
-    B --> C[Build and Push Docker Image]
-    C --> D[Create GitHub Release]
-    D --> E[Build Linux Desktop App]
-    D --> F[Build Windows Desktop App]
-    D --> G[Build macOS Desktop App]
-    E --> H[🎉 Complete Release]
-    F --> H
-    G --> H
-```
-
-## 🔄 Step-by-Step Process
-
-### 1. **Backend Build & Test**
-- ✅ Java 25 + Gradle build
-- ✅ Run all tests
-- ✅ Validate application
-
-### 2. **Docker Deployment**
-- ✅ Multi-arch build (linux/amd64, linux/arm64)
-- ✅ Push to Docker Hub: `lhamacorp/knotes:latest`
-- ✅ Deploy to https://notes.lhamacorp.com
-
-### 3. **Desktop Release Creation**
-- ✅ Create GitHub Release with version tag
-- ✅ Professional release notes (Docker + Desktop info)
-- ✅ Prepare for desktop app uploads
-
-### 4. **Cross-Platform Desktop Builds** *(Parallel)*
-- 🐧 **Linux**: `.AppImage` file (~104MB)
-- 🪟 **Windows**: `.exe` installer (~120MB)
-- 🍎 **macOS**: `.dmg` installer (~115MB)
-
-## 📦 What Users Get
-
-### 🐳 **Docker Users**:
-```bash
-docker pull lhamacorp/knotes:latest
-docker run -p 8080:8080 lhamacorp/knotes:latest
-```
-
-### 💻 **Desktop Users**:
-- Visit: `https://github.com/lhamacorp/knotes/releases/latest`
-- Download appropriate file for their OS
-- Get automatic update notifications
-
-## ⚡ **Advantages of Unified Workflow**
-
-### ✅ **Single Deploy Process**
-- One push to main = Everything deployed
-- No separate workflows to manage
-- Consistent versioning across Docker + Desktop
-
-### ✅ **Synchronized Releases**
-- Docker deployment happens first
-- Desktop apps built with latest frontend
-- Desktop apps connect to freshly deployed API
-
-### ✅ **Professional Release Notes**
-```markdown
-## 🚀 kNotes Release - Docker + Desktop Apps
-
-### 🐳 Docker Deployment:
-- Image: lhamacorp/knotes:latest
-- Deployed to: https://notes.lhamacorp.com
-
-### 📱 Desktop Apps:
-- Windows: Download .exe installer
-- macOS: Download .dmg installer
-- Linux: Download .AppImage file
-```
-
-### ✅ **Efficient Resource Usage**
-- Builds run in optimal order
-- Parallel desktop builds (faster)
-- Single GitHub release for everything
-
-## 🎯 **Your New Deployment Flow**
-
-```bash
-# Make any change (frontend, backend, or both)
-git add .
-git commit -m "Update application"
-git push origin main
-
-# GitHub Actions automatically:
-# 1. ✅ Tests and builds Java app
-# 2. ✅ Deploys Docker to production
-# 3. ✅ Creates GitHub release
-# 4. ✅ Builds desktop apps for all platforms
-# 5. ✅ Users get update notifications
-
-# Result: Full-stack deployment in ~10-15 minutes! 🚀
-```
-
-## 🔧 **Workflow Files**
-
-- ✅ **Main**: `.github/workflows/buildAndRelease.yml` (unified)
-- ❌ **Removed**: `desktop-release.yml` (merged in)
-- ❌ **Removed**: `test-desktop-release.yml` (no longer needed)
-
-## 🎉 **Benefits Summary**
-
-- **🔄 One workflow** handles everything
-- **⚡ Faster** parallel desktop builds
-- **📋 Better** release management
-- **🎯 Simpler** deployment process
-- **🔒 Consistent** versioning
-- **👥 Better UX** for users (Docker + Desktop in same release)
-
-Your release process is now **fully automated and professional**! 🚀

+ 0 - 137
WORKFLOW_BUILD_FIX.md

@@ -1,137 +0,0 @@
-# 🔧 Desktop Build Workflow Fix
-
-## ❌ **Problem:** electron-builder Publishing Failed
-
-All three OS builds were failing because electron-builder couldn't find or access the GitHub releases:
-```
-⨯ 404 Not Found
-"method: GET url: https://api.github.com/repos/lhamacorp/knotes/releases"
-"x-accepted-github-permissions": "contents=read"
-```
-
-## 🔍 **Root Cause:**
-
-1. **Repository Mismatch**: Package.json had `"owner": "lhamacorp", "repo": "knotes"` which may not match the actual repository
-2. **Permission Issues**: electron-builder's built-in publishing mechanism had token access problems
-3. **Complex Publishing**: electron-builder's GitHub publishing feature is complex and error-prone in CI environments
-
-## ✅ **Solution Applied:**
-
-### 1. **Removed electron-builder Publishing**
-**Before** (problematic):
-```json
-{
-  "publish": {
-    "provider": "github",
-    "owner": "lhamacorp",
-    "repo": "knotes"
-  }
-}
-```
-
-**After** (clean):
-```json
-// Removed publish configuration entirely
-```
-
-### 2. **Separated Build and Upload Steps**
-**Before** (combined):
-```yaml
-- name: Build and publish Linux
-  run: npm run publish-linux  # ❌ Fails with 404
-```
-
-**After** (separated):
-```yaml
-- name: Build Linux Desktop App
-  run: npm run build-linux    # ✅ Build only
-
-- name: Upload Linux Build to Release
-  run: gh release upload "$TAG" dist/kNotes-*.AppImage  # ✅ Upload separately
-```
-
-### 3. **Added --publish=never Flag**
-Updated all build scripts to prevent accidental publishing:
-```json
-{
-  "build-linux": "electron-builder --linux --publish=never",
-  "build-win": "electron-builder --win --publish=never",
-  "build-mac": "electron-builder --mac --publish=never"
-}
-```
-
-### 4. **Added Debug Output**
-Each platform now has debug steps to show what files were built:
-```yaml
-- name: Debug Build Output
-  run: |
-    echo "=== Build Output ==="
-    ls -la dist/ || echo "No dist directory"
-    echo "=== End Build Output ==="
-```
-
-### 5. **Smart Upload Logic**
-Only uploads files that actually exist:
-```yaml
-if ls dist/kNotes-*.AppImage 1> /dev/null 2>&1; then
-  echo "Found AppImage files:"
-  gh release upload "$TAG" dist/kNotes-*.AppImage --clobber
-else
-  echo "No AppImage files found"
-fi
-```
-
-## 🎯 **New Workflow Process:**
-
-```mermaid
-graph TD
-    A[Java Build ✅] --> B[Docker Deploy ✅]
-    B --> C[Create GitHub Release ✅]
-    C --> D[Build Linux Desktop]
-    C --> E[Build Windows Desktop]
-    C --> F[Build macOS Desktop]
-    D --> G[Upload Linux Files]
-    E --> H[Upload Windows Files]
-    F --> I[Upload macOS Files]
-    G --> J[Complete ✅]
-    H --> J
-    I --> J
-```
-
-## 🧪 **Expected Results:**
-
-### Desktop Builds Should Now:
-1. ✅ **Build successfully** without publishing errors
-2. ✅ **Generate files**: `.AppImage`, `.exe`, `.dmg`
-3. ✅ **Upload to release** using GitHub CLI
-4. ✅ **Show debug output** to help troubleshoot
-
-### Debug Output Will Show:
-```
-=== Build Output ===
--rw-r--r-- 1 runner docker 104410723 Jan 16 20:03 kNotes-1.1.0.AppImage
--rw-r--r-- 1 runner docker      364 Jan 16 20:03 latest-linux.yml
-=== End Build Output ===
-
-Uploading to release: v1.1.0-20260116-200325
-Found AppImage files:
--rw-r--r-- 1 runner docker 104410723 Jan 16 20:03 dist/kNotes-1.1.0.AppImage
-```
-
-## 🚀 **Benefits:**
-
-- ✅ **More Reliable**: No dependency on electron-builder's publishing
-- ✅ **Better Debugging**: Clear output showing what's built
-- ✅ **Flexible**: Easy to modify upload logic
-- ✅ **Repository Agnostic**: Works regardless of repo name/owner
-- ✅ **Simpler**: Separates concerns (build vs upload)
-
-## 📊 **Test Results:**
-
-Next workflow run should show:
-- ✅ Linux build completes and uploads `.AppImage`
-- ✅ Windows build completes and uploads `.exe`
-- ✅ macOS build completes and uploads `.dmg`
-- ✅ All files appear in the GitHub release
-
-**The electron-builder publishing issue is resolved!** 🎉

+ 0 - 107
WORKFLOW_PERMISSIONS_FIX.md

@@ -1,107 +0,0 @@
-# 🔧 GitHub Workflow Permissions Fix
-
-## ❌ **Problem:** "Resource not accessible by integration"
-
-The GitHub Actions workflow was failing when trying to create releases with the error:
-```
-Error: Resource not accessible by integration
-```
-
-## 🔍 **Root Cause:**
-
-1. **Insufficient Permissions**: The `GITHUB_TOKEN` didn't have write permissions for repository contents
-2. **Deprecated Action**: Using `actions/create-release@v1` which has known permission issues
-3. **Missing Explicit Permissions**: GitHub Actions needs explicit permissions to create releases
-
-## ✅ **Solution Applied:**
-
-### 1. **Added Explicit Permissions**
-```yaml
-permissions:
-  contents: write      # Required for creating releases and tags
-  issues: write        # Required for release management
-  pull-requests: write # Required for comprehensive workflow access
-```
-
-### 2. **Replaced Deprecated Action**
-**Before** (problematic):
-```yaml
-- uses: actions/create-release@v1  # ❌ Deprecated, permission issues
-```
-
-**After** (reliable):
-```yaml
-- name: Create Desktop App Release
-  env:
-    GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-  run: |
-    gh release create "$TAG" \
-      --title "kNotes Desktop v${VERSION}" \
-      --notes-file release-notes.md \
-      --latest
-```
-
-### 3. **Added Error Handling**
-```yaml
-gh release create "$TAG" \
-  --title "kNotes Desktop v${VERSION}" \
-  --notes-file release-notes.md \
-  --latest || {
-  echo "Release already exists, updating it..."
-  gh release edit "$TAG" \
-    --title "kNotes Desktop v${VERSION}" \
-    --notes-file release-notes.md \
-    --latest
-}
-```
-
-### 4. **Enhanced Environment Variables**
-```yaml
-env:
-  GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}        # For GitHub CLI
-  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}    # For electron-builder
-```
-
-## 🎯 **Benefits of the Fix:**
-
-- ✅ **More Reliable**: GitHub CLI is the official, maintained tool
-- ✅ **Better Permissions**: Explicit permissions prevent access issues
-- ✅ **Error Handling**: Handles edge cases like duplicate releases
-- ✅ **Future-Proof**: No deprecated actions
-- ✅ **Consistent**: Same approach across all platform builds
-
-## 📊 **Expected Results:**
-
-### Before Fix:
-```
-❌ create-desktop-release job failed
-❌ No GitHub release created
-❌ Desktop builds couldn't upload artifacts
-❌ Workflow stops with permission error
-```
-
-### After Fix:
-```
-✅ create-desktop-release job succeeds
-✅ GitHub release created with proper notes
-✅ Desktop builds upload artifacts successfully
-✅ Complete workflow runs end-to-end
-```
-
-## 🧪 **Testing:**
-
-The fix maintains compatibility with existing test workflows:
-- ✅ `Test Workflow (Dry Run)` updated
-- ✅ Manual trigger (`workflow_dispatch`) still works
-- ✅ Automatic trigger on push to main works
-
-## 🚀 **Ready to Deploy:**
-
-Your workflow should now:
-1. ✅ Build and test Java application
-2. ✅ Deploy Docker image to production
-3. ✅ Create GitHub release successfully
-4. ✅ Build desktop apps for all platforms
-5. ✅ Upload desktop binaries to the release
-
-**The permissions issue is completely resolved!** 🎉

+ 5 - 3
src/test/java/com/lhamacorp/knotes/domain/NoteTest.java

@@ -1,7 +1,9 @@
 package com.lhamacorp.knotes.domain;
 
 import org.junit.jupiter.api.Test;
+
 import java.time.Instant;
+
 import static org.junit.jupiter.api.Assertions.*;
 
 class NoteTest {
@@ -14,7 +16,7 @@ class NoteTest {
         Instant now = Instant.now();
 
         // When
-        Note note = new Note(id, content, now, now);
+        Note note = new Note(id, content, null, now, now);
 
         // Then
         assertEquals(id, note.id());
@@ -34,7 +36,7 @@ class NoteTest {
         Instant now = Instant.now();
 
         // When
-        Note note = new Note(id, (String) null, now, now);
+        Note note = new Note(id, (String) null, null, now, now);
 
         // Then
         assertEquals(id, note.id());
@@ -50,7 +52,7 @@ class NoteTest {
         Instant now = Instant.now();
 
         // When
-        Note note = new Note(id, originalContent, now, now);
+        Note note = new Note(id, originalContent, null, now, now);
         String retrievedContent = note.content();
 
         // Then

+ 72 - 6
src/test/java/com/lhamacorp/knotes/service/NoteServiceTest.java

@@ -1,9 +1,12 @@
 package com.lhamacorp.knotes.service;
 
 import com.lhamacorp.knotes.api.dto.NoteMetadata;
+import com.lhamacorp.knotes.context.UserContext;
+import com.lhamacorp.knotes.context.UserContextHolder;
 import com.lhamacorp.knotes.domain.Note;
 import com.lhamacorp.knotes.exception.NotFoundException;
 import com.lhamacorp.knotes.repository.NoteRepository;
+import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -13,8 +16,11 @@ import org.mockito.Mock;
 import org.mockito.junit.jupiter.MockitoExtension;
 
 import java.time.Instant;
+import java.util.List;
 import java.util.Optional;
 
+import static java.time.Instant.now;
+import static java.util.Collections.emptyList;
 import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
@@ -34,14 +40,27 @@ class NoteServiceTest {
     private String testContent;
     private Instant testCreatedAt;
     private Instant testModifiedAt;
+    private UserContext testUserContext;
+    private String testUserId;
 
     @BeforeEach
     void setUp() {
         testId = "01ABCDEF1234567890ABCDEF12";
+        testUserId = "user123";
         testContent = "This is a test note content";
         testCreatedAt = Instant.parse("2024-01-01T10:00:00Z");
         testModifiedAt = Instant.parse("2024-01-01T11:00:00Z");
-        testNote = new Note(testId, testContent, testCreatedAt, testModifiedAt);
+        testNote = new Note(testId, testContent, testUserId, testCreatedAt, testModifiedAt);
+
+        // Set up UserContext for all tests
+        testUserContext = new UserContext(testUserId, "testuser", List.of("USER"));
+        UserContextHolder.set(testUserContext);
+    }
+
+    @AfterEach
+    void tearDown() {
+        // Clean up UserContextHolder to avoid test pollution
+        UserContextHolder.clear();
     }
 
     @Test
@@ -135,7 +154,7 @@ class NoteServiceTest {
         String content = "New note content";
         ArgumentCaptor<Note> noteCaptor = ArgumentCaptor.forClass(Note.class);
 
-        Note savedNote = new Note("generated-ulid", content, Instant.now(), Instant.now());
+        Note savedNote = new Note("generated-ulid", content, testUserId, now(), now());
         when(repository.save(any(Note.class))).thenReturn(savedNote);
 
         // When
@@ -148,6 +167,7 @@ class NoteServiceTest {
         Note capturedNote = noteCaptor.getValue();
         assertNotNull(capturedNote.id());
         assertEquals(content, capturedNote.content());
+        assertEquals(testUserId, capturedNote.createdBy());
         assertNotNull(capturedNote.createdAt());
         assertNotNull(capturedNote.modifiedAt());
         assertEquals(capturedNote.createdAt(), capturedNote.modifiedAt());
@@ -158,7 +178,7 @@ class NoteServiceTest {
         // Given
         ArgumentCaptor<Note> noteCaptor = ArgumentCaptor.forClass(Note.class);
 
-        Note savedNote = new Note("generated-ulid", (String) null, Instant.now(), Instant.now());
+        Note savedNote = new Note("generated-ulid", (String) null, testUserId, now(), now());
         when(repository.save(any(Note.class))).thenReturn(savedNote);
 
         // When
@@ -170,6 +190,7 @@ class NoteServiceTest {
 
         Note capturedNote = noteCaptor.getValue();
         assertNull(capturedNote.content());
+        assertEquals(testUserId, capturedNote.createdBy());
     }
 
     @Test
@@ -178,7 +199,7 @@ class NoteServiceTest {
         String emptyContent = "";
         ArgumentCaptor<Note> noteCaptor = ArgumentCaptor.forClass(Note.class);
 
-        Note savedNote = new Note("generated-ulid", emptyContent, Instant.now(), Instant.now());
+        Note savedNote = new Note("generated-ulid", emptyContent, testUserId, now(), now());
         when(repository.save(any(Note.class))).thenReturn(savedNote);
 
         // When
@@ -190,6 +211,7 @@ class NoteServiceTest {
 
         Note capturedNote = noteCaptor.getValue();
         assertEquals(emptyContent, capturedNote.content());
+        assertEquals(testUserId, capturedNote.createdBy());
     }
 
     @Test
@@ -199,7 +221,7 @@ class NoteServiceTest {
         when(repository.findById(testId)).thenReturn(Optional.of(testNote));
 
         ArgumentCaptor<Note> noteCaptor = ArgumentCaptor.forClass(Note.class);
-        Note updatedNote = new Note(testId, updatedContent, testCreatedAt, Instant.now());
+        Note updatedNote = new Note(testId, updatedContent, testUserId, testCreatedAt, now());
         when(repository.save(any(Note.class))).thenReturn(updatedNote);
 
         // When
@@ -238,7 +260,7 @@ class NoteServiceTest {
         when(repository.findById(testId)).thenReturn(Optional.of(testNote));
 
         ArgumentCaptor<Note> noteCaptor = ArgumentCaptor.forClass(Note.class);
-        Note updatedNote = new Note(testId, (String) null, testCreatedAt, Instant.now());
+        Note updatedNote = new Note(testId, (String) null, testUserId, testCreatedAt, now());
         when(repository.save(any(Note.class))).thenReturn(updatedNote);
 
         // When
@@ -251,4 +273,48 @@ class NoteServiceTest {
         Note capturedNote = noteCaptor.getValue();
         assertNull(capturedNote.content());
     }
+
+    @Test
+    void findAll_withAuthenticatedUser_shouldReturnNoteIds() {
+        // Given
+        List<Note> notes = List.of(
+            new Note("note1", "content1", testUserId, testCreatedAt, testModifiedAt),
+            new Note("note2", "content2", testUserId, testCreatedAt, testModifiedAt)
+        );
+        when(repository.findAllByCreatedBy(testUserId)).thenReturn(notes);
+
+        // When
+        List<String> result = noteService.findAll();
+
+        // Then
+        assertEquals(List.of("note1", "note2"), result);
+        verify(repository).findAllByCreatedBy(testUserId);
+    }
+
+    @Test
+    void findAll_withAnonymousUser_shouldReturnEmptyList() {
+        // Given
+        UserContext anonymousUser = new UserContext("1", "anonymous", List.of());
+        UserContextHolder.set(anonymousUser);
+
+        // When
+        List<String> result = noteService.findAll();
+
+        // Then
+        assertEquals(emptyList(), result);
+        verify(repository, never()).findAllByCreatedBy(anyString());
+    }
+
+    @Test
+    void findAll_withAuthenticatedUserNoNotes_shouldReturnEmptyList() {
+        // Given
+        when(repository.findAllByCreatedBy(testUserId)).thenReturn(emptyList());
+
+        // When
+        List<String> result = noteService.findAll();
+
+        // Then
+        assertEquals(emptyList(), result);
+        verify(repository).findAllByCreatedBy(testUserId);
+    }
 }