mirror of
https://github.com/callumalpass/tasknotes.git
synced 2026-07-22 12:50:26 +00:00
test(e2e): add failing tests for issue #1350 - Reading View inline task refresh
Add tests documenting the bug where inline TaskNote widgets in Reading View don't refresh after property updates. The markdown file updates correctly, but the widget display remains stale until the file is closed and reopened. Tests cover: - Property updates (scheduled date) not refreshing inline widget display - Status toggle changes not reflected visually - Multiple instances of same task not refreshing together - Contrast with Live Preview which does refresh correctly Root cause: ReadingModeTaskLinkProcessor is a one-time post-processor with no EVENT_TASK_UPDATED listeners, unlike TaskLinkOverlay.ts (Live Preview).
This commit is contained in:
parent
709c5e16aa
commit
884b163bea
3 changed files with 450 additions and 0 deletions
16
.clump/issues/1350.json
Normal file
16
.clump/issues/1350.json
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"issue_number": 1350,
|
||||
"status": "open",
|
||||
"tags": ["inline-tasks", "reading-view", "rendering", "ux"],
|
||||
"priority": "medium",
|
||||
"difficulty": "medium",
|
||||
"risk": "low",
|
||||
"type": "bug",
|
||||
"affected_areas": ["src/editor/ReadingModeTaskLinkProcessor.ts", "src/editor/TaskLinkWidget.ts", "src/ui/TaskCard.ts"],
|
||||
"ai_summary": "Inline task widgets don't refresh after property updates in Reading View",
|
||||
"notes": "When editing inline TaskNote properties (scheduled/due dates, status) in Reading View, the underlying markdown file is updated correctly but the widget display remains stale. User must close and re-open the file to see changes. This only affects Reading View - Live Preview works correctly because TaskLinkOverlay.ts has EVENT_TASK_UPDATED listeners that trigger refreshDecorations(). The ReadingModeTaskLinkProcessor is a one-time Markdown post-processor with no event listeners, so it never re-renders widgets after initial page load. The TaskCardNoteDecorations.ts already shows how to implement refresh for Reading View widgets (at top of task notes) using debounced EVENT_TASK_UPDATED listeners.",
|
||||
"root_cause": "ReadingModeTaskLinkProcessor.ts is a one-time Markdown post-processor that replaces wikilinks with TaskLinkWidget elements during initial render. Unlike TaskLinkOverlay.ts (Live Preview) which has listeners for EVENT_TASK_UPDATED that call refreshDecorations(), the Reading View processor has no event listeners and never re-renders. When updateTaskProperty() fires EVENT_TASK_UPDATED, Reading View widgets don't receive the update.",
|
||||
"suggested_fix": "Add event handling to ReadingModeTaskLinkProcessor similar to TaskCardNoteDecorations.ts pattern: 1) Create a separate handler class that listens to EVENT_TASK_UPDATED and metadataCache.on('changed') events, 2) On update, find all inline widgets with matching task path using data attributes, 3) Replace stale widgets with fresh ones containing updated data, 4) Use debouncing (500ms like TaskCardNoteDecorations) to avoid excessive DOM manipulation. The handler should be registered per-leaf and cleaned up when leaves close.",
|
||||
"analyzed_at": "2026-01-01T10:00:00.000Z",
|
||||
"analyzed_by": "claude-opus-4-5-20251101"
|
||||
}
|
||||
|
|
@ -4108,3 +4108,423 @@ test.describe('Same Date Start/Due Task Consolidation (Issue #1351)', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// ISSUE #1350: INLINE TASK PROPERTY UPDATE FAILS IN READING VIEW
|
||||
// Bug: When editing the metadata of an inline TaskNote (e.g., Scheduled date)
|
||||
// while in Reading View, the markdown file is updated but the Reading View
|
||||
// display does NOT refresh. User must close and re-open to see changes.
|
||||
// ============================================================================
|
||||
|
||||
test.describe('Inline Task Reading View Refresh (Issue #1350)', () => {
|
||||
test.fixme('should refresh inline task display when property is updated in Reading View', async () => {
|
||||
// Issue #1350: https://github.com/anthropics/tasknotes/issues/1350
|
||||
//
|
||||
// Bug Summary:
|
||||
// When editing an inline TaskNote's property (like scheduled date) in Reading View:
|
||||
// 1. The markdown file IS updated correctly
|
||||
// 2. But the inline task widget display does NOT refresh
|
||||
// 3. User must close and re-open the file to see changes
|
||||
//
|
||||
// Root Cause: ReadingModeTaskLinkProcessor is a one-time post-processor
|
||||
// that runs when markdown is rendered. Unlike Live Preview (TaskLinkOverlay.ts),
|
||||
// it has NO event listeners for EVENT_TASK_UPDATED, so it never re-renders.
|
||||
//
|
||||
// Fix: Add event listeners to ReadingModeTaskLinkProcessor that:
|
||||
// 1. Listen for EVENT_TASK_UPDATED
|
||||
// 2. Find affected inline widgets in the DOM
|
||||
// 3. Replace them with fresh widgets containing updated data
|
||||
const page = getPage();
|
||||
|
||||
// Open the inline task test page
|
||||
const testPage = page.locator('.nav-file-title:has-text("Inline-Task-Test")');
|
||||
if (await testPage.isVisible({ timeout: 5000 }).catch(() => false)) {
|
||||
await testPage.click();
|
||||
await page.waitForTimeout(1000);
|
||||
} else {
|
||||
// Try to create/find the test file another way
|
||||
await runCommand(page, 'Quick switcher');
|
||||
await page.waitForTimeout(300);
|
||||
await page.keyboard.type('Inline-Task-Test', { delay: 30 });
|
||||
await page.waitForTimeout(300);
|
||||
await page.keyboard.press('Enter');
|
||||
await page.waitForTimeout(1000);
|
||||
}
|
||||
|
||||
// Switch to Reading View using Ctrl+E toggle
|
||||
// First check if we're in editing mode (has CM editor)
|
||||
const isEditing = await page.locator('.cm-content, .markdown-source-view.is-live-preview').isVisible({ timeout: 1000 }).catch(() => false);
|
||||
if (isEditing) {
|
||||
await page.keyboard.press('Control+e');
|
||||
await page.waitForTimeout(500);
|
||||
}
|
||||
|
||||
// Ensure we're in Reading View (preview mode) - check for markdown-reading-view class
|
||||
const readingView = page.locator('.markdown-reading-view, .markdown-preview-view');
|
||||
await expect(readingView).toBeVisible({ timeout: 5000 });
|
||||
|
||||
await page.screenshot({ path: 'test-results/screenshots/issue-1350-reading-view-before.png' });
|
||||
|
||||
// Find an inline task widget in Reading View
|
||||
// Inline widgets have class "tasknotes-inline-widget" or "task-inline-preview--reading-mode"
|
||||
const inlineWidget = page.locator('.tasknotes-inline-widget, .task-inline-preview--reading-mode').first();
|
||||
|
||||
if (!await inlineWidget.isVisible({ timeout: 5000 }).catch(() => false)) {
|
||||
console.log('[Issue #1350] Inline task widget not found - skipping test');
|
||||
// This could happen if the test file isn't properly set up
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the current scheduled date value displayed
|
||||
const scheduledBadge = inlineWidget.locator('[data-property="scheduled"], .tn-date-badge, [class*="scheduled"]').first();
|
||||
const originalValue = await scheduledBadge.textContent().catch(() => null);
|
||||
console.log('[Issue #1350] Original scheduled value:', originalValue);
|
||||
|
||||
// Click on the scheduled date to open the date picker
|
||||
if (await scheduledBadge.isVisible({ timeout: 2000 }).catch(() => false)) {
|
||||
await scheduledBadge.click();
|
||||
await page.waitForTimeout(500);
|
||||
}
|
||||
|
||||
await page.screenshot({ path: 'test-results/screenshots/issue-1350-date-picker-open.png' });
|
||||
|
||||
// Look for the date context menu
|
||||
const dateMenu = page.locator('.menu, .suggestion-container, .tn-context-menu');
|
||||
if (await dateMenu.isVisible({ timeout: 2000 }).catch(() => false)) {
|
||||
// Click on "+1 day" option
|
||||
const plusOneDay = dateMenu.locator('text="+1 day"').first();
|
||||
if (await plusOneDay.isVisible({ timeout: 2000 }).catch(() => false)) {
|
||||
await plusOneDay.click();
|
||||
await page.waitForTimeout(1000);
|
||||
} else {
|
||||
// Try finding any date option
|
||||
const tomorrow = dateMenu.locator('text="Tomorrow"').first();
|
||||
if (await tomorrow.isVisible({ timeout: 1000 }).catch(() => false)) {
|
||||
await tomorrow.click();
|
||||
await page.waitForTimeout(1000);
|
||||
} else {
|
||||
await page.keyboard.press('Escape');
|
||||
console.log('[Issue #1350] Date option not found in menu');
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log('[Issue #1350] Date menu not visible after clicking scheduled badge');
|
||||
return;
|
||||
}
|
||||
|
||||
await page.screenshot({ path: 'test-results/screenshots/issue-1350-after-date-change.png' });
|
||||
|
||||
// Verify the underlying file was updated (the file write succeeds)
|
||||
const fileWasUpdated = await page.evaluate(async () => {
|
||||
// @ts-ignore - Obsidian global
|
||||
const app = (window as any).app;
|
||||
const plugin = app?.plugins?.plugins?.['tasknotes'];
|
||||
if (!plugin) return null;
|
||||
|
||||
const allTasks = plugin.taskService?.getAllTasks?.() || [];
|
||||
// Find Buy groceries task (first inline task in test page)
|
||||
const task = allTasks.find((t: any) => t.title === 'Buy groceries');
|
||||
return task?.scheduled;
|
||||
});
|
||||
|
||||
console.log('[Issue #1350] Task scheduled value in file after update:', fileWasUpdated);
|
||||
|
||||
// Now check if the DISPLAY was updated (this is the bug!)
|
||||
const updatedValue = await scheduledBadge.textContent().catch(() => null);
|
||||
console.log('[Issue #1350] Display value after update:', updatedValue);
|
||||
|
||||
// BUG: The display value should have changed, but it doesn't!
|
||||
// The widget shows stale data until the file is closed and reopened.
|
||||
expect(updatedValue).not.toBe(originalValue);
|
||||
});
|
||||
|
||||
test.fixme('should refresh inline task status when checkbox is toggled in Reading View', async () => {
|
||||
// Issue #1350 related: Status changes should also refresh inline widgets
|
||||
//
|
||||
// When marking a task complete via its inline checkbox in Reading View,
|
||||
// the visual status indicator should update immediately.
|
||||
const page = getPage();
|
||||
|
||||
// Open a page with inline tasks
|
||||
const testPage = page.locator('.nav-file-title:has-text("Inline-Task-Test")');
|
||||
if (await testPage.isVisible({ timeout: 5000 }).catch(() => false)) {
|
||||
await testPage.click();
|
||||
await page.waitForTimeout(1000);
|
||||
}
|
||||
|
||||
// Switch to Reading View
|
||||
const isEditing = await page.locator('.cm-content, .markdown-source-view.is-live-preview').isVisible({ timeout: 1000 }).catch(() => false);
|
||||
if (isEditing) {
|
||||
await page.keyboard.press('Control+e');
|
||||
await page.waitForTimeout(500);
|
||||
}
|
||||
|
||||
const readingView = page.locator('.markdown-reading-view, .markdown-preview-view');
|
||||
await expect(readingView).toBeVisible({ timeout: 5000 });
|
||||
|
||||
// Find an inline task widget
|
||||
const inlineWidget = page.locator('.tasknotes-inline-widget, .task-inline-preview--reading-mode').first();
|
||||
|
||||
if (!await inlineWidget.isVisible({ timeout: 5000 }).catch(() => false)) {
|
||||
console.log('[Issue #1350] Inline widget not visible, skipping test');
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the status dot/checkbox element
|
||||
const statusElement = inlineWidget.locator('.tn-status-dot, .status-dot, [class*="status"], input[type="checkbox"]').first();
|
||||
const originalStatus = await statusElement.getAttribute('class').catch(() => null);
|
||||
console.log('[Issue #1350] Original status classes:', originalStatus);
|
||||
|
||||
await page.screenshot({ path: 'test-results/screenshots/issue-1350-status-before.png' });
|
||||
|
||||
// Click to toggle status
|
||||
if (await statusElement.isVisible({ timeout: 2000 }).catch(() => false)) {
|
||||
await statusElement.click();
|
||||
await page.waitForTimeout(500);
|
||||
}
|
||||
|
||||
await page.screenshot({ path: 'test-results/screenshots/issue-1350-status-after.png' });
|
||||
|
||||
// Check if file was updated
|
||||
const taskStatus = await page.evaluate(async () => {
|
||||
// @ts-ignore - Obsidian global
|
||||
const app = (window as any).app;
|
||||
const plugin = app?.plugins?.plugins?.['tasknotes'];
|
||||
if (!plugin) return null;
|
||||
|
||||
const allTasks = plugin.taskService?.getAllTasks?.() || [];
|
||||
const task = allTasks.find((t: any) => t.title === 'Buy groceries');
|
||||
return task?.status;
|
||||
});
|
||||
|
||||
console.log('[Issue #1350] Task status in file after toggle:', taskStatus);
|
||||
|
||||
// Get updated status visual
|
||||
const updatedStatus = await statusElement.getAttribute('class').catch(() => null);
|
||||
console.log('[Issue #1350] Status classes after toggle:', updatedStatus);
|
||||
|
||||
// BUG: The status indicator should have visually changed
|
||||
// But in Reading View, the widget doesn't refresh
|
||||
expect(updatedStatus).not.toBe(originalStatus);
|
||||
});
|
||||
|
||||
test.fixme('should refresh all inline task instances when one is updated', async () => {
|
||||
// Issue #1350 edge case: If the same task is referenced multiple times
|
||||
// on a page (e.g., [[Buy groceries]] appears twice), updating one
|
||||
// should refresh ALL instances.
|
||||
const page = getPage();
|
||||
|
||||
// Create a test page with duplicate task references
|
||||
await page.evaluate(async () => {
|
||||
// @ts-ignore - Obsidian global
|
||||
const app = (window as any).app;
|
||||
if (!app?.vault) return;
|
||||
|
||||
const content = `---
|
||||
title: Duplicate Task References
|
||||
---
|
||||
|
||||
# Test Page
|
||||
|
||||
First reference: [[Buy groceries]]
|
||||
|
||||
Some text in between.
|
||||
|
||||
Second reference: [[Buy groceries]]
|
||||
`;
|
||||
// Create or update the test file
|
||||
const testPath = 'Duplicate-Task-Test.md';
|
||||
const existingFile = app.vault.getAbstractFileByPath(testPath);
|
||||
if (existingFile) {
|
||||
await app.vault.modify(existingFile, content);
|
||||
} else {
|
||||
await app.vault.create(testPath, content);
|
||||
}
|
||||
});
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
// Open the test page
|
||||
await runCommand(page, 'Quick switcher');
|
||||
await page.waitForTimeout(300);
|
||||
await page.keyboard.type('Duplicate-Task-Test', { delay: 30 });
|
||||
await page.waitForTimeout(300);
|
||||
await page.keyboard.press('Enter');
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
// Switch to Reading View
|
||||
const isEditing = await page.locator('.cm-content, .markdown-source-view.is-live-preview').isVisible({ timeout: 1000 }).catch(() => false);
|
||||
if (isEditing) {
|
||||
await page.keyboard.press('Control+e');
|
||||
await page.waitForTimeout(500);
|
||||
}
|
||||
|
||||
await page.screenshot({ path: 'test-results/screenshots/issue-1350-duplicate-refs-before.png' });
|
||||
|
||||
// Find all inline widgets for the same task
|
||||
const allWidgets = page.locator('.tasknotes-inline-widget, .task-inline-preview--reading-mode');
|
||||
const widgetCount = await allWidgets.count();
|
||||
console.log(`[Issue #1350] Found ${widgetCount} inline widget instances`);
|
||||
|
||||
// Get scheduled values from all instances
|
||||
const originalValues: string[] = [];
|
||||
for (let i = 0; i < widgetCount; i++) {
|
||||
const widget = allWidgets.nth(i);
|
||||
const badge = widget.locator('[data-property="scheduled"], .tn-date-badge').first();
|
||||
const value = await badge.textContent().catch(() => '');
|
||||
originalValues.push(value || '');
|
||||
}
|
||||
console.log('[Issue #1350] Original values for all instances:', originalValues);
|
||||
|
||||
// Update the first instance
|
||||
const firstWidget = allWidgets.first();
|
||||
const firstBadge = firstWidget.locator('[data-property="scheduled"], .tn-date-badge').first();
|
||||
if (await firstBadge.isVisible({ timeout: 2000 }).catch(() => false)) {
|
||||
await firstBadge.click();
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
const menu = page.locator('.menu, .suggestion-container');
|
||||
if (await menu.isVisible({ timeout: 2000 }).catch(() => false)) {
|
||||
const plusDay = menu.locator('text="+1 day"').first();
|
||||
if (await plusDay.isVisible({ timeout: 1000 }).catch(() => false)) {
|
||||
await plusDay.click();
|
||||
await page.waitForTimeout(1000);
|
||||
} else {
|
||||
await page.keyboard.press('Escape');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await page.screenshot({ path: 'test-results/screenshots/issue-1350-duplicate-refs-after.png' });
|
||||
|
||||
// Check if ALL instances were updated
|
||||
const updatedValues: string[] = [];
|
||||
for (let i = 0; i < widgetCount; i++) {
|
||||
const widget = allWidgets.nth(i);
|
||||
const badge = widget.locator('[data-property="scheduled"], .tn-date-badge').first();
|
||||
const value = await badge.textContent().catch(() => '');
|
||||
updatedValues.push(value || '');
|
||||
}
|
||||
console.log('[Issue #1350] Updated values for all instances:', updatedValues);
|
||||
|
||||
// BUG: All instances should show the same updated value
|
||||
// But in Reading View, widgets don't refresh, and even if they did,
|
||||
// would need to refresh ALL instances, not just the one clicked.
|
||||
expect(updatedValues.every(v => v === updatedValues[0])).toBe(true);
|
||||
expect(updatedValues[0]).not.toBe(originalValues[0]);
|
||||
|
||||
// Clean up test file
|
||||
await page.evaluate(async () => {
|
||||
// @ts-ignore - Obsidian global
|
||||
const app = (window as any).app;
|
||||
if (!app?.vault) return;
|
||||
|
||||
const testPath = 'Duplicate-Task-Test.md';
|
||||
const file = app.vault.getAbstractFileByPath(testPath);
|
||||
if (file) {
|
||||
await app.vault.delete(file);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test.fixme('Live Preview refreshes but Reading View does not - demonstrates the gap', async () => {
|
||||
// Issue #1350: This test demonstrates that Live Preview DOES refresh
|
||||
// while Reading View does NOT, proving the architectural gap.
|
||||
//
|
||||
// Live Preview uses TaskLinkOverlay.ts which has event listeners.
|
||||
// Reading View uses ReadingModeTaskLinkProcessor.ts which is a one-time post-processor.
|
||||
const page = getPage();
|
||||
|
||||
// Open a page with inline task references
|
||||
const testPage = page.locator('.nav-file-title:has-text("Inline-Task-Test")');
|
||||
if (await testPage.isVisible({ timeout: 5000 }).catch(() => false)) {
|
||||
await testPage.click();
|
||||
await page.waitForTimeout(1000);
|
||||
}
|
||||
|
||||
// === Test in Live Preview mode (should work) ===
|
||||
// Ensure we're in Live Preview (editing mode)
|
||||
const isReadingView = await page.locator('.markdown-reading-view').isVisible({ timeout: 1000 }).catch(() => false);
|
||||
if (isReadingView) {
|
||||
await page.keyboard.press('Control+e'); // Toggle to editing
|
||||
await page.waitForTimeout(500);
|
||||
}
|
||||
|
||||
// Verify we're in Live Preview
|
||||
const livePreview = page.locator('.markdown-source-view.is-live-preview');
|
||||
const isLivePreview = await livePreview.isVisible({ timeout: 3000 }).catch(() => false);
|
||||
|
||||
if (isLivePreview) {
|
||||
const inlineWidgetLP = page.locator('.tasknotes-inline-widget').first();
|
||||
const scheduledBadgeLP = inlineWidgetLP.locator('[data-property="scheduled"], .tn-date-badge').first();
|
||||
const originalLP = await scheduledBadgeLP.textContent().catch(() => null);
|
||||
console.log('[Issue #1350] Live Preview - original value:', originalLP);
|
||||
|
||||
await page.screenshot({ path: 'test-results/screenshots/issue-1350-live-preview-before.png' });
|
||||
|
||||
// Update in Live Preview
|
||||
if (await scheduledBadgeLP.isVisible({ timeout: 2000 }).catch(() => false)) {
|
||||
await scheduledBadgeLP.click();
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
const menu = page.locator('.menu, .suggestion-container');
|
||||
if (await menu.isVisible({ timeout: 2000 }).catch(() => false)) {
|
||||
const plusDay = menu.locator('text="+1 day"').first();
|
||||
if (await plusDay.isVisible({ timeout: 1000 }).catch(() => false)) {
|
||||
await plusDay.click();
|
||||
await page.waitForTimeout(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const updatedLP = await scheduledBadgeLP.textContent().catch(() => null);
|
||||
console.log('[Issue #1350] Live Preview - updated value:', updatedLP);
|
||||
|
||||
await page.screenshot({ path: 'test-results/screenshots/issue-1350-live-preview-after.png' });
|
||||
|
||||
// Live Preview should have updated
|
||||
console.log('[Issue #1350] Live Preview refreshed:', originalLP !== updatedLP);
|
||||
}
|
||||
|
||||
// === Now switch to Reading View (bug case) ===
|
||||
await page.keyboard.press('Control+e'); // Toggle to Reading View
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
const readingView = page.locator('.markdown-reading-view, .markdown-preview-view');
|
||||
await expect(readingView).toBeVisible({ timeout: 5000 });
|
||||
|
||||
const inlineWidgetRV = page.locator('.tasknotes-inline-widget, .task-inline-preview--reading-mode').first();
|
||||
const scheduledBadgeRV = inlineWidgetRV.locator('[data-property="scheduled"], .tn-date-badge').first();
|
||||
const originalRV = await scheduledBadgeRV.textContent().catch(() => null);
|
||||
console.log('[Issue #1350] Reading View - value before update:', originalRV);
|
||||
|
||||
await page.screenshot({ path: 'test-results/screenshots/issue-1350-reading-view-compare-before.png' });
|
||||
|
||||
// Update in Reading View
|
||||
if (await scheduledBadgeRV.isVisible({ timeout: 2000 }).catch(() => false)) {
|
||||
await scheduledBadgeRV.click();
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
const menu = page.locator('.menu, .suggestion-container');
|
||||
if (await menu.isVisible({ timeout: 2000 }).catch(() => false)) {
|
||||
const plusDay = menu.locator('text="+1 day"').first();
|
||||
if (await plusDay.isVisible({ timeout: 1000 }).catch(() => false)) {
|
||||
await plusDay.click();
|
||||
await page.waitForTimeout(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const updatedRV = await scheduledBadgeRV.textContent().catch(() => null);
|
||||
console.log('[Issue #1350] Reading View - value after update:', updatedRV);
|
||||
|
||||
await page.screenshot({ path: 'test-results/screenshots/issue-1350-reading-view-compare-after.png' });
|
||||
|
||||
// BUG: Reading View should have updated but didn't
|
||||
console.log('[Issue #1350] Reading View refreshed:', originalRV !== updatedRV);
|
||||
|
||||
// This assertion will FAIL, demonstrating the bug
|
||||
expect(updatedRV).not.toBe(originalRV);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
14
tasknotes-e2e-vault/Inline-Task-Test.md
Normal file
14
tasknotes-e2e-vault/Inline-Task-Test.md
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
title: Inline Task Test Page
|
||||
---
|
||||
|
||||
# Inline Task Test
|
||||
|
||||
This page is used to test inline TaskNote rendering in Reading View.
|
||||
|
||||
Here are some inline task references:
|
||||
- Review this: [[Buy groceries]]
|
||||
- Weekly sync: [[Weekly team meeting]]
|
||||
- Blocked task: [[Deploy authentication update]]
|
||||
|
||||
Test editing properties in Reading View.
|
||||
Loading…
Reference in a new issue