cloudflare / wrangler-legacy

🤠 Home to Wrangler v1 (deprecated)
https://workers.cloudflare.com
Apache License 2.0
3.2k stars 335 forks source link

Implement local testing #1026

Closed Cherry closed 2 years ago

Cherry commented 4 years ago

Wrangler is awesome, but it'd be fantastic if we were able to locally test Workers without the need for an internet connection, etc. or without having to constantly upload to Cloudflare.

https://github.com/dollarshaveclub/cloudworker is generally great for testing Workers locally, but unfortunately is no longer actively maintained, is missing functionality that makes Cloudflare Workers go great, like HTMLRewriter, and is looking for volunteers. It seems Cloudflare are pretty familiar with the project already, as there's a blog post detailing Unit Testing Worker Functions.

Cloudflare wrote about Unit Testing Workers in Cloudflare Workers last year too, and commented:

Even though Cloudflare Workers deploy globally within seconds, software developers often choose to use local mock environments to have the fastest possible feedback loop while developing on their local machines. CloudWorker is perfect for this use case but as it is still a mock environment it does not guarantee an identical runtime or environment with all Cloudflare Worker APIs and features. This gap can make developers uneasy as they do not have 100% certainty that their tests will succeed in the production environment.

I think something that can "guarantee an identical runtime or environment with all Cloudflare Worker APIs and features" or at least as near-to as possible would greatly improve adoption of Workers.

I think it would be a fantastic opportunity for Cloudflare to maintain cloudworker, or even implement it directly into wrangler. Having a go-to and maintained solution for testing Workers locally that was up to date with the latest available features would be so useful.

xtuc commented 4 years ago

I agree that it's not ideal.

cloudworker not being maintenaned is news to me, and that it's pretty bad given that's the only way we give to user to unit test...

Once we have https://github.com/cloudflare/lol-html/issues/38 implemented (which is WIP), someone integrate it into cloudworker to have the real HTMLRewriter. (I also commented into the issue you linked).

I think something that can "guarantee an identical runtime or environment with all Cloudflare Worker APIs and features" or at least as near-to as possible would greatly improve adoption of Workers.

We have discussions internally. I doubt that we can guarantee that with something like cloudworker .

faun commented 4 years ago

@defjosiah Suggested a mock HTMLRewriter workaround here: https://github.com/cloudflare/wrangler/issues/1047#issuecomment-610074742

faun commented 4 years ago

We ended up generating a Cloudflare worker in the before block of our integration test suite and then sending the correct cookie authentication headers with each request: https://gist.github.com/faun/cdd68a828cf9de3200e280e177348e9e

EverlastingBugstopper commented 4 years ago

Hey @faun - you can use wrangler dev to achieve functional parity with the integration tests you have written, but it's important to note that there are a few important differences between cloudflareworkers.com and real workers. The biggest differences are that CPU limits are not enforced and request.cf is undefined, but there are other differences as well. When wrangler dev is out of beta you'll be able to run integration tests on localhost (though wrangler will still be connecting to Cloudflare's servers)

coreybutler commented 4 years ago

UPDATE (4/4/21): There was interest. The repo is available at https://github.com/author/cfw

In case anyone is interested.... I have been working on an update to the DSC cloudworker. Frankly, I didn't know about wrangler dev until I was a ways into it. I was planning to simply use it for my own purposes. However; if there is interest, I'd be willing to share the code. I have zero intention of maintaining it though (I already have more OSS projects than I can maintain). That said, I used my own CLI libs, which I do intend to support (a more formal announcement about this will come at OpenJS World in June). author/shell is the basis of it. Of course, this could be swapped out for something else too.

Here's what makes my version different:

  1. Uses modern ES Module syntax.
  2. Tracks compute time & logs the time (green < 10ms, yellow <50ms, red >50ms)
  3. It's sort of capable of tracking memory usage. I've implemented the experimental vm.measureMemory(). Color-coded warnings are built-in at various levels of memory consumption.*
  4. Implements a better reloader (seems quite a bit faster than wrangler)**
  5. Supports custom headers, allowing devs to add headers that may not be baked in (like the CF IP Country header).
  6. Supports KV expiring keys and the KV list method.
  7. Supports multiple KV persistence files.
  8. Experimental KV API support.***
  9. It's not tested, but would likely pass the original project's unit tests since it was mostly a refactor job with a few additions.

* The memory measurement is experimental in Node 14.0.0. The upgrade to V8 8.1 caused a silent failure, but it has been patched and should be in the next patch update. This tool has logic to only use the feature when it works.

** The original cloudworker leverages Node's watch feature, a native feature which has always had a bunch of duplication issues (amongst others). I implemented it with Chokidar instead. However; the performance gains are achieved by not restarting the HTTP server. Instead, the vm context is reloaded dynamically, so there is no reboot at all.

*** I added an HTTP router and a few endpoints for managing the KV store (i.e mimicking the KV REST API). It's only partially complete., but it is currently possible to interact with the KV store files in realtime (making them accessible to the worker).

image

Contrived Example Worker.js

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

async function handleRequest (request) {
  const headers = new Map(request.headers)
  console.log(headers)

  let result = await mykv.get('test')
  if (result === null) {
    await mykv.put('test', 'blah', { expirationTtl: 60 })
  }

  console.log(await mykv.get('test'))
  setTimeout(async () => {
    console.log('A record should have expired and null should print below this.')
    console.log(await mykv.get('test'))
  }, 61000)
  // await mykv.delete('test')
  // console.log(await mykv.get('test'))
  // for (let i = 0; i < 100; i++) {
  //   await mykv.put(`example_${i+1}`, (i+1).toString())
  // }
  console.log(await mykv.get('a'))
  console.log(await mykv.list({ limit: 10 }))
  console.log(await mykv.list({ limit: 10, cursor: 10 }))
  return new Response('Unsupported Source', { status: 501 })
}

Console Output

I took this screenshot after waiting a minute, to highlight how KV items are expired.

image

Response

image

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 4 years ago

This issue has been automatically closed because it has not had recent activity. You may re-open the issue if it is still relevant.

nhoughto commented 4 years ago

Yeah worth calling out that wrangler dev won't ever be a replacement for https://github.com/dollarshaveclub/cloudworker while it has a the cloud dependency, in my example the constraint of only being able to fetch() public interface facing URLs is a non-starter for CI/testing uses, as none of the endpoints it might hit are public!

Cherry commented 3 years ago

Further discussion in https://github.com/cloudflare/wrangler/issues/1823. Stalebot caught this one. 😅

jdanyow commented 3 years ago

I maintain @cfworker/dev which supports the HTMLRewriter, and has an --inspect flag to enable using the chrome dev tools to set breakpoints, watches, use the network tab, etc. https://github.com/author/cfw seems to be nicer- plus it's compatible with wrangler config.

stale[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity in the last 180 days. It will be closed if no further activity occurs in the next week. Please feel free to comment if you'd like it to remain open, and thank you for your contributions.

Cherry commented 2 years ago

Going to close this now that we have Miniflare as an official solution, and work moving forward with wrangler2 and a local dev environment.

Excited for the future of Workers!