Skip to content

Commit 6735fa7

Browse files
committed
feat: Add tests for effect
1 parent 0612091 commit 6735fa7

File tree

14 files changed

+371
-0
lines changed

14 files changed

+371
-0
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
dist
2+
node_modules
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
@sentry:registry=http://127.0.0.1:4873
2+
@sentry-internal:registry=http://127.0.0.1:4873
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"name": "node-effect-app",
3+
"version": "1.0.0",
4+
"private": true,
5+
"type": "module",
6+
"scripts": {
7+
"build": "tsc",
8+
"start": "node --import=./src/instrument.js dist/app.js",
9+
"test": "playwright test",
10+
"clean": "npx rimraf node_modules pnpm-lock.yaml",
11+
"test:build": "pnpm install && pnpm build",
12+
"test:assert": "pnpm test"
13+
},
14+
"dependencies": {
15+
"@effect/platform": "^0.94.0",
16+
"@effect/platform-node": "^0.104.0",
17+
"@sentry/core": "latest || *",
18+
"@sentry/node": "latest || *",
19+
"@types/node": "^18.19.1",
20+
"effect": "^3.0.0",
21+
"typescript": "~5.0.0"
22+
},
23+
"devDependencies": {
24+
"@playwright/test": "~1.56.0",
25+
"@sentry-internal/test-utils": "link:../../../test-utils"
26+
},
27+
"volta": {
28+
"extends": "../../package.json"
29+
}
30+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { getPlaywrightConfig } from '@sentry-internal/test-utils';
2+
3+
const config = getPlaywrightConfig({
4+
startCommand: `pnpm start`,
5+
});
6+
7+
export default config;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { HttpApi } from '@effect/platform';
2+
import { TestApi } from './Test/Api.js';
3+
4+
export class Api extends HttpApi.make('api').add(TestApi) {}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { HttpApiBuilder, HttpMiddleware, HttpServer } from '@effect/platform';
2+
import { NodeHttpServer } from '@effect/platform-node';
3+
import { Layer } from 'effect';
4+
import { createServer } from 'http';
5+
import { Api } from './Api.js';
6+
import { HttpTestLive } from './Test/Http.js';
7+
8+
const ApiLive = Layer.provide(HttpApiBuilder.api(Api), [HttpTestLive]);
9+
10+
export const HttpLive = HttpApiBuilder.serve(HttpMiddleware.logger).pipe(
11+
Layer.provide(ApiLive),
12+
HttpServer.withLogAddress,
13+
Layer.provide(NodeHttpServer.layer(createServer, { port: 3030 })),
14+
);
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { HttpApiEndpoint, HttpApiGroup } from '@effect/platform';
2+
import { Schema } from 'effect';
3+
4+
export const TestResult = Schema.Struct({
5+
status: Schema.String,
6+
});
7+
8+
export const NestedResult = Schema.Struct({
9+
result: Schema.String,
10+
});
11+
12+
export const ErrorResult = Schema.Struct({
13+
error: Schema.String,
14+
});
15+
16+
export const LogResult = Schema.Struct({
17+
logged: Schema.Boolean,
18+
});
19+
20+
export const MetricResult = Schema.Struct({
21+
incremented: Schema.Number,
22+
});
23+
24+
export class TestApi extends HttpApiGroup.make('test')
25+
.add(HttpApiEndpoint.get('success', '/test-success').addSuccess(TestResult))
26+
.add(HttpApiEndpoint.get('effectSpan', '/test-effect-span').addSuccess(TestResult))
27+
.add(HttpApiEndpoint.get('nestedSpans', '/test-nested-spans').addSuccess(NestedResult))
28+
.add(HttpApiEndpoint.get('effectError', '/test-effect-error').addSuccess(ErrorResult))
29+
.add(HttpApiEndpoint.get('effectLog', '/test-effect-log').addSuccess(LogResult))
30+
.add(HttpApiEndpoint.get('effectMetric', '/test-effect-metric').addSuccess(MetricResult))
31+
.add(HttpApiEndpoint.get('effectWithHttp', '/test-effect-with-http').addSuccess(TestResult)) {}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { HttpApiBuilder } from '@effect/platform';
2+
import { Effect, Metric } from 'effect';
3+
import { Api } from '../Api.js';
4+
5+
const requestCounter = Metric.counter('http_requests_total').pipe(Metric.withConstantInput(1));
6+
7+
export const HttpTestLive = HttpApiBuilder.group(Api, 'test', handlers =>
8+
Effect.gen(function* () {
9+
return handlers
10+
.handle('success', () => Effect.succeed({ status: 'ok' }))
11+
12+
.handle('effectSpan', () =>
13+
Effect.gen(function* () {
14+
yield* Effect.log('Starting effect span test');
15+
yield* Effect.sleep('10 millis');
16+
return { status: 'ok' };
17+
}).pipe(Effect.withSpan('test-effect-span')),
18+
)
19+
20+
.handle('nestedSpans', () => {
21+
const innerEffect = Effect.gen(function* () {
22+
yield* Effect.sleep('5 millis');
23+
return 'inner-result';
24+
}).pipe(Effect.withSpan('inner-span'));
25+
26+
return Effect.gen(function* () {
27+
const result = yield* innerEffect;
28+
yield* Effect.sleep('5 millis');
29+
return { result };
30+
}).pipe(Effect.withSpan('outer-span'));
31+
})
32+
33+
.handle('effectError', () =>
34+
Effect.gen(function* () {
35+
yield* Effect.fail(new Error('Effect error'));
36+
return { error: '' };
37+
}).pipe(
38+
Effect.withSpan('error-span'),
39+
Effect.catchAll(error =>
40+
Effect.succeed({ error: error instanceof Error ? error.message : String(error) }),
41+
),
42+
),
43+
)
44+
45+
.handle('effectLog', () =>
46+
Effect.gen(function* () {
47+
yield* Effect.log('Test info log message');
48+
yield* Effect.logDebug('Test debug log message');
49+
yield* Effect.logWarning('Test warning log message');
50+
yield* Effect.logError('Test error log message');
51+
return { logged: true };
52+
}),
53+
)
54+
55+
.handle('effectMetric', () =>
56+
Effect.gen(function* () {
57+
yield* Metric.increment(requestCounter);
58+
yield* Metric.increment(requestCounter);
59+
yield* Metric.increment(requestCounter);
60+
return { incremented: 3 };
61+
}),
62+
)
63+
64+
.handle('effectWithHttp', () =>
65+
Effect.gen(function* () {
66+
yield* Effect.log('Processing request');
67+
yield* Effect.sleep('10 millis');
68+
return { status: 'ok' };
69+
}).pipe(Effect.withSpan('process-request', { kind: 'server' })),
70+
);
71+
}),
72+
);
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { NodeRuntime } from '@effect/platform-node';
2+
import { Layer } from 'effect';
3+
import { effectLayer } from '@sentry/core/effect';
4+
import { HttpLive } from './Http.js';
5+
6+
const MainLive = HttpLive.pipe(Layer.provide(effectLayer));
7+
8+
MainLive.pipe(Layer.launch, NodeRuntime.runMain);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import * as Sentry from '@sentry/node';
2+
3+
Sentry.init({
4+
environment: 'qa',
5+
dsn: process.env.E2E_TEST_DSN,
6+
debug: !!process.env.DEBUG,
7+
tunnel: `http://localhost:3031/`,
8+
tracesSampleRate: 1,
9+
enableLogs: true,
10+
});

0 commit comments

Comments
 (0)