Skip to content

Merge branch 'beta' into chore/refactor-smartblocks-search #2182

Merge branch 'beta' into chore/refactor-smartblocks-search

Merge branch 'beta' into chore/refactor-smartblocks-search #2182

GitHub Actions / Tests succeeded Oct 15, 2024 in 1s

425 passed, 0 failed and 0 skipped

Tests passed successfully

✅ reports/tests-junit.xml

425 tests were completed in 27s with 425 passed, 0 failed and 0 skipped.

Test suite Passed Failed Skipped Time
src/api/helpers.test.ts 20✅ 39ms
src/api/index.test.tsx 26✅ 203ms
src/api/logging.test.tsx 7✅ 50ms
src/clients/citoid/base.test.ts 4✅ 137ms
src/clients/citoid/hooks.test.ts 3✅ 1s
src/clients/index.test.ts 1✅ 118ms
src/clients/semantic/base.test.ts 1✅ 85ms
src/clients/semantic/hooks.test.ts 1✅ 96ms
src/clients/zotero/base.test.ts 22✅ 567ms
src/clients/zotero/helpers.test.ts 19✅ 28ms
src/clients/zotero/hooks.test.ts 5✅ 306ms
src/clients/zotero/mutations.test.tsx 3✅ 272ms
src/components/Dashboard/Explorer/QueryBuilder/queries.test.ts 56✅ 23ms
src/components/Dashboard/Explorer/QueryBuilder/utils.test.ts 1✅ 5ms
src/components/Dashboard/Explorer/QueryPDFs/helpers.test.ts 2✅ 8ms
src/components/Dashboard/TagManager/utils.test.ts 11✅ 13ms
src/components/GraphWatcher/helpers.test.ts 6✅ 10ms
src/components/GraphWatcher/Menus/helpers.test.ts 12✅ 10ms
src/components/GraphWatcher/Menus/utils.test.tsx 9✅ 96ms
src/components/GraphWatcher/WebImport/helpers.test.tsx 3✅ 35ms
src/components/NotesDrawer/helpers.test.ts 1✅ 4ms
src/components/SearchPanel/helpers.test.ts 9✅ 12ms
src/components/UserSettings/common.test.ts 3✅ 7ms
src/components/ZoteroImport/helpers.test.ts 2✅ 7ms
src/hooks/index.test.ts 17✅ 66ms
src/services/events/index.test.ts 14✅ 76ms
src/services/idb/index.test.ts 4✅ 70ms
src/services/react-query/index.test.ts 6✅ 17ms
src/services/search/index.test.ts 30✅ 23ms
src/services/smartblocks/helpers.test.ts 5✅ 10ms
src/services/smartblocks/index.test.ts 19✅ 615ms
tests/utils/annotations.test.ts 4✅ 9ms
tests/utils/formatters.test.ts 33✅ 15ms
tests/utils/items.test.ts 2✅ 6ms
tests/utils/misc.test.ts 6✅ 13ms
tests/utils/notes.test.ts 8✅ 10ms
tests/utils/search.test.ts 15✅ 17ms
tests/utils/setup.test.tsx 35✅ 61ms

✅ src/api/helpers.test.ts

src/api/helpers.test.ts
  ✅ cleanBibliographyHTML > formats citations with one content div (like Chicago)
  ✅ cleanBibliographyHTML > formats citations with multiple content divs (like Vancouver)
  ✅ compareAnnotationRawIndices
  ✅ formatNotes > sorts output
  ✅ formatNotes > handles nested output (with preset)
  ✅ formatNotes > handles nested output (with custom string)
  ✅ formatNotes > handles nested output, with block checking
  ✅ formatNotes > handles nested output, with block checking & position
  ✅ formatZoteroAnnotations > formats with defaults
  ✅ formatZoteroAnnotations > groups by day added
  ✅ getItemCreators > 0
  ✅ getItemCreators > 1
  ✅ getItemCreators > 2
  ✅ getItemCreators > 3
  ✅ getItemDateAdded
  ✅ getItemTags > 0
  ✅ getItemTags > 1
  ✅ getItemTags > 2
  ✅ getItemTags > 3
  ✅ getItemTags > 4

✅ src/api/index.test.tsx

