1+ 'use strict' ;
2+
3+ const test = require ( 'tap' ) . test ;
4+ const os = require ( 'os' ) ;
5+
6+ test ( 'network interface display handles both string and numeric family values' , ( t ) => {
7+ t . plan ( 4 ) ;
8+
9+ // Store original function to restore later
10+ const originalNetworkInterfaces = os . networkInterfaces ;
11+
12+ // Mock data with string family values (Node < 18)
13+ const mockInterfacesString = {
14+ 'eth0' : [
15+ { family : 'IPv4' , address : '192.168.1.100' , internal : false } ,
16+ { family : 'IPv6' , address : '::1' , internal : false }
17+ ] ,
18+ 'lo' : [
19+ { family : 'IPv4' , address : '127.0.0.1' , internal : true }
20+ ]
21+ } ;
22+
23+ // Mock data with numeric family values (Node >= 18)
24+ const mockInterfacesNumeric = {
25+ 'eth0' : [
26+ { family : 4 , address : '192.168.1.100' , internal : false } ,
27+ { family : 6 , address : '::1' , internal : false }
28+ ] ,
29+ 'lo' : [
30+ { family : 4 , address : '127.0.0.1' , internal : true }
31+ ]
32+ } ;
33+
34+ // Test the logic that filters IPv4 interfaces (extracted from bin/http-server)
35+ function getIPv4Addresses ( interfaces ) {
36+ const addresses = [ ] ;
37+ Object . keys ( interfaces ) . forEach ( function ( dev ) {
38+ interfaces [ dev ] . forEach ( function ( details ) {
39+ // This is the fix: handle both string and numeric family values
40+ if ( details . family === 'IPv4' || details . family === 4 ) {
41+ addresses . push ( details . address ) ;
42+ }
43+ } ) ;
44+ } ) ;
45+ return addresses ;
46+ }
47+
48+ // Test with string family values
49+ let addresses = getIPv4Addresses ( mockInterfacesString ) ;
50+ t . equal ( addresses . length , 2 , 'Should find 2 IPv4 addresses with string family' ) ;
51+ t . ok ( addresses . includes ( '192.168.1.100' ) , 'Should include external IPv4 address' ) ;
52+
53+ // Test with numeric family values
54+ addresses = getIPv4Addresses ( mockInterfacesNumeric ) ;
55+ t . equal ( addresses . length , 2 , 'Should find 2 IPv4 addresses with numeric family' ) ;
56+ t . ok ( addresses . includes ( '192.168.1.100' ) , 'Should include external IPv4 address' ) ;
57+
58+ // Restore original function
59+ os . networkInterfaces = originalNetworkInterfaces ;
60+ } ) ;
61+
62+ test ( 'network interface filtering excludes IPv6 link-local addresses' , ( t ) => {
63+ t . plan ( 2 ) ;
64+
65+ const mockInterfaces = {
66+ 'eth0' : [
67+ { family : 4 , address : '192.168.1.100' , internal : false } ,
68+ { family : 6 , address : '2001:db8::1' , internal : false } ,
69+ { family : 6 , address : 'fe80::1' , internal : false } // link-local, should be excluded
70+ ]
71+ } ;
72+
73+ // Extract the IPv6 filtering logic from bin/http-server
74+ const ipv6Addresses = [ ] ;
75+ const ipv4Addresses = [ ] ;
76+
77+ Object . keys ( mockInterfaces ) . forEach ( function ( dev ) {
78+ mockInterfaces [ dev ] . forEach ( function ( details ) {
79+ if ( details . family === 'IPv4' || details . family === 4 ) {
80+ ipv4Addresses . push ( details . address ) ;
81+ }
82+ if ( ( details . family === 'IPv6' || details . family === 6 ) &&
83+ ! details . address . startsWith ( "fe80" ) ) {
84+ ipv6Addresses . push ( details . address ) ;
85+ }
86+ } ) ;
87+ } ) ;
88+
89+ t . equal ( ipv4Addresses . length , 1 , 'Should find 1 IPv4 address' ) ;
90+ t . equal ( ipv6Addresses . length , 1 , 'Should find 1 non-link-local IPv6 address' ) ;
91+ } ) ;
0 commit comments