Skip to content
Open
55 changes: 55 additions & 0 deletions __mocks__/factories/noteFactory.js
Copy link
Collaborator

Choose a reason for hiding this comment

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

@mlevison This is a great start. Thanks! A starting observation:

  • For generalized use, the term "note" is misleading here, because these objects you created are not notes, they are objects with paragraphs arrays. In your tests, you are just accessing that one attribute, which makes sense. However the term "note" is an important distinction because if I wanted to construct a test, I would expect a note to have a title, type, filename, frontmatterAttributes, etc. This is why I was suggesting you use JEST helpers to give you a quick/easy way to create basic note attributes in JSON form.
  • Also, defining them all in a single file may get unwieldy if we add lots and lots of them over time. you may want to search the code for the string "const factory = async" to see how factory files are loaded dynamically in Templating by Mike. this way, each test file is actually its own file and does not have to be concatenated in a never-ending single file. That said, I don't like that the Templating factory loader code is import code is repeated. should definitely be a shared function.
    There are a always a lot of ways to deal with these two things. Look forward to hearing your thoughts.

Copy link
Collaborator

Choose a reason for hiding this comment

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

And on a different 'note' (ha ha), I would even at this early stage suggest adding a richer set of content. I.e. note links, dates, emojis, URLs, Markdown links, non-Roman characters. Each of these has caused issues in the past.

Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
export const noteWIthOpenAndCancelledTasks = {
paragraphs: [
{ type: 'title', lineIndex: 0, content: 'Title', headingLevel: 1 },
{ type: 'empty', lineIndex: 1 },
{ type: 'title', lineIndex: 2, content: 'Tasks for 3.4.22', headingLevel: 2 },
{ type: 'open', lineIndex: 3, content: 'task 1' },
{ type: 'title', lineIndex: 4, content: 'Journal for 3.4.22' },
{ type: 'list', lineIndex: 5, content: 'first journal entry' },
{ type: 'list', lineIndex: 6, content: 'second journal entry' },
{ type: 'empty', lineIndex: 7 },
{ type: 'title', lineIndex: 8, content: 'Done ...', headingLevel: 2 },
{ type: 'title', lineIndex: 9, content: 'Cancelled', headingLevel: 2 },
{ type: 'cancelled', lineIndex: 10, content: 'task cancelled' },
],
}

export const noteWIthDoneAndScheduledTasks = {
paragraphs: [
{ type: 'title', lineIndex: 0, content: 'Title', headingLevel: 1 },
{ type: 'empty', lineIndex: 1 },
{ type: 'title', lineIndex: 2, content: 'Tasks for 3.4.22', headingLevel: 2 },
{ type: 'scheduled', lineIndex: 3, content: 'task 1' },
{ type: 'title', lineIndex: 4, content: 'Journal for 3.4.22' },
{ type: 'list', lineIndex: 5, content: 'first journal entry' },
{ type: 'list', lineIndex: 6, content: 'second journal entry' },
{ type: 'empty', lineIndex: 7 },
{ type: 'title', lineIndex: 8, content: 'Done ...', headingLevel: 2 },
{ type: 'done', lineIndex: 10, content: 'task finished' },
],
}

export const noteWithOpenAndDoneTasks = {
paragraphs: [
{ type: 'title', lineIndex: 0, content: 'Title', headingLevel: 1 },
{ type: 'empty', lineIndex: 1 },
{ type: 'open', lineIndex: 2, content: 'Open task 1' },
{ type: 'open', lineIndex: 3, content: 'Open task 2' },
{ type: 'done', lineIndex: 4, content: 'Done task' },
],
}

export const noteWithOneTaskOfEachType = {
paragraphs: [
{ type: 'title', lineIndex: 0, content: 'Title', headingLevel: 1 },
{ type: 'empty', lineIndex: 1 },
{ type: 'open', lineIndex: 2, content: 'Open task 1' },
{ type: 'scheduled', lineIndex: 3, content: 'Scheduled task 2' },
{ type: 'done', lineIndex: 4, content: 'Done task' },
{ type: 'cancelled', lineIndex: 5, content: 'Cancelled task' },
{ type: 'checklist', lineIndex: 6, content: 'checklist' },
{ type: 'checklistDone', lineIndex: 7, content: 'checklistDone' },
{ type: 'checklistCancelled', lineIndex: 8, content: 'checklistCancelled' },
{ type: 'checklistScheduled', lineIndex: 9, content: 'checklistScheduled' },
],
}
78 changes: 78 additions & 0 deletions helpers/__tests__/tasks.test..js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/* global jest, describe, test, expect, beforeAll, afterAll, beforeEach, afterEach */
import { noteWIthOpenAndCancelledTasks, noteWIthDoneAndScheduledTasks, noteWithOpenAndDoneTasks, noteWithOneTaskOfEachType } from '@mocks/factories/noteFactory'