src/api/index.test.tsx
  ✅ Formatting utils > formatNotes
  ✅ Formatting utils > formatPDFs
  ✅ Formatting utils > getItemDateAdded
  ✅ Formatting utils > getItemLink
  ✅ Formatting utils > getItemPublication > 0 - no brackets
  ✅ Formatting utils > getItemPublication > 1 - no brackets
  ✅ Formatting utils > getItemPublication > 2 - no brackets
  ✅ Formatting utils > getItemPublication > 3 - no brackets
  ✅ Formatting utils > getItemPublication > 0 - with brackets
  ✅ Formatting utils > getItemPublication > 1 - with brackets
  ✅ Formatting utils > getItemPublication > 2 - with brackets
  ✅ Formatting utils > getItemPublication > 3 - with brackets
  ✅ Formatting utils > Retrieving the formatted type for an item > 0
  ✅ Formatting utils > Retrieving the formatted type for an item > 1
  ✅ Retrieval utils > Retrieving creators data for an item
  ✅ Retrieval utils > Retrieving tags data for an item
  ✅ Retrieval utils > Retrieving bibliography for an item > It should return the clean bibliography
  ✅ Retrieval utils > Retrieving bibliographic entries for a list of citekeys
  ✅ Database connectivity > can manage the cache
  ✅ Database connectivity > can delete the database
  ✅ isDataCached > returns false when no data has been persisted yet
  ✅ isDataCached > returns true when data has been persisted
  ✅ isDataCached > returns false when there is no database
  ✅ Error logging when the database no longer exists > handles attempting to clear the React Query store
  ✅ Error logging when the database no longer exists > handles attempting to check if there is cached data
  ✅ Error logging when the database no longer exists > handles attempting to fetch the timestamp for the last caching operation

✅ src/api/logging.test.tsx

src/api/logging.test.tsx
  ✅ ZoteroRoamLog > uses fallback values
  ✅ ZoteroRoamLog > initializes with values provided
  ✅ ZoteroRoamLog > calls the toaster when showToaster is provided
  ✅ ZoteroRoamLog > creates the right message for the toaster
  ✅ Logger > logs errors
  ✅ Logger > logs infos
  ✅ Logger > logs warnings

✅ src/clients/citoid/base.test.ts

src/clients/citoid/base.test.ts
  ✅ fetchCitoid > 0 Successfully mocking Citoid data for https://www.jmir.org/2021/9/e27283
  ✅ fetchCitoid > 1 Successfully mocking Citoid data for https://doi.org/10.1370/afm.1918
  ✅ fetchCitoid > 2 Successfully mocking Citoid data for https://doi.org/10.3122/jabfm.2017.01.160355
  ✅ fetchCitoid > 0 Successfully mocking Citoid error for https://projects.iq.harvard.edu/files/harvarduxgroup/files/ux-research-guide-sample-questions-for-user-interviews.pdf

✅ src/clients/citoid/hooks.test.ts

src/clients/citoid/hooks.test.ts
  ✅ useCitoids > 1 valid identifier
  ✅ useCitoids > 1 invalid identifier
  ✅ useCitoids > 1 valid + 1 invalid

✅ src/clients/index.test.ts

src/clients/index.test.ts
  ✅ Mock fallback > is called when no matching handler exists

✅ src/clients/semantic/base.test.ts

src/clients/semantic/base.test.ts
  ✅ Fetching mocked Semantic data > 0 Successfully mocking Semantic data for 10.1503/cmaj.210229

✅ src/clients/semantic/hooks.test.ts

src/clients/semantic/hooks.test.ts
  ✅ useSemantic > returns fetch results - 10.1503/cmaj.210229

✅ src/clients/zotero/base.test.ts

