Skip to content

Commit ac6a218

Browse files
committed
up
1 parent a9530a8 commit ac6a218

File tree

3 files changed

+174
-161
lines changed

3 files changed

+174
-161
lines changed

spec/tests/useAsyncIterMemo.spec.ts

Lines changed: 159 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1-
import { nextTick } from 'node:process';
21
import { it, describe, expect, afterEach } from 'vitest';
32
import { gray } from 'colorette';
43
import { renderHook, cleanup as cleanupMountedReactTrees } from '@testing-library/react';
54
import { useAsyncIterMemo, iterateFormatted } from '../libEntrypoint.js';
65
import { pipe } from '../utils/pipe.js';
6+
import { IterableChannelTestHelper } from '../utils/IterableChannelTestHelper.js';
7+
import { feedChannelAcrossTicks } from '../utils/feedChannelAcrossTicks.js';
78
import { asyncIterToArray } from '../utils/asyncIterToArray.js';
89
import { asyncIterTake } from '../utils/asyncIterTake.js';
910
import { asyncIterOf } from '../utils/asyncIterOf.js';
1011
import { asyncIterTickSeparatedOf } from '../utils/asyncIterTickSeparatedOf.js';
11-
import { IterableChannelTestHelper } from '../utils/IterableChannelTestHelper.js';
1212

1313
afterEach(() => {
1414
cleanupMountedReactTrees();
1515
});
1616

