Skip to content

Commit b959613

Browse files
committed
🔀 Merge remote-tracking branch 'upstream/master' into docs/ds2-21-updates
2 parents 01cb9f4 + b3d4d89 commit b959613

23 files changed

+331
-773
lines changed

‎.github/workflows/test-codegen.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131

3232
strategy:
3333
matrix:
34-
node-version: [12.x]
34+
node-version: ['16.x']
3535

3636
steps:
3737
- uses: actions/checkout@v2

‎.github/workflows/tests.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
runs-on: ubuntu-latest
2929
strategy:
3030
matrix:
31-
node: ['14.x']
31+
node: ['16.x']
3232

3333
steps:
3434
- name: Checkout repo
@@ -58,7 +58,7 @@ jobs:
5858
strategy:
5959
fail-fast: false
6060
matrix:
61-
node: ['14.x']
61+
node: ['16.x']
6262
steps:
6363
- name: Checkout repo
6464
uses: actions/checkout@v2
@@ -95,7 +95,7 @@ jobs:
9595
strategy:
9696
fail-fast: false
9797
matrix:
98-
node: ['14.x']
98+
node: ['16.x']
9999
ts: ['4.1', '4.2', '4.3', '4.4', '4.5', '4.6', '4.7']
100100
steps:
101101
- name: Checkout repo

‎packages/rtk-query-codegen-openapi/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"@reduxjs/toolkit": "^1.6.0",
3636
"@types/commander": "^2.12.2",
3737
"@types/glob-to-regexp": "^0.4.0",
38-
"@types/jest": "^26.0.20",
38+
"@types/jest": "^27",
3939
"@types/lodash": "^4.14.165",
4040
"@types/node": "^14.14.12",
4141
"@types/prettier": "^2.1.6",
@@ -46,11 +46,11 @@
4646
"esbuild": "^0.13.10",
4747
"esbuild-runner": "^2.2.1",
4848
"husky": "^4.3.6",
49-
"jest": "^26.6.3",
49+
"jest": "^27",
5050
"msw": "^0.41.1",
5151
"openapi-types": "^9.1.0",
5252
"pretty-quick": "^3.1.0",
53-
"ts-jest": "^26.4.4",
53+
"ts-jest": "^27",
5454
"ts-node": "^10.4.0",
5555
"yalc": "^1.0.0-pre.47"
5656
},

‎packages/rtk-query-codegen-openapi/test/cli.test.ts

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ afterEach(() => {
3333

3434
describe('CLI options testing', () => {
3535
test('generation with `config.example.js`', async () => {
36-
jest.setTimeout(10000);
37-
3836
const out = await cli([`./config.example.js`], __dirname);
3937

4038
expect(out).toEqual({
@@ -46,11 +44,9 @@ Done
4644
});
4745

4846
expect(fs.readFileSync(path.resolve(tmpDir, 'example.ts'), 'utf-8')).toMatchSnapshot();
49-
});
47+
}, 25000);
5048

5149
test('paths are relative to configfile, not to cwd', async () => {
52-
jest.setTimeout(10000);
53-
5450
const out = await cli([`../test/config.example.js`], path.resolve(__dirname, '../src'));
5551

5652
expect(out).toEqual({
@@ -62,11 +58,9 @@ Done
6258
});
6359

6460
expect(fs.readFileSync(path.resolve(tmpDir, 'example.ts'), 'utf-8')).toMatchSnapshot();
65-
});
61+
}, 25000);
6662

6763
test('ts, js and json all work the same', async () => {
68-
jest.setTimeout(25000);
69-
7064
await cli([`./config.example.js`], __dirname);
7165
const fromJs = fs.readFileSync(path.resolve(tmpDir, 'example.ts'), 'utf-8');
7266
await cli([`./config.example.ts`], __dirname);
@@ -76,12 +70,10 @@ Done
7670

7771
expect(fromTs).toEqual(fromJs);
7872
expect(fromJson).toEqual(fromJs);
79-
});
73+
}, 25000);
8074

8175
test('missing parameters doesnt fail', async () => {
82-
jest.setTimeout(25000);
83-
8476
const out = await cli([`./config.invalid-example.json`], __dirname);
85-
expect(out.stderr).toContain("Error: path parameter petId does not seem to be defined in '/pet/{petId}'!")
86-
});
77+
expect(out.stderr).toContain("Error: path parameter petId does not seem to be defined in '/pet/{petId}'!");
78+
}, 25000);
8779
});