src/clients/zotero/base.test.ts
  ✅ Fetching mocked API Key permissions > 0 Fetching permissions for keyWithFullAccess
  ✅ Fetching mocked API Key permissions > 1 Fetching permissions for keyWithNoGroupAccess
  ✅ Fetching mocked bibliography > 0 Fetching bibliography as bib for itemInLibrary
  ✅ Fetching mocked bibliography > 1 Fetching bibliography as bib for itemFromUserLibrary
  ✅ Fetching mocked bibliography entries > 0 Fetching a bibliography entry from userLibrary
  ✅ Fetching mocked bibliography entries > 1 Fetching a bibliography entry from groupLibrary
  ✅ Fetching mocked collections > 0 There should be no items older than latest in userLibrary
  ✅ Fetching mocked collections > 1 There should be no items older than latest in groupLibrary
  ✅ Fetching mocked collections > 0 Fetching collections for userLibrary
  ✅ Fetching mocked collections > 1 Fetching collections for groupLibrary
  ✅ Fetching mocked deleted entities > 0 Fetching entities deleted from userLibrary
  ✅ Fetching mocked deleted entities > 1 Fetching entities deleted from groupLibrary
  ✅ Fetching mocked deleted entities > 0 Checking that no entities are versioned over latest in userLibrary
  ✅ Fetching mocked deleted entities > 1 Checking that no entities are versioned over latest in groupLibrary
  ✅ Fetching mocked items > 0 Fetching items for userLibrary
  ✅ Fetching mocked items > 1 Fetching items for groupLibrary
  ✅ writeItems > 0 Updating an item from userLibrary
  ✅ writeItems > 1 Updating an item from groupLibrary
  ✅ fetchTags > 0 Fetching tags for userLibrary
  ✅ fetchTags > 1 Fetching tags for groupLibrary
  ✅ deleteTags > 0 Deleting tags in userLibrary
  ✅ deleteTags > 1 Deleting tags in groupLibrary

✅ src/clients/zotero/helpers.test.ts

src/clients/zotero/helpers.test.ts
  ✅ Extracting citekeys for Zotero items
  ✅ Comparing tag entries > Tag comparison 0
  ✅ Comparing tag entries > Tag comparison 1
  ✅ Comparing tag entries > Tag comparison 2
  ✅ Comparing tag entries > Tag comparison 3
  ✅ Comparing tag entries > Tag comparison 4
  ✅ Comparing tag entries > Tag comparison 5
  ✅ Comparing tag entries > Inputs with incorrect format are detected
  ✅ Building tag maps > New entries are added correctly
  ✅ Building tag maps > New entries are appended correctly - Object entries
  ✅ Building tag maps > New entries are appended correctly - Array entries
  ✅ Building tag maps > Duplicates are prevented - Object entries
  ✅ Building tag maps > Duplicates are prevented - Array entries
  ✅ Building tag maps > Badly constructed maps are detected
  ✅ Creating formatted tag lists > 0 Creating tag list for userLibrary
  ✅ Creating formatted tag lists > 1 Creating tag list for groupLibrary
  ✅ Merging data updates
  ✅ wrappedFetchItems > Fetching items when query cache is empty
  ✅ wrappedFetchItems > Fetching items when query cache has version data

✅ src/clients/zotero/hooks.test.ts

src/clients/zotero/hooks.test.ts
  ✅ useCollections > returns fetch results
  ✅ Hook for items queries > returns fetch results
  ✅ Hook for tags queries > returns fetch results
  ✅ useWriteableLibraries > Key with full access
  ✅ useWriteableLibraries > Key with no group access

✅ src/clients/zotero/mutations.test.tsx

src/clients/zotero/mutations.test.tsx
  ✅ Mutation hooks for the Zotero API > useDeleteTags > callback on success
  ✅ Mutation hooks for the Zotero API > useImportCitoids > callback on success
  ✅ Mutation hooks for the Zotero API > useModifyTags > callback on success

✅ src/components/Dashboard/Explorer/QueryBuilder/queries.test.ts