import { getAllTasksFromCurrentNote } from '../tasks.js'
import * as sorting from '@helpers/sorting'
import { CustomConsole } from '@jest/console' // see note below
import { Calendar, Clipboard, CommandBar, DataStore, Editor, NotePlan, simpleFormatter, Paragraph /* Note, mockWasCalledWithString, Paragraph */ } from '@mocks/index'

beforeAll(() => {
global.Calendar = Calendar
global.Clipboard = Clipboard
global.CommandBar = CommandBar
global.DataStore = DataStore
global.Editor = Editor
global.NotePlan = NotePlan
global.console = new CustomConsole(process.stdout, process.stderr, simpleFormatter) // minimize log footprint
DataStore.settings['_logLevel'] = 'none' //change this to DEBUG to get more logging (or 'none' for none)
})

describe('mlevison.GenAITaskChecker', () => {
describe('test getTasksByType', () => {
test('prove Open and Cancelled Tasks found in sample note', () => {
const foundTasks = sorting.getTasksByType(noteWIthOpenAndCancelledTasks.paragraphs)

expect(foundTasks.open.length).toBe(1)
expect(foundTasks.done.length).toBe(0)
expect(foundTasks.cancelled.length).toBe(1)
expect(foundTasks.scheduled.length).toBe(0)
expect(foundTasks.checklist.length).toBe(0)
expect(foundTasks.checklistDone.length).toBe(0)
expect(foundTasks.checklistCancelled.length).toBe(0)
expect(foundTasks.checklistScheduled.length).toBe(0)
})

test('prove Done Tasks found in sample note', () => {
const foundTasks = sorting.getTasksByType(noteWIthDoneAndScheduledTasks.paragraphs)

expect(foundTasks.open.length).toBe(0)
expect(foundTasks.done.length).toBe(1)
expect(foundTasks.cancelled.length).toBe(0)
expect(foundTasks.scheduled.length).toBe(1)
expect(foundTasks.checklist.length).toBe(0)
expect(foundTasks.checklistDone.length).toBe(0)
expect(foundTasks.checklistCancelled.length).toBe(0)
expect(foundTasks.checklistScheduled.length).toBe(0)
})
})

describe('getAllTasksFromCurrentNote', () => {
test('returns open and done tasks from current note', () => {
const tasks = getAllTasksFromCurrentNote(noteWithOpenAndDoneTasks)
expect(tasks.length).toBe(3)
expect(tasks[0].content).toBe('Open task 1')
expect(tasks[1].content).toBe('Open task 2')
expect(tasks[2].content).toBe('Done task')
})

test('returns open and cancelled tasks from current note', () => {
const tasks = getAllTasksFromCurrentNote(noteWIthOpenAndCancelledTasks)
expect(tasks.length).toBe(2)
expect(tasks[0].content).toBe('task 1')
expect(tasks[1].content).toBe('task cancelled')
})

test('returns one of each task types from current note', () => {
const tasks = getAllTasksFromCurrentNote(noteWithOneTaskOfEachType)
expect(tasks.length).toBe(8)
expect(tasks[0].content).toBe('Open task 1')
expect(tasks[1].content).toBe('Scheduled task 2')
expect(tasks[2].content).toBe('Done task')
expect(tasks[3].content).toBe('Cancelled task')
expect(tasks[4].content).toBe('checklist')
expect(tasks[5].content).toBe('checklistScheduled')
expect(tasks[6].content).toBe('checklistDone')
expect(tasks[7].content).toBe('checklistCancelled')
})
})
})
10 changes: 10 additions & 0 deletions helpers/tasks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { getTasksByType } from './sorting'

export function getAllTasksFromCurrentNote(currentNote) {
// This function will extract all tasks from the current note and return them grouped by type
// It uses the getTasksByType function to categorize the tasks
const groupedTasks = getTasksByType(currentNote.paragraphs)

return groupedTasks.open.concat(groupedTasks.scheduled, groupedTasks.done, groupedTasks.cancelled, groupedTasks.checklist, groupedTasks.checklistScheduled,
groupedTasks.checklistDone, groupedTasks.checklistCancelled)
}
Loading