Skip to content

Commit

Permalink
Merge pull request #102 from danielr18/update-next-14
Browse files Browse the repository at this point in the history
Update to support Next 14 / next-redux-wrapper 8
  • Loading branch information
danielr18 authored Nov 4, 2023
2 parents 0d1fc8c + 3f7e4ca commit b39f8c0
Show file tree
Hide file tree
Showing 23 changed files with 7,395 additions and 19,654 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ jobs:
steps:
- uses: actions/checkout@v2

- name: Use Node.js 16.x
- name: Use Node.js 18.x
uses: actions/setup-node@v1
with:
node-version: 16.x
node-version: 18.x

- name: npm install
run: |
Expand Down
21 changes: 21 additions & 0 deletions cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* eslint-disable @typescript-eslint/no-var-requires */
import { defineConfig } from 'cypress'

export default defineConfig({
e2e: {
baseUrl: 'http://localhost:3000',
setupNodeEvents(on, config) {
require('@cypress/code-coverage/task')(on, config)
// include any other plugin code...

// It's IMPORTANT to return the config object
// with any changed environment variables
return config
},
env: {
codeCoverage: {
url: '/api/__coverage__',
},
},
},
})
8 changes: 0 additions & 8 deletions cypress.json

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/// <reference types="Cypress" />

import { onLocationChanged } from '../../test-lib/actions';
import locationFromUrl from '../../test-lib/utils/locationFromUrl';