src/components/Dashboard/Explorer/QueryBuilder/queries.test.ts
  ✅ Input checks > 0 Abstract exists accepts ...
  ✅ Input checks > 1 Abstract does not exist accepts ...
  ✅ Input checks > 2 Abstract contains accepts ...
  ✅ Input checks > 3 Abstract does not contain accepts ...
  ✅ Input checks > 4 Citekey exists accepts ...
  ✅ Input checks > 5 Citekey does not exist accepts ...
  ✅ Input checks > 6 DOI exists accepts ...
  ✅ Input checks > 7 DOI does not exist accepts ...
  ✅ Input checks > 8 Item added before accepts ...
  ✅ Input checks > 9 Item added after accepts ...
  ✅ Input checks > 10 Item added between accepts ...
  ✅ Input checks > 11 Item type is any of accepts ...
  ✅ Input checks > 12 Item type is not accepts ...
  ✅ Input checks > 13 Notes exist accepts ...
  ✅ Input checks > 14 Notes do not exist accepts ...
  ✅ Input checks > 15 PDF exists accepts ...
  ✅ Input checks > 16 PDF does not exist accepts ...
  ✅ Input checks > 17 Roam page exists accepts ...
  ✅ Input checks > 18 Roam page does not exist accepts ...
  ✅ Input checks > 19 Tags include accepts ...
  ✅ Input checks > 20 Tags include any of accepts ...
  ✅ Input checks > 21 Tags do not include accepts ...
  ✅ Input checks > 22 Title contains accepts ...
  ✅ Input checks > 23 Title does not contain accepts ...
  ✅ Search queries > returns true when given no terms or incomplete terms
  ✅ Search queries > rejects invalid query terms
  ✅ Search queries > supports complex queries
  ✅ Search queries > Querying abstract > 0 Abstract exists (%p) ... null
  ✅ Search queries > Querying abstract > 1 Abstract does not exist (%p) ... null
  ✅ Search queries > Querying abstract > 2 Abstract contains (%p) ... ipsum
  ✅ Search queries > Querying abstract > 3 Abstract does not contain (%p) ... knowledge
  ✅ Search queries > Querying abstract > 4 Abstract does not contain (%p) ...
  ✅ Search queries > Querying citekey > 0 Citekey exists (%p) ... null
  ✅ Search queries > Querying citekey > 1 Citekey does not exist (%p) ... null
  ✅ Search queries > Querying DOI > 0 DOI exists (%p) ... null
  ✅ Search queries > Querying DOI > 1 DOI does not exist (%p) ... null
  ✅ Search queries > Querying added-on date > 0 Item added before (%p) ... 2022-04-01T00:00:00.000Z
  ✅ Search queries > Querying added-on date > 1 Item added before (%p) ... null
  ✅ Search queries > Querying added-on date > 2 Item added after (%p) ... 2022-01-01T00:00:00.000Z
  ✅ Search queries > Querying added-on date > 3 Item added after (%p) ... null
  ✅ Search queries > Querying added-on date > 4 Item added between (%p) ... [ 2022-01-01T00:00:00.000Z, 2022-04-01T00:00:00.000Z ]
  ✅ Search queries > Querying added-on date > 5 Item added between (%p) ... [ null, 2022-04-01T00:00:00.000Z ]
  ✅ Search queries > Querying added-on date > 6 Item added between (%p) ... [ 2022-01-01T00:00:00.000Z, null ]
  ✅ Search queries > Querying item type > 0 Item type is any of (%p) ... [ 'book', 'bookChapter', 'podcast' ]
  ✅ Search queries > Querying item type > 1 Item type is not (%p) ... [ 'journalArticle' ]
  ✅ Search queries > Querying notes > 0 Notes exist (%p) ... null
  ✅ Search queries > Querying notes > 1 Notes do not exist (%p) ... null
  ✅ Search queries > Querying PDFs > 0 PDF exists (%p) ... null
  ✅ Search queries > Querying PDFs > 1 PDF does not exist (%p) ... null
  ✅ Search queries > Querying Roam page > 0 Roam page exists (%p) ... null
  ✅ Search queries > Querying Roam page > 1 Roam page does not exist (%p) ... null
  ✅ Search queries > Querying tags > 0 Tags include (%p) ... [ 'healthcare', 'policy' ]
  ✅ Search queries > Querying tags > 1 Tags include any of (%p) ... [ 'healthcare', 'policy' ]
  ✅ Search queries > Querying tags > 2 Tags do not include (%p) ... [ 'policy', 'systems design' ]
  ✅ Search queries > Querying title > 0 Title contains (%p) ... systems
  ✅ Search queries > Querying title > 1 Title does not contain (%p) ... systems

✅ src/components/Dashboard/Explorer/QueryBuilder/utils.test.ts

src/components/Dashboard/Explorer/QueryBuilder/utils.test.ts
  ✅ Correctly adds sibling to an element

✅ src/components/Dashboard/Explorer/QueryPDFs/helpers.test.ts

src/components/Dashboard/Explorer/QueryPDFs/helpers.test.ts
  ✅ Identifies the connections of a PDF item
  ✅ Formats PDF metadata

✅ src/components/Dashboard/TagManager/utils.test.ts

