diff --git a/package.json b/package.json
index 16d0d10c6e489..9c3110dd99972 100644
--- a/package.json
+++ b/package.json
@@ -21,6 +21,7 @@
"@sentry/browser": "7.55.2",
"@sentry/webpack-plugin": "2.2.2",
"@types/dompurify": "^3.0.2",
+ "@types/js-cookie": "^3.0.3",
"@types/jest": "^29.5.3",
"@types/js-yaml": "^3.0.0",
"@types/node": "^20.3.1",
diff --git a/src/components/__tests__/__snapshots__/codeBlock.test.js.snap b/src/components/__tests__/__snapshots__/codeBlock.test.js.snap
new file mode 100644
index 0000000000000..5a9974eb4eb26
--- /dev/null
+++ b/src/components/__tests__/__snapshots__/codeBlock.test.js.snap
@@ -0,0 +1,250 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`CodeWrapper renders multiple placeholders 1`] = `
+
+ process.env.MY_ENV =
+
+
+
+
+ example-org
+
+
+
+ +
+
+
+
+
+ example-project
+
+
+
+
+`;
+
+exports[`CodeWrapper renders org auth token placeholder when not signed in 1`] = `
+
+ process.env.MY_ENV =
+ sntrys_YOUR_TOKEN_HERE
+
+`;
+
+exports[`CodeWrapper renders org auth token placeholder when signed in 1`] = `
+
+ process.env.MY_ENV =
+
+ Click to generate token
+
+
+`;
+
+exports[`CodeWrapper renders with placeholder 1`] = `
+
+ process.env.MY_ENV =
+
+
+
+
+ example-org
+
+
+
+
+`;
+
+exports[`CodeWrapper renders with placeholder in middle of text 1`] = `
+
+ process.env.MY_ENV = https://
+
+
+
+
+ example-org
+
+
+
+ .sentry.io
+
+`;
+
+exports[`CodeWrapper renders without placeholder 1`] = `
+
+ process.env.MY_ENV = 'foo'
+
+`;
diff --git a/src/components/__tests__/codeBlock.test.js b/src/components/__tests__/codeBlock.test.js
new file mode 100644
index 0000000000000..0d6f5d39fd0c1
--- /dev/null
+++ b/src/components/__tests__/codeBlock.test.js
@@ -0,0 +1,74 @@
+import React from 'react';
+import {create} from 'react-test-renderer';
+
+import {CodeWrapper} from '../codeBlock';
+import {_setCachedCodeKeywords, CodeContextProvider, DEFAULTS} from '../codeContext';
+
+describe('CodeWrapper', () => {
+ beforeEach(() => {
+ _setCachedCodeKeywords(DEFAULTS);
+ });
+
+ it('renders without placeholder', () => {
+ const tree = create(
+
+ process.env.MY_ENV = 'foo'
+
+ );
+
+ expect(tree.toJSON()).toMatchSnapshot();
+ });
+
+ it('renders with placeholder', () => {
+ const tree = create(
+
+ process.env.MY_ENV = ___ORG_SLUG___
+
+ );
+
+ expect(tree.toJSON()).toMatchSnapshot();
+ });
+
+ it('renders with placeholder in middle of text', () => {
+ const tree = create(
+
+ process.env.MY_ENV = https://___ORG_SLUG___.sentry.io
+
+ );
+
+ expect(tree.toJSON()).toMatchSnapshot();
+ });
+
+ it('renders org auth token placeholder when not signed in', () => {
+ const tree = create(
+
+ process.env.MY_ENV = ___ORG_AUTH_TOKEN___
+
+ );
+
+ expect(tree.toJSON()).toMatchSnapshot();
+ });
+ it('renders org auth token placeholder when signed in', () => {
+ _setCachedCodeKeywords({...DEFAULTS, USER: {ID: 123, NAME: 'test@sentry.io'}});
+
+ const tree = create(
+
+ process.env.MY_ENV = ___ORG_AUTH_TOKEN___
+
+ );
+
+ expect(tree.toJSON()).toMatchSnapshot();
+ });
+
+ it('renders multiple placeholders', () => {
+ const tree = create(
+
+
+ process.env.MY_ENV = ___ORG_SLUG___ + ___PROJECT_SLUG___
+
+
+ );
+
+ expect(tree.toJSON()).toMatchSnapshot();
+ });
+});
diff --git a/src/components/basePage.tsx b/src/components/basePage.tsx
index 6cabfb80450ce..54f6ecd9ce404 100644
--- a/src/components/basePage.tsx
+++ b/src/components/basePage.tsx
@@ -3,7 +3,7 @@ import React, {Fragment, useState} from 'react';
import {getCurrentTransaction} from '../utils';
import {Banner} from './banner';
-import {CodeContext, useCodeContextState} from './codeContext';
+import {CodeContextProvider} from './codeContext';
import {GitHubCTA} from './githubCta';
import {Layout} from './layout';
import {SEO} from './seo';
@@ -77,9 +77,7 @@ export function BasePage({
>
{title}
-
- {children}
-
+ {children}
{file && (
(cachedCodeKeywords ? false : true);
@@ -248,13 +248,13 @@ export function useCodeContextState(fetcher = fetchCodeKeywords): CodeContextTyp
useEffect(() => {
if (cachedCodeKeywords === null) {
setIsLoading(true);
- fetcher().then((config: CodeKeywords) => {
+ fetchCodeKeywords().then((config: CodeKeywords) => {
cachedCodeKeywords = config;
setCodeKeywords(config);
setIsLoading(false);
});
}
- }, [setIsLoading, setCodeKeywords, fetcher]);
+ }, [setIsLoading, setCodeKeywords]);
// sharedKeywordSelection maintains a global mapping for each "keyword"
// namespace to the index of the selected item.
@@ -273,5 +273,10 @@ export function useCodeContextState(fetcher = fetchCodeKeywords): CodeContextTyp
isLoading,
};
- return result;
+ return {children};
+}
+
+/** For tests only. */
+export function _setCachedCodeKeywords(codeKeywords: CodeKeywords) {
+ cachedCodeKeywords = codeKeywords;
}
diff --git a/yarn.lock b/yarn.lock
index a593ac4472aee..aaf6b0c89759c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3056,6 +3056,11 @@
expect "^29.0.0"
pretty-format "^29.0.0"
+"@types/js-cookie@^3.0.3":
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-3.0.3.tgz#d6bfbbdd0c187354ca555213d1962f6d0691ff4e"
+ integrity sha512-Xe7IImK09HP1sv2M/aI+48a20VX+TdRJucfq4vfRVy6nWN8PYPOEnlMRSgxJAgYQIXJVL8dZ4/ilAM7dWNaOww==
+
"@types/js-yaml@^3.0.0":
version "3.12.7"
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.7.tgz#330c5d97a3500e9c903210d6e49f02964af04a0e"