Skip to content

Commit

Permalink
test(otel): Migrate to Vitest (#15545)
Browse files Browse the repository at this point in the history
  • Loading branch information
timfish authored Feb 28, 2025
1 parent d12c192 commit ba4586f
Show file tree
Hide file tree
Showing 25 changed files with 259 additions and 211 deletions.
1 change: 0 additions & 1 deletion packages/opentelemetry/jest.config.js

This file was deleted.

6 changes: 3 additions & 3 deletions packages/opentelemetry/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@
"clean": "rimraf build coverage sentry-opentelemetry-*.tgz",
"fix": "eslint . --format stylish --fix",
"lint": "eslint . --format stylish",
"test": "yarn test:jest",
"test:jest": "jest",
"test:watch": "jest --watch",
"test": "yarn test:unit",
"test:unit": "vitest run",
"test:watch": "vitest --watch",
"yalc:publish": "yalc publish --push --sig"
},
"volta": {
Expand Down
233 changes: 123 additions & 110 deletions packages/opentelemetry/test/asyncContextStrategy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
withIsolationScope,
withScope,
} from '@sentry/core';
import { describe, beforeEach, afterEach, afterAll, test, expect, it } from 'vitest';

import type { Scope } from '@sentry/core';
import { setOpenTelemetryContextAsyncContextStrategy } from '../src/asyncContextStrategy';
Expand Down Expand Up @@ -301,130 +302,142 @@ describe('asyncContextStrategy', () => {
});

