Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save jmchilton/aba988aec7f0878a8bc9cd93252ed63b to your computer and use it in GitHub Desktop.

Select an option

Save jmchilton/aba988aec7f0878a8bc9cd93252ed63b to your computer and use it in GitHub Desktop.

Unit Test Review: SidebarList & useSidebarSelection

Overall Assessment

Both test files are solid. All 8 mutation experiments were caught (8/8), confirming these tests actually verify real behavior rather than being auto-generated fluff.

SidebarList.test.ts

Tests to consider eliminating:

  1. "does not render items when loading" and "does not render loading state when empty" — These test that Vue's v-if/v-else-if/v-else chain works correctly. This is framework behavior, not application logic. The positive tests already implicitly cover mutual exclusivity. Same for "does not render loading or empty states".

    That said, these are cheap to maintain and provide documentation value. Low priority to remove.

  2. "shows loading indicator when isLoading is true" vs "renders default loading message" — These could be one test. The first checks .exists(), the second checks .text(). If text is present, the element exists. Same pattern for empty state.

Suggestions:

  • The mountList helper uses as any cast. Fine for Vue 2.7 compat.
  • The scoped slot test string uses Vue 2 syntax. Will need updating on Vue 3 migration.

useSidebarSelection.test.ts

Tests to consider eliminating: None — each test covers a distinct behavior path.

Missing coverage worth adding:

  1. allSelected false positive — If selectedIds contains IDs not in items, allSelected could be true incorrectly (size match without content match). Worth a test.

  2. Shift-click preserves existing non-range selections — The shift-click tests start from clean state. Test: select "a", normal-click "b", shift-click "d" — does "a" remain selected?

  3. pruneAfterDelete when no items were selected — edge case, should be a no-op.

Duplication / Abstraction Opportunities

Repeated useSidebarSelection setup could use a helper:

function setup(...ids: string[]) {
    const items = ref(makeItems(...ids));
    return { items, ...useSidebarSelection(items, (i) => i.id) };
}

Collapses ~3 lines per test into 1. Moderate win across 18 tests.

Mutation Testing Results

# File Mutation Result
1 SidebarList.vue role="button" -> role="link" CAUGHT
2 SidebarList.vue Remove tabindex="0" CAUGHT
3 SidebarList.vue "Enter" -> "Space" CAUGHT
4 SidebarList.vue Remove @click handler CAUGHT
5 useSidebarSelection.ts Remove lastClickedIndex.value = null in toggleSelectionMode CAUGHT
6 useSidebarSelection.ts event.shiftKey -> !event.shiftKey CAUGHT
7 useSidebarSelection.ts Remove empty-list guard in pruneAfterDelete CAUGHT
8 useSidebarSelection.ts Remove items.length > 0 guard in allSelected CAUGHT

Summary

Aspect SidebarList useSidebarSelection
Mutation kill rate 4/4 4/4
Redundant tests 2-3 (low priority) 0
Missing coverage None significant 2 edge cases
Abstraction opportunity None setup() helper
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment