Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
react-magnetic-di
Advanced tools
A new take for dependency injection in React for your tests, storybooks and even experiments in production.
Dependency injection and component injection for testing purposes is not a new topic. Indeed, the ability to provide a custom implementation of a component/hook while testing or writing storybooks and examples it is extremely valuable.
A common pattern to solve this problem is injecting those "dependencies" in the component via props. However, that approach has a some of downsides:
We are leaking internal implementation details. Props are the public API of a component and we are polluting them with keys that are not relevant for actual consumers, and we are doing that just for our testing needs
Our dependencies are mixed together with other props, which makes them hard to recognise, analyse and might introduce naming conflicts
It introduces additional complexity, for instance when we have spread props down, as we probably don't want pass the dependencies down too
react-magnetic-di
takes inspiration from React PropTypes, forcing you to declare the dependencies statically and then using React Context to optionally override those dependencies, with nearly-zero performane overhead when the injection system is off.
npm i react-magnetic-di
# or
yarn add react-magnetic-di
Given a component with complex UI interaction or data dependencies, like a Modal or an Apollo Query, we want to be able integration test it without necessarily test those other dependencies. To achieve that, we define the dependencies on the class component:
import React, { Component } from 'react';
import { provideDependencies } from 'react-magnetic-di';
import { Modal as ModalDI } from 'material-ui';
import { Query as QueryDI } from 'react-apollo';
class MyComponent extends Component {
static dependencies = provideDependencies({
Modal: ModalDI,
Query: QueryDI,
});
render() {
const { Modal, Query } = MyComponent.dependencies();
return (
<Modal>
<Query>{({ data }) => data && 'Done!'}</Query>
</Modal>
);
}
}
Or on our functional component with hooks:
import React, { Component } from 'react';
import { provideDependencies } from 'react-magnetic-di';
import { Modal as ModalDI } from 'material-ui';
import { useQuery as useQueryDI } from 'react-apollo-hooks';
function MyComponent() {
const { Modal, useQuery } = MyComponent.dependencies();
const { data } = useQuery();
return <Modal>{data && 'Done!'}</Modal>;
}
MyComponent.dependencies = provideDependencies({
Modal: ModalDI,
useQuery: useQueryDI,
});
Finally, in the integration tests and storybooks we wrap the component with DependencyProvider
to override any dependency:
import React from 'react';
import { DependencyProvider } from 'react-magnetic-di';
import { ModalOpen, useQueryMock } from './examples';
storiesOf('Modal content', module).add('with text', () => (
<DependencyProvider use={{ Modal: ModalOpen, useQuery: useQueryMock }}>
<MyComponent />
</DependencyProvider>
));
In the example above we replace all Modal
dependencies across all components in the tree with the open version, but that might be wrong for useQuery
, as we might want to provide different data to different components. DependencyProvider
enables targeted dependency injection via target
prop. Together with providers composition it allows multiple, explicit dependency injections:
storiesOf('App', module).add('with text', () => (
/* replace Modal on all components */
<DependencyProvider use={{ Modal: ModalOpen }}>
{/* in MyComponent use one set of data */}
<DependencyProvider target={MyComponent} use={{ useQuery: useQueryMock }}>
{/* in MyOtherComponent use a different set of data */}
<DependencyProvider
target={MyOtherComponent}
use={{ useQuery: useQueryOtherMock }}
>
<MyApp />
</DependencyProvider>
</DependencyProvider>
</DependencyProvider>
));
Defines whenever context replacement is allowed or not. By default is NODE_ENV !== 'production'
. It can be enabled also in prod, but it is not recommended.
import { settings } from 'react-magnetic-di';
// only enable during testing
setting.enabled = process.env.NODE_ENV === 'test';
To test your changes you can run the examples (with npm run start
).
Also, make sure you run npm run preversion
before creating you PR so you will double check that linting, types and tests are fine.
FAQs
Context driven dependency injection
The npm package react-magnetic-di receives a total of 8,170 weekly downloads. As such, react-magnetic-di popularity was classified as popular.
We found that react-magnetic-di demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.