"""Tests for netlist module: builder pattern, rendering, template functions.""" import pytest from mcp_ltspice.netlist import ( Netlist, buck_converter, colpitts_oscillator, common_emitter_amplifier, differential_amplifier, h_bridge, inverting_amplifier, ldo_regulator, non_inverting_amplifier, rc_lowpass, voltage_divider, ) class TestNetlistBuilder: def test_add_resistor(self): n = Netlist().add_resistor("R1", "in", "out", "10k") assert len(n.components) == 1 assert n.components[0].name == "R1" assert n.components[0].value == "10k" def test_add_capacitor(self): n = Netlist().add_capacitor("C1", "out", "0", "100n") assert len(n.components) == 1 assert n.components[0].value == "100n" def test_add_inductor(self): n = Netlist().add_inductor("L1", "a", "b", "10u", series_resistance="0.1") assert "Rser=0.1" in n.components[0].params def test_chaining(self): """Builder methods return self for chaining.""" n = ( Netlist("Test") .add_resistor("R1", "a", "b", "1k") .add_capacitor("C1", "b", "0", "1n") ) assert len(n.components) == 2 def test_add_voltage_source_dc(self): n = Netlist().add_voltage_source("V1", "in", "0", dc="5") assert "5" in n.components[0].value def test_add_voltage_source_ac(self): n = Netlist().add_voltage_source("V1", "in", "0", ac="1") assert "AC 1" in n.components[0].value def test_add_voltage_source_pulse(self): n = Netlist().add_voltage_source( "V1", "g", "0", pulse=("0", "5", "0", "1n", "1n", "5u", "10u") ) rendered = n.render() assert "PULSE(" in rendered def test_add_voltage_source_sin(self): n = Netlist().add_voltage_source( "V1", "in", "0", sin=("0", "1", "1k") ) rendered = n.render() assert "SIN(" in rendered def test_add_directive(self): n = Netlist().add_directive(".tran 10m") assert ".tran 10m" in n.directives def test_add_meas(self): n = Netlist().add_meas("tran", "vmax", "MAX V(out)") assert any("vmax" in d for d in n.directives) class TestNetlistRender: def test_render_contains_title(self): n = Netlist("My Circuit") text = n.render() assert "* My Circuit" in text def test_render_contains_components(self): n = ( Netlist() .add_resistor("R1", "in", "out", "10k") .add_capacitor("C1", "out", "0", "100n") ) text = n.render() assert "R1 in out 10k" in text assert "C1 out 0 100n" in text def test_render_contains_backanno_and_end(self): n = Netlist() text = n.render() assert ".backanno" in text assert ".end" in text def test_render_includes_directive(self): n = Netlist().add_directive(".ac dec 100 1 1meg") text = n.render() assert ".ac dec 100 1 1meg" in text def test_render_includes_comment(self): n = Netlist().add_comment("Test comment") text = n.render() assert "* Test comment" in text def test_render_includes_lib(self): n = Netlist().add_lib("LT1001") text = n.render() assert ".lib LT1001" in text class TestTemplateNetlists: """All template functions should return valid Netlist objects.""" @pytest.mark.parametrize( "factory", [ voltage_divider, rc_lowpass, inverting_amplifier, non_inverting_amplifier, differential_amplifier, common_emitter_amplifier, buck_converter, ldo_regulator, colpitts_oscillator, h_bridge, ], ) def test_template_returns_netlist(self, factory): n = factory() assert isinstance(n, Netlist) @pytest.mark.parametrize( "factory", [ voltage_divider, rc_lowpass, inverting_amplifier, non_inverting_amplifier, differential_amplifier, common_emitter_amplifier, buck_converter, ldo_regulator, colpitts_oscillator, h_bridge, ], ) def test_template_has_backanno_and_end(self, factory): text = factory().render() assert ".backanno" in text assert ".end" in text @pytest.mark.parametrize( "factory", [ voltage_divider, rc_lowpass, inverting_amplifier, non_inverting_amplifier, differential_amplifier, common_emitter_amplifier, buck_converter, ldo_regulator, colpitts_oscillator, h_bridge, ], ) def test_template_has_components(self, factory): n = factory() assert len(n.components) > 0 @pytest.mark.parametrize( "factory", [ voltage_divider, rc_lowpass, inverting_amplifier, non_inverting_amplifier, differential_amplifier, common_emitter_amplifier, buck_converter, ldo_regulator, colpitts_oscillator, h_bridge, ], ) def test_template_has_sim_directive(self, factory): n = factory() # Should have at least one directive starting with a sim type sim_types = [".tran", ".ac", ".dc", ".op", ".noise", ".tf"] text = n.render() assert any(sim in text.lower() for sim in sim_types), ( f"No simulation directive found in {factory.__name__}" )