Skip to content

Commit ce2e98c

Browse files
committed
feat: add tests for curly_vector function to validate handling of Matplotlib-style aliases and conflicting parameters
1 parent 8af1b45 commit ce2e98c

File tree

1 file changed

+107
-0
lines changed

1 file changed

+107
-0
lines changed

tests/test_plot_modplot.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,40 @@ def test_curly_vector_accepts_quiver_pivot_alias(
219219

220220
plt.close(fig)
221221

222+
@patch("skyborn.plot.vector_plot._curly_vector_ncl")
223+
def test_curly_vector_accepts_quiver_style_aliases(
224+
self, mock_ncl_curly, sample_vector_field
225+
):
226+
"""Matplotlib-style aliases should resolve onto canonical kwargs."""
227+
x, y, u, v = sample_vector_field
228+
color_field = np.hypot(u, v)
229+
mock_ncl_curly.return_value = Mock(spec=CurlyVectorPlotSet)
230+
fig, ax = plt.subplots(figsize=(6, 4))
231+
232+
curly_vector(
233+
ax,
234+
x,
235+
y,
236+
u,
237+
v,
238+
c=color_field,
239+
linewidths=2.5,
240+
facecolors="gold",
241+
edgecolors="navy",
242+
vmin=0.1,
243+
vmax=1.2,
244+
)
245+
246+
kwargs = mock_ncl_curly.call_args.kwargs
247+
np.testing.assert_allclose(kwargs["color"], color_field)
248+
assert kwargs["linewidth"] == pytest.approx(2.5)
249+
assert kwargs["facecolor"] == "gold"
250+
assert kwargs["edgecolor"] == "navy"
251+
assert kwargs["vmin"] == pytest.approx(0.1)
252+
assert kwargs["vmax"] == pytest.approx(1.2)
253+
254+
plt.close(fig)
255+
222256
def test_curly_vector_rejects_conflicting_anchor_and_pivot(
223257
self, sample_vector_field
224258
):
@@ -231,6 +265,55 @@ def test_curly_vector_rejects_conflicting_anchor_and_pivot(
231265

232266
plt.close(fig)
233267

268+
@pytest.mark.parametrize(
269+
("kwargs", "message"),
270+
[
271+
({"color": "k", "c": "r"}, "Use only one of 'c' or 'color'"),
272+
(
273+
{"linewidth": 1.0, "linewidths": 2.0},
274+
"Use only one of 'linewidth' or 'linewidths'",
275+
),
276+
(
277+
{"facecolor": "gold", "facecolors": "orange"},
278+
"Use only one of 'facecolor' or 'facecolors'",
279+
),
280+
(
281+
{"edgecolor": "k", "edgecolors": "face"},
282+
"Use only one of 'edgecolor' or 'edgecolors'",
283+
),
284+
],
285+
)
286+
def test_curly_vector_rejects_conflicting_style_aliases(
287+
self, sample_vector_field, kwargs, message
288+
):
289+
"""Conflicting singular/plural style aliases should fail fast."""
290+
x, y, u, v = sample_vector_field
291+
fig, ax = plt.subplots(figsize=(6, 4))
292+
293+
with pytest.raises(ValueError, match=message):
294+
curly_vector(ax, x, y, u, v, **kwargs)
295+
296+
plt.close(fig)
297+
298+
def test_curly_vector_rejects_norm_with_vmin_vmax(self, sample_vector_field):
299+
"""Matplotlib-style normalization inputs should not be ambiguous."""
300+
x, y, u, v = sample_vector_field
301+
fig, ax = plt.subplots(figsize=(6, 4))
302+
303+
with pytest.raises(ValueError, match="Use only one of 'norm' or 'vmin'/'vmax'"):
304+
curly_vector(
305+
ax,
306+
x,
307+
y,
308+
u,
309+
v,
310+
c=np.hypot(u, v),
311+
norm=mcolors.Normalize(0.0, 1.0),
312+
vmin=0.0,
313+
)
314+
315+
plt.close(fig)
316+
234317
def test_curly_vector_open_arrowstyle_uses_open_heads(self, sample_vector_field):
235318
"""Test that ``arrowstyle='->'`` uses open line heads."""
236319
x, y, u, v = sample_vector_field
@@ -252,6 +335,30 @@ def test_curly_vector_open_arrowstyle_uses_open_heads(self, sample_vector_field)
252335

253336
plt.close(fig)
254337

338+
def test_curly_vector_edgecolors_face_matches_facecolor(self, sample_vector_field):
339+
"""Filled heads should accept ``edgecolors='face'`` like Matplotlib."""
340+
x, y, u, v = sample_vector_field
341+
fig, ax = plt.subplots(figsize=(6, 4))
342+
343+
result = curly_vector(
344+
ax,
345+
x,
346+
y,
347+
u,
348+
v,
349+
arrowstyle="-|>",
350+
density=0.8,
351+
facecolors="gold",
352+
edgecolors="face",
353+
)
354+
355+
assert result.arrows
356+
face_rgba = np.asarray(result.arrows[0].get_facecolor())
357+
edge_rgba = np.asarray(result.arrows[0].get_edgecolor())
358+
np.testing.assert_allclose(face_rgba, edge_rgba)
359+
360+
plt.close(fig)
361+
255362
def test_curly_vector_filled_arrowstyle_creates_arrow_paths(
256363
self, sample_vector_field
257364
):

0 commit comments

Comments
 (0)