Skip to content

Commit 1ed92a9

Browse files
authored
test(plugin-cloudflare-workers): add cloudflare e2e tests (#2646)
* test(plugin-cloudflare-workers): add e2e test fixture and feature * ci(plugin-cloudflare-workers): add CI pipeline * ci(plugin-cloudflare-workers): apply code review suggestions
1 parent db3484d commit 1ed92a9

16 files changed

Lines changed: 11373 additions & 0 deletions

File tree

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
steps:
2+
3+
- group: ":cloudflare: Cloudflare Worker Tests"
4+
steps:
5+
- label: ":cloudflare: Cloudflare Worker tests"
6+
timeout_in_minutes: 15
7+
agents:
8+
queue: macos-15-isolated
9+
env:
10+
NODE_VERSION: "22"
11+
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "1"
12+
VERBOSE: "1"
13+
commands:
14+
- "cd test/cloudflare-workers"
15+
- "bundle install"
16+
- "bundle exec maze-runner"
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
steps:
2+
- block: "Trigger Cloudflare Workers pipeline"
3+
key: "trigger-cloudflare-pipeline"
4+
5+
- label: ":pipeline: Upload Cloudflare Workers pipeline"
6+
depends_on: "trigger-cloudflare-pipeline"
7+
agents:
8+
queue: macos
9+
timeout_in_minutes: 5
10+
command: buildkite-agent pipeline upload .buildkite/basic/cloudflare-pipeline.yml

.buildkite/package_manifest.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,5 +147,30 @@
147147
"pipeline": ".buildkite/basic/expo-pipeline.yml",
148148
"block": ".buildkite/block/expo-pipeline.block.yml",
149149
"paths": []
150+
},
151+
{
152+
"pipeline": ".buildkite/basic/cloudflare-pipeline.yml",
153+
"block": ".buildkite/block/cloudflare-pipeline.block.yml",
154+
"paths": [
155+
"test/cloudflare-workers",
156+
"packages/core",
157+
"packages/node",
158+
"packages/delivery-node",
159+
"packages/plugin-app-duration",
160+
"packages/plugin-console-breadcrumbs",
161+
"packages/plugin-contextualize",
162+
"packages/plugin-intercept",
163+
"packages/plugin-node-device",
164+
"packages/plugin-node-in-project",
165+
"packages/plugin-node-surrounding-code",
166+
"packages/plugin-node-uncaught-exception",
167+
"packages/plugin-node-unhandled-rejection",
168+
"packages/plugin-server-session",
169+
"packages/plugin-stackframe-path-normaliser",
170+
"packages/plugin-strip-project-root",
171+
"packages/plugin-cloudflare-workers",
172+
"packages/plugin-browser-session",
173+
"packages/in-flight"
174+
]
150175
}
151176
]

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ packages/**/fixtures
1010
test/browser
1111
test/node
1212
test/react-native-cli/features/fixtures
13+
test/cloudflare-workers

test/cloudflare-workers/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules/
2+
.wrangler/
3+
.tgz
4+
package-lock.json
5+
/Gemfile.lock

