Skip to content

Commit 7f97434

Browse files
committed
move all string util tests to utils
1 parent b9d0c56 commit 7f97434

File tree

3 files changed

+55
-73
lines changed

3 files changed

+55
-73
lines changed

packages/browser/test/unit/string.test.ts

Lines changed: 0 additions & 59 deletions
This file was deleted.

packages/utils/src/string.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,11 @@ export function isMatchingPattern(value: string, pattern: RegExp | string): bool
104104
return false;
105105
}
106106

107-
type GlobalWithBase64Helpers = {
108-
// browser
107+
export type GlobalBase64Helpers = {
108+
// browser and Node 16+
109109
atob?: (base64String: string) => string;
110110
btoa?: (utf8String: string) => string;
111-
// Node
111+
// all versions of Node
112112
Buffer?: { from: (input: string, encoding: string) => { toString: (encoding: string) => string } };
113113
};
114114

@@ -120,7 +120,7 @@ type GlobalWithBase64Helpers = {
120120
* @returns A base64-encoded version of the string
121121
*/
122122
export function unicodeToBase64(plaintext: string): string {
123-
const globalObject = getGlobalObject<GlobalWithBase64Helpers>();
123+
const globalObject = getGlobalObject<GlobalBase64Helpers>();
124124

125125
// To account for the fact that different platforms use different character encodings natively, our `tracestate`
126126
// spec calls for all jsonified data to be encoded in UTF-8 bytes before being passed to the base64 encoder.
@@ -129,7 +129,7 @@ export function unicodeToBase64(plaintext: string): string {
129129
throw new Error(`Input must be a string. Received input of type '${typeof plaintext}'.`);
130130
}
131131

132-
// browser
132+
// browser and Node 16+
133133
if ('btoa' in globalObject) {
134134
// encode using UTF-8
135135
const bytes = new TextEncoder().encode(plaintext);
@@ -142,7 +142,7 @@ export function unicodeToBase64(plaintext: string): string {
142142
return globalObject.btoa!(bytesAsString);
143143
}
144144

145-
// Node
145+
// fallback for Node <= 14
146146
if ('Buffer' in globalObject) {
147147
// encode using UTF-8
148148
// TODO: if TS ever learns about "in", we can get rid of the non-null assertion
@@ -173,7 +173,7 @@ export function unicodeToBase64(plaintext: string): string {
173173
* @returns A Unicode string
174174
*/
175175
export function base64ToUnicode(base64String: string): string {
176-
const globalObject = getGlobalObject<GlobalWithBase64Helpers>();
176+
const globalObject = getGlobalObject<GlobalBase64Helpers>();
177177

178178
// To account for the fact that different platforms use different character encodings natively, our `tracestate` spec
179179
// calls for all jsonified data to be encoded in UTF-8 bytes before being passed to the base64 encoder. So to reverse
@@ -183,7 +183,7 @@ export function base64ToUnicode(base64String: string): string {
183183
throw new Error(`Input must be a string. Received input of type '${typeof base64String}'.`);
184184
}
185185

186-
// browser
186+
// browser and Node 16+
187187
if ('atob' in globalObject) {
188188
// `atob` returns a string rather than bytes, so we first need to encode using the native encoding (UTF-16)
189189
// TODO: if TS ever learns about "in", we can get rid of the non-null assertion
@@ -195,7 +195,7 @@ export function base64ToUnicode(base64String: string): string {
195195
return new TextDecoder().decode(Uint8Array.from(bytes));
196196
}
197197

198-
// Node
198+
// fallback for Node <= 14
199199
if ('Buffer' in globalObject) {
200200
// unlike the browser, Node can go straight from base64 to bytes
201201
// TODO: if TS ever learns about "in", we can get rid of the non-null assertion

packages/utils/test/string.test.ts

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { base64ToUnicode, isMatchingPattern, truncate, unicodeToBase64 } from '../src/string';
1+
import { JSDOM } from 'jsdom';
2+
3+
import * as crossPlatformUtils from '../src/crossplatform';
4+
import { base64ToUnicode, GlobalBase64Helpers, isMatchingPattern, truncate, unicodeToBase64 } from '../src/string';
25

36
// See https://tools.ietf.org/html/rfc4648#section-4 for base64 spec
47
// eslint-disable-next-line no-useless-escape
@@ -50,13 +53,51 @@ describe('isMatchingPattern()', () => {
5053
});
5154
});
5255

53-
// NOTE: These tests are copied (and adapted for chai syntax) to `string.test.ts` in `@sentry/browser`. The
54-
// base64-conversion functions have a different implementation in browser and node, so they're copied there to prove
55-
// they work in a real live browser. If you make changes here, make sure to also port them over to that copy.
56-
describe('base64ToUnicode/unicodeToBase64', () => {
56+
// these functions use different built-ins depending on whether the code is running in Node or in the browser, so test
57+
// both environments
58+
describe.each(['node', 'browser'])('base64ToUnicode/unicodeToBase64 (%s)', (testEnv: string) => {
5759
const unicodeString = 'Dogs are great!';
5860
const base64String = 'RG9ncyBhcmUgZ3JlYXQh';
5961

62+
let atobSpy: jest.SpyInstance, btoaSpy: jest.SpyInstance, bufferSpy: jest.SpyInstance;
63+
64+
beforeAll(() => {
65+
const { Buffer, ...nonBufferGlobals } = global as typeof global & GlobalBase64Helpers;
66+
67+
// By default, all tests in run in a node environment. To mimic the behavior of a browser, we need to adjust what is
68+
// available globally.
69+
if (testEnv === 'browser') {
70+
const { window } = new JSDOM('', { url: 'http://dogs.are.great/' });
71+
72+
atobSpy = jest.spyOn(window, 'atob');
73+
btoaSpy = jest.spyOn(window, 'btoa');
74+
75+
jest
76+
.spyOn(crossPlatformUtils, 'getGlobalObject')
77+
.mockReturnValue({ atob: atobSpy, btoa: btoaSpy, ...nonBufferGlobals } as any);
78+
}
79+
// no need to adjust what's in `global`, but set up a spy so we can make sure the right functions are getting called
80+
// in the right environments
81+
else {
82+
bufferSpy = jest.spyOn(Buffer, 'from');
83+
}
84+
});
85+
86+
afterAll(() => {
87+
jest.restoreAllMocks();
88+
});
89+
90+
it('meta: uses the right mock given test env', () => {
91+
unicodeToBase64(unicodeString);
92+
base64ToUnicode(base64String);
93+
if (testEnv === 'browser') {
94+
expect(atobSpy).toHaveBeenCalled();
95+
expect(btoaSpy).toHaveBeenCalled();
96+
} else {
97+
expect(bufferSpy).toHaveBeenCalled();
98+
}
99+
});
100+
60101
test('converts to valid base64', () => {
61102
expect(BASE64_REGEX.test(unicodeToBase64(unicodeString))).toBe(true);
62103
});

0 commit comments

Comments
 (0)