Expand Down Expand Up @@ -227,10 +225,12 @@ describe('Connected Next Router', () => {
cy.location('pathname').should('include', '/about');
cy.contains('Push /delay').click();
cy.location('pathname').should('include', '/delay');
cy.contains('Delay');
cy.window().then((window) => {
window.reduxStore.dispatch(onLocationChanged(locationFromUrl('/about')));
});
cy.location('pathname').should('include', '/about');
cy.contains('About');
cy.window().then((window) => {
window.reduxStore.dispatch(onLocationChanged(locationFromUrl('/delay')));
window.reduxStore.dispatch(onLocationChanged(locationFromUrl('/ssg')));
Expand Down
22 changes: 0 additions & 22 deletions cypress/plugins/index.js

This file was deleted.

25 changes: 0 additions & 25 deletions cypress/support/commands.js

This file was deleted.

1 change: 1 addition & 0 deletions cypress/support/e2e.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import '@cypress/code-coverage/support'
21 changes: 0 additions & 21 deletions cypress/support/index.js

This file was deleted.

6 changes: 3 additions & 3 deletions e2e/components/navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,17 +98,17 @@ const Navigation = () => {
<ul>
<li>
<Link href={{ pathname: '/' }}>
<a>Push /</a>
Push /
</Link>
</li>
<li>
<Link href="/about?foo=bar" replace>
<a>Replace /about</a>
Replace /about
</Link>
</li>
<li>
<Link href="/blog/[postId]" as="/blog/3">
<a>Push /blog/3</a>
Push /blog/3
</Link>
</li>
</ul>
Expand Down
2 changes: 1 addition & 1 deletion e2e/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module.exports = {
webpack(config) {
// Allows to mock process.env.NODE_ENV from tests
config.plugins.filter(p => p instanceof webpack.DefinePlugin).forEach(plugin => {
plugin.definitions['process.env.NODE_ENV'] = `("NODE_ENV" in window ? window["NODE_ENV"] : "${process.env.NODE_ENV}")`
plugin.definitions['process.env.NODE_ENV'] = `((typeof window !== 'undefined' && "NODE_ENV" in window) ? window["NODE_ENV"] : "${process.env.NODE_ENV}")`
});
return config;
},
Expand Down
49 changes: 35 additions & 14 deletions e2e/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,39 @@
import App from 'next/app'
import React from 'react'
import { ConnectedRouter } from '../../test-lib'
import { wrapper } from '../store/configure-store'
import App, { AppProps } from 'next/app'
import React, { useEffect, useMemo } from 'react'
import { ConnectedRouter, initialRouterState } from '../../test-lib'
import { customRouterWrapper, wrapper } from '../store/configure-store'
import { Provider } from 'react-redux';
import Router from 'next/router';
import { onLocationChanged } from '../../test-lib/actions';
import locationFromUrl from '../../test-lib/utils/locationFromUrl';

class ExampleApp extends App {
render() {
const { Component, pageProps } = this.props
const Wrapper = Component['disableConnectedRouter'] ? React.Fragment : ConnectedRouter;
return (
export default function ExampleApp({ Component, ...rest }: AppProps) {
const Wrapper = Component['disableConnectedRouter'] ? React.Fragment : ConnectedRouter;
// Hack to support different implementations for the e2e tests
const reduxWrapper = useMemo(() => {
return rest.pageProps?.router === 'custom' ? customRouterWrapper : wrapper;
}, []);
const {store, props} = reduxWrapper.useWrappedStore(rest);

useEffect(() => {
Router.ready(() => {
store.dispatch(onLocationChanged(locationFromUrl(Router.asPath)));
});
}, [store]);

useEffect(() => {
if (typeof window === 'undefined') return;
window['reduxStore'] = store;
return () => {
delete window['reduxStore'];
}
}, [store]);

return (
<Provider store={store}>
<Wrapper>
<Component {...pageProps} />
<Component {...props.pageProps} />
</Wrapper>
)
}
</Provider>
);
}

export default wrapper.withRedux(ExampleApp)
14 changes: 7 additions & 7 deletions e2e/pages/bps.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import React from 'react'
import { useSelector } from 'react-redux'
import { NextPage } from 'next'
import Router from 'next/router'
import { useRouter } from 'next/router'
import Navigation from '../components/navigation'
import { State } from '../typings'

const About : NextPage = () => {
const routerState = useSelector((state: State) => state.router)

const router = useRouter()
React.useEffect(() => {
Router.beforePopState(() => {
Router.replace('/hello')
return true;
router.beforePopState(() => {
router.replace('/hello')
return false;
});
}, [Router])
}, [router])

return (
<div>
<h1>About</h1>
<h1>BPS</h1>
<pre>{JSON.stringify(routerState)}</pre>
<Navigation />
</div>
Expand Down
7 changes: 7 additions & 0 deletions e2e/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react'
import Navigation from '../components/navigation'
import { GetServerSideProps } from 'next';

const Home = () => (
<div>
Expand All @@ -8,4 +9,10 @@ const Home = () => (
</div>
)

// For testing purposes, we need to pass a custom router based on a query param
export const getServerSideProps: GetServerSideProps = async (context) => {
const { query } = context;
return { props: { router: query.router || null } }
}

export default Home
60 changes: 40 additions & 20 deletions e2e/store/configure-store.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import { createStore, applyMiddleware, combineReducers, AnyAction, compose } from 'redux'
import { legacy_createStore as createStore, applyMiddleware, combineReducers, AnyAction, compose, Store } from 'redux'
import { createRouterMiddleware, initialRouterState, routerReducer } from '../../test-lib'
import { format } from 'url'
import { Reducer } from 'redux'
import { MakeStore, HYDRATE, createWrapper } from 'next-redux-wrapper'
import { AppContext } from 'next/app'
import { MakeStore, HYDRATE, createWrapper, Context } from 'next-redux-wrapper'
import { State } from '../typings'
import Router from 'next/router'
import { onLocationChanged } from '../../test-lib/actions'
import locationFromUrl from '../../test-lib/utils/locationFromUrl'

const combinedReducer = combineReducers({
router: routerReducer,
})

const composeEnhancers = typeof window !== 'undefined' ? window['__REDUX_DEVTOOLS_EXTENSION_COMPOSE__'] || compose : compose;

const composeEnhancers =
(typeof window !== 'undefined' &&
window['__REDUX_DEVTOOLS_EXTENSION_COMPOSE__']) ||
compose;

const reducer: Reducer<State, AnyAction> = (state, action) => {
if (action.type === HYDRATE) {
if (action.type === HYDRATE) {
const nextState = {
...state, // use previous state
...action.payload, // apply delta from hydration
Expand All @@ -28,10 +31,27 @@ const reducer: Reducer<State, AnyAction> = (state, action) => {
}
}

export const initStore: MakeStore<State> = (context) => {
const { asPath, query } = (context as AppContext).ctx || Router.router || {};
let routerMiddleware;
if (query && query.router === 'custom') {
export const initStore: MakeStore<Store<State>> = (context: Context) => {
let routerMiddleware = createRouterMiddleware();
// Context is empty when using the useWrappedStore hook.
// See https://github.com/kirill-konshin/next-redux-wrapper/issues/554
const initialState: State = {
router: initialRouterState()
};
const store = createStore(
reducer,
initialState,
composeEnhancers(applyMiddleware(routerMiddleware))
);
return store;
}

export const initCustomRouterStore: MakeStore<Store<State>> = (context: Context) => {
const initialState: State = {
router: initialRouterState()
};
let routerMiddleware: ReturnType<typeof createRouterMiddleware>;
if (typeof window !== 'undefined') {
Router['pushRoute'] = Router.push;
routerMiddleware = createRouterMiddleware({
methods: {
Expand All @@ -40,15 +60,15 @@ export const initStore: MakeStore<State> = (context) => {
},
});
} else {
routerMiddleware = createRouterMiddleware()
}
let initialState
if (asPath) {
initialState = {
router: initialRouterState(asPath),
}
routerMiddleware = createRouterMiddleware();
}
return createStore(reducer, initialState, composeEnhancers(applyMiddleware(routerMiddleware)))
const store = createStore(
reducer,
initialState,
composeEnhancers(applyMiddleware(routerMiddleware))
);
return store;
}

export const wrapper = createWrapper(initStore, { storeKey: 'reduxStore' })
export const wrapper = createWrapper(initStore)
export const customRouterWrapper = createWrapper(initCustomRouterStore)
1 change: 0 additions & 1 deletion e2e/typings.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,4 @@ import { AppContext } from 'next/app';
import { RouterState } from '../test-lib/types';
export interface State {
router: RouterState,
routerEventCounts: any
}
Loading

0 comments on commit b39f8c0

Please sign in to comment.