src/components/Dashboard/TagManager/utils.test.ts
  ✅ Collects tag stats
  ✅ Counts tag usage
  ✅ Identifies singleton tags > { roam: [], zotero: [ { tag: 'culture' } ] }
  ✅ Identifies singleton tags > { roam: [ { title: 'culture' } ], zotero: [ { tag: 'culture' } ] }
  ✅ Identifies singleton tags > { roam: [ { title: 'Culture' } ], zotero: [ { tag: 'culture' } ] }
  ✅ Identifies singleton tags > { roam: [], zotero: [ { tag: 'culture' }, { tag: 'Culture' } ] }
  ✅ Makes correct suggestions for tags > { roam: [], zotero: [ { tag: 'PKM' } ] }
  ✅ Makes correct suggestions for tags > { roam: [], zotero: [ { tag: 'PKM', meta: { type: +0 } }, { tag: 'PKM', meta: { type: 1 } } ] }
  ✅ Makes correct suggestions for tags > { roam: [ { title: 'housing' }, { title: 'Housing' } ], zotero: [ { tag: 'housing' } ] }
  ✅ Match Zotero tags with Roam pages
  ✅ Sorts tags list

✅ src/components/GraphWatcher/helpers.test.ts

src/components/GraphWatcher/helpers.test.ts
  ✅ hasNodeListChanged > Empty list doesn't get identified as a change
  ✅ hasNodeListChanged > Identical list doesn't get identified as a change
  ✅ hasNodeListChanged > Non-empty list becoming empty is a change
  ✅ hasNodeListChanged > Empty list becoming non-empty is a change
  ✅ hasNodeListChanged > Change in list contents is a change
  ✅ sortElems > sorts object arrays on a string key

✅ src/components/GraphWatcher/Menus/helpers.test.ts

src/components/GraphWatcher/Menus/helpers.test.ts
  ✅ cleanSemantic > simplifies SemanticScholar item metadata
  ✅ compareItemsByYear > sorts Zotero items by publication year & creators
  ✅ getAuthorLastName > extracts from single names
  ✅ getAuthorLastName > extracts from simple names
  ✅ getAuthorLastName > extracts from names with hyphen
  ✅ getAuthorLastName > extracts from names with particle
  ✅ getAuthorLastName > extracts from names with middle name
  ✅ makeAuthorsSummary > returns an empty string when given an empty input
  ✅ makeAuthorsSummary > formats correctly with 1 author
  ✅ makeAuthorsSummary > formats correctly with 2 authors
  ✅ makeAuthorsSummary > formats correctly with 3 authors
  ✅ makeAuthorsSummary > formats correctly with 4+ authors

✅ src/components/GraphWatcher/Menus/utils.test.tsx

src/components/GraphWatcher/Menus/utils.test.tsx
  ✅ Citekey menu containers are inserted > 0
  ✅ Citekey menu containers are inserted > 1
  ✅ DNP menu containers are inserted > 0
  ✅ DNP menu containers are inserted > 1
  ✅ DNP menu containers are inserted > 2
  ✅ DNP menu containers are inserted > 3
  ✅ DNP menu containers are inserted > 4
  ✅ Tag menu containers are inserted > 0
  ✅ Tag menu containers are inserted > 1

✅ src/components/GraphWatcher/WebImport/helpers.test.tsx

src/components/GraphWatcher/WebImport/helpers.test.tsx
  ✅ WebImport divs are inserted > 0
  ✅ WebImport divs are inserted > 1
  ✅ matchArrays > Finds if two string arrays have elements in common

✅ src/components/NotesDrawer/helpers.test.ts

src/components/NotesDrawer/helpers.test.ts
  ✅ simplifyZoteroNotes

✅ src/components/SearchPanel/helpers.test.ts

src/components/SearchPanel/helpers.test.ts
  ✅ cleanLibrary > Simplifies Zotero item metadata
  ✅ formatItemReferenceWithDefault > page-reference
  ✅ formatItemReferenceWithDefault > raw
  ✅ formatItemReferenceWithDefault > tag
  ✅ formatItemReferenceWithDefault > citation
  ✅ formatItemReferenceWithDefault > citekey
  ✅ Item reference formatting - with template > 0 - @{{key}}
  ✅ Item reference formatting - with template > 1 - [{{title}}]([[@{{key}}]])
  ✅ Item reference formatting - with template > 2 - [{{authors}} ({{year}})]([[@{{key}}]])

✅ src/components/UserSettings/common.test.ts

src/components/UserSettings/common.test.ts
  ✅ camelToTitleCase > 0 - someText
  ✅ camelToTitleCase > 1 - toggleDashboard
  ✅ camelToTitleCase > 2 - copyAsReference

✅ src/components/ZoteroImport/helpers.test.ts

src/components/ZoteroImport/helpers.test.ts
  ✅ Zotero collections sorting > returns an empty array when given an empty input
  ✅ Zotero collections sorting > correctly sorts an array of Zotero collections