1717
describe('`useAsyncIterMemo` hook', () => {
18-
it(gray('___ ___ ___ 1'), async () => {
18+
it(gray('When given mixed iterable and plain values, will work correctly'), async () => {
1919
const renderedHook = renderHook(
2020
({ val1, val2, iter1, iter2 }) =>
2121
useAsyncIterMemo((...deps) => deps, [val1, val2, iter1, iter2]),
@@ -37,177 +37,176 @@ describe('`useAsyncIterMemo` hook', () => {
3737
expect(await asyncIterToArray(resIter2)).toStrictEqual(['d', 'e', 'f']);
3838
});
3939

40-
it(gray('___ ___ ___ 2'), async () => {
41-
const channel1 = new IterableChannelTestHelper<string>();
42-
const channel2 = new IterableChannelTestHelper<string>();
43-
let timesRerun = 0;
44-
45-
const renderedHook = renderHook(
46-
({ val1, val2, iter1, iter2 }) =>
47-
useAsyncIterMemo(
48-
(...deps) => {
49-
timesRerun++;
50-
return deps;
40+
it(
41+
gray(
42+
'When updated consecutively with formatted iterables of the same source iterables each time, will work correctly and not re-run factory function'
43+
),
44+
async () => {
45+
const channel1 = new IterableChannelTestHelper<string>();
46+
const channel2 = new IterableChannelTestHelper<string>();
47+
let timesRerun = 0;
48+
49+
const renderedHook = renderHook(
50+
({ val1, val2, iter1, iter2 }) =>
51+
useAsyncIterMemo(
52+
(...deps) => {
53+
timesRerun++;
54+
return deps;
55+
},
56+
[val1, val2, iter1, iter2]
57+
),
58+
{
59+
initialProps: {
60+
val1: 'a',
61+
val2: 'b',
62+
iter1: iterateFormatted(channel1, v => `${v}_formatted_1st_time`),
63+
iter2: iterateFormatted(channel2, v => `${v}_formatted_1st_time`),
5164
},
52-
[val1, val2, iter1, iter2]
53-
),
54-
{
55-
initialProps: {
56-
val1: 'a',
57-
val2: 'b',
58-
iter1: iterateFormatted(channel1, v => `${v}_formatted_1st_time`),
59-
iter2: iterateFormatted(channel2, v => `${v}_formatted_1st_time`),
60-
},
61-
}
62-
);
63-
64-
const hookFirstResult = renderedHook.result.current;
65-
66-
{
67-
expect(timesRerun).toStrictEqual(1);
65+
}
66+
);
6867

69-
const [, , resIter1, resIter2] = hookFirstResult;
68+
const hookFirstResult = renderedHook.result.current;
7069

71-
feedChannelAcrossTicks(channel1, ['a', 'b', 'c']);
72-
const resIter1Values = await pipe(resIter1, asyncIterTake(3), asyncIterToArray);
73-
expect(resIter1Values).toStrictEqual([
74-
'a_formatted_1st_time',
75-
'b_formatted_1st_time',
76-
'c_formatted_1st_time',
77-
]);
70+
{
71+
expect(timesRerun).toStrictEqual(1);
72+
73+
const [, , resIter1, resIter2] = hookFirstResult;
74+
75+
feedChannelAcrossTicks(channel1, ['a', 'b', 'c']);
76+
const resIter1Values = await pipe(resIter1, asyncIterTake(3), asyncIterToArray);
77+
expect(resIter1Values).toStrictEqual([
78+
'a_formatted_1st_time',
79+
'b_formatted_1st_time',
80+
'c_formatted_1st_time',
81+
]);
82+
83+
feedChannelAcrossTicks(channel2, ['d', 'e', 'f']);
84+
const resIter2Values = await pipe(resIter2, asyncIterTake(3), asyncIterToArray);
85+
expect(resIter2Values).toStrictEqual([
86+
'd_formatted_1st_time',
87+
'e_formatted_1st_time',
88+
'f_formatted_1st_time',
89+
]);
90+
}
7891

79-
feedChannelAcrossTicks(channel2, ['d', 'e', 'f']);
80-
const resIter2Values = await pipe(resIter2, asyncIterTake(3), asyncIterToArray);
92+
renderedHook.rerender({
93+
val1: 'a',
94+
val2: 'b',
95+
iter1: iterateFormatted(channel1, v => `${v}_formatted_2nd_time`),
96+
iter2: iterateFormatted(channel2, v => `${v}_formatted_2nd_time`),
97+
});
8198

82-
expect(resIter2Values).toStrictEqual([
83-
'd_formatted_1st_time',
84-
'e_formatted_1st_time',
85-
'f_formatted_1st_time',
86-
]);
87-
}
99+
const hookSecondResult = renderedHook.result.current;
88100

89-
renderedHook.rerender({
90-
val1: 'a',
91-
val2: 'b',
92-
iter1: iterateFormatted(channel1, v => `${v}_formatted_2nd_time`),
93-
iter2: iterateFormatted(channel2, v => `${v}_formatted_2nd_time`),
94-
});
95-
96-
const hookSecondResult = renderedHook.result.current;
97-
98-
{
99-
expect(timesRerun).toStrictEqual(1);
100-
expect(hookFirstResult).toStrictEqual(hookSecondResult);
101-
102-
const [, , resIter1, resIter2] = hookSecondResult;
103-
104-
feedChannelAcrossTicks(channel1, ['a', 'b', 'c']);
105-
const resIter1Values = await pipe(resIter1, asyncIterTake(3), asyncIterToArray);
106-
expect(resIter1Values).toStrictEqual([
107-
'a_formatted_2nd_time',
108-
'b_formatted_2nd_time',
109-
'c_formatted_2nd_time',
110-
]);
111-
112-
feedChannelAcrossTicks(channel2, ['d', 'e', 'f']);
113-
const resIter2Values = await pipe(resIter2, asyncIterTake(3), asyncIterToArray);
114-
expect(resIter2Values).toStrictEqual([
115-
'd_formatted_2nd_time',
116-
'e_formatted_2nd_time',
117-
'f_formatted_2nd_time',
118-
]);
101+
{
102+
expect(timesRerun).toStrictEqual(1);
103+
expect(hookFirstResult).toStrictEqual(hookSecondResult);
104+
105+
const [, , resIter1, resIter2] = hookSecondResult;
106+
107+
feedChannelAcrossTicks(channel1, ['a', 'b', 'c']);
108+
const resIter1Values = await pipe(resIter1, asyncIterTake(3), asyncIterToArray);
109+
expect(resIter1Values).toStrictEqual([
110+
'a_formatted_2nd_time',
111+
'b_formatted_2nd_time',
112+
'c_formatted_2nd_time',
113+
]);
114+
115+
feedChannelAcrossTicks(channel2, ['d', 'e', 'f']);
116+
const resIter2Values = await pipe(resIter2, asyncIterTake(3), asyncIterToArray);
117+
expect(resIter2Values).toStrictEqual([
118+
'd_formatted_2nd_time',
119+
'e_formatted_2nd_time',
120+
'f_formatted_2nd_time',
121+
]);
122+
}
119123
}
120-
});
124+
);
125+
126+
it(
127+
gray(
128+
'When updated consecutively with formatted iterables of different source iterables each time, will work correctly and re-run factory function'
129+
),
130+
async () => {
131+
const iter1 = asyncIterTickSeparatedOf('a', 'b', 'c');
132+
const iter2 = asyncIterTickSeparatedOf('d', 'e', 'f');
133+
let timesRerun = 0;
134+
135+
const renderedHook = renderHook(
136+
({ val1, val2, iter1, iter2 }) =>
137+
useAsyncIterMemo(
138+
(...deps) => {
139+
timesRerun++;
140+
return deps;
141+
},
142+
[val1, val2, iter1, iter2]
143+
),
144+
{
145+
initialProps: {
146+
val1: 'a',
147+
val2: 'b',
148+
iter1: iterateFormatted(iter1, v => `${v}_formatted_1st_time`),
149+
iter2: iterateFormatted(iter2, v => `${v}_formatted_1st_time`),
150+
},
151+
}
152+
);
121153

122-
it(gray('___ ___ ___ 3'), async () => {
123-
const iter1 = asyncIterTickSeparatedOf('a', 'b', 'c');
124-
const iter2 = asyncIterTickSeparatedOf('d', 'e', 'f');
125-
let timesRerun = 0;
154+
const hookFirstResult = renderedHook.result.current;
126155

127-
const renderedHook = renderHook(
128-
({ val1, val2, iter1, iter2 }) =>
129-
useAsyncIterMemo(
130-
(...deps) => {
131-
timesRerun++;
132-
return deps;
133-
},
134-
[val1, val2, iter1, iter2]
135-
),
136156
{
137-
initialProps: {
138-
val1: 'a',
139-
val2: 'b',
140-
iter1: iterateFormatted(iter1, v => `${v}_formatted_1st_time`),
141-
iter2: iterateFormatted(iter2, v => `${v}_formatted_1st_time`),
142-
},
157+
expect(timesRerun).toStrictEqual(1);
158+
159+
const [, , resIter1, resIter2] = hookFirstResult;
160+
161+
const resIter1Values = await pipe(resIter1, asyncIterTake(3), asyncIterToArray);
162+
expect(resIter1Values).toStrictEqual([
163+
'a_formatted_1st_time',
164+
'b_formatted_1st_time',
165+
'c_formatted_1st_time',
166+
]);
167+
168+
const resIter2Values = await pipe(resIter2, asyncIterTake(3), asyncIterToArray);
169+
expect(resIter2Values).toStrictEqual([
170+
'd_formatted_1st_time',
171+
'e_formatted_1st_time',
172+
'f_formatted_1st_time',
173+
]);
143174
}
144-
);
145-
146-
const hookFirstResult = renderedHook.result.current;
147175

148-
{
149-
expect(timesRerun).toStrictEqual(1);
176+
const differentIter1 = asyncIterTickSeparatedOf('a', 'b', 'c');
177+
const differentIter2 = asyncIterTickSeparatedOf('d', 'e', 'f');
150178

151-
const [, , resIter1, resIter2] = hookFirstResult;
179+
renderedHook.rerender({
180+
val1: 'a',
181+
val2: 'b',
182+
iter1: iterateFormatted(differentIter1, v => `${v}_formatted_2nd_time`),
183+
iter2: iterateFormatted(differentIter2, v => `${v}_formatted_2nd_time`),
184+
});
152185

153-
const resIter1Values = await pipe(resIter1, asyncIterTake(3), asyncIterToArray);
154-
expect(resIter1Values).toStrictEqual([
155-
'a_formatted_1st_time',
156-
'b_formatted_1st_time',
157-
'c_formatted_1st_time',
158-
]);
159-
160-
const resIter2Values = await pipe(resIter2, asyncIterTake(3), asyncIterToArray);
161-
expect(resIter2Values).toStrictEqual([
162-
'd_formatted_1st_time',
163-
'e_formatted_1st_time',
164-
'f_formatted_1st_time',
165-
]);
166-
}
186+
const hookSecondResult = renderedHook.result.current;
167187

168-
const differentIter1 = asyncIterTickSeparatedOf('a', 'b', 'c');
169-
const differentIter2 = asyncIterTickSeparatedOf('d', 'e', 'f');
170-
171-
renderedHook.rerender({
172-
val1: 'a',
173-
val2: 'b',
174-
iter1: iterateFormatted(differentIter1, v => `${v}_formatted_2nd_time`),
175-
iter2: iterateFormatted(differentIter2, v => `${v}_formatted_2nd_time`),
176-
});
177-
178-
const hookSecondResult = renderedHook.result.current;
179-
180-
{
181-
expect(timesRerun).toStrictEqual(2);
182-
183-
expect(hookFirstResult[0]).toStrictEqual(hookSecondResult[0]);
184-
expect(hookFirstResult[1]).toStrictEqual(hookSecondResult[1]);
185-
expect(hookFirstResult[2]).not.toStrictEqual(hookSecondResult[2]);
186-
expect(hookFirstResult[3]).not.toStrictEqual(hookSecondResult[3]);
187-
188-
const resIter1Values = await pipe(hookSecondResult[2], asyncIterTake(3), asyncIterToArray);
189-
expect(resIter1Values).toStrictEqual([
190-
'a_formatted_2nd_time',
191-
'b_formatted_2nd_time',
192-
'c_formatted_2nd_time',
193-
]);
194-
195-
const resIter2Values = await pipe(hookSecondResult[3], asyncIterTake(3), asyncIterToArray);
196-
expect(resIter2Values).toStrictEqual([
197-
'd_formatted_2nd_time',
198-
'e_formatted_2nd_time',
199-
'f_formatted_2nd_time',
200-
]);
188+
{
189+
expect(timesRerun).toStrictEqual(2);
190+
191+
expect(hookFirstResult[0]).toStrictEqual(hookSecondResult[0]);
192+
expect(hookFirstResult[1]).toStrictEqual(hookSecondResult[1]);
193+
expect(hookFirstResult[2]).not.toStrictEqual(hookSecondResult[2]);
194+
expect(hookFirstResult[3]).not.toStrictEqual(hookSecondResult[3]);
195+
196+
const resIter1Values = await pipe(hookSecondResult[2], asyncIterTake(3), asyncIterToArray);
197+
expect(resIter1Values).toStrictEqual([
198+
'a_formatted_2nd_time',
199+
'b_formatted_2nd_time',
200+
'c_formatted_2nd_time',
201+
]);
202+
203+
const resIter2Values = await pipe(hookSecondResult[3], asyncIterTake(3), asyncIterToArray);
204+
expect(resIter2Values).toStrictEqual([
205+
'd_formatted_2nd_time',
206+
'e_formatted_2nd_time',
207+
'f_formatted_2nd_time',
208+
]);
209+
}
201210
}
202-
});
211+
);
203212
});
204-
205-
async function feedChannelAcrossTicks<const T>(
206-
channel: IterableChannelTestHelper<T>,
207-
values: T[]
208-
): Promise<void> {
209-
for (const value of values) {
210-
await new Promise(resolve => nextTick(resolve));
211-
channel.put(value);
212-
}
213-
}

spec/utils/feedChannelAcrossTicks.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { nextTick } from 'node:process';
2+
import { type IterableChannelTestHelper } from './IterableChannelTestHelper.js';
3+
4+
export { feedChannelAcrossTicks };
5+
6+
async function feedChannelAcrossTicks<const T>(
7+
channel: IterableChannelTestHelper<T>,
8+
values: T[]
9+
): Promise<void> {
10+
for (const value of values) {
11+
await new Promise(resolve => nextTick(resolve));
12+
channel.put(value);
13+
}
14+
}

src/useAsyncIterMemo/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ const useAsyncIterMemo: {
4343
value =>
4444
(latestDepsRef.current[i] as ReactAsyncIterable<unknown, unknown>)[
4545
reactAsyncIterSpecialInfoSymbol
46-
].formatFn(value, iterationIdx++) // TODO: Any change there won't be a `.formatFn` here if its possible that this might be called somehow at the moment the deps were changed completely?
46+
].formatFn(value, iterationIdx++) // TODO: Any chance there won't be a `.formatFn` here if its possible that this might be called somehow at the moment the deps were changed completely?
4747
);
4848
})();
4949
}) as DepsWithReactAsyncItersWrapped<TDeps>;

0 commit comments

Comments
 (0)