mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-23 15:47:53 -05:00
Merge pull request #7353 from cwillisf/remove-sentry
fix: remove Sentry and rewrite ErrorBoundary tests
This commit is contained in:
commit
ecdd686c7f
10 changed files with 42 additions and 265 deletions
|
@ -165,7 +165,6 @@ the beginning of the command, before `npm start`:
|
|||
| `ASSET_HOST` | `https://assets.scratch.mit.edu` | Hostname for asset requests |
|
||||
| `BACKPACK_HOST` | `https://backpack.scratch.mit.edu` | Hostname for backpack requests |
|
||||
| `PROJECT_HOST` | `https://projects.scratch.mit.edu` | Hostname for project requests |
|
||||
| `SENTRY_DSN` | `''` | DSN for Sentry |
|
||||
| `FALLBACK` | `''` | Pass-through location for old site |
|
||||
| `GA_TRACKER` | `''` | Where to log Google Analytics data |
|
||||
| `NODE_ENV` | `null` | If not `production`, app acts like development |
|
||||
|
|
152
package-lock.json
generated
152
package-lock.json
generated
|
@ -9,7 +9,6 @@
|
|||
"version": "1.0.0",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@sentry/browser": "4.4.2",
|
||||
"bunyan": "1.8.15",
|
||||
"clipboard-copy": "2.0.1",
|
||||
"express": "4.16.1",
|
||||
|
@ -93,6 +92,7 @@
|
|||
"react-slick": "0.16.0",
|
||||
"react-string-replace": "0.4.1",
|
||||
"react-telephone-input": "4.3.4",
|
||||
"react-test-renderer": "16.14.0",
|
||||
"redux": "3.5.2",
|
||||
"redux-mock-store": "1.5.4",
|
||||
"redux-thunk": "2.0.1",
|
||||
|
@ -1645,81 +1645,6 @@
|
|||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/browser": {
|
||||
"version": "4.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-4.4.2.tgz",
|
||||
"integrity": "sha512-km5p3hPz+aoY4UiEvYxAdRJAbIK30urZSuMs/3zAUVe+8Zij0IHjHmdi9JtrMqpn+rAcWCxtRmFSYlkiKjdSUg==",
|
||||
"dependencies": {
|
||||
"@sentry/core": "4.4.2",
|
||||
"@sentry/types": "4.4.2",
|
||||
"@sentry/utils": "4.4.2",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/core": {
|
||||
"version": "4.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-4.4.2.tgz",
|
||||
"integrity": "sha512-hJyAodTCf4sZfVdf41Rtuzj4EsyzYq5rdMZ+zc2Vinwdf8D0/brHe91fHeO0CKXEb2P0wJsrjwMidG/ccq/M8A==",
|
||||
"dependencies": {
|
||||
"@sentry/hub": "4.4.2",
|
||||
"@sentry/minimal": "4.4.2",
|
||||
"@sentry/types": "4.4.2",
|
||||
"@sentry/utils": "4.4.2",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/hub": {
|
||||
"version": "4.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-4.4.2.tgz",
|
||||
"integrity": "sha512-oe9ytXkTWyD+QmOpVzHAqTbRV4Hc0ee2Nt6HvrDtRmlXzQxfvTWG2F8KYT6w8kzqg5klnuRpnsmgTTV3KuNBVQ==",
|
||||
"dependencies": {
|
||||
"@sentry/types": "4.4.2",
|
||||
"@sentry/utils": "4.4.2",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/minimal": {
|
||||
"version": "4.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-4.4.2.tgz",
|
||||
"integrity": "sha512-GEZZiNvVgqFAESZhAe3vjwTInn13lI2bSI3ItQN4RUWKL/W4n/fwVoDJbkb1U8aWxanuMnRDEpKwyQv6zYTZfw==",
|
||||
"dependencies": {
|
||||
"@sentry/hub": "4.4.2",
|
||||
"@sentry/types": "4.4.2",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/types": {
|
||||
"version": "4.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-4.4.2.tgz",
|
||||
"integrity": "sha512-QyQd6PKKIyjJgaq/RQjsxPJEWbXcuiWZ9RvSnhBjS5jj53HEzkM1qkbAFqlYHJ1DTJJ1EuOM4+aTmGzHe93zuA==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/utils": {
|
||||
"version": "4.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-4.4.2.tgz",
|
||||
"integrity": "sha512-j/Ad8G1abHlJdD2q7aWWbSOSeWB5M5v1R1VKL8YPlwEbSvvmEQWePhBKFI0qlnKd2ObdUQsj86pHEXJRSFNfCw==",
|
||||
"dependencies": {
|
||||
"@sentry/types": "4.4.2",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@sindresorhus/is": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz",
|
||||
|
@ -20568,15 +20493,6 @@
|
|||
"react-is": "^16.8.1"
|
||||
}
|
||||
},
|
||||
"node_modules/react-test-renderer/node_modules/scheduler": {
|
||||
"version": "0.19.1",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz",
|
||||
"integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/react-tooltip": {
|
||||
"version": "3.8.0",
|
||||
"resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-3.8.0.tgz",
|
||||
|
@ -33054,63 +32970,6 @@
|
|||
"integrity": "sha512-cphYw/y/l36UJ8fv/LXyK+lHlxMXtoydJUsgA4u5QnaUaSZYepuSHik6PewJGT4qvaPwT5ImvHWwX2kElWXvoQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@sentry/browser": {
|
||||
"version": "4.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-4.4.2.tgz",
|
||||
"integrity": "sha512-km5p3hPz+aoY4UiEvYxAdRJAbIK30urZSuMs/3zAUVe+8Zij0IHjHmdi9JtrMqpn+rAcWCxtRmFSYlkiKjdSUg==",
|
||||
"requires": {
|
||||
"@sentry/core": "4.4.2",
|
||||
"@sentry/types": "4.4.2",
|
||||
"@sentry/utils": "4.4.2",
|
||||
"tslib": "^1.9.3"
|
||||
}
|
||||
},
|
||||
"@sentry/core": {
|
||||
"version": "4.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-4.4.2.tgz",
|
||||
"integrity": "sha512-hJyAodTCf4sZfVdf41Rtuzj4EsyzYq5rdMZ+zc2Vinwdf8D0/brHe91fHeO0CKXEb2P0wJsrjwMidG/ccq/M8A==",
|
||||
"requires": {
|
||||
"@sentry/hub": "4.4.2",
|
||||
"@sentry/minimal": "4.4.2",
|
||||
"@sentry/types": "4.4.2",
|
||||
"@sentry/utils": "4.4.2",
|
||||
"tslib": "^1.9.3"
|
||||
}
|
||||
},
|
||||
"@sentry/hub": {
|
||||
"version": "4.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-4.4.2.tgz",
|
||||
"integrity": "sha512-oe9ytXkTWyD+QmOpVzHAqTbRV4Hc0ee2Nt6HvrDtRmlXzQxfvTWG2F8KYT6w8kzqg5klnuRpnsmgTTV3KuNBVQ==",
|
||||
"requires": {
|
||||
"@sentry/types": "4.4.2",
|
||||
"@sentry/utils": "4.4.2",
|
||||
"tslib": "^1.9.3"
|
||||
}
|
||||
},
|
||||
"@sentry/minimal": {
|
||||
"version": "4.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-4.4.2.tgz",
|
||||
"integrity": "sha512-GEZZiNvVgqFAESZhAe3vjwTInn13lI2bSI3ItQN4RUWKL/W4n/fwVoDJbkb1U8aWxanuMnRDEpKwyQv6zYTZfw==",
|
||||
"requires": {
|
||||
"@sentry/hub": "4.4.2",
|
||||
"@sentry/types": "4.4.2",
|
||||
"tslib": "^1.9.3"
|
||||
}
|
||||
},
|
||||
"@sentry/types": {
|
||||
"version": "4.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-4.4.2.tgz",
|
||||
"integrity": "sha512-QyQd6PKKIyjJgaq/RQjsxPJEWbXcuiWZ9RvSnhBjS5jj53HEzkM1qkbAFqlYHJ1DTJJ1EuOM4+aTmGzHe93zuA=="
|
||||
},
|
||||
"@sentry/utils": {
|
||||
"version": "4.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-4.4.2.tgz",
|
||||
"integrity": "sha512-j/Ad8G1abHlJdD2q7aWWbSOSeWB5M5v1R1VKL8YPlwEbSvvmEQWePhBKFI0qlnKd2ObdUQsj86pHEXJRSFNfCw==",
|
||||
"requires": {
|
||||
"@sentry/types": "4.4.2",
|
||||
"tslib": "^1.9.3"
|
||||
}
|
||||
},
|
||||
"@sindresorhus/is": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz",
|
||||
|
@ -49108,15 +48967,6 @@
|
|||
"object-assign": "^4.1.1",
|
||||
"react-is": "^16.8.1"
|
||||
}
|
||||
},
|
||||
"scheduler": {
|
||||
"version": "0.19.1",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz",
|
||||
"integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
},
|
||||
"homepage": "https://github.com/llk/scratch-www#readme",
|
||||
"dependencies": {
|
||||
"@sentry/browser": "4.4.2",
|
||||
"bunyan": "1.8.15",
|
||||
"clipboard-copy": "2.0.1",
|
||||
"express": "4.16.1",
|
||||
|
@ -128,6 +127,7 @@
|
|||
"react-slick": "0.16.0",
|
||||
"react-string-replace": "0.4.1",
|
||||
"react-telephone-input": "4.3.4",
|
||||
"react-test-renderer": "16.14.0",
|
||||
"redux": "3.5.2",
|
||||
"redux-mock-store": "1.5.4",
|
||||
"redux-thunk": "2.0.1",
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
const PropTypes = require('prop-types');
|
||||
const React = require('react');
|
||||
const Sentry = require('@sentry/browser');
|
||||
|
||||
const CrashMessageComponent = require('../crashmessage/crashmessage.jsx');
|
||||
import log from '../../lib/log.js';
|
||||
|
@ -9,28 +8,37 @@ class ErrorBoundary extends React.Component {
|
|||
constructor (props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
hasError: false,
|
||||
errorId: null
|
||||
error: null,
|
||||
errorInfo: null
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an error caught by this ErrorBoundary component.
|
||||
* @param {Error} error - the error that was caught.
|
||||
* @param {React.ErrorInfo} errorInfo - the React error info associated with the error.
|
||||
*/
|
||||
componentDidCatch (error, errorInfo) {
|
||||
// Display fallback UI
|
||||
Sentry.withScope(scope => {
|
||||
scope.setTag('project', 'scratch-www');
|
||||
if (this.props.componentName) {
|
||||
scope.setTag('component', this.props.componentName);
|
||||
}
|
||||
Object.keys(errorInfo).forEach(key => {
|
||||
scope.setExtra(key, errorInfo[key]);
|
||||
});
|
||||
Sentry.captureException(error);
|
||||
});
|
||||
error = error || {
|
||||
stack: 'Unknown stack',
|
||||
message: 'Unknown error'
|
||||
};
|
||||
errorInfo = errorInfo || {
|
||||
componentStack: 'Unknown component stack'
|
||||
};
|
||||
|
||||
// only remember the first error: later errors might just be side effects of that first one
|
||||
if (!this.state.error) {
|
||||
// store error & errorInfo for debugging
|
||||
this.setState({
|
||||
hasError: true,
|
||||
errorId: Sentry.lastEventId()
|
||||
error,
|
||||
errorInfo
|
||||
});
|
||||
log.error(`Unhandled Error: ${error}, info: ${errorInfo}`);
|
||||
}
|
||||
|
||||
// report every error in the console
|
||||
const componentInfo = this.props.componentName ? ` in ${this.props.componentName}` : '';
|
||||
log.error(`Unhandled Error${componentInfo}: ${error.stack}\nComponent stack: ${errorInfo.componentStack}`);
|
||||
}
|
||||
|
||||
handleBack () {
|
||||
|
@ -38,10 +46,9 @@ class ErrorBoundary extends React.Component {
|
|||
}
|
||||
|
||||
render () {
|
||||
if (this.state.hasError) {
|
||||
if (this.state.error) {
|
||||
return (
|
||||
<CrashMessageComponent
|
||||
eventId={this.state.errorId}
|
||||
onBack={this.handleBack}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
const initSentry = () => {
|
||||
// initialize Sentry instance, making sure it hasn't been initialized already
|
||||
if (!window.Sentry && `${process.env.SENTRY_DSN}` !== '') {
|
||||
const Sentry = require('@sentry/browser');
|
||||
|
||||
Sentry.init({
|
||||
dsn: `${process.env.SENTRY_DSN}`,
|
||||
// Do not collect global onerror, only collect specifically from React error boundaries.
|
||||
// TryCatch plugin also includes errors from setTimeouts (i.e. the VM)
|
||||
integrations: integrations => integrations.filter(i =>
|
||||
!(i.name === 'GlobalHandlers' || i.name === 'TryCatch'))
|
||||
});
|
||||
|
||||
window.Sentry = Sentry; // Allow GUI access to Sentry via window
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = initSentry;
|
|
@ -3,9 +3,6 @@ const render = require('../../lib/render.jsx');
|
|||
const Scratch3Registration = require('../../components/registration/scratch3-registration.jsx');
|
||||
const ErrorBoundary = require('../../components/errorboundary/errorboundary.jsx');
|
||||
|
||||
const initSentry = require('../../lib/sentry.js');
|
||||
initSentry();
|
||||
|
||||
require('./join.scss');
|
||||
const Register = () => (
|
||||
<ErrorBoundary componentName="Join">
|
||||
|
|
|
@ -14,9 +14,6 @@ const previewActions = require('../../redux/preview.js');
|
|||
const GUI = require('scratch-gui');
|
||||
const IntlGUI = injectIntl(GUI.default);
|
||||
|
||||
const initSentry = require('../../lib/sentry.js');
|
||||
initSentry();
|
||||
|
||||
class EmbedView extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
|
|
|
@ -39,9 +39,7 @@ const IntlGUI = injectIntl(GUI.default);
|
|||
|
||||
const localStorageAvailable = 'localStorage' in window && window.localStorage !== null;
|
||||
|
||||
const initSentry = require('../../lib/sentry.js');
|
||||
const xhr = require('xhr');
|
||||
initSentry();
|
||||
|
||||
class Preview extends React.Component {
|
||||
constructor (props) {
|
||||
|
|
|
@ -1,76 +1,24 @@
|
|||
import React from 'react';
|
||||
const {mountWithIntl} = require('../../helpers/intl-helpers.jsx');
|
||||
|
||||
jest.mock('@sentry/browser', () => {
|
||||
const setExtra = jest.fn();
|
||||
const setTag = jest.fn();
|
||||
|
||||
const makeScope = (setExtraParam, setTagParam) => {
|
||||
const thisScope = {
|
||||
setExtra: setExtraParam,
|
||||
setTag: setTagParam
|
||||
};
|
||||
return thisScope;
|
||||
};
|
||||
const Sentry = {
|
||||
captureException: jest.fn(),
|
||||
lastEventId: function () {
|
||||
return 0;
|
||||
},
|
||||
setExtra: setExtra,
|
||||
setTag: setTag,
|
||||
withScope: jest.fn(cb => {
|
||||
cb(makeScope(setExtra, setTag));
|
||||
})
|
||||
};
|
||||
return Sentry;
|
||||
});
|
||||
|
||||
const Sentry = require('@sentry/browser');
|
||||
import CrashMessageComponent from '../../../src/components/crashmessage/crashmessage.jsx';
|
||||
import ErrorBoundary from '../../../src/components/errorboundary/errorboundary.jsx';
|
||||
|
||||
const ChildComponent = () => <div>hello</div>;
|
||||
|
||||
describe('ErrorBoundary', () => {
|
||||
let errorBoundaryWrapper;
|
||||
|
||||
const ChildClass = () => (
|
||||
<div>
|
||||
Children here
|
||||
</div>
|
||||
);
|
||||
test('ErrorBoundary shows children before error and CrashMessageComponent after', () => {
|
||||
const child = <ChildComponent />;
|
||||
const wrapper = mountWithIntl(<ErrorBoundary>{child}</ErrorBoundary>);
|
||||
const childWrapper = wrapper.childAt(0);
|
||||
|
||||
beforeEach(() => {
|
||||
errorBoundaryWrapper = mountWithIntl(
|
||||
<ErrorBoundary
|
||||
componentName="TestEBName"
|
||||
>
|
||||
<ChildClass id="childClass" />
|
||||
</ErrorBoundary>
|
||||
);
|
||||
});
|
||||
expect(wrapper.containsMatchingElement(child)).toBeTruthy();
|
||||
expect(wrapper.containsMatchingElement(<CrashMessageComponent />)).toBeFalsy();
|
||||
|
||||
test('calling ErrorBoundary\'s componentDidCatch() calls Sentry.withScope()', () => {
|
||||
const errorBoundaryInstance = errorBoundaryWrapper.instance();
|
||||
errorBoundaryInstance.componentDidCatch('error', {});
|
||||
expect(Sentry.withScope).toHaveBeenCalled();
|
||||
});
|
||||
childWrapper.simulateError(new Error('fake error for testing purposes'));
|
||||
|
||||
test('calling ErrorBoundary\'s componentDidCatch() calls Sentry.captureException()', () => {
|
||||
const errorBoundaryInstance = errorBoundaryWrapper.instance();
|
||||
errorBoundaryInstance.componentDidCatch('error', {});
|
||||
expect(Sentry.captureException).toHaveBeenCalledWith('error');
|
||||
});
|
||||
|
||||
test('throwing error under ErrorBoundary calls Sentry.withScope()', () => {
|
||||
const child = errorBoundaryWrapper.find('#childClass');
|
||||
expect(child.exists()).toEqual(true);
|
||||
child.simulateError({}, {});
|
||||
expect(Sentry.withScope).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('ErrorBoundary with name prop causes Sentry to setTag with that name', () => {
|
||||
const child = errorBoundaryWrapper.find('#childClass');
|
||||
expect(child.exists()).toEqual(true);
|
||||
child.simulateError({});
|
||||
expect(Sentry.setTag).toHaveBeenCalledWith('component', 'TestEBName');
|
||||
expect(wrapper.containsMatchingElement(child)).toBeFalsy();
|
||||
expect(wrapper.containsMatchingElement(<CrashMessageComponent />)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -230,8 +230,7 @@ module.exports = {
|
|||
'process.env.CLOUDDATA_HOST': '"' + (process.env.CLOUDDATA_HOST || 'clouddata.scratch.mit.edu') + '"',
|
||||
'process.env.PROJECT_HOST': '"' + (process.env.PROJECT_HOST || 'https://projects.scratch.mit.edu') + '"',
|
||||
'process.env.STATIC_HOST': '"' + (process.env.STATIC_HOST || 'https://uploads.scratch.mit.edu') + '"',
|
||||
'process.env.SCRATCH_ENV': '"' + (process.env.SCRATCH_ENV || 'development') + '"',
|
||||
'process.env.SENTRY_DSN': '"' + (process.env.SENTRY_DSN || '') + '"'
|
||||
'process.env.SCRATCH_ENV': '"' + (process.env.SCRATCH_ENV || 'development') + '"'
|
||||
})
|
||||
])
|
||||
.concat(process.env.ANALYZE_BUNDLE === 'true' ? [
|
||||
|
|
Loading…
Reference in a new issue