-
Notifications
You must be signed in to change notification settings - Fork 2
Update depedencies to fix known security vulnerabiltiies #165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Enzyme does not support React >= 17, and we want to upgrade to that version to resolve known security vulnerabilities in the dependant libraries. Apparentely, React Testing Library is the recommended replacement (https://testing-library.com/docs/react-testing-library/migrate-from-enzyme).
* This quickly snowballs to updating the React version as some of the dependant libraries (like react-tag-input) only support the latest one. * The other major chunk of vulnerabilities was in webpack. * Tests were migrated from Enzyme to React Testing Library beforehand
Apparantely, React Router 7 is going to bring some changes, and people are encouraged to opt int to those early.
// manipulate underlying UI library (it can be used not only with React). | ||
// Since we use React 16, we need to set a proper adapter. | ||
configure({ adapter: new Adapter() }) | ||
// React Testing Library setup - jest-dom provides custom matchers for DOM elements |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like we don't need a custom test setup anymore?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like it.
@@ -3,7 +3,7 @@ const process = require('process') | |||
|
|||
const webpack = require('webpack') | |||
|
|||
const CleanWebpackPlugin = require('clean-webpack-plugin') | |||
const { CleanWebpackPlugin } = require('clean-webpack-plugin') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unpacking, or deconstruction. Most likely require('clean-webpack-plugin')
used to return just one class, and now it returns a mapping (object in js) where CleanWebpackPlugin is just one of its keys.
The syntax with { CleanWebpackPlugin }
just allows to bind the CleanWebpackPlugin
key of the require('clean-webpack-plugin')
object to the CleanWebpackPlugin
local constant.
@@ -168,29 +168,24 @@ module.exports = () => { | |||
loader: 'css-loader', | |||
options: { | |||
modules: false, | |||
minimize: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did Claude decide to drop this?
// Enable source maps if they are specified in devtool | ||
// option. God-Knows-Why css-loader doesn't check devtool | ||
// value in order to initialize its sourceMap value, hence | ||
// this line. | ||
sourceMap: true, | ||
url: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this needed now?
{ | ||
test: /\.(png|svg|jpg|woff|svg|ttf|woff2|eot)$/, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is svg dropped?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW, it seems svg was duplicated.
|
||
node: { | ||
net: 'empty', | ||
fallback: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's this for?
@@ -1,6 +1,6 @@ | |||
@font-face | |||
font-family: "IconFont" | |||
src: url("../assets/fonts/icon-font.woff") format("woff") | |||
src: url("../../assets/fonts/icon-font.woff") format("woff") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's only one level up?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤷
<Route path="/sign-in" element={<SignIn />} /> | ||
{/* Routes renders the first matched route, so we need to keep this | ||
one last as the regexp below matches the paths of other pages */} | ||
<Route path="/:id" element={<Snippet />} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
([a-zA-Z0-9]+)
should have been preserved?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably. But I don't think it's important. Worst case we will stop showing 404 on something that doesn't look like a legit snippet ID.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably. But I don't think it's important. Worst case we will stop showing 404 on something that doesn't look like a legit snippet ID.
}, | ||
"scripts": { | ||
"lint": "eslint --ignore-path .gitignore --ext ts .", | ||
"lint": "eslint --ext ts,tsx src/", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This no longer lints the tests?
|
||
import Spinner from '../../../src/components/common/Spinner' | ||
|
||
// Mock the SVG import to prevent test failures |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I remember, webpack
patches the import
statement so it can track what was used and produce the final bundle that contains what was used only. In addition to that, it extends import
behavior in not compatible way -- it allows importing assets, so it can do the same thing for icons and images and literally anything else.
@lotrien @ikalnytskyi Check out this magnificent creation by Claude :) |
"joi": "^17.13.3", | ||
"parse-link-header": "^2.0.0", | ||
"querystring-es3": "^0.2.1", | ||
"react": "^18.3.1", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, why it wasn't updated to the latest stable version? 🤔
|
||
import Spinner from '../../../src/components/common/Spinner' | ||
|
||
// Mock the SVG import to prevent test failures |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I remember, webpack
patches the import
statement so it can track what was used and produce the final bundle that contains what was used only. In addition to that, it extends import
behavior in not compatible way -- it allows importing assets, so it can do the same thing for icons and images and literally anything else.
const spinnerWrapper = container.querySelector('.spinner') | ||
|
||
expect(spinnerWrapper).toBeInTheDocument() | ||
expect(spinnerWrapper).toHaveClass('spinner') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: A silly check because we already query by a class name (see L15).
const { container } = render(<Title title={title} />) | ||
const titleElement = container.querySelector('.title') | ||
|
||
expect(titleElement).toHaveClass('title') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto.
// manipulate underlying UI library (it can be used not only with React). | ||
// Since we use React 16, we need to set a proper adapter. | ||
configure({ adapter: new Adapter() }) | ||
// React Testing Library setup - jest-dom provides custom matchers for DOM elements |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like it.
|
||
// Each time we change something, a new version of bundled assets is | ||
// produced. Since we use hash in filenames in order to invalidate cache | ||
// on change, we end up having multiple outdated copies in output | ||
// directory. Let's cleanup it before produce a fresh build. | ||
new CleanWebpackPlugin([path.resolve(__dirname, 'dist')]), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems it defaults now to output.path
of the main webpack config which points to the same directory.
@@ -1,6 +1,6 @@ | |||
@font-face | |||
font-family: "IconFont" | |||
src: url("../assets/fonts/icon-font.woff") format("woff") | |||
src: url("../../assets/fonts/icon-font.woff") format("woff") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤷
@@ -7,17 +7,17 @@ const Sidebar: FC = () => ( | |||
<nav className="sidebar"> | |||
<ul className="sidebar-list"> | |||
<li className="sidebar-item"> | |||
<NavLink exact to="/" activeClassName="active" title="New Snippet"> | |||
<NavLink to="/" className={({ isActive }) => isActive ? "active" : ""} title="New Snippet" end> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since our navlinks are always active, do we even need this change?
Also, what's that "end" at the end?
<Route path="/sign-in" element={<SignIn />} /> | ||
{/* Routes renders the first matched route, so we need to keep this | ||
one last as the regexp below matches the paths of other pages */} | ||
<Route path="/:id" element={<Snippet />} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably. But I don't think it's important. Worst case we will stop showing 404 on something that doesn't look like a legit snippet ID.
<Route path="/sign-in" element={<SignIn />} /> | ||
{/* Routes renders the first matched route, so we need to keep this | ||
one last as the regexp below matches the paths of other pages */} | ||
<Route path="/:id" element={<Snippet />} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably. But I don't think it's important. Worst case we will stop showing 404 on something that doesn't look like a legit snippet ID.
This quickly snowballs into updating the React version, as some of the dependent libraries require the latest one. Updating React requires dropping Enzyme in favour of React Testing Library.
The other major chunk of vulnerabilities is in webpack