‎packages/toolkit/jest.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
module.exports = {
2+
testEnvironment: 'jest-environment-jsdom',
23
setupFilesAfterEnv: ['./jest.setup.js'],
34
testMatch: ['<rootDir>/src/**/*.(spec|test).[jt]s?(x)'],
45
moduleNameMapper: {

‎packages/toolkit/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"@testing-library/react": "^13.3.0",
3333
"@testing-library/user-event": "^14.2.0",
3434
"@types/convert-source-map": "^1.5.1",
35-
"@types/jest": "^24.0.11",
35+
"@types/jest": "^27",
3636
"@types/json-stringify-safe": "^5.0.0",
3737
"@types/nanoid": "^2.1.0",
3838
"@types/node": "^10.14.4",
@@ -57,7 +57,7 @@
5757
"eslint-plugin-react-hooks": "^4.2.0",
5858
"fs-extra": "^9.1.0",
5959
"invariant": "^2.2.4",
60-
"jest": "^26.6.3",
60+
"jest": "^27",
6161
"json-stringify-safe": "^5.0.1",
6262
"magic-string": "^0.25.7",
6363
"merge-source-map": "^1.1.0",
@@ -71,7 +71,7 @@
7171
"size-limit": "^4.11.0",
7272
"source-map": "^0.7.3",
7373
"terser": "^5.6.1",
74-
"ts-jest": "^26.5.5",
74+
"ts-jest": "^27",
7575
"tslib": "^1.10.0",
7676
"typescript": "~4.2.4",
7777
"yargs": "^15.3.1"

‎packages/toolkit/src/createSlice.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,16 @@ export function createSlice<
262262
if (!name) {
263263
throw new Error('`name` is a required option for createSlice')
264264
}
265+
266+
if (
267+
typeof process !== 'undefined' &&
268+
process.env.NODE_ENV === 'development'
269+
) {
270+
if(options.initialState === undefined) {
271+
console.error('You must provide an `initialState` value that is not `undefined`. You may have misspelled `initialState`')
272+
}
273+
}
274+
265275
const initialState =
266276
typeof options.initialState == 'function'
267277
? options.initialState

‎packages/toolkit/src/entities/sorted_state_adapter.ts

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -71,33 +71,30 @@ export function createSortedStateAdapter<T>(
7171
return updateManyMutably([update], state)
7272
}
7373

74-
// eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
75-
function takeUpdatedModel(models: T[], update: Update<T>, state: R): boolean {
76-
if (!(update.id in state.entities)) {
77-
return false
78-
}
79-
80-
const original = state.entities[update.id]
81-
const updated = Object.assign({}, original, update.changes)
82-
const newKey = selectIdValue(updated, selectId)
83-
84-
delete state.entities[update.id]
85-
86-
models.push(updated)
87-
88-
return newKey !== update.id
89-
}
90-
9174
function updateManyMutably(
9275
updates: ReadonlyArray<Update<T>>,
9376
state: R
9477
): void {
95-
const models: T[] = []
78+
let appliedUpdates = false
79+
80+
for (let update of updates) {
81+
const entity = state.entities[update.id]
82+
if (!entity) {
83+
continue
84+
}
9685

97-
updates.forEach((update) => takeUpdatedModel(models, update, state))
86+
appliedUpdates = true
9887

99-
if (models.length !== 0) {
100-
merge(models, state)
88+
Object.assign(entity, update.changes)
89+
const newId = selectId(entity)
90+
if (update.id !== newId) {
91+
delete state.entities[update.id]
92+
state.entities[newId] = entity
93+
}
94+
}
95+
96+
if (appliedUpdates) {
97+
resortEntities(state)
10198
}
10299
}
103100

@@ -139,6 +136,10 @@ export function createSortedStateAdapter<T>(
139136
state.entities[selectId(model)] = model
140137
})
141138

139+
resortEntities(state)
140+
}
141+
142+
function resortEntities(state: R) {
142143
const allEntities = Object.values(state.entities) as T[]
143144
allEntities.sort(sort)
144145

‎packages/toolkit/src/entities/tests/sorted_state_adapter.test.ts

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,34 @@ describe('Sorted State Adapter', () => {
343343
})
344344
})
345345