test/cloudflare-workers/Gemfile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
source 'https://rubygems.org'
2+
3+
gem 'bugsnag-maze-runner', '~>10.0'
4+
5+
# Use a branch of Maze Runner
6+
# gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner', branch: 'tms/use-maze-check'
7+
8+
# Locally, you can run against Maze Runner branches and uncommitted changes:
9+
#gem 'bugsnag-maze-runner', path: '../../../maze-runner'
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
Feature: @bugsnag/plugin-cloudflare-workers
2+
3+
Scenario: A handled error
4+
When I start the worker "cloudflare-worker"
5+
And I wait for the host "localhost" to open port "8787"
6+
Then I open the URL "http://localhost:8787/handled?a=1&b=2" and get a 200 response with body "Hello World!"
7+
8+
Then I wait to receive a session
9+
And the session is valid for the session reporting API version "1" for the "Bugsnag Node" notifier
10+
11+
Then I wait to receive an error
12+
Then the error is valid for the error reporting API version "4" for the "Bugsnag Node" notifier
13+
And the event "unhandled" is false
14+
And the event "severity" equals "warning"
15+
And the exception "errorClass" equals "Error"
16+
And the exception "message" equals "handled"
17+
And the exception "type" equals "nodejs"
18+
And the "file" of stack frame 0 matches "index.js"
19+
And the event "request.url" equals "http://localhost:8787/handled?a=1&b=2"
20+
And the event "request.httpMethod" equals "GET"
21+
And the event "request.clientIp" is not null
22+
And the event "request.headers" is not null
23+
And the event "metaData.request.path" equals "/handled"
24+
And the event "metaData.request.query.a" equals "1"
25+
And the event "metaData.request.query.b" equals "2"
26+
27+
Scenario: An unhandled error
28+
When I start the worker "cloudflare-worker"
29+
And I wait for the host "localhost" to open port "8787"
30+
Then I open the URL "http://localhost:8787/unhandled?a=1&b=2" and get a 500 response
31+
32+
Then I wait to receive a session
33+
And the session is valid for the session reporting API version "1" for the "Bugsnag Node" notifier
34+
35+
Then I wait to receive an error
36+
Then the error is valid for the error reporting API version "4" for the "Bugsnag Node" notifier
37+
And the event "unhandled" is true
38+
And the event "severity" equals "error"
39+
And the exception "errorClass" equals "Error"
40+
And the exception "message" equals "unhandled"
41+
And the exception "type" equals "nodejs"
42+
And the "file" of stack frame 0 matches "index.js"
43+
And the event "request.url" equals "http://localhost:8787/unhandled?a=1&b=2"
44+
And the event "request.httpMethod" equals "GET"
45+
And the event "request.clientIp" is not null
46+
And the event "request.headers" is not null
47+
And the event "metaData.request.path" equals "/unhandled"
48+
And the event "metaData.request.query.a" equals "1"
49+
And the event "metaData.request.query.b" equals "2"
50+
51+
Scenario: Metadata from one request do not appear in another
52+
When I start the worker "cloudflare-worker"
53+
And I wait for the host "localhost" to open port "8787"
54+
Then I open the URL "http://localhost:8787/metadata_a" and get a 200 response with body "Hello World!"
55+
56+
Then I wait to receive a session
57+
And the session is valid for the session reporting API version "1" for the "Bugsnag Node" notifier
58+
59+
Then I wait to receive an error
60+
Then the error is valid for the error reporting API version "4" for the "Bugsnag Node" notifier
61+
And the event "unhandled" is false
62+
And the event "severity" equals "warning"
63+
And the exception "errorClass" equals "Error"
64+
And the exception "message" equals "Metadata A Error"
65+
And the exception "type" equals "nodejs"
66+
And the "file" of stack frame 0 matches "index.js"
67+
And the event "request.url" equals "http://localhost:8787/metadata_a"
68+
And the event "request.httpMethod" equals "GET"
69+
And the event "request.clientIp" is not null
70+
And the event "request.headers" is not null
71+
And the event "metaData.request.path" equals "/metadata_a"
72+
And the event "metaData.Metadata A" is not null
73+
And the event "metaData.Metadata B" is null
74+
75+
And I discard the oldest session
76+
And I discard the oldest error
77+
78+
And I open the URL "http://localhost:8787/metadata_b" and get a 200 response with body "Hello World!"
79+
80+
And I wait to receive a session
81+
And the session is valid for the session reporting API version "1" for the "Bugsnag Node" notifier
82+
83+
And I wait to receive an error
84+
And the error is valid for the error reporting API version "4" for the "Bugsnag Node" notifier
85+
And the event "unhandled" is false
86+
And the event "severity" equals "warning"
87+
And the exception "errorClass" equals "Error"
88+
And the exception "message" equals "Metadata B Error"
89+
And the exception "type" equals "nodejs"
90+
And the "file" of stack frame 0 matches "index.js"
91+
And the event "request.url" equals "http://localhost:8787/metadata_b"
92+
And the event "request.httpMethod" equals "GET"
93+
And the event "request.clientIp" is not null
94+
And the event "request.headers" is not null
95+
And the event "metaData.request.path" equals "/metadata_b"
96+
And the event "metaData.Metadata A" is null
97+
And the event "metaData.Metadata B" is not null
98+
99+
Scenario: Breadcrumbs from one request do not appear in another
100+
When I start the worker "cloudflare-worker"
101+
And I wait for the host "localhost" to open port "8787"
102+
Then I open the URL "http://localhost:8787/breadcrumbs_a" and get a 200 response with body "Hello World!"
103+
104+
Then I wait to receive a session
105+
And the session is valid for the session reporting API version "1" for the "Bugsnag Node" notifier
106+
107+
Then I wait to receive an error
108+
Then the error is valid for the error reporting API version "4" for the "Bugsnag Node" notifier
109+
And the exception "message" equals "Breadcrumb A Error"
110+
And the event "request.url" equals "http://localhost:8787/breadcrumbs_a"
111+
And the event "request.httpMethod" equals "GET"
112+
And the event "request.clientIp" is not null
113+
And the event has a "manual" breadcrumb named "Breadcrumb A"
114+
115+
And I discard the oldest session
116+
And I discard the oldest error
117+
118+
And I open the URL "http://localhost:8787/breadcrumbs_b" and get a 200 response with body "Hello World!"
119+
120+
And I wait to receive a session
121+
And the session is valid for the session reporting API version "1" for the "Bugsnag Node" notifier
122+
123+
And I wait to receive an error
124+
And the error is valid for the error reporting API version "4" for the "Bugsnag Node" notifier
125+
And the exception "message" equals "Breadcrumb B Error"
126+
And the event "request.url" equals "http://localhost:8787/breadcrumbs_b"
127+
And the event "request.httpMethod" equals "GET"
128+
And the event "request.clientIp" is not null
129+
And the event has a "manual" breadcrumb named "Breadcrumb B"
130+
And the event does not have a "manual" breadcrumb with message "Breadcrumb A"
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "cloudflare-worker",
3+
"version": "0.0.0",
4+
"private": true,
5+
"scripts": {
6+
"deploy": "wrangler deploy",
7+
"dev": "wrangler dev",
8+
"start": "wrangler dev --inspector-port 0 --show-interactive-dev-session false --live-reload false --var BUGSNAG_API_KEY:$BUGSNAG_API_KEY --var BUGSNAG_NOTIFY_ENDPOINT:$BUGSNAG_NOTIFY_ENDPOINT --var BUGSNAG_SESSIONS_ENDPOINT:$BUGSNAG_SESSIONS_ENDPOINT",
9+
"cf-typegen": "wrangler types"
10+
},
11+
"devDependencies": {
12+
"@types/node": "^25.0.2",
13+
"typescript": "^5.5.2",
14+
"wrangler": "^4.54.0"
15+
}
16+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import Bugsnag from '@bugsnag/node'
2+
import BugsnagPluginCloudflareWorkers from '@bugsnag/plugin-cloudflare-workers'
3+
4+
Bugsnag.start({
5+
apiKey: process.env.BUGSNAG_API_KEY,
6+
endpoints: {
7+
notify: process.env.BUGSNAG_NOTIFY_ENDPOINT,
8+
sessions: process.env.BUGSNAG_SESSIONS_ENDPOINT
9+
},
10+
plugins: [BugsnagPluginCloudflareWorkers],
11+
})
12+
13+
const plugin = Bugsnag.getPlugin('cloudflareWorkers')
14+
15+
const bugsnagHandler = plugin!.createHandler()
16+
17+
export default {
18+
fetch: bugsnagHandler(async (request, env, ctx): Promise<Response> => {
19+
if (request.url.includes('/handled')) {
20+
Bugsnag.notify(new Error('handled'));
21+
} else if (request.url.includes('/unhandled')) {
22+
throw new Error('unhandled');
23+
} else if (request.url.includes('/metadata_a')) {
24+
Bugsnag.addMetadata('Metadata A', 'a', 'value a');
25+
Bugsnag.notify(new Error('Metadata A Error'));
26+
} else if (request.url.includes('/metadata_b')) {
27+
Bugsnag.addMetadata('Metadata B', 'b', 'value b');
28+
Bugsnag.notify(new Error('Metadata B Error'));
29+
} else if (request.url.includes('/breadcrumbs_a')) {
30+
Bugsnag.leaveBreadcrumb('Breadcrumb A', { message: 'Breadcrumb A' })
31+
Bugsnag.notify(new Error('Breadcrumb A Error'));
32+
} else if (request.url.includes('/breadcrumbs_b')) {
33+
Bugsnag.leaveBreadcrumb('Breadcrumb B', { message: 'Breadcrumb B' })
34+
Bugsnag.notify(new Error('Breadcrumb B Error'));
35+
}
36+
37+
return new Response('Hello World!');
38+
}),
39+
} satisfies ExportedHandler<Env>;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"compilerOptions": {
3+
/* Visit https://aka.ms/tsconfig.json to read more about this file */
4+
5+
/* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
6+
"target": "es2024",
7+
/* Specify a set of bundled library declaration files that describe the target runtime environment. */
8+
"lib": ["es2024"],
9+
/* Specify what JSX code is generated. */
10+
"jsx": "react-jsx",
11+
12+
/* Specify what module code is generated. */
13+
"module": "es2022",
14+
/* Specify how TypeScript looks up a file from a given module specifier. */
15+
"moduleResolution": "Bundler",
16+
/* Enable importing .json files */
17+
"resolveJsonModule": true,
18+
19+
/* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
20+
"allowJs": true,
21+
/* Enable error reporting in type-checked JavaScript files. */
22+
"checkJs": false,
23+
24+
/* Disable emitting files from a compilation. */
25+
"noEmit": true,
26+
27+
/* Ensure that each file can be safely transpiled without relying on other imports. */
28+
"isolatedModules": true,
29+
/* Allow 'import x from y' when a module doesn't have a default export. */
30+
"allowSyntheticDefaultImports": true,
31+
/* Ensure that casing is correct in imports. */
32+
"forceConsistentCasingInFileNames": true,
33+
34+
/* Enable all strict type-checking options. */
35+
"strict": true,
36+
37+
/* Skip type checking all .d.ts files. */
38+
"skipLibCheck": true,
39+
"types": [
40+
"./worker-configuration.d.ts",
41+
"node"
42+
]
43+
},
44+
"exclude": ["test"],
45+
"include": ["worker-configuration.d.ts", "src/**/*.ts"]
46+
}

0 commit comments

Comments
 (0)