@@ -794,6 +794,112 @@ test("Miniflare: getBindings() returns all bindings", async (t) => {
794794 } ;
795795 t . throws ( ( ) => bindings . KV . get ( "key" ) , expectations ) ;
796796} ) ;
797+ test ( "Miniflare: getWorker() allows dispatching events directly" , async ( t ) => {
798+ const mf = new Miniflare ( {
799+ modules : true ,
800+ script : `
801+ let lastScheduledController;
802+ let lastQueueBatch;
803+ export default {
804+ async fetch(request, env, ctx) {
805+ const { pathname } = new URL(request.url);
806+ if (pathname === "/scheduled") {
807+ return Response.json({
808+ scheduledTime: lastScheduledController?.scheduledTime,
809+ cron: lastScheduledController?.cron,
810+ });
811+ } else if (pathname === "/queue") {
812+ return Response.json({
813+ queue: lastQueueBatch.queue,
814+ messages: lastQueueBatch.messages.map((message) => ({
815+ id: message.id,
816+ timestamp: message.timestamp.getTime(),
817+ body: message.body,
818+ bodyType: message.body.constructor.name,
819+ })),
820+ });
821+ } else {
822+ return new Response(null, { status: 404 });
823+ }
824+ },
825+ async scheduled(controller, env, ctx) {
826+ lastScheduledController = controller;
827+ if (controller.cron === "* * * * *") controller.noRetry();
828+ },
829+ async queue(batch, env, ctx) {
830+ lastQueueBatch = batch;
831+ if (batch.queue === "needy") batch.retryAll();
832+ for (const message of batch.messages) {
833+ if (message.id === "perfect") message.ack();
834+ }
835+ }
836+ }` ,
837+ } ) ;
838+ t . teardown ( ( ) => mf . dispose ( ) ) ;
839+ const fetcher = await mf . getWorker ( ) ;
840+
841+ // Check `Fetcher#scheduled()` (implicitly testing `Fetcher#fetch()`)
842+ let scheduledResult = await fetcher . scheduled ( {
843+ cron : "* * * * *" ,
844+ } ) ;
845+ t . deepEqual ( scheduledResult , { outcome : "ok" , noRetry : true } ) ;
846+ scheduledResult = await fetcher . scheduled ( {
847+ scheduledTime : new Date ( 1000 ) ,
848+ cron : "30 * * * *" ,
849+ } ) ;
850+ t . deepEqual ( scheduledResult , { outcome : "ok" , noRetry : false } ) ;
851+
852+ let res = await fetcher . fetch ( "http://localhost/scheduled" ) ;
853+ const scheduledController = await res . json ( ) ;
854+ t . deepEqual ( scheduledController , {
855+ scheduledTime : 1000 ,
856+ cron : "30 * * * *" ,
857+ } ) ;
858+
859+ // Check `Fetcher#queue()`
860+ let queueResult = await fetcher . queue ( "needy" , [
861+ { id : "a" , timestamp : new Date ( 1000 ) , body : "a" } ,
862+ { id : "b" , timestamp : new Date ( 2000 ) , body : { b : 1 } } ,
863+ ] ) ;
864+ t . deepEqual ( queueResult , {
865+ outcome : "ok" ,
866+ retryAll : true ,
867+ ackAll : false ,
868+ explicitRetries : [ ] ,
869+ explicitAcks : [ ] ,
870+ } ) ;
871+ queueResult = await fetcher . queue ( "queue" , [
872+ { id : "c" , timestamp : new Date ( 3000 ) , body : new Uint8Array ( [ 1 , 2 , 3 ] ) } ,
873+ { id : "perfect" , timestamp : new Date ( 4000 ) , body : new Date ( 5000 ) } ,
874+ ] ) ;
875+ t . deepEqual ( queueResult , {
876+ outcome : "ok" ,
877+ retryAll : false ,
878+ ackAll : false ,
879+ explicitRetries : [ ] ,
880+ explicitAcks : [ "perfect" ] ,
881+ } ) ;
882+
883+ res = await fetcher . fetch ( "http://localhost/queue" ) ;
884+ const queueBatch = await res . json ( ) ;
885+ t . deepEqual ( queueBatch , {
886+ queue : "queue" ,
887+ messages : [
888+ {
889+ id : "c" ,
890+ timestamp : 3000 ,
891+ body : { 0 : 1 , 1 : 2 , 2 : 3 } ,
892+ bodyType : "Uint8Array" ,
893+ } ,
894+ {
895+ id : "perfect" ,
896+ timestamp : 4000 ,
897+ body : "1970-01-01T00:00:05.000Z" ,
898+ bodyType : "Date" ,
899+ } ,
900+ ] ,
901+ } ) ;
902+ } ) ;
797903test ( "Miniflare: getBindings() and friends return bindings for different workers" , async ( t ) => {
798904 const mf = new Miniflare ( {
799905 workers : [
@@ -802,7 +908,7 @@ test("Miniflare: getBindings() and friends return bindings for different workers
802908 modules : true ,
803909 script : `
804910 export class DurableObject {}
805- export default { fetch() { return new Response(null, { status: 404 } ); } }
911+ export default { fetch() { return new Response("a" ); } }
806912 ` ,
807913 d1Databases : [ "DB" ] ,
808914 durableObjects : { DO : "DurableObject" } ,
@@ -811,14 +917,14 @@ test("Miniflare: getBindings() and friends return bindings for different workers
811917 // 2nd worker unnamed, to validate that not specifying a name when
812918 // getting bindings gives the entrypoint, not the unnamed worker
813919 script :
814- 'addEventListener("fetch", (event) => event.respondWith(new Response(null, { status: 404 } )));' ,
920+ 'addEventListener("fetch", (event) => event.respondWith(new Response("unnamed" )));' ,
815921 kvNamespaces : [ "KV" ] ,
816922 queueProducers : [ "QUEUE" ] ,
817923 } ,
818924 {
819925 name : "b" ,
820926 script :
821- 'addEventListener("fetch", (event) => event.respondWith(new Response(null, { status: 404 } )));' ,
927+ 'addEventListener("fetch", (event) => event.respondWith(new Response("b" )));' ,
822928 r2Buckets : [ "BUCKET" ] ,
823929 } ,
824930 ] ,
@@ -837,6 +943,18 @@ test("Miniflare: getBindings() and friends return bindings for different workers
837943 message : '"c" worker not found' ,
838944 } ) ;
839945
946+ // Check `getWorker()`
947+ let fetcher = await mf . getWorker ( ) ;
948+ t . is ( await ( await fetcher . fetch ( "http://localhost" ) ) . text ( ) , "a" ) ;
949+ fetcher = await mf . getWorker ( "" ) ;
950+ t . is ( await ( await fetcher . fetch ( "http://localhost" ) ) . text ( ) , "unnamed" ) ;
951+ fetcher = await mf . getWorker ( "b" ) ;
952+ t . is ( await ( await fetcher . fetch ( "http://localhost" ) ) . text ( ) , "b" ) ;
953+ await t . throwsAsync ( ( ) => mf . getWorker ( "c" ) , {
954+ instanceOf : TypeError ,
955+ message : '"c" worker not found' ,
956+ } ) ;
957+
840958 const unboundExpectations = ( name : string ) : ThrowsExpectation < TypeError > => ( {
841959 instanceOf : TypeError ,
842960 message : `"${ name } " unbound in "c" worker` ,
0 commit comments