@@ -678,7 +678,7 @@ def test_list_taxonomies(self):
678678 @pytest .mark .migration
679679 def test_supported_tokens (self ):
680680 """Test supported tokens endpoint."""
681- self .assert_endpoint_equal ("eth/supported_tokens/ " )
681+ self .assert_endpoint_equal ("eth/supported_tokens" )
682682
683683
684684class TestSearchParameters (MigrationTestBase ):
@@ -1064,7 +1064,7 @@ def test_get_address_multi_currency(self, currency, address):
10641064 @pytest .mark .parametrize ("currency" , ["btc" , "eth" ])
10651065 def test_supported_tokens_multi_currency (self , currency ):
10661066 """Test supported_tokens across different currencies."""
1067- self .assert_endpoint_equal (f"{ currency } /supported_tokens/ " )
1067+ self .assert_endpoint_equal (f"{ currency } /supported_tokens" )
10681068
10691069
10701070class TestPagination (MigrationTestBase ):
@@ -1222,7 +1222,7 @@ def test_eth_tx_flows(self):
12221222 @pytest .mark .migration
12231223 def test_eth_supported_tokens (self ):
12241224 """Test ETH supported tokens with pagination."""
1225- self .assert_endpoint_equal ("eth/supported_tokens/ ?pagesize=10" )
1225+ self .assert_endpoint_equal ("eth/supported_tokens?pagesize=10" )
12261226
12271227
12281228class TestLinksEndpoints (MigrationTestBase ):
@@ -1468,12 +1468,12 @@ class TestMultipleCurrencies(MigrationTestBase):
14681468 @pytest .mark .parametrize ("currency" , ["btc" , "bch" , "ltc" , "zec" ])
14691469 def test_supported_tokens_utxo (self , currency ):
14701470 """Test supported tokens for UTXO chains."""
1471- self .assert_endpoint_equal (f"{ currency } /supported_tokens/ " )
1471+ self .assert_endpoint_equal (f"{ currency } /supported_tokens" )
14721472
14731473 @pytest .mark .migration
14741474 def test_trx_supported_tokens (self ):
14751475 """Test TRX supported tokens."""
1476- self .assert_endpoint_equal ("trx/supported_tokens/ " )
1476+ self .assert_endpoint_equal ("trx/supported_tokens" )
14771477
14781478
14791479class TestOnlyIdsFilter (MigrationTestBase ):
@@ -1634,6 +1634,49 @@ def test_eth_large_address_txs(self):
16341634 )
16351635
16361636
1637+ class TestRouteConventions :
1638+ """Tests for route definition conventions (no running servers needed)."""
1639+
1640+ def test_no_trailing_slashes_in_routes (self ):
1641+ """Ensure no routes have trailing slashes (causes 307 redirects)."""
1642+ from gsrest .routes import (
1643+ addresses ,
1644+ blocks ,
1645+ bulk ,
1646+ entities ,
1647+ general ,
1648+ rates ,
1649+ tags ,
1650+ tokens ,
1651+ txs ,
1652+ )
1653+
1654+ routers = [
1655+ ("addresses" , addresses .router ),
1656+ ("blocks" , blocks .router ),
1657+ ("bulk" , bulk .router ),
1658+ ("entities" , entities .router ),
1659+ ("general" , general .router ),
1660+ ("rates" , rates .router ),
1661+ ("tags" , tags .router ),
1662+ ("tokens" , tokens .router ),
1663+ ("txs" , txs .router ),
1664+ ]
1665+
1666+ violations = []
1667+ for module_name , router in routers :
1668+ for route in router .routes :
1669+ path = getattr (route , "path" , "" )
1670+ # Check for trailing slash (but "/" alone is fine)
1671+ if path != "/" and path .endswith ("/" ):
1672+ violations .append (f"{ module_name } : { path } " )
1673+
1674+ if violations :
1675+ msg = "Routes with trailing slashes found (causes 307 redirects):\n "
1676+ msg += "\n " .join (f" - { v } " for v in violations )
1677+ assert False , msg
1678+
1679+
16371680if __name__ == "__main__" :
16381681 # Quick manual test
16391682 check_servers_available ()
0 commit comments