function RCI(name=:RCI)
    model = BondGraph(name)
    C = Component(:C)
    R = Component(:R)
    I = Component(:I)
    SS = Component(:SS)
    zero_law = EqualEffort()

    add_node!(model, [C, R, I, SS, zero_law])
    connect!(model, R, zero_law)
    connect!(model, C, zero_law)
    connect!(model, zero_law, I)
    connect!(model, zero_law, SS)

    model
end

# Based on https://bondgraphtools.readthedocs.io/en/latest/tutorials/RC.html
@testset "BondGraph Construction" begin
    model = BondGraph(:RC)
    C = Component(:C)
    R = Component(:R)
    zero_law = EqualEffort()

    add_node!(model, [R, C, zero_law])
    @test R in model.nodes
    @test C in model.nodes
    @test zero_law in model.nodes

    b1 = connect!(model, R, zero_law)
    b2 = connect!(model, zero_law, C)
    @test b1 in model.bonds
    @test b2 in model.bonds
end

@testset "BondGraph Modification" begin
    model = BondGraph(:RCI)
    C = Component(:C)
    R = Component(:R)
    I = Component(:I)
    SS = Component(:SS)
    zero_law = EqualEffort()
    one_law = EqualFlow()

    add_node!(model, [C, R, I, SS, zero_law, one_law])
    remove_node!(model, [SS, one_law])
    @test !(SS in model.nodes)
    @test !(one_law in model.nodes)

    connect!(model, R, zero_law)
    connect!(model, C, zero_law)

    @test I.freeports == [true]
    b1 = connect!(model, zero_law, I)
    @test ne(model) == 3
    @test b1 in model.bonds
    @test I.freeports == [false]

    disconnect!(model, zero_law, I)
    @test ne(model) == 2
    @test !(b1 in model.bonds)
    @test I.freeports == [true]

    connect!(model, zero_law, I)
    swap!(model, zero_law, one_law)
    @test I.freeports == [false]
    @test one_law in model.nodes
    @test inneighbors(model, one_law) == [R, C]
    @test outneighbors(model, one_law) == [I]
end

@testset "Construction Failure" begin
    model = BondGraph(:RC)
    C = new(:C)
    R = new(:R)
    zero_law = EqualEffort()

    add_node!(model, [R, C, zero_law])
    @test_logs (:warn, "R:R already in model") add_node!(model, R)
    @test_logs (:warn, "0 already in model") add_node!(model, zero_law)

    connect!(model, R, zero_law)
    @test_throws ErrorException connect!(model, R, zero_law)
    @test_throws ErrorException connect!(model, C, R)

    one_law = EqualFlow()
    @test_logs (:warn, "1 not in model") remove_node!(model, one_law)

    tf = new(:TF)
    add_node!(model, tf)
    @test_throws ErrorException swap!(model, tf, C)
end

@testset "Chemical reaction" begin
    model = BondGraph(:Chemical)
    A = Component(:C, :A)
    B = Component(:C, :B)
    C = Component(:C, :C)
    D = Component(:C, :D)
    Re = Component(:Re, :Reaction, numports=2)
    J_AB = EqualFlow()
    J_CD = EqualFlow()

    add_node!(model, [A, B, C, D, Re, J_AB, J_CD])
    connect!(model, A, J_AB)
    connect!(model, B, J_AB)
    connect!(model, C, J_CD)
    connect!(model, D, J_CD)

    @test freeports(Re) == [true, true]
    @test freeports(J_AB) == [false, false]

    # Connecting junctions to specific ports in Re
    connect!(model, Re, J_CD, srcportindex=2)
    @test freeports(Re) == [true, false]

    # connecting to a full port should fail
    @test_throws ErrorException connect!(model, J_AB, Re, dstportindex=2)

    connect!(model, J_AB, Re, dstportindex=1)
    @test freeports(Re) == [false, false]

    @test nv(model) == 7
    @test ne(model) == 6
end

@testset "Standard components" begin
    tf = new(:TF,:n)
    @test tf isa Component{2}
    @test tf.type == :TF
    @test numports(tf) == 2

    r = new(:R)
    @test r isa Component{1}
    @test r.type == :R
end

@parameters t
D = Differential(t)

@testset "Equations" begin
    c = new(:C)
    @parameters C
    @variables E[1](t) F[1](t) q(t)
    @test cr(c) == [
        0 ~ q/C - E[1],
        D(q) ~ F[1]
    ]
