@@ -2,7 +2,7 @@ import { Backend } from 'fastly:backend';
2
2
import { CacheOverride } from 'fastly:cache-override' ;
3
3
import { allowDynamicBackends } from "fastly:experimental" ;
4
4
import { pass , assert , assertDoesNotThrow , assertThrows , assertRejects , assertResolves } from "./assertions.js" ;
5
- import { routes } from "./routes.js" ;
5
+ import { isRunningLocally , routes } from "./routes.js" ;
6
6
7
7
/// The backend name is already in use.
8
8
@@ -61,7 +61,7 @@ import { routes } from "./routes.js";
61
61
{
62
62
routes . set ( "/backend/interface" , async ( ) => {
63
63
let actual = Reflect . ownKeys ( Backend )
64
- let expected = [ "prototype" , "length" , "name" ]
64
+ let expected = [ "prototype" , "exists" , "fromName" , "health" , " length", "name" ]
65
65
let error = assert ( actual , expected , `Reflect.ownKeys(Backend)` )
66
66
if ( error ) { return error }
67
67
@@ -75,6 +75,60 @@ import { routes } from "./routes.js";
75
75
error = assert ( actual , expected , `Reflect.getOwnPropertyDescriptor(Backend, 'prototype')` )
76
76
if ( error ) { return error }
77
77
78
+ actual = Reflect . getOwnPropertyDescriptor ( Backend , 'exists' )
79
+ expected = {
80
+ "value" : Backend . exists ,
81
+ "writable" : true ,
82
+ "enumerable" : true ,
83
+ "configurable" : true
84
+ }
85
+ error = assert ( actual , expected , `Reflect.getOwnPropertyDescriptor(Backend, 'exists')` )
86
+ if ( error ) { return error }
87
+
88
+ error = assert ( typeof Backend . exists , 'function' , `typeof Backend.exists` )
89
+ if ( error ) { return error }
90
+
91
+ error = assert ( Backend . exists . length , 1 , `Backend.exists.length` )
92
+ if ( error ) { return error }
93
+ error = assert ( Backend . exists . name , "exists" , `Backend.exists.name` )
94
+ if ( error ) { return error }
95
+
96
+ actual = Reflect . getOwnPropertyDescriptor ( Backend , 'fromName' )
97
+ expected = {
98
+ "value" : Backend . fromName ,
99
+ "writable" : true ,
100
+ "enumerable" : true ,
101
+ "configurable" : true
102
+ }
103
+ error = assert ( actual , expected , `Reflect.getOwnPropertyDescriptor(Backend, 'fromName')` )
104
+ if ( error ) { return error }
105
+
106
+ error = assert ( typeof Backend . fromName , 'function' , `typeof Backend.fromName` )
107
+ if ( error ) { return error }
108
+
109
+ error = assert ( Backend . fromName . length , 1 , `Backend.fromName.length` )
110
+ if ( error ) { return error }
111
+ error = assert ( Backend . fromName . name , "fromName" , `Backend.fromName.name` )
112
+ if ( error ) { return error }
113
+
114
+ actual = Reflect . getOwnPropertyDescriptor ( Backend , 'health' )
115
+ expected = {
116
+ "value" : Backend . health ,
117
+ "writable" : true ,
118
+ "enumerable" : true ,
119
+ "configurable" : true
120
+ }
121
+ error = assert ( actual , expected , `Reflect.getOwnPropertyDescriptor(Backend, 'health')` )
122
+ if ( error ) { return error }
123
+
124
+ error = assert ( typeof Backend . health , 'function' , `typeof Backend.health` )
125
+ if ( error ) { return error }
126
+
127
+ error = assert ( Backend . health . length , 1 , `Backend.health.length` )
128
+ if ( error ) { return error }
129
+ error = assert ( Backend . health . name , "health" , `Backend.health.name` )
130
+ if ( error ) { return error }
131
+
78
132
actual = Reflect . getOwnPropertyDescriptor ( Backend , 'length' )
79
133
expected = {
80
134
"value" : 1 ,
@@ -96,7 +150,7 @@ import { routes } from "./routes.js";
96
150
if ( error ) { return error }
97
151
98
152
actual = Reflect . ownKeys ( Backend . prototype )
99
- expected = [ "constructor" , "toString" ]
153
+ expected = [ "constructor" , "toString" , "toName" ]
100
154
error = assert ( actual , expected , `Reflect.ownKeys(Backend.prototype)` )
101
155
if ( error ) { return error }
102
156
@@ -114,6 +168,8 @@ import { routes } from "./routes.js";
114
168
if ( error ) { return error }
115
169
error = assert ( typeof Backend . prototype . toString , 'function' , `typeof Backend.prototype.toString` )
116
170
if ( error ) { return error }
171
+ error = assert ( typeof Backend . prototype . toName , 'function' , `typeof Backend.prototype.toName` )
172
+ if ( error ) { return error }
117
173
118
174
actual = Reflect . getOwnPropertyDescriptor ( Backend . prototype . constructor , 'length' )
119
175
expected = {
@@ -155,6 +211,26 @@ import { routes } from "./routes.js";
155
211
error = assert ( actual , expected , `Reflect.getOwnPropertyDescriptor(Backend.prototype.toString, 'name')` )
156
212
if ( error ) { return error }
157
213
214
+ actual = Reflect . getOwnPropertyDescriptor ( Backend . prototype . toName , 'length' )
215
+ expected = {
216
+ "value" : 0 ,
217
+ "writable" : false ,
218
+ "enumerable" : false ,
219
+ "configurable" : true
220
+ }
221
+ error = assert ( actual , expected , `Reflect.getOwnPropertyDescriptor(Backend.prototype.toName, 'length')` )
222
+ if ( error ) { return error }
223
+
224
+ actual = Reflect . getOwnPropertyDescriptor ( Backend . prototype . toName , 'name' )
225
+ expected = {
226
+ "value" : "toName" ,
227
+ "writable" : false ,
228
+ "enumerable" : false ,
229
+ "configurable" : true
230
+ }
231
+ error = assert ( actual , expected , `Reflect.getOwnPropertyDescriptor(Backend.prototype.toName, 'name')` )
232
+ if ( error ) { return error }
233
+
158
234
return pass ( 'ok' )
159
235
} ) ;
160
236
@@ -1291,6 +1367,220 @@ import { routes } from "./routes.js";
1291
1367
} ) ;
1292
1368
}
1293
1369
}
1370
+
1371
+ // exists
1372
+ {
1373
+ routes . set ( "/backend/exists/called-as-constructor-function" , async ( ) => {
1374
+ let error = assertThrows ( ( ) => {
1375
+ new Backend . exists ( )
1376
+ } , TypeError , `Backend.exists is not a constructor` )
1377
+ if ( error ) { return error }
1378
+ return pass ( 'ok' )
1379
+ } ) ;
1380
+ routes . set ( "/backend/exists/empty-parameter" , async ( ) => {
1381
+ let error = assertThrows ( ( ) => {
1382
+ Backend . exists ( )
1383
+ } , TypeError , `Backend.exists: At least 1 argument required, but only 0 passed` )
1384
+ if ( error ) { return error }
1385
+ return pass ( 'ok' )
1386
+ } ) ;
1387
+ // https://tc39.es/ecma262/#sec-tostring
1388
+ routes . set ( "/backend/exists/parameter-calls-7.1.17-ToString" , async ( ) => {
1389
+ let sentinel ;
1390
+ const test = ( ) => {
1391
+ sentinel = Symbol ( ) ;
1392
+ const name = {
1393
+ toString ( ) {
1394
+ throw sentinel ;
1395
+ }
1396
+ }
1397
+ Backend . exists ( name )
1398
+ }
1399
+ let error = assertThrows ( test )
1400
+ if ( error ) { return error }
1401
+ try {
1402
+ test ( )
1403
+ } catch ( thrownError ) {
1404
+ let error = assert ( thrownError , sentinel , 'thrownError === sentinel' )
1405
+ if ( error ) { return error }
1406
+ }
1407
+ error = assertThrows ( ( ) => Backend . exists ( Symbol ( ) ) , TypeError , `can't convert symbol to string` )
1408
+ if ( error ) { return error }
1409
+ return pass ( 'ok' )
1410
+ } ) ;
1411
+
1412
+ routes . set ( "/backend/exists/parameter-invalid" , async ( ) => {
1413
+ // null
1414
+ let error = assertThrows ( ( ) => Backend . exists ( null ) , TypeError )
1415
+ if ( error ) { return error }
1416
+ // undefined
1417
+ error = assertThrows ( ( ) => Backend . exists ( undefined ) , TypeError )
1418
+ if ( error ) { return error }
1419
+ // .length > 254
1420
+ error = assertThrows ( ( ) => Backend . exists ( 'a' . repeat ( 255 ) ) , TypeError )
1421
+ if ( error ) { return error }
1422
+ // .length == 0
1423
+ error = assertThrows ( ( ) => Backend . exists ( '' ) , TypeError )
1424
+ if ( error ) { return error }
1425
+ return pass ( 'ok' )
1426
+ } ) ;
1427
+ routes . set ( "/backend/exists/happy-path-backend-exists" , async ( ) => {
1428
+ let error = assert ( Backend . exists ( 'TheOrigin' ) , true , `Backend.exists('TheOrigin')` )
1429
+ if ( error ) { return error }
1430
+ return pass ( 'ok' )
1431
+ } ) ;
1432
+ routes . set ( "/backend/exists/happy-path-backend-does-not-exist" , async ( ) => {
1433
+ let error = assert ( Backend . exists ( 'meow' ) , false , `Backend.exists('meow')` )
1434
+ if ( error ) { return error }
1435
+ return pass ( 'ok' )
1436
+ } ) ;
1437
+ }
1438
+
1439
+ // fromName
1440
+ {
1441
+ routes . set ( "/backend/fromName/called-as-constructor-function" , async ( ) => {
1442
+ let error = assertThrows ( ( ) => {
1443
+ new Backend . fromName ( )
1444
+ } , TypeError , `Backend.fromName is not a constructor` )
1445
+ if ( error ) { return error }
1446
+ return pass ( 'ok' )
1447
+ } ) ;
1448
+ routes . set ( "/backend/fromName/empty-parameter" , async ( ) => {
1449
+ let error = assertThrows ( ( ) => {
1450
+ Backend . fromName ( )
1451
+ } , TypeError , `Backend.fromName: At least 1 argument required, but only 0 passed` )
1452
+ if ( error ) { return error }
1453
+ return pass ( 'ok' )
1454
+ } ) ;
1455
+ // https://tc39.es/ecma262/#sec-tostring
1456
+ routes . set ( "/backend/fromName/parameter-calls-7.1.17-ToString" , async ( ) => {
1457
+ let sentinel ;
1458
+ const test = ( ) => {
1459
+ sentinel = Symbol ( ) ;
1460
+ const name = {
1461
+ toString ( ) {
1462
+ throw sentinel ;
1463
+ }
1464
+ }
1465
+ Backend . fromName ( name )
1466
+ }
1467
+ let error = assertThrows ( test )
1468
+ if ( error ) { return error }
1469
+ try {
1470
+ test ( )
1471
+ } catch ( thrownError ) {
1472
+ let error = assert ( thrownError , sentinel , 'thrownError === sentinel' )
1473
+ if ( error ) { return error }
1474
+ }
1475
+ error = assertThrows ( ( ) => Backend . fromName ( Symbol ( ) ) , TypeError , `can't convert symbol to string` )
1476
+ if ( error ) { return error }
1477
+ return pass ( 'ok' )
1478
+ } ) ;
1479
+
1480
+ routes . set ( "/backend/fromName/parameter-invalid" , async ( ) => {
1481
+ // null
1482
+ let error = assertThrows ( ( ) => Backend . fromName ( null ) , TypeError )
1483
+ if ( error ) { return error }
1484
+ // undefined
1485
+ error = assertThrows ( ( ) => Backend . fromName ( undefined ) , TypeError )
1486
+ if ( error ) { return error }
1487
+ // .length > 254
1488
+ error = assertThrows ( ( ) => Backend . fromName ( 'a' . repeat ( 255 ) ) , TypeError )
1489
+ if ( error ) { return error }
1490
+ // .length == 0
1491
+ error = assertThrows ( ( ) => Backend . fromName ( '' ) , TypeError )
1492
+ if ( error ) { return error }
1493
+ return pass ( 'ok' )
1494
+ } ) ;
1495
+ routes . set ( "/backend/fromName/happy-path-backend-exists" , async ( ) => {
1496
+ allowDynamicBackends ( false ) ;
1497
+ let error = assert ( Backend . fromName ( 'TheOrigin' ) instanceof Backend , true , `Backend.fromName('TheOrigin') instanceof Backend` )
1498
+ if ( error ) { return error }
1499
+
1500
+ error = await assertResolves ( ( ) => fetch ( 'https://http-me.glitch.me/headers' , {
1501
+ backend : Backend . fromName ( 'TheOrigin' ) ,
1502
+ } ) ) ;
1503
+ if ( error ) { return error }
1504
+
1505
+ return pass ( 'ok' )
1506
+ } ) ;
1507
+ routes . set ( "/backend/fromName/happy-path-backend-does-not-exist" , async ( ) => {
1508
+ let error = assertThrows ( ( ) => Backend . fromName ( 'meow' ) , Error , "Backend.fromName: backend named 'meow' does not exist" )
1509
+ if ( error ) { return error }
1510
+ return pass ( 'ok' )
1511
+ } ) ;
1512
+ }
1513
+
1514
+ // health
1515
+ {
1516
+ routes . set ( "/backend/health/called-as-constructor-function" , async ( ) => {
1517
+ let error = assertThrows ( ( ) => {
1518
+ new Backend . health ( )
1519
+ } , TypeError , `Backend.health is not a constructor` )
1520
+ if ( error ) { return error }
1521
+ return pass ( 'ok' )
1522
+ } ) ;
1523
+ routes . set ( "/backend/health/empty-parameter" , async ( ) => {
1524
+ let error = assertThrows ( ( ) => {
1525
+ Backend . health ( )
1526
+ } , TypeError , `Backend.health: At least 1 argument required, but only 0 passed` )
1527
+ if ( error ) { return error }
1528
+ return pass ( 'ok' )
1529
+ } ) ;
1530
+ // https://tc39.es/ecma262/#sec-tostring
1531
+ routes . set ( "/backend/health/parameter-calls-7.1.17-ToString" , async ( ) => {
1532
+ let sentinel ;
1533
+ const test = ( ) => {
1534
+ sentinel = Symbol ( ) ;
1535
+ const name = {
1536
+ toString ( ) {
1537
+ throw sentinel ;
1538
+ }
1539
+ }
1540
+ Backend . health ( name )
1541
+ }
1542
+ let error = assertThrows ( test )
1543
+ if ( error ) { return error }
1544
+ try {
1545
+ test ( )
1546
+ } catch ( thrownError ) {
1547
+ let error = assert ( thrownError , sentinel , 'thrownError === sentinel' )
1548
+ if ( error ) { return error }
1549
+ }
1550
+ error = assertThrows ( ( ) => Backend . health ( Symbol ( ) ) , TypeError , `can't convert symbol to string` )
1551
+ if ( error ) { return error }
1552
+ return pass ( 'ok' )
1553
+ } ) ;
1554
+
1555
+ routes . set ( "/backend/health/parameter-invalid" , async ( ) => {
1556
+ // null
1557
+ let error = assertThrows ( ( ) => Backend . health ( null ) , TypeError )
1558
+ if ( error ) { return error }
1559
+ // undefined
1560
+ error = assertThrows ( ( ) => Backend . health ( undefined ) , TypeError )
1561
+ if ( error ) { return error }
1562
+ // .length > 254
1563
+ error = assertThrows ( ( ) => Backend . health ( 'a' . repeat ( 255 ) ) , TypeError )
1564
+ if ( error ) { return error }
1565
+ // .length == 0
1566
+ error = assertThrows ( ( ) => Backend . health ( '' ) , TypeError )
1567
+ if ( error ) { return error }
1568
+ return pass ( 'ok' )
1569
+ } ) ;
1570
+ routes . set ( "/backend/health/happy-path-backend-exists" , async ( ) => {
1571
+ let error = assert ( typeof Backend . health ( 'TheOrigin' ) , 'string' , "typeof Backend.health('TheOrigin')" ) ;
1572
+ if ( error ) { return error }
1573
+ error = assert ( Backend . health ( 'TheOrigin' ) , 'unknown' , "Backend.health('TheOrigin')" ) ;
1574
+ if ( error ) { return error }
1575
+
1576
+ return pass ( 'ok' )
1577
+ } ) ;
1578
+ routes . set ( "/backend/health/happy-path-backend-does-not-exist" , async ( ) => {
1579
+ let error = assertThrows ( ( ) => Backend . health ( 'meow' ) , Error , "Backend.health: backend named 'meow' does not exist" )
1580
+ if ( error ) { return error }
1581
+ return pass ( 'ok' )
1582
+ } ) ;
1583
+ }
1294
1584
}
1295
1585
1296
1586
function createValidHttpMeBackend ( ) {
0 commit comments