346+
it('should maintain a stable sorting order when updating items', () => {
347+
interface OrderedEntity {
348+
id: string
349+
order: number
350+
ts: number
351+
}
352+
const sortedItemsAdapter = createEntityAdapter<OrderedEntity>({
353+
sortComparer: (a, b) => a.order - b.order,
354+
})
355+
const withInitialItems = sortedItemsAdapter.setAll(
356+
sortedItemsAdapter.getInitialState(),
357+
[
358+
{ id: 'A', order: 1, ts: 0 },
359+
{ id: 'B', order: 2, ts: 0 },
360+
{ id: 'C', order: 3, ts: 0 },
361+
{ id: 'D', order: 3, ts: 0 },
362+
{ id: 'E', order: 3, ts: 0 },
363+
]
364+
)
365+
366+
const updated = sortedItemsAdapter.updateOne(withInitialItems, {
367+
id: 'C',
368+
changes: { ts: 5 },
369+
})
370+
371+
expect(updated.ids).toEqual(['A', 'B', 'C', 'D', 'E'])
372+
})
373+
346374
it('should let you update many entities by id in the state', () => {
347375
const firstChange = { title: 'Zack' }
348376
const secondChange = { title: 'Aaron' }
@@ -652,12 +680,20 @@ describe('Sorted State Adapter', () => {
652680
test('updateMany', () => {
653681
const firstChange = { title: 'First Change' }
654682
const secondChange = { title: 'Second Change' }
655-
const withMany = adapter.setAll(state, [TheGreatGatsby, AClockworkOrange])
683+
const thirdChange = { title: 'Third Change' }
684+
const fourthChange = { author: 'Fourth Change' }
685+
const withMany = adapter.setAll(state, [
686+
TheGreatGatsby,
687+
AClockworkOrange,
688+
TheHobbit,
689+
])
656690

657691
const result = createNextState(withMany, (draft) => {
658692
adapter.updateMany(draft, [
659-
{ id: TheGreatGatsby.id, changes: firstChange },
660-
{ id: AClockworkOrange.id, changes: secondChange },
693+
{ id: TheHobbit.id, changes: firstChange },
694+
{ id: TheGreatGatsby.id, changes: secondChange },
695+
{ id: AClockworkOrange.id, changes: thirdChange },
696+
{ id: TheHobbit.id, changes: fourthChange },
661697
])
662698
})
663699

@@ -666,14 +702,20 @@ describe('Sorted State Adapter', () => {
666702
"entities": Object {
667703
"aco": Object {
668704
"id": "aco",
669-
"title": "Second Change",
705+
"title": "Third Change",
670706
},
671707
"tgg": Object {
672708
"id": "tgg",
709+
"title": "Second Change",
710+
},
711+
"th": Object {
712+
"author": "Fourth Change",
713+
"id": "th",
673714
"title": "First Change",
674715
},
675716
},
676717
"ids": Array [
718+
"th",
677719
"tgg",
678720
"aco",
679721
],

‎packages/toolkit/src/entities/tests/utils.spec.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { selectIdValue } from '../utils'
21
import { AClockworkOrange } from './fixtures/book'
32

43
describe('Entity utils', () => {
@@ -12,26 +11,29 @@ describe('Entity utils', () => {
1211

1312
afterEach(() => {
1413
process.env = OLD_ENV
14+
jest.resetAllMocks()
1515
})
1616

1717
it('should not warn when key does exist', () => {
18-
const spy = spyOn(console, 'warn')
19-
20-
selectIdValue(AClockworkOrange, (book) => book.id)
18+
const { selectIdValue } = require('../utils')
19+
const spy = jest.spyOn(console, 'warn')
2120

21+
selectIdValue(AClockworkOrange, (book: any) => book.id)
2222
expect(spy).not.toHaveBeenCalled()
2323
})
2424

2525
it('should warn when key does not exist in dev mode', () => {
26-
const spy = spyOn(console, 'warn')
26+
const { selectIdValue } = require('../utils')
27+
const spy = jest.spyOn(console, 'warn')
2728

2829
selectIdValue(AClockworkOrange, (book: any) => book.foo)
2930

3031
expect(spy).toHaveBeenCalled()
3132
})
3233

3334
it('should warn when key is undefined in dev mode', () => {
34-
const spy = spyOn(console, 'warn')
35+
const { selectIdValue } = require('../utils')
36+
const spy = jest.spyOn(console, 'warn')
3537

3638
const undefinedAClockworkOrange = { ...AClockworkOrange, id: undefined }
3739
selectIdValue(undefinedAClockworkOrange, (book: any) => book.id)
@@ -41,7 +43,8 @@ describe('Entity utils', () => {
4143

4244
it('should not warn when key does not exist in prod mode', () => {
4345
process.env.NODE_ENV = 'production'
44-
const spy = spyOn(console, 'warn')
46+
const { selectIdValue } = require('../utils')
47+
const spy = jest.spyOn(console, 'warn')
4548

4649
selectIdValue(AClockworkOrange, (book: any) => book.foo)
4750

@@ -50,7 +53,8 @@ describe('Entity utils', () => {
5053

5154
it('should not warn when key is undefined in prod mode', () => {
5255
process.env.NODE_ENV = 'production'
53-
const spy = spyOn(console, 'warn')
56+
const { selectIdValue } = require('../utils')
57+
const spy = jest.spyOn(console, 'warn')
5458

5559
const undefinedAClockworkOrange = { ...AClockworkOrange, id: undefined }
5660
selectIdValue(undefinedAClockworkOrange, (book: any) => book.id)

0 commit comments

Comments
 (0)