✅ src/hooks/index.test.ts

src/hooks/index.test.ts
  ✅ Hook for array reducer > Add an element
  ✅ Hook for array reducer > Remove an element
  ✅ Hook for array reducer > Update an element
  ✅ Hook for boolean state > Toggle method
  ✅ Hook for boolean state > Set method
  ✅ Hook for boolean state > Switch on
  ✅ Hook for boolean state > Switch off
  ✅ Hook for filters list > Toggle filter on
  ✅ Hook for filters list > Toggle filter off
  ✅ Hook for multiple selection state > Behavior with base config
  ✅ Hook for multiple selection state > With custom match functions
  ✅ Hook for numeric state
  ✅ Hook for pagination
  ✅ Hook for single selection state > Behavior with base config
  ✅ Hook for single selection state > With custom transform function
  ✅ Hook for text state
  ✅ Hook for toggle state > Toggle method

✅ src/services/events/index.test.ts

src/services/events/index.test.ts
  ✅ metadataAdded > hook behavior on error
  ✅ metadataAdded > hook behavior on success
  ✅ metadataAdded > hook fallback
  ✅ notesAdded > hook behavior on error
  ✅ notesAdded > hook behavior on success
  ✅ notesAdded > hook fallback
  ✅ tagsDeleted > hook behavior on error
  ✅ tagsDeleted > hook behavior on success
  ✅ tagsModified > hook behavior on error
  ✅ tagsModified > hook behavior on partial success
  ✅ tagsModified > hook behavior on full success
  ✅ writeFinished > hook behavior on error
  ✅ writeFinished > hook behavior on partial success
  ✅ writeFinished > hook behavior on full success

✅ src/services/idb/index.test.ts

src/services/idb/index.test.ts
  ✅ Store handling
  ✅ DB creation
  ✅ DB deletion
  ✅ DB conflict

✅ src/services/react-query/index.test.ts

src/services/react-query/index.test.ts
  ✅ selectItemChildren
  ✅ selectItemCollections
  ✅ selectItemRelated
  ✅ selectItems
  ✅ selectTags > 0 Retrieving tags data for 0
  ✅ selectTags > 1 Retrieving tags data for 1

✅ src/services/search/index.test.ts

src/services/search/index.test.ts
  ✅ Query > _parse() > handles single-term queries
  ✅ Query > _parse() > handles operator queries > 'history|sociology'
  ✅ Query > _parse() > handles operator queries > '-history|sociology'
  ✅ Query > _parse() > handles operator queries > 'history&sociology'
  ✅ Query > _parse() > handles operator queries > '-history&sociology'
  ✅ Query > _parse() > handles operator queries > '(history|sociology)'
  ✅ Query > _parse() > handles operator queries > '(history&sociology)'
  ✅ Query > _parse() > handles operator queries > '-(history|sociology)'
  ✅ Query > _parse() > handles operator queries > '-(history&sociology)'
  ✅ Query > _parse() > handles multi-level queries > '(history|sociology)&TODO'
  ✅ Query > _parse() > handles multi-level queries > 'history|(sociology&TODO)'
  ✅ Query > _parse() > handles multi-level queries > '(-history)|(sociology&TODO)'
  ✅ Query > _parse() > handles multi-level queries > '-history|(sociology&TODO)'
  ✅ Query > _parse() > handles multi-level queries > '-(history|(sociology&TODO))'
  ✅ Query > _parse() > handles multi-level queries > '-((sociology&TODO)|history)'
  ✅ Query > _parse() > handles multi-level queries > '(-DONE)&(history|sociology)'
  ✅ Query > match() > query: 'systems' | expect: true
  ✅ Query > match() > query: 'software' | expect: false
  ✅ Query > match() > query: '-TODO' | expect: true
  ✅ Query > match() > query: 'systems&software' | expect: false
  ✅ Query > match() > query: '(systems&software)' | expect: false
  ✅ Query > match() > query: 'software|TODO' | expect: false
  ✅ Query > match() > query: '(software|TODO)' | expect: false
  ✅ Query > match() > query: 'PKM&culture' | expect: true
  ✅ Query > match() > query: '(PKM&culture)' | expect: true
  ✅ Query > match() > query: 'TODO&(systems|culture)' | expect: false
  ✅ Query > match() > query: 'history|(systems&culture)' | expect: true
  ✅ Query > match() > query: '-systems&TODO' | expect: true
  ✅ Query > match() > query: '-(systems&TODO)' | expect: true
  ✅ Query > match() > query: '(-systems)&TODO' | expect: false