describe('withScope()', () => {
it('will make the passed scope the active scope within the callback', done => {
withScope(scope => {
expect(getCurrentScope()).toBe(scope);
done();
});
});

it('will pass a scope that is different from the current active isolation scope', done => {
withScope(scope => {
expect(getIsolationScope()).not.toBe(scope);
done();
});
});

it('will always make the inner most passed scope the current scope when nesting calls', done => {
withIsolationScope(_scope1 => {
withIsolationScope(scope2 => {
expect(getIsolationScope()).toBe(scope2);
it('will make the passed scope the active scope within the callback', () =>
new Promise<void>(done => {
withScope(scope => {
expect(getCurrentScope()).toBe(scope);
done();
});
});
});

it('forks the scope when not passing any scope', done => {
const initialScope = getCurrentScope();
initialScope.setTag('aa', 'aa');

withScope(scope => {
expect(getCurrentScope()).toBe(scope);
scope.setTag('bb', 'bb');
expect(scope).not.toBe(initialScope);
expect(scope.getScopeData().tags).toEqual({ aa: 'aa', bb: 'bb' });
done();
});
});

it('forks the scope when passing undefined', done => {
const initialScope = getCurrentScope();
initialScope.setTag('aa', 'aa');
}));

withScope(undefined, scope => {
expect(getCurrentScope()).toBe(scope);
scope.setTag('bb', 'bb');
expect(scope).not.toBe(initialScope);
expect(scope.getScopeData().tags).toEqual({ aa: 'aa', bb: 'bb' });
done();
});
});
it('will pass a scope that is different from the current active isolation scope', () =>
new Promise<void>(done => {
withScope(scope => {
expect(getIsolationScope()).not.toBe(scope);
done();
});
}));

it('will always make the inner most passed scope the current scope when nesting calls', () =>
new Promise<void>(done => {
withIsolationScope(_scope1 => {
withIsolationScope(scope2 => {
expect(getIsolationScope()).toBe(scope2);
done();
});
});
}));

it('forks the scope when not passing any scope', () =>
new Promise<void>(done => {
const initialScope = getCurrentScope();
initialScope.setTag('aa', 'aa');

withScope(scope => {
expect(getCurrentScope()).toBe(scope);
scope.setTag('bb', 'bb');
expect(scope).not.toBe(initialScope);
expect(scope.getScopeData().tags).toEqual({ aa: 'aa', bb: 'bb' });
done();
});
}));

it('forks the scope when passing undefined', () =>
new Promise<void>(done => {
const initialScope = getCurrentScope();
initialScope.setTag('aa', 'aa');

withScope(undefined, scope => {
expect(getCurrentScope()).toBe(scope);
scope.setTag('bb', 'bb');
expect(scope).not.toBe(initialScope);
expect(scope.getScopeData().tags).toEqual({ aa: 'aa', bb: 'bb' });
done();
});
}));

it('sets the passed in scope as active scope', done => {
const initialScope = getCurrentScope();
initialScope.setTag('aa', 'aa');
it('sets the passed in scope as active scope', () =>
new Promise<void>(done => {
const initialScope = getCurrentScope();
initialScope.setTag('aa', 'aa');

const customScope = new ScopeClass();
const customScope = new ScopeClass();

withScope(customScope, scope => {
expect(getCurrentScope()).toBe(customScope);
expect(scope).toBe(customScope);
done();
});
});
withScope(customScope, scope => {
expect(getCurrentScope()).toBe(customScope);
expect(scope).toBe(customScope);
done();
});
}));
});

describe('withIsolationScope()', () => {
it('will make the passed isolation scope the active isolation scope within the callback', done => {
withIsolationScope(scope => {
expect(getIsolationScope()).toBe(scope);
done();
});
});

it('will pass an isolation scope that is different from the current active scope', done => {
withIsolationScope(scope => {
expect(getCurrentScope()).not.toBe(scope);
done();
});
});

it('will always make the inner most passed scope the current scope when nesting calls', done => {
withIsolationScope(_scope1 => {
withIsolationScope(scope2 => {
expect(getIsolationScope()).toBe(scope2);
it('will make the passed isolation scope the active isolation scope within the callback', () =>
new Promise<void>(done => {
withIsolationScope(scope => {
expect(getIsolationScope()).toBe(scope);
done();
});
});
});

it('forks the isolation scope when not passing any isolation scope', done => {
const initialScope = getIsolationScope();
initialScope.setTag('aa', 'aa');

withIsolationScope(scope => {
expect(getIsolationScope()).toBe(scope);
scope.setTag('bb', 'bb');
expect(scope).not.toBe(initialScope);
expect(scope.getScopeData().tags).toEqual({ aa: 'aa', bb: 'bb' });
done();
});
});

it('forks the isolation scope when passing undefined', done => {
const initialScope = getIsolationScope();
initialScope.setTag('aa', 'aa');
}));

withIsolationScope(undefined, scope => {
expect(getIsolationScope()).toBe(scope);
scope.setTag('bb', 'bb');
expect(scope).not.toBe(initialScope);
expect(scope.getScopeData().tags).toEqual({ aa: 'aa', bb: 'bb' });
done();
});
});
it('will pass an isolation scope that is different from the current active scope', () =>
new Promise<void>(done => {
withIsolationScope(scope => {
expect(getCurrentScope()).not.toBe(scope);
done();
});
}));

it('will always make the inner most passed scope the current scope when nesting calls', () =>
new Promise<void>(done => {
withIsolationScope(_scope1 => {
withIsolationScope(scope2 => {
expect(getIsolationScope()).toBe(scope2);
done();
});
});
}));

it('forks the isolation scope when not passing any isolation scope', () =>
new Promise<void>(done => {
const initialScope = getIsolationScope();
initialScope.setTag('aa', 'aa');

withIsolationScope(scope => {
expect(getIsolationScope()).toBe(scope);
scope.setTag('bb', 'bb');
expect(scope).not.toBe(initialScope);
expect(scope.getScopeData().tags).toEqual({ aa: 'aa', bb: 'bb' });
done();
});
}));

it('forks the isolation scope when passing undefined', () =>
new Promise<void>(done => {
const initialScope = getIsolationScope();
initialScope.setTag('aa', 'aa');

withIsolationScope(undefined, scope => {
expect(getIsolationScope()).toBe(scope);
scope.setTag('bb', 'bb');
expect(scope).not.toBe(initialScope);
expect(scope.getScopeData().tags).toEqual({ aa: 'aa', bb: 'bb' });
done();
});
}));

it('sets the passed in isolation scope as active isolation scope', done => {
const initialScope = getIsolationScope();
initialScope.setTag('aa', 'aa');
it('sets the passed in isolation scope as active isolation scope', () =>
new Promise<void>(done => {
const initialScope = getIsolationScope();
initialScope.setTag('aa', 'aa');

const customScope = new ScopeClass();
const customScope = new ScopeClass();

withIsolationScope(customScope, scope => {
expect(getIsolationScope()).toBe(customScope);
expect(scope).toBe(customScope);
done();
});
});
withIsolationScope(customScope, scope => {
expect(getIsolationScope()).toBe(customScope);
expect(scope).toBe(customScope);
done();
});
}));
});
});
1 change: 1 addition & 0 deletions packages/opentelemetry/test/custom/client.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ProxyTracer } from '@opentelemetry/api';
import { describe, expect, it } from 'vitest';

import { TestClient, getDefaultTestClientOptions } from '../helpers/TestClient';

Expand Down
20 changes: 12 additions & 8 deletions packages/opentelemetry/test/helpers/mockSdkInit.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { ProxyTracerProvider, context, propagation, trace } from '@opentelemetry/api';
import { BasicTracerProvider } from '@opentelemetry/sdk-trace-base';
import type { ClientOptions, Options } from '@sentry/core';
import { getClient } from '@sentry/core';

import { getCurrentScope, getGlobalScope, getIsolationScope } from '@sentry/core';
import { getCurrentScope, getGlobalScope, getIsolationScope, flush } from '@sentry/core';
import { setOpenTelemetryContextAsyncContextStrategy } from '../../src/asyncContextStrategy';
import { clearOpenTelemetrySetupCheck } from '../../src/utils/setupCheck';
import { init as initTestClient } from './TestClient';
import { initOtel } from './initOtel';
import type { OpenTelemetryClient } from '../../src/types';

const PUBLIC_DSN = 'https://username@domain/123';

Expand All @@ -24,6 +26,7 @@ function resetGlobals(): void {
getCurrentScope().setClient(undefined);
getIsolationScope().clear();
getGlobalScope().clear();
delete (global as any).__SENTRY__;
}

export function mockSdkInit(options?: Partial<ClientOptions>) {
Expand All @@ -32,25 +35,26 @@ export function mockSdkInit(options?: Partial<ClientOptions>) {
init({ dsn: PUBLIC_DSN, ...options });
}

export function cleanupOtel(_provider?: BasicTracerProvider): void {
export async function cleanupOtel(_provider?: BasicTracerProvider): Promise<void> {
clearOpenTelemetrySetupCheck();

const provider = getProvider(_provider);

if (!provider) {
return;
if (provider) {
await provider.forceFlush();
await provider.shutdown();
}

void provider.forceFlush();
void provider.shutdown();

// Disable all globally registered APIs
trace.disable();
context.disable();
propagation.disable();

await flush();
}

export function getProvider(_provider?: BasicTracerProvider): BasicTracerProvider | undefined {
let provider = _provider || trace.getTracerProvider();
let provider = _provider || getClient<OpenTelemetryClient>()?.traceProvider || trace.getTracerProvider();

if (provider instanceof ProxyTracerProvider) {
provider = provider.getDelegate();
Expand Down
Loading

0 comments on commit ba4586f

Please sign in to comment.