end

@testset "Parameters" begin
    tf = new(:TF)
    @parameters r
    @test iszero(BondGraphs.params(tf) - [r])

    Ce = new(:Ce)
    @parameters k R T
    @test iszero(BondGraphs.params(Ce) - [k, R, T])

    Re = new(:Re)
    @parameters r R T
    @test iszero(BondGraphs.params(Re) - [r, R, T])
end

@testset "State variables" begin
    r = new(:R)
    @test isempty(BondGraphs.state_vars(r))

    @variables q(t)
    c = new(:C)
    @test isequal(BondGraphs.state_vars(c), [q])

    ce = new(:ce)
    @test isequal(BondGraphs.state_vars(c), [q])
end

@testset "Inserting Nodes" begin
    bg = RCI()

    c, r, 𝟎 = bg.nodes[[1,2,5]]

    bondc0 = getbonds(bg, c, 𝟎)[1]
    bondr0 = getbonds(bg, r, 𝟎)[1]

    tf = Component(:TF, numports=2)
    insert_node!(bg, bondc0, tf)
    insert_node!(bg, bondr0, EqualFlow())

    @test tf in bg.nodes
    @test nv(bg) == 7
    @test ne(bg) == 6
end

@testset "Merging components" begin
    bg = RCI()

    newC = Component(:C, :newC)
    newR = Component(:R, :newR)
    add_node!(bg, [newC, newR])
    connect!(bg, newC, newR)

    C = getnodes(bg, "C")[1]
    merge_nodes!(bg, C, newC)

    R = getnodes(bg, "R")[1]
    merge_nodes!(bg, R, newR; junction=EqualFlow())

    @test isempty(getnodes(bg, "newC"))
    @test length(getnodes(bg, "1")) == 1
    @test length(getnodes(bg, "0")) == 2
    @test nv(bg) == 7
    @test ne(bg) == 7
end

@testset "Simplifying Junctions" begin
    bg = RCI()
    C, R, I, SS, 𝟎 = bg.nodes

    J0_new_1 = EqualEffort(;name=:new0_1)
    J0_new_2 = EqualEffort(;name=:new0_2)
    insert_node!(bg, (C, 𝟎), J0_new_1)
    insert_node!(bg, (R, 𝟎), J0_new_2)
    connect!(bg, J0_new_1, J0_new_2)

    J1_new_1 = EqualFlow(;name=:new1_1)
    J1_new_2 = EqualFlow(;name=:new1_2)
    add_node!(bg, J1_new_1)
    connect!(bg, 𝟎, J1_new_1)
    insert_node!(bg, (SS, 𝟎), J1_new_2)

    # Removing junction redundancies
    simplify_junctions!(bg, squash_identical=false)
    @test length(getnodes(bg, "1")) == 0
    @test nv(bg) == 7
    @test ne(bg) == 7

    # Squashing junction duplicates into a single junction
    #simplify_junctions!(bg)
    @test_broken length(getnodes(bg, :𝟎)) == 1
    @test_broken nv(bg) == 5
    @test_broken ne(bg) == 4
end

@testset "BondGraphNodes" begin
    C = Component(:C)
    bg1 = BondGraph(:BG1)
    bg2 = BondGraph(:BG2)
    bg3 = BondGraph(:BG3)
    main = BondGraph(:Main)

    bgn1 = BondGraphNode(bg1)
    bgn2 = BondGraphNode(bg2)
    bgn3 = BondGraphNode(bg3)

    @test bgn1.bondgraph === bg1
    @test bgn1.type === :BG
    @test bgn1.name === bg1.name
    @test freeports(bgn1) == Bool[]

    add_node!(bg1, C)
    add_node!(bg2, bgn1)
    add_node!(bg3, bgn2)
    add_node!(main, bgn3)

    @test main.BG3.BG2.BG1.C === C
end

# @testset "Expose component" begin
    
# end

# @testset "Nested BondGraphs" begin
#     bg_1 = RCI("RCI_1")
#     bg_2 = RCI("RCI_2")
#     bgn_1 = BondGraphNode(bg_1)
#     bgn_2 = BondGraphNode(bg_2)

#     bg_main = BondGraph("BG_Main")

#     #add_node!(bg_main, [bgn_1, bgn_2])
#     #connect!(bg_main, bgn_1, bgn_2)

# end