✅ src/services/smartblocks/helpers.test.ts

src/services/smartblocks/helpers.test.ts
  ✅ reformatImportableBlocks > 0 - []
  ✅ reformatImportableBlocks > 1 - [ 'some', 'block' ]
  ✅ reformatImportableBlocks > 2 - [ 'some', { string: 'object', text: 'object', children: [] } ]
  ✅ reformatImportableBlocks > 3 - [ 'some', { string: 'object', text: 'object', children: [ 'child', 'string' ] } ]
  ✅ reformatImportableBlocks > throws when passed an invalid element

✅ src/services/smartblocks/index.test.ts

src/services/smartblocks/index.test.ts
  ✅ All commands return correct output > ZOTERORANDOMCITEKEY
  ✅ All commands return correct output > ZOTEROITEMABSTRACT
  ✅ All commands return correct output > ZOTEROITEMCITATION > It returns the correct output
  ✅ All commands return correct output > ZOTEROITEMCITEKEY
  ✅ All commands return correct output > ZOTEROITEMCOLLECTIONS
  ✅ All commands return correct output > ZOTEROITEMCREATORS
  ✅ All commands return correct output > ZOTEROITEMDATEADDED
  ✅ All commands return correct output > ZOTEROITEMKEY
  ✅ All commands return correct output > ZOTEROITEMLINK
  ✅ All commands return correct output > ZOTEROITEMMETADATA
  ✅ All commands return correct output > ZOTEROITEMPUBLICATION
  ✅ All commands return correct output > ZOTEROITEMRELATED
  ✅ All commands return correct output > ZOTEROITEMTAGS
  ✅ All commands return correct output > ZOTEROITEMTITLE
  ✅ All commands return correct output > ZOTEROITEMTYPE
  ✅ All commands return correct output > ZOTEROITEMURL
  ✅ All commands return correct output > ZOTEROITEMYEAR
  ✅ All commands return correct output > ZOTERONOTES
  ✅ All commands return correct output > ZOTEROPDFS

✅ tests/utils/annotations.test.ts

tests/utils/annotations.test.ts
  ✅ Extracts annotation indices from string > 0 - 00001|00002|00003
  ✅ Extracts annotation indices from string > 1 - 00045|00056|00067
  ✅ Sorts annotation indices
  ✅ Simplifies annotations

✅ tests/utils/formatters.test.ts

tests/utils/formatters.test.ts
  ✅ Creating timestamps > formats with 24-hour clock
  ✅ Creating timestamps > formats correctly with single digits for minutes
  ✅ Creating from-ago dates > identifies dates from today
  ✅ Creating from-ago dates > identifies dates from yesterday
  ✅ Creating from-ago dates > identifies dates from earlier in the year
  ✅ Creating from-ago dates > identifies dates from previous years
  ✅ Parsing DOIs > converts DOI to lowercase
  ✅ Parsing DOIs > parses DOI from full URL
  ✅ Parsing DOIs > rejects DOI with incorrect format
  ✅ Parsing DOIs > rejects empty string
  ✅ Transforming DOIs
  ✅ Making Zotero local link > creates Markdown link by default
  ✅ Making Zotero local link > correctly generates the target URL
  ✅ Making Zotero local link > correctly generates the target URL for an item in a group library
  ✅ Making Zotero web link > creates Markdown link by default
  ✅ Making Zotero web link > correctly generates the target URL for user libraries
  ✅ Making Zotero web link > correctly generates the target URL for group libraries
  ✅ Making PDF links > creates target link by default
  ✅ Making PDF links > correctly generates Markdown link
  ✅ Making PDF links > has fallback defaults
  ✅ Formatting Zotero item references > formats as inline reference
  ✅ Formatting Zotero item references > formats as citation
  ✅ Formatting Zotero item references > formats as citekey
  ✅ Formatting Zotero item references > formats as key
  ✅ Formatting Zotero item references > formats as page reference
  ✅ Formatting Zotero item references > formats as popover
  ✅ Formatting Zotero item references > formats as tag
  ✅ Formatting Zotero item references > formats as Zettlr-like reference
  ✅ Formatting Zotero item references > formats with a custom template
  ✅ Formatting Zotero item references > uses the citekey format as fallback
  ✅ Pluralizes tokens
  ✅ Creating a dictionary > Creates dictionary from string Array
  ✅ Creating a dictionary > Bad inputs are detected

