Add test coverage of status class
This commit is contained in:
@@ -57,8 +57,11 @@ class StatusEntry:
|
||||
|
||||
@classmethod
|
||||
def duplicate(cls, source: StatusEntry) -> StatusEntry:
|
||||
"""Create a shallow copy of the source object."""
|
||||
return dataclasses.replace(source)
|
||||
"""Create a deep copy of the source object."""
|
||||
cls = dataclasses.replace(source)
|
||||
cls.color = QColor(source.color)
|
||||
cls.icon = QIcon(source.icon)
|
||||
return cls
|
||||
|
||||
# END Class StatusEntry
|
||||
|
||||
|
||||
+1
-1
@@ -75,7 +75,7 @@ class MockStatusBar:
|
||||
class MockTheme:
|
||||
|
||||
def __init__(self):
|
||||
self.baseIconHeight = 10
|
||||
self.baseIconHeight = 20
|
||||
return
|
||||
|
||||
def getPixmap(self, *a):
|
||||
|
||||
@@ -26,7 +26,7 @@ from tools import C
|
||||
|
||||
from PyQt5.QtGui import QColor, QIcon
|
||||
|
||||
from novelwriter.core.status import NWStatus
|
||||
from novelwriter.core.status import NWStatus, StatusEntry, _ShapeCache
|
||||
from novelwriter.enum import nwStatusShape
|
||||
|
||||
statusKeys = [C.sNew, C.sNote, C.sDraft, C.sFinished]
|
||||
@@ -34,7 +34,36 @@ importKeys = [C.iNew, C.iMinor, C.iMajor, C.iMain]
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreStatus_Internal(mockRnd):
|
||||
def testCoreStatus_StatusEntry():
|
||||
"""Test the StatusEntry class."""
|
||||
color = QColor(255, 0, 0)
|
||||
icon = NWStatus.createIcon(24, color, nwStatusShape.CIRCLE)
|
||||
entry = StatusEntry("Test", color, nwStatusShape.CIRCLE, icon, 42)
|
||||
|
||||
# Check values
|
||||
assert entry.name == "Test"
|
||||
assert entry.color is color
|
||||
assert entry.shape == nwStatusShape.CIRCLE
|
||||
assert entry.icon is icon
|
||||
assert entry.count == 42
|
||||
|
||||
# Make a copy
|
||||
other = StatusEntry.duplicate(entry)
|
||||
assert other is not entry
|
||||
|
||||
# Check copy is not the same
|
||||
assert other.name == "Test"
|
||||
assert other.color is not color # Not the same object
|
||||
assert other.color == color # But same colours
|
||||
assert other.shape == nwStatusShape.CIRCLE
|
||||
assert other.icon is not icon # Not the same icon, but a copy
|
||||
assert other.count == 42
|
||||
|
||||
# END Test testCoreStatus_StatusEntry
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreStatus_Internal(mockGUI, mockRnd):
|
||||
"""Test all the internal functions of the NWStatus class."""
|
||||
nStatus = NWStatus(NWStatus.STATUS)
|
||||
nImport = NWStatus(NWStatus.IMPORT)
|
||||
@@ -82,18 +111,25 @@ def testCoreStatus_Internal(mockRnd):
|
||||
assert nImport._isKey("i12345F") is False # Not a lower case hex value
|
||||
assert nImport._isKey("i12345f") is True # Valid hex value
|
||||
|
||||
assert nStatus._checkKey(None) == "s000008" # Creates next key
|
||||
assert nStatus._checkKey("s654321") == "s654321" # Status key accepted
|
||||
assert nStatus._checkKey("i123456") == "s000009" # Import key not accepted
|
||||
|
||||
assert nImport._checkKey(None) == "i00000a" # Creates next key
|
||||
assert nImport._checkKey("s654321") == "i00000b" # Status key not accepted
|
||||
assert nImport._checkKey("i123456") == "i123456" # Import key accepted
|
||||
|
||||
# END Test testCoreStatus_Internal
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreStatus_Iterator(mockRnd):
|
||||
def testCoreStatus_Iterator(mockGUI, mockRnd):
|
||||
"""Test the iterator functions of the NWStatus class."""
|
||||
nStatus = NWStatus(NWStatus.STATUS)
|
||||
|
||||
nStatus.add(None, "New", (100, 100, 100), "SQUARE", 0)
|
||||
nStatus.add(None, "Note", (200, 50, 0), "SQUARE", 0)
|
||||
nStatus.add(None, "Draft", (200, 150, 0), "SQUARE", 0)
|
||||
nStatus.add(None, "Finished", (50, 200, 0), "SQUARE", 0)
|
||||
nStatus.add(None, "Note", (200, 50, 0), "CIRCLE", 1)
|
||||
nStatus.add(None, "Draft", (200, 150, 0), "SQUARE", 2)
|
||||
nStatus.add(None, "Finished", (50, 200, 0), "CIRCLE", 3)
|
||||
|
||||
# Direct access
|
||||
entry = nStatus[statusKeys[0]]
|
||||
@@ -106,36 +142,63 @@ def testCoreStatus_Iterator(mockRnd):
|
||||
assert len(nStatus._store) == 4
|
||||
assert len(nStatus) == 4
|
||||
|
||||
# Content : Keys
|
||||
assert [k for k, _ in nStatus.iterItems()] == [
|
||||
"s000000", "s000001", "s000002", "s000003"
|
||||
]
|
||||
|
||||
# Content : Names
|
||||
assert [e.name for _, e in nStatus.iterItems()] == [
|
||||
"New", "Note", "Draft", "Finished"
|
||||
]
|
||||
|
||||
# Content : Colours
|
||||
assert [e.color for _, e in nStatus.iterItems()] == [
|
||||
QColor(100, 100, 100), QColor(200, 50, 0), QColor(200, 150, 0), QColor(50, 200, 0)
|
||||
]
|
||||
|
||||
# Content : Shape
|
||||
assert [e.shape for _, e in nStatus.iterItems()] == [
|
||||
nwStatusShape.SQUARE, nwStatusShape.CIRCLE, nwStatusShape.SQUARE, nwStatusShape.CIRCLE
|
||||
]
|
||||
|
||||
# Content : Count
|
||||
assert [e.count for _, e in nStatus.iterItems()] == [0, 1, 2, 3]
|
||||
|
||||
# END Test testCoreStatus_Iterator
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreStatus_Entries(mockRnd):
|
||||
def testCoreStatus_Entries(mockGUI, mockRnd):
|
||||
"""Test all the simple setters for the NWStatus class."""
|
||||
nStatus = NWStatus(NWStatus.STATUS)
|
||||
|
||||
# Write
|
||||
# =====
|
||||
# Add
|
||||
# ===
|
||||
|
||||
# Have a key
|
||||
# Has a key
|
||||
nStatus.add(statusKeys[0], "Entry 1", (200, 100, 50), "SQUARE", 0)
|
||||
assert nStatus[statusKeys[0]].name == "Entry 1"
|
||||
assert nStatus[statusKeys[0]].color == QColor(200, 100, 50)
|
||||
assert nStatus[statusKeys[0]].shape == nwStatusShape.SQUARE
|
||||
|
||||
# Don't have a key
|
||||
# Doesn't have a key
|
||||
nStatus.add(None, "Entry 2", (210, 110, 60), "SQUARE", 0)
|
||||
assert nStatus[statusKeys[1]].name == "Entry 2"
|
||||
assert nStatus[statusKeys[1]].color == QColor(210, 110, 60)
|
||||
assert nStatus[statusKeys[1]].shape == nwStatusShape.SQUARE
|
||||
|
||||
# Wrong colour spec
|
||||
nStatus.add(None, "Entry 3", "what?", "SQUARE", 0) # type: ignore
|
||||
# Wrong colour spec, unknown shape
|
||||
nStatus.add(None, "Entry 3", "what?", "", 0) # type: ignore
|
||||
assert nStatus[statusKeys[2]].name == "Entry 3"
|
||||
assert nStatus[statusKeys[2]].color == QColor(100, 100, 100)
|
||||
assert nStatus[statusKeys[2]].shape == nwStatusShape.SQUARE
|
||||
|
||||
# Wrong colour count
|
||||
nStatus.add(None, "Entry 4", (10, 20), "SQUARE", 0) # type: ignore
|
||||
nStatus.add(None, "Entry 4", (10, 20), "CIRCLE", 0) # type: ignore
|
||||
assert nStatus[statusKeys[3]].name == "Entry 4"
|
||||
assert nStatus[statusKeys[3]].color == QColor(100, 100, 100)
|
||||
assert nStatus[statusKeys[3]].shape == nwStatusShape.CIRCLE
|
||||
|
||||
# Check
|
||||
# =====
|
||||
@@ -174,6 +237,15 @@ def testCoreStatus_Entries(mockRnd):
|
||||
assert isinstance(nStatus[statusKeys[3]].icon, QIcon)
|
||||
assert isinstance(nStatus["blablabla"].icon, QIcon)
|
||||
|
||||
# Shape Access
|
||||
# ============
|
||||
|
||||
assert nStatus[statusKeys[0]].shape == nwStatusShape.SQUARE
|
||||
assert nStatus[statusKeys[1]].shape == nwStatusShape.SQUARE
|
||||
assert nStatus[statusKeys[2]].shape == nwStatusShape.SQUARE
|
||||
assert nStatus[statusKeys[3]].shape == nwStatusShape.CIRCLE
|
||||
assert nStatus["blablabla"].shape == nwStatusShape.SQUARE
|
||||
|
||||
# Increment and Count Access
|
||||
# ==========================
|
||||
|
||||
@@ -195,37 +267,19 @@ def testCoreStatus_Entries(mockRnd):
|
||||
assert nStatus[statusKeys[2]].count == 0
|
||||
assert nStatus[statusKeys[3]].count == 0
|
||||
|
||||
# Reorder
|
||||
# =======
|
||||
# Update
|
||||
# ======
|
||||
|
||||
# cOrder = list(nStatus._store.keys())
|
||||
# assert cOrder == statusKeys
|
||||
assert list(nStatus._store.keys()) == statusKeys
|
||||
|
||||
# # Wrong length
|
||||
# assert nStatus.reorder([]) is False
|
||||
# Reverse
|
||||
order: list[tuple[str | None, StatusEntry]] = list(nStatus.iterItems())
|
||||
nStatus.update(list(reversed(order)))
|
||||
assert list(nStatus._store.keys()) == list(reversed(statusKeys))
|
||||
|
||||
# # No change
|
||||
# assert nStatus.reorder(cOrder) is False
|
||||
|
||||
# # Actual re-order
|
||||
# nOrder = [
|
||||
# statusKeys[0],
|
||||
# statusKeys[2],
|
||||
# statusKeys[1],
|
||||
# statusKeys[3],
|
||||
# ]
|
||||
# assert nStatus.reorder(nOrder) is True
|
||||
# assert list(nStatus._store.keys()) == nOrder
|
||||
|
||||
# # Add an unknown key
|
||||
# wOrder = nOrder.copy()
|
||||
# wOrder[3] = nStatus._newKey()
|
||||
# assert nStatus.reorder(wOrder) is False
|
||||
# assert list(nStatus._store.keys()) == nOrder
|
||||
|
||||
# # Put it back
|
||||
# assert nStatus.reorder(cOrder) is True
|
||||
# assert list(nStatus._store.keys()) == cOrder
|
||||
# Restore
|
||||
nStatus.update(order)
|
||||
assert list(nStatus._store.keys()) == statusKeys
|
||||
|
||||
# Default
|
||||
# =======
|
||||
@@ -242,46 +296,31 @@ def testCoreStatus_Entries(mockRnd):
|
||||
|
||||
nStatus._default = default
|
||||
|
||||
# # Remove
|
||||
# # ======
|
||||
# Remove
|
||||
# ======
|
||||
# This uses update with deleted items
|
||||
|
||||
# # Non-existing entry
|
||||
# assert nStatus.remove("blablabla") is False
|
||||
order: list[tuple[str | None, StatusEntry]] = list(nStatus.iterItems())
|
||||
|
||||
# # Non-zero entry
|
||||
# nStatus.increment(statusKeys[3])
|
||||
# assert nStatus.remove(statusKeys[3]) is False
|
||||
# Remove Entry 0
|
||||
nStatus.update([order[1], order[3], order[2]])
|
||||
assert list(nStatus._store.keys()) == [statusKeys[1], statusKeys[3], statusKeys[2]]
|
||||
assert nStatus._default == statusKeys[1]
|
||||
|
||||
# # Delete last entry
|
||||
# nStatus.resetCounts()
|
||||
# lastName = nStatus[statusKeys[3]].name
|
||||
# assert lastName == "Entry 4"
|
||||
# assert nStatus.remove(statusKeys[3]) is True
|
||||
# assert nStatus.check(statusKeys[3]) == nStatus._default
|
||||
# assert nStatus.check(lastName) == nStatus._default
|
||||
|
||||
# # Delete default entry, Entry 2 is new default
|
||||
# firstName = nStatus[nStatus._default].name
|
||||
# assert firstName == "Entry 1"
|
||||
# assert nStatus.remove(nStatus._default) is True # type: ignore
|
||||
# assert nStatus[firstName].name == "Entry 2"
|
||||
|
||||
# # Remove remaining entries
|
||||
# assert nStatus.remove(statusKeys[1]) is True
|
||||
# assert nStatus.remove(statusKeys[2]) is True
|
||||
|
||||
# assert len(nStatus) == 0
|
||||
# assert nStatus._default is None
|
||||
# Remove Entry 1
|
||||
nStatus.update([order[3], order[2]])
|
||||
assert list(nStatus._store.keys()) == [statusKeys[3], statusKeys[2]]
|
||||
assert nStatus._default == statusKeys[3]
|
||||
|
||||
# END Test testCoreStatus_Entries
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreStatus_PackUnpack(mockRnd):
|
||||
"""Test all the pack/unpack of the NWStatus class."""
|
||||
def testCoreStatus_Pack(mockGUI, mockRnd):
|
||||
"""Test data packing of the NWStatus class."""
|
||||
nStatus = NWStatus(NWStatus.STATUS)
|
||||
nStatus.add(None, "New", (100, 100, 100), "SQUARE", 0)
|
||||
nStatus.add(None, "Note", (200, 50, 0), "SQUARE", 0)
|
||||
nStatus.add(None, "Note", (200, 50, 0), "CIRCLE", 0)
|
||||
nStatus.add(None, "Draft", (200, 150, 0), "SQUARE", 0)
|
||||
nStatus.add(None, "Finished", (50, 200, 0), "SQUARE", 0)
|
||||
|
||||
@@ -306,7 +345,7 @@ def testCoreStatus_PackUnpack(mockRnd):
|
||||
"red": "200",
|
||||
"green": "50",
|
||||
"blue": "0",
|
||||
"shape": "SQUARE",
|
||||
"shape": "CIRCLE",
|
||||
}),
|
||||
("Draft", {
|
||||
"key": statusKeys[2],
|
||||
@@ -326,4 +365,30 @@ def testCoreStatus_PackUnpack(mockRnd):
|
||||
}),
|
||||
]
|
||||
|
||||
# END Test testCoreStatus_PackUnpack
|
||||
# END Test testCoreStatus_Pack
|
||||
|
||||
|
||||
@pytest.mark.core
|
||||
def testCoreStatus_ShapeCache():
|
||||
"""Test the _ShapeCache class."""
|
||||
shapes = _ShapeCache()
|
||||
|
||||
# Generate all shapes
|
||||
square = shapes.getShape(nwStatusShape.SQUARE)
|
||||
circle = shapes.getShape(nwStatusShape.CIRCLE)
|
||||
triangle = shapes.getShape(nwStatusShape.TRIANGLE)
|
||||
diamond = shapes.getShape(nwStatusShape.DIAMOND)
|
||||
pentagon = shapes.getShape(nwStatusShape.PENTAGON)
|
||||
star = shapes.getShape(nwStatusShape.STAR)
|
||||
pacman = shapes.getShape(nwStatusShape.PACMAN)
|
||||
|
||||
# Request again should return from cache
|
||||
assert shapes.getShape(nwStatusShape.SQUARE) is square
|
||||
assert shapes.getShape(nwStatusShape.CIRCLE) is circle
|
||||
assert shapes.getShape(nwStatusShape.TRIANGLE) is triangle
|
||||
assert shapes.getShape(nwStatusShape.DIAMOND) is diamond
|
||||
assert shapes.getShape(nwStatusShape.PENTAGON) is pentagon
|
||||
assert shapes.getShape(nwStatusShape.STAR) is star
|
||||
assert shapes.getShape(nwStatusShape.PACMAN) is pacman
|
||||
|
||||
# END Test testCoreStatus_ShapeCache
|
||||
|
||||
Reference in New Issue
Block a user