✅ tests/utils/items.test.ts

tests/utils/items.test.ts
  ✅ Categorizes Zotero items
  ✅ Identifies the children of a Zotero item

✅ tests/utils/misc.test.ts

tests/utils/misc.test.ts
  ✅ Appends element in array
  ✅ Removes array element at index
  ✅ Updates value of array element
  ✅ Executing a function by name > executes a function attached to the window
  ✅ Executing a function by name > executes the function with args
  ✅ Executing a function by name > throws a custom error if the function doesn't exist

✅ tests/utils/notes.test.ts

tests/utils/notes.test.ts
  ✅ Splitting HTML notes > No separator provided - function throws
  ✅ Splitting HTML notes > Incorrect type of separator provided - function throws
  ✅ Splitting HTML notes > Simple separator
  ✅ Splitting HTML notes > HTML tag separator
  ✅ Parsing HTML notes > cleans markup from rich tags
  ✅ Parsing HTML notes > formats links into Markdown
  ✅ Parsing HTML notes > removes newlines
  ✅ Parsing HTML notes > cleans list markup

✅ tests/utils/search.test.ts

tests/utils/search.test.ts
  ✅ Search engine inputs > rejects invalid search inputs
  ✅ Search engine inputs > applies search to an array
  ✅ Search engine inputs > escapes strings with special characters > 0 - In-text *asterisks*
  ✅ Search engine inputs > escapes strings with special characters > 1 - *Self-Management
  ✅ Case-sensitive search
  ✅ Search - matching modes > matches on partial words
  ✅ Search - matching modes > matches on word boundaries only
  ✅ Search - matching modes > finds exact matches - single-word query
  ✅ Search - matching modes > finds exact matches - multi-word query
  ✅ Search - compounds > matches compounds - single-word query
  ✅ Search - compounds > matches compounds - multi-word query
  ✅ Search - word order > matches words in the order provided
  ✅ Search - word order > matches words in any order
  ✅ Search - word order > matches in the order provided, on word boundaries
  ✅ Search - word order > matches words in any order, on word boundaries

✅ tests/utils/setup.test.tsx

tests/utils/setup.test.tsx
  ✅ Parsing user data requests > passes if an empty array of requests is provided
  ✅ Parsing user data requests > throws if none of the requests has an API key
  ✅ Parsing user data requests > throws if any of the requests is missing a data URI
  ✅ Parsing user data requests > throws if any of the requests has an incorrect data URI
  ✅ Parsing user data requests > throws if any of the requests has an incorrect library ID
  ✅ Parsing user data requests > throws if any of the requests has an incorrect library type
  ✅ Parsing user data requests > throws if the same library is provided twice
  ✅ Parsing user data requests > accepts an Object as input
  ✅ Parsing user data requests > returns proper configuration when given correct input
  ✅ Parsing user data requests > returns proper configuration when given correct input (from library)
  ✅ Parsing mock data requests > should be a valid configuration
  ✅ Parsing initial user settings > should return defaults if given no settings
  ✅ Parsing user shortcuts > 0 - {}
  ✅ Parsing user shortcuts > 1 - { copyDefault: 'alt+E' }
  ✅ Parsing user shortcuts > 2 - { toggleDashboard: 'alt+ +' }
  ✅ Parsing user shortcuts > 3 - { goToItemPage: '' }
  ✅ Creating IndexedDB persister > persist, restore, delete client
  ✅ Creating IndexedDB persister > persist errors are raised
  ✅ Filtering queries for persistence > 0
  ✅ Filtering queries for persistence > 1
  ✅ Filtering queries for persistence > 2
  ✅ Filtering queries for persistence > 3
  ✅ Filtering queries for persistence > 4
  ✅ Filtering queries for persistence > 5
  ✅ Initial configuration > Roam Depot - no requests set
  ✅ Initial configuration > Roam Depot - requests are provided
  ✅ Initial configuration > RoamJS
  ✅ Theme setter > use_dark_theme = true
  ✅ Theme setter > use_dark_theme = false
  ✅ Portals setup > Extension slot > Topbar exists: true
  ✅ Portals setup > Extension slot > Topbar exists: false
  ✅ Portals setup > Portals container > App exists: true
  ✅ Portals setup > Portals container > App exists: false
  ✅ Teardown > Extension slot
  ✅ Teardown > Portals container